MythTV master
bitreader.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Unlicense
2// Created by Scott Theisen, 2022-2024
3/* The Unlicense
4This is free and unencumbered software released into the public domain.
5
6Anyone is free to copy, modify, publish, use, compile, sell, or
7distribute this software, either in source code form or as a compiled
8binary, for any purpose, commercial or non-commercial, and by any
9means.
10
11In jurisdictions that recognize copyright laws, the author or authors
12of this software dedicate any and all copyright interest in the
13software to the public domain. We make this dedication for the benefit
14of the public at large and to the detriment of our heirs and
15successors. We intend this dedication to be an overt act of
16relinquishment in perpetuity of all present and future rights to this
17software under copyright law.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25OTHER DEALINGS IN THE SOFTWARE.
26
27For more information, please refer to <https://unlicense.org>
28*/
29
36#ifndef BIT_READER_H
37#define BIT_READER_H
38
39#include <algorithm>
40#include <array>
41#include <cstdint>
42
43#if __has_include(<bit>) // C++20
44#include <bit>
45#endif
46
48{
49 public:
50 BitReader(const uint8_t* buffer, uint64_t size) :
51 m_buffer(buffer),
52 m_bufferEnd(buffer + size)
53 {
54 }
55 ~BitReader() = default;
56
57 void skip_bits(unsigned n)
58 {
59 if (m_cacheSize > n)
60 {
61 m_cache <<= n;
62 m_cacheSize -= n;
63 }
64 else
65 {
66 n -= m_cacheSize;
67 m_cacheSize = 0;
68 m_cache = 0;
69 m_bitIndex += n;
70 unsigned quotient = m_bitIndex / kBitsPerRead;
72 m_buffer += quotient;
73 }
74 }
75 uint32_t show_bits(unsigned n)
76 {
77 //assert(n <= 32);
78 if (m_cacheSize < n)
79 {
80 refill_cache(32);
81 }
82 return static_cast<uint32_t>(get_upper_bits(m_cache, n));
83 }
84 uint64_t show_bits64(unsigned n)
85 {
86 //assert(n <= 64);
87 if (m_cacheSize < n)
88 {
89 refill_cache(64);
90 }
91 return get_upper_bits(m_cache, n);
92 }
93 bool next_bit() { return get_bits(1) == 1; }
95 uint32_t get_bits(unsigned n)
96 {
97 uint32_t ret = show_bits(n);
98 skip_bits(n);
99 return ret;
100 }
102 uint64_t get_bits64(unsigned n)
103 {
104 uint64_t ret = show_bits64(n);
105 skip_bits(n);
106 return ret;
107 }
108
115 {
116 return get_ue_golomb(13);
117 }
118
125 {
126 uint32_t buf = show_bits(32);
127 unsigned lz = clz(buf);
128 unsigned length = lz + 1;
129 skip_bits(lz);
130
131 if (length > 32)
132 {
133 skip_bits(length);
134 return UINT32_MAX;
135 }
136
137 return get_bits(length) - 1;
138 }
139
146 {
147 return get_ue_golomb(5);
148 }
149
154 {
155 uint32_t buf = get_ue_golomb_long() + 1;
156 // revert the -1 offset to get the raw value
157
158 if (buf & 1)
159 {
160 return -(buf >> 1);
161 }
162 return buf >> 1;
163 }
164
166 {
167 return m_cacheSize + (kBitsPerRead * static_cast<int64_t>(m_bufferEnd - m_buffer)) - m_bitIndex;
168 }
169
170 private:
171 int get_ue_golomb(unsigned max_length);
172 static unsigned clz(uint32_t v)
173 {
174#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L // C++20 <bit>
175 return std::countl_zero(v);
176#else
177 // based on public domain log2_floor
178 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
179 if (v == 0)
180 {
181 return 32;
182 }
183 static constexpr std::array<int,32> MultiplyDeBruijnBitPosition =
184 {
185 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
186 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
187 };
188
189 v |= v >> 1; // first round down to one less than a power of 2
190 v |= v >> 2;
191 v |= v >> 4;
192 v |= v >> 8;
193 v |= v >> 16;
194
195 return 31 - MultiplyDeBruijnBitPosition[static_cast<uint32_t>(v * 0x07C4ACDDU) >> 27];
196#endif
197 }
198
199 static constexpr uint64_t get_upper_bits(uint64_t val, unsigned bits)
200 {
201 // protect against undefined behavior
202 if (bits == 0)
203 {
204 return UINT64_C(0);
205 }
206 if (bits > 64)
207 {
208 return val;
209 }
210 return val >> (64 - bits);
211 }
212
213 void refill_cache(unsigned min_bits);
214
215 const uint8_t *m_buffer;
216 const uint8_t * const m_bufferEnd;
217 unsigned m_bitIndex {0};
218
225 uint64_t m_cache {0};
226 unsigned m_cacheSize {0};
227
228 static constexpr unsigned kCacheSizeMax {64};
229 static constexpr unsigned kBitsPerRead { 8};
230};
231
235inline int BitReader::get_ue_golomb(unsigned max_length)
236{
237 uint32_t buf = show_bits(32);
238 unsigned lz = clz(buf);
239 unsigned length = lz + 1;
240 unsigned size = lz + length; // total length
241
242 skip_bits(size);
243
244 if (length > max_length || length > 16)
245 {
246 return -1;
247 }
248
249 buf >>= 32 - size; // remove irrelevant trailing bits
250
251 return buf - 1; // offset for storing 0
252}
253
254inline void BitReader::refill_cache(unsigned min_bits)
255{
256 min_bits = std::min(min_bits, kCacheSizeMax);
257
258 //if (m_bitIndex >= kBitsPerRead)
259 {
260 unsigned quotient = m_bitIndex / kBitsPerRead;
262 m_buffer += quotient;
263 }
264
265 while (m_cacheSize < min_bits && m_buffer < m_bufferEnd)
266 {
267 unsigned shift = kCacheSizeMax - m_cacheSize;
268 unsigned bits = kBitsPerRead - m_bitIndex;
269 if (shift >= bits)
270 {
271 m_cache |= static_cast<uint64_t>(*m_buffer) << (shift - bits);
272 m_bitIndex = 0;
273 m_buffer++;
274 m_cacheSize += bits;
275 }
276 else
277 {
278 m_cache |= static_cast<uint64_t>(*m_buffer) >> (bits - shift);
279 m_bitIndex += shift;
280 m_cacheSize += shift;
281 return; // m_cacheSize == kCacheSizeMax
282 }
283
284 }
285}
286
287#endif // BIT_READER_H
unsigned m_cacheSize
Definition: bitreader.h:226
unsigned m_bitIndex
index for next bit read from the MSB
Definition: bitreader.h:217
int get_ue_golomb_31()
read unsigned exp golomb code, constraint to a max of 31.
Definition: bitreader.h:145
bool next_bit()
Definition: bitreader.h:93
uint32_t show_bits(unsigned n)
Definition: bitreader.h:75
int get_ue_golomb()
Read an unsigned Exp-Golomb code in the range 0 to 8190 (2^13 - 2).
Definition: bitreader.h:114
BitReader(const uint8_t *buffer, uint64_t size)
Definition: bitreader.h:50
static constexpr unsigned kCacheSizeMax
Definition: bitreader.h:228
static constexpr uint64_t get_upper_bits(uint64_t val, unsigned bits)
Definition: bitreader.h:199
int64_t get_bits_left()
Definition: bitreader.h:165
static constexpr unsigned kBitsPerRead
Definition: bitreader.h:229
static unsigned clz(uint32_t v)
Definition: bitreader.h:172
~BitReader()=default
uint64_t get_bits64(unsigned n)
Read 0-64 bits.
Definition: bitreader.h:102
void refill_cache(unsigned min_bits)
Definition: bitreader.h:254
const uint8_t *const m_bufferEnd
past the end pointer
Definition: bitreader.h:216
const uint8_t * m_buffer
next memory location to read from
Definition: bitreader.h:215
void skip_bits(unsigned n)
Definition: bitreader.h:57
uint32_t get_ue_golomb_long()
Read an unsigned Exp-Golomb code in the range 0 to UINT32_MAX-1.
Definition: bitreader.h:124
int get_se_golomb()
read signed exp golomb code.
Definition: bitreader.h:153
uint64_t m_cache
cache for reads.
Definition: bitreader.h:225
uint64_t show_bits64(unsigned n)
Definition: bitreader.h:84
uint32_t get_bits(unsigned n)
Read 0-32 bits.
Definition: bitreader.h:95