/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 <brunsli/types.h> |
13 | | |
14 | | #include "../common/platform.h" |
15 | | |
16 | | namespace brunsli { |
17 | | |
18 | | struct BrunsliBitReader { |
19 | | const uint8_t* next_; |
20 | | const uint8_t* end_; |
21 | | uint32_t num_bits_; |
22 | | uint32_t bits_; |
23 | | /* |
24 | | Number of "virtual" zero bytes located after the end of buffer being |
25 | | put into the bit buffer. |
26 | | |
27 | | The concept of debt is useful for two purposes: |
28 | | - postpone handling of "unexpected end of input" |
29 | | - allow efficient peeking of input near the end |
30 | | |
31 | | It is OK to have debt, while "balance" is non-negative. |
32 | | BrunsliBitReaderUnload returns debt, if possible. |
33 | | */ |
34 | | uint32_t num_debt_bytes_; |
35 | | bool is_healthy_; |
36 | | bool is_optimistic_; |
37 | | }; |
38 | | |
39 | | /** |
40 | | * Prepare instance. |
41 | | * |
42 | | * The instance lifecycle looks like: |
43 | | * - Init |
44 | | * - Resume |
45 | | * - (read bits) |
46 | | * - Suspend |
47 | | * - (optionally, go back to Resume stage) |
48 | | * - Finish |
49 | | */ |
50 | | void BrunsliBitReaderInit(BrunsliBitReader* br); |
51 | | /** |
52 | | * Supply instance with new chunk of input. |
53 | | */ |
54 | | void BrunsliBitReaderResume(BrunsliBitReader* br, const uint8_t* buffer, |
55 | | size_t length); |
56 | | /** |
57 | | * Returns the number of unused bytes. |
58 | | */ |
59 | | size_t BrunsliBitReaderSuspend(BrunsliBitReader* br); |
60 | | /** |
61 | | * Drops unused bits of the last used byte. |
62 | | * |
63 | | * Marks instance as unhealthy, if unused bits are not all 0. |
64 | | */ |
65 | | void BrunsliBitReaderFinish(BrunsliBitReader* br); |
66 | | |
67 | | bool BrunsliBitReaderIsHealthy(BrunsliBitReader* br); |
68 | | |
69 | 35.5M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { |
70 | 35.5M | return ~((0xFFFFFFFFu) << n); |
71 | 35.5M | } brunsli_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 69 | 27.4M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 70 | 27.4M | return ~((0xFFFFFFFFu) << n); | 71 | 27.4M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 69 | 38.0k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 70 | 38.0k | return ~((0xFFFFFFFFu) << n); | 71 | 38.0k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 69 | 251k | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 70 | 251k | return ~((0xFFFFFFFFu) << n); | 71 | 251k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int) Line | Count | Source | 69 | 1.94M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 70 | 1.94M | return ~((0xFFFFFFFFu) << n); | 71 | 1.94M | } |
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 | 69 | 5.95M | static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) { | 70 | 5.95M | return ~((0xFFFFFFFFu) << n); | 71 | 5.95M | } |
|
72 | | |
73 | | /* Internal. */ |
74 | 140k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { |
75 | 140k | br->num_bits_ += 8; |
76 | 140k | br->num_debt_bytes_++; |
77 | 140k | } brunsli_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 74 | 50 | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 75 | 50 | br->num_bits_ += 8; | 76 | 50 | br->num_debt_bytes_++; | 77 | 50 | } |
context_map_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 74 | 634 | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 75 | 634 | br->num_bits_ += 8; | 76 | 634 | br->num_debt_bytes_++; | 77 | 634 | } |
histogram_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 74 | 2.14k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 75 | 2.14k | br->num_bits_ += 8; | 76 | 2.14k | br->num_debt_bytes_++; | 77 | 2.14k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*) Line | Count | Source | 74 | 138k | static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) { | 75 | 138k | br->num_bits_ += 8; | 76 | 138k | br->num_debt_bytes_++; | 77 | 138k | } |
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*) |
78 | | |
79 | | /* Internal. */ |
80 | | static BRUNSLI_INLINE void BrunsliBitReaderMaybeFetchByte(BrunsliBitReader* br, |
81 | 29.6M | uint32_t n_bits) { |
82 | 29.6M | if (br->num_bits_ < n_bits) { |
83 | 11.6M | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { |
84 | 140k | BrunsliBitReaderOweByte(br); |
85 | 11.4M | } else { |
86 | 11.4M | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; |
87 | 11.4M | br->num_bits_ += 8; |
88 | 11.4M | br->next_++; |
89 | 11.4M | } |
90 | 11.6M | } |
91 | 29.6M | } brunsli_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 81 | 27.4M | uint32_t n_bits) { | 82 | 27.4M | if (br->num_bits_ < n_bits) { | 83 | 11.3M | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 84 | 50 | BrunsliBitReaderOweByte(br); | 85 | 11.3M | } else { | 86 | 11.3M | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 87 | 11.3M | br->num_bits_ += 8; | 88 | 11.3M | br->next_++; | 89 | 11.3M | } | 90 | 11.3M | } | 91 | 27.4M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 81 | 38.3k | uint32_t n_bits) { | 82 | 38.3k | if (br->num_bits_ < n_bits) { | 83 | 1.17k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 84 | 634 | BrunsliBitReaderOweByte(br); | 85 | 634 | } else { | 86 | 538 | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 87 | 538 | br->num_bits_ += 8; | 88 | 538 | br->next_++; | 89 | 538 | } | 90 | 1.17k | } | 91 | 38.3k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 81 | 256k | uint32_t n_bits) { | 82 | 256k | if (br->num_bits_ < n_bits) { | 83 | 58.0k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 84 | 2.14k | BrunsliBitReaderOweByte(br); | 85 | 55.9k | } else { | 86 | 55.9k | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 87 | 55.9k | br->num_bits_ += 8; | 88 | 55.9k | br->next_++; | 89 | 55.9k | } | 90 | 58.0k | } | 91 | 256k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 81 | 1.94M | uint32_t n_bits) { | 82 | 1.94M | if (br->num_bits_ < n_bits) { | 83 | 164k | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 84 | 138k | BrunsliBitReaderOweByte(br); | 85 | 138k | } else { | 86 | 26.6k | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 87 | 26.6k | br->num_bits_ += 8; | 88 | 26.6k | br->next_++; | 89 | 26.6k | } | 90 | 164k | } | 91 | 1.94M | } |
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 | 81 | 30.5k | uint32_t n_bits) { | 82 | 30.5k | if (br->num_bits_ < n_bits) { | 83 | 0 | if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) { | 84 | 0 | BrunsliBitReaderOweByte(br); | 85 | 0 | } else { | 86 | 0 | br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_; | 87 | 0 | br->num_bits_ += 8; | 88 | 0 | br->next_++; | 89 | 0 | } | 90 | 0 | } | 91 | 30.5k | } |
|
92 | | |
93 | | /** |
94 | | * Turns instance to optimistic mode. |
95 | | * |
96 | | * The only difference with regular operating mode is that CanRead always |
97 | | * returns "true". Use this mode only when instance is supplied with complete |
98 | | * input. |
99 | | */ |
100 | | void BrunsliBitReaderSetOptimistic(BrunsliBitReader* br); |
101 | | |
102 | | /** |
103 | | * Returns true if there is enough input. |
104 | | * |
105 | | * Guaranteed to work correctly only in normalized state. |
106 | | */ |
107 | | bool BrunsliBitReaderCanRead(BrunsliBitReader* br, size_t n_bits); |
108 | | |
109 | | static BRUNSLI_INLINE uint32_t BrunsliBitReaderGet(BrunsliBitReader* br, |
110 | 29.6M | uint32_t n_bits) { |
111 | 29.6M | BRUNSLI_DCHECK(n_bits <= 24); |
112 | 29.6M | BrunsliBitReaderMaybeFetchByte(br, n_bits); |
113 | 29.6M | if (n_bits > 8) { |
114 | 11.9k | BrunsliBitReaderMaybeFetchByte(br, n_bits); |
115 | 11.9k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); |
116 | 11.9k | } |
117 | 29.6M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); |
118 | 29.6M | } brunsli_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 110 | 27.4M | uint32_t n_bits) { | 111 | 27.4M | BRUNSLI_DCHECK(n_bits <= 24); | 112 | 27.4M | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 113 | 27.4M | if (n_bits > 8) { | 114 | 5.96k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 5.96k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 116 | 5.96k | } | 117 | 27.4M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 118 | 27.4M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 110 | 38.0k | uint32_t n_bits) { | 111 | 38.0k | BRUNSLI_DCHECK(n_bits <= 24); | 112 | 38.0k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 113 | 38.0k | if (n_bits > 8) { | 114 | 343 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 343 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 116 | 343 | } | 117 | 38.0k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 118 | 38.0k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 110 | 251k | uint32_t n_bits) { | 111 | 251k | BRUNSLI_DCHECK(n_bits <= 24); | 112 | 251k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 113 | 251k | if (n_bits > 8) { | 114 | 5.40k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 5.40k | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 116 | 5.40k | } | 117 | 251k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 118 | 251k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 110 | 1.94M | uint32_t n_bits) { | 111 | 1.94M | BRUNSLI_DCHECK(n_bits <= 24); | 112 | 1.94M | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 113 | 1.94M | if (n_bits > 8) { | 114 | 284 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 284 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 116 | 284 | } | 117 | 1.94M | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 118 | 1.94M | } |
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 | 110 | 30.5k | uint32_t n_bits) { | 111 | 30.5k | BRUNSLI_DCHECK(n_bits <= 24); | 112 | 30.5k | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 113 | 30.5k | if (n_bits > 8) { | 114 | 0 | BrunsliBitReaderMaybeFetchByte(br, n_bits); | 115 | 0 | if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits); | 116 | 0 | } | 117 | 30.5k | return br->bits_ & BrunsliBitReaderBitMask(n_bits); | 118 | 30.5k | } |
|
119 | | |
120 | | static BRUNSLI_INLINE void BrunsliBitReaderDrop(BrunsliBitReader* br, |
121 | 29.6M | uint32_t n_bits) { |
122 | 29.6M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); |
123 | 29.6M | br->bits_ >>= n_bits; |
124 | 29.6M | br->num_bits_ -= n_bits; |
125 | 29.6M | } brunsli_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 121 | 27.4M | uint32_t n_bits) { | 122 | 27.4M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 123 | 27.4M | br->bits_ >>= n_bits; | 124 | 27.4M | br->num_bits_ -= n_bits; | 125 | 27.4M | } |
context_map_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 121 | 38.0k | uint32_t n_bits) { | 122 | 38.0k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 123 | 38.0k | br->bits_ >>= n_bits; | 124 | 38.0k | br->num_bits_ -= n_bits; | 125 | 38.0k | } |
histogram_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 121 | 251k | uint32_t n_bits) { | 122 | 251k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 123 | 251k | br->bits_ >>= n_bits; | 124 | 251k | br->num_bits_ -= n_bits; | 125 | 251k | } |
huffman_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int) Line | Count | Source | 121 | 1.94M | uint32_t n_bits) { | 122 | 1.94M | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 123 | 1.94M | br->bits_ >>= n_bits; | 124 | 1.94M | br->num_bits_ -= n_bits; | 125 | 1.94M | } |
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 | 121 | 30.5k | uint32_t n_bits) { | 122 | 30.5k | BRUNSLI_DCHECK(n_bits <= br->num_bits_); | 123 | 30.5k | br->bits_ >>= n_bits; | 124 | 30.5k | br->num_bits_ -= n_bits; | 125 | 30.5k | } |
|
126 | | |
127 | | BRUNSLI_INLINE uint32_t BrunsliBitReaderRead(BrunsliBitReader* br, |
128 | 27.7M | uint32_t n_bits) { |
129 | 27.7M | uint32_t result = BrunsliBitReaderGet(br, n_bits); |
130 | 27.7M | BrunsliBitReaderDrop(br, n_bits); |
131 | 27.7M | return result; |
132 | 27.7M | } |
133 | | |
134 | | } // namespace brunsli |
135 | | |
136 | | #endif // BRUNSLI_DEC_BIT_READER_H_ |