/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 | 11.1M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { |
69 | 11.1M | return ~((0xFFFFFFFFu) << n); |
70 | 11.1M | } brunsli_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 7.77M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 7.77M | return ~((0xFFFFFFFFu) << n); | 70 | 7.77M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 37.9k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 37.9k | return ~((0xFFFFFFFFu) << n); | 70 | 37.9k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 262k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 262k | return ~((0xFFFFFFFFu) << n); | 70 | 262k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 68 | 1.86M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 1.86M | return ~((0xFFFFFFFFu) << n); | 70 | 1.86M | } |
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 | 1.16M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 69 | 1.16M | return ~((0xFFFFFFFFu) << n); | 70 | 1.16M | } |
|
71 | | |
72 | | /* Internal. */ |
73 | 157k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { |
74 | 157k | br->num_bits_ += 8; |
75 | 157k | br->num_debt_bytes_++; |
76 | 157k | } brunsli_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 55 | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 55 | br->num_bits_ += 8; | 75 | 55 | br->num_debt_bytes_++; | 76 | 55 | } |
context_map_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 743 | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 743 | br->num_bits_ += 8; | 75 | 743 | br->num_debt_bytes_++; | 76 | 743 | } |
histogram_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 2.04k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 2.04k | br->num_bits_ += 8; | 75 | 2.04k | br->num_debt_bytes_++; | 76 | 2.04k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 73 | 154k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 74 | 154k | br->num_bits_ += 8; | 75 | 154k | br->num_debt_bytes_++; | 76 | 154k | } |
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 | 9.97M | uint32_t n_bits) { |
81 | 9.97M | if (br->num_bits_ < n_bits) { |
82 | 4.94M | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { |
83 | 157k | BrunsliBitReaderOweByte(br); |
84 | 4.78M | } else { |
85 | 4.78M | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; |
86 | 4.78M | br->num_bits_ += 8; |
87 | 4.78M | br->next_++; |
88 | 4.78M | } |
89 | 4.94M | } |
90 | 9.97M | } brunsli_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 7.77M | uint32_t n_bits) { | 81 | 7.77M | if (br->num_bits_ < n_bits) { | 82 | 4.70M | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 55 | BrunsliBitReaderOweByte(br); | 84 | 4.70M | } else { | 85 | 4.70M | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 4.70M | br->num_bits_ += 8; | 87 | 4.70M | br->next_++; | 88 | 4.70M | } | 89 | 4.70M | } | 90 | 7.77M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 38.2k | uint32_t n_bits) { | 81 | 38.2k | if (br->num_bits_ < n_bits) { | 82 | 1.37k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 743 | BrunsliBitReaderOweByte(br); | 84 | 743 | } else { | 85 | 636 | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 636 | br->num_bits_ += 8; | 87 | 636 | br->next_++; | 88 | 636 | } | 89 | 1.37k | } | 90 | 38.2k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 268k | uint32_t n_bits) { | 81 | 268k | if (br->num_bits_ < n_bits) { | 82 | 61.1k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 2.04k | BrunsliBitReaderOweByte(br); | 84 | 59.1k | } else { | 85 | 59.1k | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 59.1k | br->num_bits_ += 8; | 87 | 59.1k | br->next_++; | 88 | 59.1k | } | 89 | 61.1k | } | 90 | 268k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 80 | 1.86M | uint32_t n_bits) { | 81 | 1.86M | if (br->num_bits_ < n_bits) { | 82 | 179k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 83 | 154k | BrunsliBitReaderOweByte(br); | 84 | 154k | } else { | 85 | 25.1k | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 86 | 25.1k | br->num_bits_ += 8; | 87 | 25.1k | br->next_++; | 88 | 25.1k | } | 89 | 179k | } | 90 | 1.86M | } |
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 | 29.1k | uint32_t n_bits) { | 81 | 29.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 | 29.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 | 9.96M | uint32_t n_bits) { |
110 | 9.96M | BRUNSLI_DCHECK(n_bits <= 24); |
111 | 9.96M | BrunsliBitReaderMaybeFetchByte(br, n_bits); |
112 | 9.96M | if (n_bits > 8) { |
113 | 12.3k | BrunsliBitReaderMaybeFetchByte(br, n_bits); |
114 | 12.3k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); |
115 | 12.3k | } |
116 | 9.96M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); |
117 | 9.96M | } brunsli_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 7.77M | uint32_t n_bits) { | 110 | 7.77M | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 7.77M | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 7.77M | if (n_bits > 8) { | 113 | 5.60k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 5.60k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 5.60k | } | 116 | 7.77M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 7.77M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 37.9k | uint32_t n_bits) { | 110 | 37.9k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 37.9k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 37.9k | if (n_bits > 8) { | 113 | 307 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 307 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 307 | } | 116 | 37.9k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 37.9k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 262k | uint32_t n_bits) { | 110 | 262k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 262k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 262k | if (n_bits > 8) { | 113 | 6.18k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 6.18k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 6.18k | } | 116 | 262k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 262k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 109 | 1.86M | uint32_t n_bits) { | 110 | 1.86M | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 1.86M | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 1.86M | if (n_bits > 8) { | 113 | 243 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 243 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 243 | } | 116 | 1.86M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 1.86M | } |
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 | 29.1k | uint32_t n_bits) { | 110 | 29.1k | BRUNSLI_DCHECK(n_bits <= 24); | 111 | 29.1k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 112 | 29.1k | if (n_bits > 8) { | 113 | 0 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 114 | 0 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 0 | } | 116 | 29.1k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 117 | 29.1k | } |
|
118 | | |
119 | | static BRUNSLI_INLINE void BrunsliBitReaderDrop(BrunsliBitReader* br, |
120 | 9.96M | uint32_t n_bits) { |
121 | 9.96M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); |
122 | 9.96M | br->bits_ >>= n_bits; |
123 | 9.96M | br->num_bits_ -= n_bits; |
124 | 9.96M | } brunsli_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 7.77M | uint32_t n_bits) { | 121 | 7.77M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 7.77M | br->bits_ >>= n_bits; | 123 | 7.77M | br->num_bits_ -= n_bits; | 124 | 7.77M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 37.9k | uint32_t n_bits) { | 121 | 37.9k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 37.9k | br->bits_ >>= n_bits; | 123 | 37.9k | br->num_bits_ -= n_bits; | 124 | 37.9k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 262k | uint32_t n_bits) { | 121 | 262k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 262k | br->bits_ >>= n_bits; | 123 | 262k | br->num_bits_ -= n_bits; | 124 | 262k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 120 | 1.86M | uint32_t n_bits) { | 121 | 1.86M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 1.86M | br->bits_ >>= n_bits; | 123 | 1.86M | br->num_bits_ -= n_bits; | 124 | 1.86M | } |
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 | 29.1k | uint32_t n_bits) { | 121 | 29.1k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 122 | 29.1k | br->bits_ >>= n_bits; | 123 | 29.1k | br->num_bits_ -= n_bits; | 124 | 29.1k | } |
|
125 | | |
126 | | BRUNSLI_INLINE uint32_t BrunsliBitReaderRead(BrunsliBitReader* br, |
127 | 8.11M | uint32_t n_bits) { |
128 | 8.11M | uint32_t result = BrunsliBitReaderGet(br, n_bits); |
129 | 8.11M | BrunsliBitReaderDrop(br, n_bits); |
130 | 8.11M | return result; |
131 | 8.11M | } |
132 | | |
133 | | } // namespace brunsli |
134 | | |
135 | | #endif // BRUNSLI_DEC_BIT_READER_H_ |