1/* Copyright 2010 Google Inc. All Rights Reserved. 2 3 Distributed under MIT license. 4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5*/ 6 7/* Write bits into a byte array. */ 8 9#ifndef BROTLI_ENC_WRITE_BITS_H_ 10#define BROTLI_ENC_WRITE_BITS_H_ 11 12#include "../common/platform.h" 13#include <brotli/types.h> 14 15#if defined(__cplusplus) || defined(c_plusplus) 16extern "C" { 17#endif 18 19/* This function writes bits into bytes in increasing addresses, and within 20 a byte least-significant-bit first. 21 22 The function can write up to 56 bits in one go with WriteBits 23 Example: let's assume that 3 bits (Rs below) have been written already: 24 25 BYTE-0 BYTE+1 BYTE+2 26 27 0000 0RRR 0000 0000 0000 0000 28 29 Now, we could write 5 or less bits in MSB by just shifting by 3 30 and OR'ing to BYTE-0. 31 32 For n bits, we take the last 5 bits, OR that with high bits in BYTE-0, 33 and locate the rest in BYTE+1, BYTE+2, etc. */ 34static BROTLI_INLINE void BrotliWriteBits(size_t n_bits, 35 uint64_t bits, 36 size_t* BROTLI_RESTRICT pos, 37 uint8_t* BROTLI_RESTRICT array) { 38 BROTLI_LOG(("WriteBits %2d 0x%08x%08x %10d\n", (int)n_bits, 39 (uint32_t)(bits >> 32), (uint32_t)(bits & 0xFFFFFFFF), 40 (int)*pos)); 41 BROTLI_DCHECK((bits >> n_bits) == 0); 42 BROTLI_DCHECK(n_bits <= 56); 43#if defined(BROTLI_LITTLE_ENDIAN) 44 /* This branch of the code can write up to 56 bits at a time, 45 7 bits are lost by being perhaps already in *p and at least 46 1 bit is needed to initialize the bit-stream ahead (i.e. if 7 47 bits are in *p and we write 57 bits, then the next write will 48 access a byte that was never initialized). */ 49 { 50 uint8_t* p = &array[*pos >> 3]; 51 uint64_t v = (uint64_t)(*p); /* Zero-extend 8 to 64 bits. */ 52 v |= bits << (*pos & 7); 53 BROTLI_UNALIGNED_STORE64LE(p, v); /* Set some bits. */ 54 *pos += n_bits; 55 } 56#else 57 /* implicit & 0xFF is assumed for uint8_t arithmetics */ 58 { 59 uint8_t* array_pos = &array[*pos >> 3]; 60 const size_t bits_reserved_in_first_byte = (*pos & 7); 61 size_t bits_left_to_write; 62 bits <<= bits_reserved_in_first_byte; 63 *array_pos++ |= (uint8_t)bits; 64 for (bits_left_to_write = n_bits + bits_reserved_in_first_byte; 65 bits_left_to_write >= 9; 66 bits_left_to_write -= 8) { 67 bits >>= 8; 68 *array_pos++ = (uint8_t)bits; 69 } 70 *array_pos = 0; 71 *pos += n_bits; 72 } 73#endif 74} 75 76static BROTLI_INLINE void BrotliWriteBitsPrepareStorage( 77 size_t pos, uint8_t* array) { 78 BROTLI_LOG(("WriteBitsPrepareStorage %10d\n", (int)pos)); 79 BROTLI_DCHECK((pos & 7) == 0); 80 array[pos >> 3] = 0; 81} 82 83#if defined(__cplusplus) || defined(c_plusplus) 84} /* extern "C" */ 85#endif 86 87#endif /* BROTLI_ENC_WRITE_BITS_H_ */ 88