1// Copyright 2010 Google Inc. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15// Write bits into a byte array. 16 17#ifndef BROTLI_ENC_WRITE_BITS_H_ 18#define BROTLI_ENC_WRITE_BITS_H_ 19 20#include <assert.h> 21#if defined(OS_MACOSX) 22 #include <machine/endian.h> 23#else 24 #include <endian.h> 25#endif 26#include <stdint.h> 27#include <stdio.h> 28 29#include "./port.h" 30 31namespace brotli { 32 33//#define BIT_WRITER_DEBUG 34 35// This function writes bits into bytes in increasing addresses, and within 36// a byte least-significant-bit first. 37// 38// The function can write up to 56 bits in one go with WriteBits 39// Example: let's assume that 3 bits (Rs below) have been written already: 40// 41// BYTE-0 BYTE+1 BYTE+2 42// 43// 0000 0RRR 0000 0000 0000 0000 44// 45// Now, we could write 5 or less bits in MSB by just sifting by 3 46// and OR'ing to BYTE-0. 47// 48// For n bits, we take the last 5 bits, OR that with high bits in BYTE-0, 49// and locate the rest in BYTE+1, BYTE+2, etc. 50inline void WriteBits(int n_bits, 51 uint64_t bits, 52 int * __restrict pos, 53 uint8_t * __restrict array) { 54#ifdef BIT_WRITER_DEBUG 55 printf("WriteBits %2d 0x%016llx %10d\n", n_bits, bits, *pos); 56#endif 57#ifdef IS_LITTLE_ENDIAN 58 // This branch of the code can write up to 56 bits at a time, 59 // 7 bits are lost by being perhaps already in *p and at least 60 // 1 bit is needed to initialize the bit-stream ahead (i.e. if 7 61 // bits are in *p and we write 57 bits, then the next write will 62 // access a byte that was never initialized). 63 uint8_t *p = &array[*pos >> 3]; 64 uint64_t v = *p; 65 v |= bits << (*pos & 7); 66 BROTLI_UNALIGNED_STORE64(p, v); // Set some bits. 67 *pos += n_bits; 68#else 69 // implicit & 0xff is assumed for uint8_t arithmetics 70 uint8_t *array_pos = &array[*pos >> 3]; 71 const int bits_reserved_in_first_byte = (*pos & 7); 72 bits <<= bits_reserved_in_first_byte; 73 *array_pos++ |= bits; 74 for (int bits_left_to_write = n_bits - 8 + bits_reserved_in_first_byte; 75 bits_left_to_write >= 1; 76 bits_left_to_write -= 8) { 77 bits >>= 8; 78 *array_pos++ = bits; 79 } 80 *array_pos = 0; 81 *pos += n_bits; 82#endif 83} 84 85inline void WriteBitsPrepareStorage(int pos, uint8_t *array) { 86#ifdef BIT_WRITER_DEBUG 87 printf("WriteBitsPrepareStorage %10d\n", pos); 88#endif 89 assert((pos & 7) == 0); 90 array[pos >> 3] = 0; 91} 92 93} // namespace brotli 94 95#endif // BROTLI_ENC_WRITE_BITS_H_ 96