blob: c3140c198235ee263a2ba4291b0bf45cc8913c13 [file] [log] [blame]
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +02001// 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>
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +020021#include <stdint.h>
22#include <stdio.h>
23
24#include "./port.h"
25
26namespace brotli {
27
28//#define BIT_WRITER_DEBUG
29
30// This function writes bits into bytes in increasing addresses, and within
31// a byte least-significant-bit first.
32//
33// The function can write up to 56 bits in one go with WriteBits
34// Example: let's assume that 3 bits (Rs below) have been written already:
35//
36// BYTE-0 BYTE+1 BYTE+2
37//
38// 0000 0RRR 0000 0000 0000 0000
39//
40// Now, we could write 5 or less bits in MSB by just sifting by 3
41// and OR'ing to BYTE-0.
42//
43// For n bits, we take the last 5 bits, OR that with high bits in BYTE-0,
44// and locate the rest in BYTE+1, BYTE+2, etc.
45inline void WriteBits(int n_bits,
46 uint64_t bits,
47 int * __restrict pos,
48 uint8_t * __restrict array) {
49#ifdef BIT_WRITER_DEBUG
50 printf("WriteBits %2d 0x%016llx %10d\n", n_bits, bits, *pos);
51#endif
Zoltan Szabadkab4f39bf2014-10-28 13:25:22 +010052 assert(bits < 1ULL << n_bits);
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +020053#ifdef IS_LITTLE_ENDIAN
54 // This branch of the code can write up to 56 bits at a time,
55 // 7 bits are lost by being perhaps already in *p and at least
56 // 1 bit is needed to initialize the bit-stream ahead (i.e. if 7
57 // bits are in *p and we write 57 bits, then the next write will
58 // access a byte that was never initialized).
59 uint8_t *p = &array[*pos >> 3];
60 uint64_t v = *p;
61 v |= bits << (*pos & 7);
62 BROTLI_UNALIGNED_STORE64(p, v); // Set some bits.
63 *pos += n_bits;
64#else
65 // implicit & 0xff is assumed for uint8_t arithmetics
66 uint8_t *array_pos = &array[*pos >> 3];
67 const int bits_reserved_in_first_byte = (*pos & 7);
68 bits <<= bits_reserved_in_first_byte;
69 *array_pos++ |= bits;
70 for (int bits_left_to_write = n_bits - 8 + bits_reserved_in_first_byte;
71 bits_left_to_write >= 1;
72 bits_left_to_write -= 8) {
73 bits >>= 8;
74 *array_pos++ = bits;
75 }
76 *array_pos = 0;
77 *pos += n_bits;
78#endif
79}
80
81inline void WriteBitsPrepareStorage(int pos, uint8_t *array) {
82#ifdef BIT_WRITER_DEBUG
83 printf("WriteBitsPrepareStorage %10d\n", pos);
84#endif
85 assert((pos & 7) == 0);
86 array[pos >> 3] = 0;
87}
88
89} // namespace brotli
90
91#endif // BROTLI_ENC_WRITE_BITS_H_