/src/brunsli/c/dec/bit_reader.h
Line | Count | Source |
1 | | // Copyright (c) Google LLC 2019 |
2 | | // |
3 | | // Use of this source code is governed by an MIT-style |
4 | | // license that can be found in the LICENSE file or at |
5 | | // https://opensource.org/licenses/MIT. |
6 | | |
7 | | /* Bit reading helpers */ |
8 | | |
9 | | #ifndef BRUNSLI_DEC_BIT_READER_H_ |
10 | | #define BRUNSLI_DEC_BIT_READER_H_ |
11 | | |
12 | | #include "../common/platform.h" |
13 | | #include <brunsli/types.h> |
14 | | |
15 | | namespace brunsli { |
16 | | |
17 | | struct BrunsliBitReader { |
18 | | const uint8_t* next_; |
19 | | const uint8_t* end_; |
20 | | uint32_t num_bits_; |
21 | | uint32_t bits_; |
22 | | /* |
23 | | Number of "virtual" zero bytes located after the end of buffer being |
24 | | put into the bit buffer. |
25 | | |
26 | | The concept of debt is useful for two purposes: |
27 | | - postpone handling of "unexpected end of input" |
28 | | - allow efficient peeking of input near the end |
29 | | |
30 | | It is OK to have debt, while "balance" is non-negative. |
31 | | BrunsliBitReaderUnload returns debt, if possible. |
32 | | */ |
33 | | uint32_t num_debt_bytes_; |
34 | | bool is_healthy_; |
35 | | bool is_optimistic_; |
36 | | }; |
37 | | |
38 | | /** |
39 | | * Prepare instance. |
40 | | * |
41 | | * The instance lifecycle looks like: |
42 | | * - Init |
43 | | * - Resume |
44 | | * - (read bits) |
45 | | * - Suspend |
46 | | * - (optionally, go back to Resume stage) |
47 | | * - Finish |
48 | | */ |
49 | | void BrunsliBitReaderInit(BrunsliBitReader* br); |
50 | | /** |
51 | | * Supply instance with new chunk of input. |
52 | | */ |
53 | | void BrunsliBitReaderResume(BrunsliBitReader* br, const uint8_t* buffer, |
54 | | size_t length); |
55 | | /** |
56 | | * Returns the number of unused bytes. |
57 | | */ |
58 | | size_t BrunsliBitReaderSuspend(BrunsliBitReader* br); |
59 | | /** |
60 | | * Drops unused bits of the last used byte. |
61 | | * |
62 | | * Marks instance as unhealthy, if unused bits are not all 0. |
63 | | */ |
64 | | void BrunsliBitReaderFinish(BrunsliBitReader* br); |
65 | | |
66 | | bool BrunsliBitReaderIsHealthy(BrunsliBitReader* br); |
67 | | |
68 | 13.6M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { |
69 | 13.6M | return ~((0xFFFFFFFFu) << n); |
70 | 13.6M | } brunsli_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 8.60M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 8.60M | return ~((0xFFFFFFFFu) << n); | 70 | 8.60M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 30.9k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 30.9k | return ~((0xFFFFFFFFu) << n); | 70 | 30.9k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 249k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 249k | return ~((0xFFFFFFFFu) << n); | 70 | 249k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 1.63M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 1.63M | return ~((0xFFFFFFFFu) << n); | 70 | 1.63M | } |
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) bit_reader.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 3.08M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 3.08M | return ~((0xFFFFFFFFu) << n); | 70 | 3.08M | } |
|
71 | | |
72 | | /* Internal. */ |
73 | 147k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { |
74 | 147k | br->num_bits_ += 8; |
75 | 147k | br->num_debt_bytes_++; |
76 | 147k | } brunsli_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 49 | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 49 | br->num_bits_ += 8; | 75 | 49 | br->num_debt_bytes_++; | 76 | 49 | } |
context_map_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 1.09k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 1.09k | br->num_bits_ += 8; | 75 | 1.09k | br->num_debt_bytes_++; | 76 | 1.09k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 1.85k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 1.85k | br->num_bits_ += 8; | 75 | 1.85k | br->num_debt_bytes_++; | 76 | 1.85k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 144k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 144k | br->num_bits_ += 8; | 75 | 144k | br->num_debt_bytes_++; | 76 | 144k | } |
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Unexecuted instantiation: bit_reader.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) |
77 | | |
78 | | /* Internal. */ |
79 | | static BRUNSLI_INLINE void BrunsliBitReaderMaybeFetchByte(BrunsliBitReader* br, |
80 | 10.5M | uint32_t n_bits) { |
81 | 10.5M | if (br->num_bits_ < n_bits) { |
82 | 5.53M | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { |
83 | 147k | BrunsliBitReaderOweByte(br); |
84 | 5.39M | } else { |
85 | 5.39M | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; |
86 | 5.39M | br->num_bits_ += 8; |
87 | 5.39M | br->next_++; |
88 | 5.39M | } |
89 | 5.53M | } |
90 | 10.5M | } brunsli_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 8.61M | uint32_t n_bits) { | 81 | 8.61M | if (br->num_bits_ < n_bits) { | 82 | 5.31M | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 49 | BrunsliBitReaderOweByte(br); | 84 | 5.31M | } else { | 85 | 5.31M | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 5.31M | br->num_bits_ += 8; | 87 | 5.31M | br->next_++; | 88 | 5.31M | } | 89 | 5.31M | } | 90 | 8.61M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 31.1k | uint32_t n_bits) { | 81 | 31.1k | if (br->num_bits_ < n_bits) { | 82 | 1.60k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 1.09k | BrunsliBitReaderOweByte(br); | 84 | 1.09k | } else { | 85 | 518 | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 518 | br->num_bits_ += 8; | 87 | 518 | br->next_++; | 88 | 518 | } | 89 | 1.60k | } | 90 | 31.1k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 254k | uint32_t n_bits) { | 81 | 254k | if (br->num_bits_ < n_bits) { | 82 | 56.8k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 1.85k | BrunsliBitReaderOweByte(br); | 84 | 54.9k | } else { | 85 | 54.9k | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 54.9k | br->num_bits_ += 8; | 87 | 54.9k | br->next_++; | 88 | 54.9k | } | 89 | 56.8k | } | 90 | 254k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 1.63M | uint32_t n_bits) { | 81 | 1.63M | if (br->num_bits_ < n_bits) { | 82 | 167k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 144k | BrunsliBitReaderOweByte(br); | 84 | 144k | } else { | 85 | 23.2k | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 23.2k | br->num_bits_ += 8; | 87 | 23.2k | br->next_++; | 88 | 23.2k | } | 89 | 167k | } | 90 | 1.63M | } |
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) bit_reader.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 27.5k | uint32_t n_bits) { | 81 | 27.5k | if (br->num_bits_ < n_bits) { | 82 | 0 | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 0 | BrunsliBitReaderOweByte(br); | 84 | 0 | } else { | 85 | 0 | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 0 | br->num_bits_ += 8; | 87 | 0 | br->next_++; | 88 | 0 | } | 89 | 0 | } | 90 | 27.5k | } |
|
91 | | |
92 | | /** |
93 | | * Turns instance to optimistic mode. |
94 | | * |
95 | | * The only difference with regular operating mode is that CanRead always |
96 | | * returns "true". Use this mode only when instance is supplied with complete |
97 | | * input. |
98 | | */ |
99 | | void BrunsliBitReaderSetOptimistic(BrunsliBitReader* br); |
100 | | |
101 | | /** |
102 | | * Returns true if there is enough input. |
103 | | * |
104 | | * Guaranteed to work correctly only in normalized state. |
105 | | */ |
106 | | bool BrunsliBitReaderCanRead(BrunsliBitReader* br, size_t n_bits); |
107 | | |
108 | | static BRUNSLI_INLINE uint32_t BrunsliBitReaderGet(BrunsliBitReader* br, |
109 | 10.5M | uint32_t n_bits) { |
110 | 10.5M | BRUNSLI_DCHECK(n_bits <= 24); |
111 | 10.5M | BrunsliBitReaderMaybeFetchByte(br, n_bits); |
112 | 10.5M | if (n_bits > 8) { |
113 | 10.5k | BrunsliBitReaderMaybeFetchByte(br, n_bits); |
114 | 10.5k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); |
115 | 10.5k | } |
116 | 10.5M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); |
117 | 10.5M | } brunsli_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 8.60M | uint32_t n_bits) { | 110 | 8.60M | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 8.60M | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 8.60M | if (n_bits > 8) { | 113 | 4.90k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 4.90k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 4.90k | } | 116 | 8.60M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 8.60M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 30.9k | uint32_t n_bits) { | 110 | 30.9k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 30.9k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 30.9k | if (n_bits > 8) { | 113 | 212 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 212 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 212 | } | 116 | 30.9k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 30.9k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 249k | uint32_t n_bits) { | 110 | 249k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 249k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 249k | if (n_bits > 8) { | 113 | 5.25k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 5.25k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 5.25k | } | 116 | 249k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 249k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 1.63M | uint32_t n_bits) { | 110 | 1.63M | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 1.63M | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 1.63M | if (n_bits > 8) { | 113 | 173 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 173 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 173 | } | 116 | 1.63M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 1.63M | } |
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) bit_reader.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 27.5k | uint32_t n_bits) { | 110 | 27.5k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 27.5k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 27.5k | if (n_bits > 8) { | 113 | 0 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 0 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 0 | } | 116 | 27.5k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 27.5k | } |
|
118 | | |
119 | | static BRUNSLI_INLINE void BrunsliBitReaderDrop(BrunsliBitReader* br, |
120 | 10.5M | uint32_t n_bits) { |
121 | 10.5M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); |
122 | 10.5M | br->bits_ >>= n_bits; |
123 | 10.5M | br->num_bits_ -= n_bits; |
124 | 10.5M | } brunsli_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 8.60M | uint32_t n_bits) { | 121 | 8.60M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 8.60M | br->bits_ >>= n_bits; | 123 | 8.60M | br->num_bits_ -= n_bits; | 124 | 8.60M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 30.9k | uint32_t n_bits) { | 121 | 30.9k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 30.9k | br->bits_ >>= n_bits; | 123 | 30.9k | br->num_bits_ -= n_bits; | 124 | 30.9k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 249k | uint32_t n_bits) { | 121 | 249k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 249k | br->bits_ >>= n_bits; | 123 | 249k | br->num_bits_ -= n_bits; | 124 | 249k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 1.63M | uint32_t n_bits) { | 121 | 1.63M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 1.63M | br->bits_ >>= n_bits; | 123 | 1.63M | br->num_bits_ -= n_bits; | 124 | 1.63M | } |
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) bit_reader.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 27.5k | uint32_t n_bits) { | 121 | 27.5k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 27.5k | br->bits_ >>= n_bits; | 123 | 27.5k | br->num_bits_ -= n_bits; | 124 | 27.5k | } |
|
125 | | |
126 | | BRUNSLI_INLINE uint32_t BrunsliBitReaderRead(BrunsliBitReader* br, |
127 | 8.92M | uint32_t n_bits) { |
128 | 8.92M | uint32_t result = BrunsliBitReaderGet(br, n_bits); |
129 | 8.92M | BrunsliBitReaderDrop(br, n_bits); |
130 | 8.92M | return result; |
131 | 8.92M | } |
132 | | |
133 | | } // namespace brunsli |
134 | | |
135 | | #endif // BRUNSLI_DEC_BIT_READER_H_ |