126fa459cSmrg/* Copyright 2010 Google Inc. All Rights Reserved. 226fa459cSmrg 326fa459cSmrg Distributed under MIT license. 426fa459cSmrg See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 526fa459cSmrg*/ 626fa459cSmrg 726fa459cSmrg/* Write bits into a byte array. */ 826fa459cSmrg 926fa459cSmrg#ifndef BROTLI_ENC_WRITE_BITS_H_ 1026fa459cSmrg#define BROTLI_ENC_WRITE_BITS_H_ 1126fa459cSmrg 1226fa459cSmrg#include "../common/platform.h" 1326fa459cSmrg#include <brotli/types.h> 1426fa459cSmrg 1526fa459cSmrg#if defined(__cplusplus) || defined(c_plusplus) 1626fa459cSmrgextern "C" { 1726fa459cSmrg#endif 1826fa459cSmrg 1926fa459cSmrg/* This function writes bits into bytes in increasing addresses, and within 2026fa459cSmrg a byte least-significant-bit first. 2126fa459cSmrg 2226fa459cSmrg The function can write up to 56 bits in one go with WriteBits 2326fa459cSmrg Example: let's assume that 3 bits (Rs below) have been written already: 2426fa459cSmrg 2526fa459cSmrg BYTE-0 BYTE+1 BYTE+2 2626fa459cSmrg 2726fa459cSmrg 0000 0RRR 0000 0000 0000 0000 2826fa459cSmrg 2926fa459cSmrg Now, we could write 5 or less bits in MSB by just shifting by 3 3026fa459cSmrg and OR'ing to BYTE-0. 3126fa459cSmrg 3226fa459cSmrg For n bits, we take the last 5 bits, OR that with high bits in BYTE-0, 3326fa459cSmrg and locate the rest in BYTE+1, BYTE+2, etc. */ 3426fa459cSmrgstatic BROTLI_INLINE void BrotliWriteBits(size_t n_bits, 3526fa459cSmrg uint64_t bits, 3626fa459cSmrg size_t* BROTLI_RESTRICT pos, 3726fa459cSmrg uint8_t* BROTLI_RESTRICT array) { 3826fa459cSmrg BROTLI_LOG(("WriteBits %2d 0x%08x%08x %10d\n", (int)n_bits, 3926fa459cSmrg (uint32_t)(bits >> 32), (uint32_t)(bits & 0xFFFFFFFF), 4026fa459cSmrg (int)*pos)); 4126fa459cSmrg BROTLI_DCHECK((bits >> n_bits) == 0); 4226fa459cSmrg BROTLI_DCHECK(n_bits <= 56); 4326fa459cSmrg#if defined(BROTLI_LITTLE_ENDIAN) 4426fa459cSmrg /* This branch of the code can write up to 56 bits at a time, 4526fa459cSmrg 7 bits are lost by being perhaps already in *p and at least 4626fa459cSmrg 1 bit is needed to initialize the bit-stream ahead (i.e. if 7 4726fa459cSmrg bits are in *p and we write 57 bits, then the next write will 4826fa459cSmrg access a byte that was never initialized). */ 4926fa459cSmrg { 5026fa459cSmrg uint8_t* p = &array[*pos >> 3]; 5126fa459cSmrg uint64_t v = (uint64_t)(*p); /* Zero-extend 8 to 64 bits. */ 5226fa459cSmrg v |= bits << (*pos & 7); 5326fa459cSmrg BROTLI_UNALIGNED_STORE64LE(p, v); /* Set some bits. */ 5426fa459cSmrg *pos += n_bits; 5526fa459cSmrg } 5626fa459cSmrg#else 5726fa459cSmrg /* implicit & 0xFF is assumed for uint8_t arithmetics */ 5826fa459cSmrg { 5926fa459cSmrg uint8_t* array_pos = &array[*pos >> 3]; 6026fa459cSmrg const size_t bits_reserved_in_first_byte = (*pos & 7); 6126fa459cSmrg size_t bits_left_to_write; 6226fa459cSmrg bits <<= bits_reserved_in_first_byte; 6326fa459cSmrg *array_pos++ |= (uint8_t)bits; 6426fa459cSmrg for (bits_left_to_write = n_bits + bits_reserved_in_first_byte; 6526fa459cSmrg bits_left_to_write >= 9; 6626fa459cSmrg bits_left_to_write -= 8) { 6726fa459cSmrg bits >>= 8; 6826fa459cSmrg *array_pos++ = (uint8_t)bits; 6926fa459cSmrg } 7026fa459cSmrg *array_pos = 0; 7126fa459cSmrg *pos += n_bits; 7226fa459cSmrg } 7326fa459cSmrg#endif 7426fa459cSmrg} 7526fa459cSmrg 7626fa459cSmrgstatic BROTLI_INLINE void BrotliWriteBitsPrepareStorage( 7726fa459cSmrg size_t pos, uint8_t* array) { 7826fa459cSmrg BROTLI_LOG(("WriteBitsPrepareStorage %10d\n", (int)pos)); 7926fa459cSmrg BROTLI_DCHECK((pos & 7) == 0); 8026fa459cSmrg array[pos >> 3] = 0; 8126fa459cSmrg} 8226fa459cSmrg 8326fa459cSmrg#if defined(__cplusplus) || defined(c_plusplus) 8426fa459cSmrg} /* extern "C" */ 8526fa459cSmrg#endif 8626fa459cSmrg 8726fa459cSmrg#endif /* BROTLI_ENC_WRITE_BITS_H_ */ 88