/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 | 3.49M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { |
69 | 3.49M | return ~((0xFFFFFFFFu) << n); |
70 | 3.49M | } brunsli_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 2.47M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 2.47M | return ~((0xFFFFFFFFu) << n); | 70 | 2.47M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 9.05k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 9.05k | return ~((0xFFFFFFFFu) << n); | 70 | 9.05k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 126k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 126k | return ~((0xFFFFFFFFu) << n); | 70 | 126k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 803k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 803k | return ~((0xFFFFFFFFu) << n); | 70 | 803k | } |
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 | 72.2k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 72.2k | return ~((0xFFFFFFFFu) << n); | 70 | 72.2k | } |
|
71 | | |
72 | | /* Internal. */ |
73 | 30.9k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { |
74 | 30.9k | br->num_bits_ += 8; |
75 | 30.9k | br->num_debt_bytes_++; |
76 | 30.9k | } brunsli_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 29 | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 29 | br->num_bits_ += 8; | 75 | 29 | br->num_debt_bytes_++; | 76 | 29 | } |
context_map_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 223 | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 223 | br->num_bits_ += 8; | 75 | 223 | br->num_debt_bytes_++; | 76 | 223 | } |
histogram_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 579 | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 579 | br->num_bits_ += 8; | 75 | 579 | br->num_debt_bytes_++; | 76 | 579 | } |
huffman_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 30.0k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 30.0k | br->num_bits_ += 8; | 75 | 30.0k | br->num_debt_bytes_++; | 76 | 30.0k | } |
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 | 3.43M | uint32_t n_bits) { |
81 | 3.43M | if (br->num_bits_ < n_bits) { |
82 | 1.54M | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { |
83 | 30.9k | BrunsliBitReaderOweByte(br); |
84 | 1.51M | } else { |
85 | 1.51M | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; |
86 | 1.51M | br->num_bits_ += 8; |
87 | 1.51M | br->next_++; |
88 | 1.51M | } |
89 | 1.54M | } |
90 | 3.43M | } brunsli_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 2.48M | uint32_t n_bits) { | 81 | 2.48M | if (br->num_bits_ < n_bits) { | 82 | 1.47M | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 29 | BrunsliBitReaderOweByte(br); | 84 | 1.47M | } else { | 85 | 1.47M | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 1.47M | br->num_bits_ += 8; | 87 | 1.47M | br->next_++; | 88 | 1.47M | } | 89 | 1.47M | } | 90 | 2.48M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 9.14k | uint32_t n_bits) { | 81 | 9.14k | if (br->num_bits_ < n_bits) { | 82 | 272 | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 223 | BrunsliBitReaderOweByte(br); | 84 | 223 | } else { | 85 | 49 | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 49 | br->num_bits_ += 8; | 87 | 49 | br->next_++; | 88 | 49 | } | 89 | 272 | } | 90 | 9.14k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 128k | uint32_t n_bits) { | 81 | 128k | if (br->num_bits_ < n_bits) { | 82 | 26.8k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 579 | BrunsliBitReaderOweByte(br); | 84 | 26.2k | } else { | 85 | 26.2k | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 26.2k | br->num_bits_ += 8; | 87 | 26.2k | br->next_++; | 88 | 26.2k | } | 89 | 26.8k | } | 90 | 128k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 803k | uint32_t n_bits) { | 81 | 803k | if (br->num_bits_ < n_bits) { | 82 | 41.5k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 30.0k | BrunsliBitReaderOweByte(br); | 84 | 30.0k | } else { | 85 | 11.4k | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 11.4k | br->num_bits_ += 8; | 87 | 11.4k | br->next_++; | 88 | 11.4k | } | 89 | 41.5k | } | 90 | 803k | } |
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 | 12.1k | uint32_t n_bits) { | 81 | 12.1k | 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 | 12.1k | } |
|
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 | 3.43M | uint32_t n_bits) { |
110 | 3.43M | BRUNSLI_DCHECK(n_bits <= 24); |
111 | 3.43M | BrunsliBitReaderMaybeFetchByte(br, n_bits); |
112 | 3.43M | if (n_bits > 8) { |
113 | 3.59k | BrunsliBitReaderMaybeFetchByte(br, n_bits); |
114 | 3.59k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); |
115 | 3.59k | } |
116 | 3.43M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); |
117 | 3.43M | } brunsli_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 2.47M | uint32_t n_bits) { | 110 | 2.47M | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 2.47M | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 2.47M | if (n_bits > 8) { | 113 | 1.42k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 1.42k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 1.42k | } | 116 | 2.47M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 2.47M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 9.05k | uint32_t n_bits) { | 110 | 9.05k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 9.05k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 9.05k | if (n_bits > 8) { | 113 | 93 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 93 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 93 | } | 116 | 9.05k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 9.05k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 126k | uint32_t n_bits) { | 110 | 126k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 126k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 126k | if (n_bits > 8) { | 113 | 2.02k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 2.02k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 2.02k | } | 116 | 126k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 126k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 803k | uint32_t n_bits) { | 110 | 803k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 803k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 803k | if (n_bits > 8) { | 113 | 54 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 54 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 54 | } | 116 | 803k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 803k | } |
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 | 12.1k | uint32_t n_bits) { | 110 | 12.1k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 12.1k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 12.1k | if (n_bits > 8) { | 113 | 0 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 0 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 0 | } | 116 | 12.1k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 12.1k | } |
|
118 | | |
119 | | static BRUNSLI_INLINE void BrunsliBitReaderDrop(BrunsliBitReader* br, |
120 | 3.43M | uint32_t n_bits) { |
121 | 3.43M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); |
122 | 3.43M | br->bits_ >>= n_bits; |
123 | 3.43M | br->num_bits_ -= n_bits; |
124 | 3.43M | } brunsli_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 2.47M | uint32_t n_bits) { | 121 | 2.47M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 2.47M | br->bits_ >>= n_bits; | 123 | 2.47M | br->num_bits_ -= n_bits; | 124 | 2.47M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 9.05k | uint32_t n_bits) { | 121 | 9.05k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 9.05k | br->bits_ >>= n_bits; | 123 | 9.05k | br->num_bits_ -= n_bits; | 124 | 9.05k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 126k | uint32_t n_bits) { | 121 | 126k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 126k | br->bits_ >>= n_bits; | 123 | 126k | br->num_bits_ -= n_bits; | 124 | 126k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 803k | uint32_t n_bits) { | 121 | 803k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 803k | br->bits_ >>= n_bits; | 123 | 803k | br->num_bits_ -= n_bits; | 124 | 803k | } |
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 | 12.1k | uint32_t n_bits) { | 121 | 12.1k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 12.1k | br->bits_ >>= n_bits; | 123 | 12.1k | br->num_bits_ -= n_bits; | 124 | 12.1k | } |
|
125 | | |
126 | | BRUNSLI_INLINE uint32_t BrunsliBitReaderRead(BrunsliBitReader* br, |
127 | 2.62M | uint32_t n_bits) { |
128 | 2.62M | uint32_t result = BrunsliBitReaderGet(br, n_bits); |
129 | 2.62M | BrunsliBitReaderDrop(br, n_bits); |
130 | 2.62M | return result; |
131 | 2.62M | } |
132 | | |
133 | | } // namespace brunsli |
134 | | |
135 | | #endif // BRUNSLI_DEC_BIT_READER_H_ |