Zserio C++ runtime library  1.0.1
Built for Zserio 2.14.0
BitStreamReader.cpp
Go to the documentation of this file.
1 #include <array>
2 #include <limits>
3 
6 #include "zserio/FloatUtil.h"
7 #include "zserio/RuntimeArch.h"
8 
9 namespace zserio
10 {
11 
12 namespace
13 {
14 
15 // max size calculated to prevent overflows in internal comparisons
16 const size_t MAX_BUFFER_SIZE = std::numeric_limits<size_t>::max() / 8 - 4;
17 
18 using BitPosType = BitStreamReader::BitPosType;
19 using ReaderContext = BitStreamReader::ReaderContext;
20 
21 #ifdef ZSERIO_RUNTIME_64BIT
22 using BaseType = uint64_t;
23 using BaseSignedType = int64_t;
24 #else
25 using BaseType = uint32_t;
26 using BaseSignedType = int32_t;
27 #endif
28 
29 #ifdef ZSERIO_RUNTIME_64BIT
30 const std::array<BaseType, 65> MASK_TABLE = {
31  UINT64_C(0x00),
32  UINT64_C(0x0001),
33  UINT64_C(0x0003),
34  UINT64_C(0x0007),
35  UINT64_C(0x000f),
36  UINT64_C(0x001f),
37  UINT64_C(0x003f),
38  UINT64_C(0x007f),
39  UINT64_C(0x00ff),
40  UINT64_C(0x01ff),
41  UINT64_C(0x03ff),
42  UINT64_C(0x07ff),
43  UINT64_C(0x0fff),
44  UINT64_C(0x1fff),
45  UINT64_C(0x3fff),
46  UINT64_C(0x7fff),
47  UINT64_C(0xffff),
48  UINT64_C(0x0001ffff),
49  UINT64_C(0x0003ffff),
50  UINT64_C(0x0007ffff),
51  UINT64_C(0x000fffff),
52  UINT64_C(0x001fffff),
53  UINT64_C(0x003fffff),
54  UINT64_C(0x007fffff),
55  UINT64_C(0x00ffffff),
56  UINT64_C(0x01ffffff),
57  UINT64_C(0x03ffffff),
58  UINT64_C(0x07ffffff),
59  UINT64_C(0x0fffffff),
60  UINT64_C(0x1fffffff),
61  UINT64_C(0x3fffffff),
62  UINT64_C(0x7fffffff),
63  UINT64_C(0xffffffff),
64 
65  UINT64_C(0x00000001ffffffff),
66  UINT64_C(0x00000003ffffffff),
67  UINT64_C(0x00000007ffffffff),
68  UINT64_C(0x0000000fffffffff),
69  UINT64_C(0x0000001fffffffff),
70  UINT64_C(0x0000003fffffffff),
71  UINT64_C(0x0000007fffffffff),
72  UINT64_C(0x000000ffffffffff),
73  UINT64_C(0x000001ffffffffff),
74  UINT64_C(0x000003ffffffffff),
75  UINT64_C(0x000007ffffffffff),
76  UINT64_C(0x00000fffffffffff),
77  UINT64_C(0x00001fffffffffff),
78  UINT64_C(0x00003fffffffffff),
79  UINT64_C(0x00007fffffffffff),
80  UINT64_C(0x0000ffffffffffff),
81  UINT64_C(0x0001ffffffffffff),
82  UINT64_C(0x0003ffffffffffff),
83  UINT64_C(0x0007ffffffffffff),
84  UINT64_C(0x000fffffffffffff),
85  UINT64_C(0x001fffffffffffff),
86  UINT64_C(0x003fffffffffffff),
87  UINT64_C(0x007fffffffffffff),
88  UINT64_C(0x00ffffffffffffff),
89  UINT64_C(0x01ffffffffffffff),
90  UINT64_C(0x03ffffffffffffff),
91  UINT64_C(0x07ffffffffffffff),
92  UINT64_C(0x0fffffffffffffff),
93  UINT64_C(0x1fffffffffffffff),
94  UINT64_C(0x3fffffffffffffff),
95  UINT64_C(0x7fffffffffffffff),
96  UINT64_C(0xffffffffffffffff),
97 };
98 #else
99 const std::array<BaseType, 33> MASK_TABLE = {
100  UINT32_C(0x00),
101  UINT32_C(0x0001),
102  UINT32_C(0x0003),
103  UINT32_C(0x0007),
104  UINT32_C(0x000f),
105  UINT32_C(0x001f),
106  UINT32_C(0x003f),
107  UINT32_C(0x007f),
108  UINT32_C(0x00ff),
109  UINT32_C(0x01ff),
110  UINT32_C(0x03ff),
111  UINT32_C(0x07ff),
112  UINT32_C(0x0fff),
113  UINT32_C(0x1fff),
114  UINT32_C(0x3fff),
115  UINT32_C(0x7fff),
116  UINT32_C(0xffff),
117  UINT32_C(0x0001ffff),
118  UINT32_C(0x0003ffff),
119  UINT32_C(0x0007ffff),
120  UINT32_C(0x000fffff),
121  UINT32_C(0x001fffff),
122  UINT32_C(0x003fffff),
123  UINT32_C(0x007fffff),
124  UINT32_C(0x00ffffff),
125  UINT32_C(0x01ffffff),
126  UINT32_C(0x03ffffff),
127  UINT32_C(0x07ffffff),
128  UINT32_C(0x0fffffff),
129  UINT32_C(0x1fffffff),
130  UINT32_C(0x3fffffff),
131  UINT32_C(0x7fffffff),
132  UINT32_C(0xffffffff),
133 };
134 #endif
135 
136 const uint8_t VARINT_SIGN_1 = UINT8_C(0x80);
137 const uint8_t VARINT_BYTE_1 = UINT8_C(0x3f);
138 const uint8_t VARINT_BYTE_N = UINT8_C(0x7f);
139 const uint8_t VARINT_HAS_NEXT_1 = UINT8_C(0x40);
140 const uint8_t VARINT_HAS_NEXT_N = UINT8_C(0x80);
141 
142 const uint8_t VARUINT_BYTE = UINT8_C(0x7f);
143 const uint8_t VARUINT_HAS_NEXT = UINT8_C(0x80);
144 
145 const uint32_t VARSIZE_MAX_VALUE = (UINT32_C(1) << 31U) - 1;
146 
147 #ifdef ZSERIO_RUNTIME_64BIT
148 inline BaseType parse64(Span<const uint8_t>::const_iterator bufferIt)
149 {
150  return static_cast<BaseType>(*bufferIt) << 56U | static_cast<BaseType>(*(bufferIt + 1)) << 48U |
151  static_cast<BaseType>(*(bufferIt + 2)) << 40U | static_cast<BaseType>(*(bufferIt + 3)) << 32U |
152  static_cast<BaseType>(*(bufferIt + 4)) << 24U | static_cast<BaseType>(*(bufferIt + 5)) << 16U |
153  static_cast<BaseType>(*(bufferIt + 6)) << 8U | static_cast<BaseType>(*(bufferIt + 7));
154 }
155 
156 inline BaseType parse56(Span<const uint8_t>::const_iterator bufferIt)
157 {
158  return static_cast<BaseType>(*bufferIt) << 48U | static_cast<BaseType>(*(bufferIt + 1)) << 40U |
159  static_cast<BaseType>(*(bufferIt + 2)) << 32U | static_cast<BaseType>(*(bufferIt + 3)) << 24U |
160  static_cast<BaseType>(*(bufferIt + 4)) << 16U | static_cast<BaseType>(*(bufferIt + 5)) << 8U |
161  static_cast<BaseType>(*(bufferIt + 6));
162 }
163 
164 inline BaseType parse48(Span<const uint8_t>::const_iterator bufferIt)
165 {
166  return static_cast<BaseType>(*bufferIt) << 40U | static_cast<BaseType>(*(bufferIt + 1)) << 32U |
167  static_cast<BaseType>(*(bufferIt + 2)) << 24U | static_cast<BaseType>(*(bufferIt + 3)) << 16U |
168  static_cast<BaseType>(*(bufferIt + 4)) << 8U | static_cast<BaseType>(*(bufferIt + 5));
169 }
170 
171 inline BaseType parse40(Span<const uint8_t>::const_iterator bufferIt)
172 {
173  return static_cast<BaseType>(*bufferIt) << 32U | static_cast<BaseType>(*(bufferIt + 1)) << 24U |
174  static_cast<BaseType>(*(bufferIt + 2)) << 16U | static_cast<BaseType>(*(bufferIt + 3)) << 8U |
175  static_cast<BaseType>(*(bufferIt + 4));
176 }
177 #endif
178 inline BaseType parse32(Span<const uint8_t>::const_iterator bufferIt)
179 {
180  return static_cast<BaseType>(*bufferIt) << 24U | static_cast<BaseType>(*(bufferIt + 1)) << 16U |
181  static_cast<BaseType>(*(bufferIt + 2)) << 8U | static_cast<BaseType>(*(bufferIt + 3));
182 }
183 
184 inline BaseType parse24(Span<const uint8_t>::const_iterator bufferIt)
185 {
186  return static_cast<BaseType>(*bufferIt) << 16U | static_cast<BaseType>(*(bufferIt + 1)) << 8U |
187  static_cast<BaseType>(*(bufferIt + 2));
188 }
189 
190 inline BaseType parse16(Span<const uint8_t>::const_iterator bufferIt)
191 {
192  return static_cast<BaseType>(*bufferIt) << 8U | static_cast<BaseType>(*(bufferIt + 1));
193 }
194 
195 inline BaseType parse8(Span<const uint8_t>::const_iterator bufferIt)
196 {
197  return static_cast<BaseType>(*bufferIt);
198 }
199 
201 inline void throwNumBitsIsNotValid(uint8_t numBits)
202 {
203  throw CppRuntimeException("BitStreamReader: ReadBits #")
204  << numBits << " is not valid, reading from stream failed!";
205 }
206 
208 inline void checkNumBits(uint8_t numBits)
209 {
210  if (numBits > 32)
211  throwNumBitsIsNotValid(numBits);
212 }
213 
215 inline void checkNumBits64(uint8_t numBits)
216 {
217  if (numBits > 64)
218  throwNumBitsIsNotValid(numBits);
219 }
220 
222 inline void throwEof()
223 {
224  throw CppRuntimeException("BitStreamReader: Reached eof(), reading from stream failed!");
225 }
226 
228 inline void loadCacheNext(ReaderContext& ctx, uint8_t numBits)
229 {
230  static const uint8_t cacheBitSize = sizeof(BaseType) * 8;
231 
232  // ctx.bitIndex is always byte aligned and ctx.cacheNumBits is always zero in this call
233  const size_t byteIndex = ctx.bitIndex >> 3U;
234  if (ctx.bufferBitSize >= ctx.bitIndex + cacheBitSize)
235  {
236  ctx.cache =
237 #ifdef ZSERIO_RUNTIME_64BIT
238  parse64(ctx.buffer.begin() + byteIndex);
239 #else
240  parse32(ctx.buffer.begin() + byteIndex);
241 #endif
242  ctx.cacheNumBits = cacheBitSize;
243  }
244  else
245  {
246  if (ctx.bitIndex + numBits > ctx.bufferBitSize)
247  throwEof();
248 
249  ctx.cacheNumBits = static_cast<uint8_t>(ctx.bufferBitSize - ctx.bitIndex);
250 
251  // buffer must be always available in full bytes, even if some last bits are not used
252  const uint8_t alignedNumBits = static_cast<uint8_t>((ctx.cacheNumBits + 7U) & ~0x7U);
253 
254  switch (alignedNumBits)
255  {
256 #ifdef ZSERIO_RUNTIME_64BIT
257  case 64:
258  ctx.cache = parse64(ctx.buffer.begin() + byteIndex);
259  break;
260  case 56:
261  ctx.cache = parse56(ctx.buffer.begin() + byteIndex);
262  break;
263  case 48:
264  ctx.cache = parse48(ctx.buffer.begin() + byteIndex);
265  break;
266  case 40:
267  ctx.cache = parse40(ctx.buffer.begin() + byteIndex);
268  break;
269 #endif
270  case 32:
271  ctx.cache = parse32(ctx.buffer.begin() + byteIndex);
272  break;
273  case 24:
274  ctx.cache = parse24(ctx.buffer.begin() + byteIndex);
275  break;
276  case 16:
277  ctx.cache = parse16(ctx.buffer.begin() + byteIndex);
278  break;
279  default: // 8
280  ctx.cache = parse8(ctx.buffer.begin() + byteIndex);
281  break;
282  }
283 
284  ctx.cache >>= static_cast<uint8_t>(alignedNumBits - ctx.cacheNumBits);
285  }
286 }
287 
289 inline BaseType readBitsImpl(ReaderContext& ctx, uint8_t numBits)
290 {
291  BaseType value = 0;
292  if (ctx.cacheNumBits < numBits)
293  {
294  // read all remaining cache bits
295  value = ctx.cache & MASK_TABLE[ctx.cacheNumBits];
296  ctx.bitIndex += ctx.cacheNumBits;
297  numBits = static_cast<uint8_t>(numBits - ctx.cacheNumBits);
298 
299  // load next piece of buffer into cache
300  loadCacheNext(ctx, numBits);
301 
302  // add the remaining bits to the result
303  // if numBits is sizeof(BaseType) * 8 here, value is already 0 (see MASK_TABLE[0])
304  if (numBits < sizeof(BaseType) * 8)
305  value <<= numBits;
306  }
307  value |= ((ctx.cache >> static_cast<uint8_t>(ctx.cacheNumBits - numBits)) & MASK_TABLE[numBits]);
308  ctx.cacheNumBits = static_cast<uint8_t>(ctx.cacheNumBits - numBits);
309  ctx.bitIndex += numBits;
310 
311  return value;
312 }
313 
315 inline BaseSignedType readSignedBitsImpl(ReaderContext& ctx, uint8_t numBits)
316 {
317  static const uint8_t typeSize = sizeof(BaseSignedType) * 8;
318  BaseType value = readBitsImpl(ctx, numBits);
319 
320  // Skip the signed overflow correction if numBits == typeSize.
321  // In that case, the value that comes out the readBits function
322  // is already correct.
323  if (numBits != 0 && numBits < typeSize &&
324  (value >= (static_cast<BaseType>(1) << static_cast<uint8_t>(numBits - 1))))
325  {
326  value -= static_cast<BaseType>(1) << numBits;
327  }
328 
329  return static_cast<BaseSignedType>(value);
330 }
331 
332 #ifndef ZSERIO_RUNTIME_64BIT
334 inline uint64_t readBits64Impl(ReaderContext& ctx, uint8_t numBits)
335 {
336  // read the first 32 bits
337  numBits = static_cast<uint8_t>(numBits - 32);
338  uint64_t value = readBitsImpl(ctx, 32);
339 
340  // add the remaining bits
341  value <<= numBits;
342  value |= readBitsImpl(ctx, numBits);
343 
344  return value;
345 }
346 #endif
347 
348 } // namespace
349 
351  buffer(readBuffer),
352  bufferBitSize(readBufferBitSize),
353  cache(0),
354  cacheNumBits(0),
355  bitIndex(0)
356 {
357  if (buffer.size() > MAX_BUFFER_SIZE)
358  {
359  throw CppRuntimeException("BitStreamReader: Buffer size exceeded limit '")
360  << MAX_BUFFER_SIZE << "' bytes!";
361  }
362 }
363 
364 BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferByteSize) :
365  BitStreamReader(Span<const uint8_t>(buffer, bufferByteSize))
366 {}
367 
369  m_context(buffer, buffer.size() * 8)
370 {}
371 
373  m_context(buffer, bufferBitSize)
374 {
375  if (buffer.size() < (bufferBitSize + 7) / 8)
376  {
377  throw CppRuntimeException("BitStreamReader: Wrong buffer bit size ('")
378  << buffer.size() << "' < '" << (bufferBitSize + 7) / 8 << "')!";
379  }
380 }
381 
382 BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferBitSize, BitsTag) :
383  m_context(Span<const uint8_t>(buffer, (bufferBitSize + 7) / 8), bufferBitSize)
384 {}
385 
387 {
388  checkNumBits(numBits);
389 
390  return static_cast<uint32_t>(readBitsImpl(m_context, numBits));
391 }
392 
394 {
395  checkNumBits64(numBits);
396 
397 #ifdef ZSERIO_RUNTIME_64BIT
398  return readBitsImpl(m_context, numBits);
399 #else
400  if (numBits <= 32)
401  return readBitsImpl(m_context, numBits);
402 
403  return readBits64Impl(m_context, numBits);
404 #endif
405 }
406 
408 {
409  checkNumBits64(numBits);
410 
411 #ifdef ZSERIO_RUNTIME_64BIT
412  return readSignedBitsImpl(m_context, numBits);
413 #else
414  if (numBits <= 32)
415  return readSignedBitsImpl(m_context, numBits);
416 
417  int64_t value = static_cast<int64_t>(readBits64Impl(m_context, numBits));
418 
419  // Skip the signed overflow correction if numBits == 64.
420  // In that case, the value that comes out the readBits function
421  // is already correct.
422  const bool needsSignExtension =
423  numBits < 64 && (static_cast<uint64_t>(value) >= (UINT64_C(1) << (numBits - 1)));
424  if (needsSignExtension)
425  value -= UINT64_C(1) << numBits;
426 
427  return value;
428 #endif
429 }
430 
432 {
433  checkNumBits(numBits);
434 
435  return static_cast<int32_t>(readSignedBitsImpl(m_context, numBits));
436 }
437 
439 {
440  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
441  const bool sign = (byte & VARINT_SIGN_1) != 0;
442  uint64_t result = byte & VARINT_BYTE_1;
443  if ((byte & VARINT_HAS_NEXT_1) == 0)
444  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
445 
446  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
447  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
448  if ((byte & VARINT_HAS_NEXT_N) == 0)
449  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
450 
451  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
452  result = static_cast<uint64_t>(result) << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
453  if ((byte & VARINT_HAS_NEXT_N) == 0)
454  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
455 
456  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
457  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
458  if ((byte & VARINT_HAS_NEXT_N) == 0)
459  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
460 
461  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
462  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
463  if ((byte & VARINT_HAS_NEXT_N) == 0)
464  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
465 
466  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
467  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
468  if ((byte & VARINT_HAS_NEXT_N) == 0)
469  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
470 
471  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
472  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
473  if ((byte & VARINT_HAS_NEXT_N) == 0)
474  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
475 
476  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
477  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
478 }
479 
481 {
482  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
483  const bool sign = (byte & VARINT_SIGN_1) != 0;
484  uint32_t result = byte & VARINT_BYTE_1;
485  if ((byte & VARINT_HAS_NEXT_1) == 0)
486  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
487 
488  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
489  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
490  if ((byte & VARINT_HAS_NEXT_N) == 0)
491  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
492 
493  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
494  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
495  if ((byte & VARINT_HAS_NEXT_N) == 0)
496  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
497 
498  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
499  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
500 }
501 
503 {
504  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
505  const bool sign = (byte & VARINT_SIGN_1) != 0;
506  uint16_t result = byte & VARINT_BYTE_1;
507  if ((byte & VARINT_HAS_NEXT_1) == 0)
508  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
509 
510  result = static_cast<uint16_t>(result << 8U);
511  result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
512  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
513 }
514 
516 {
517  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
518  uint64_t result = byte & VARUINT_BYTE;
519  if ((byte & VARUINT_HAS_NEXT) == 0)
520  return result;
521 
522  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
523  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
524  if ((byte & VARUINT_HAS_NEXT) == 0)
525  return result;
526 
527  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
528  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
529  if ((byte & VARUINT_HAS_NEXT) == 0)
530  return result;
531 
532  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
533  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
534  if ((byte & VARUINT_HAS_NEXT) == 0)
535  return result;
536 
537  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
538  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
539  if ((byte & VARUINT_HAS_NEXT) == 0)
540  return result;
541 
542  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
543  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
544  if ((byte & VARUINT_HAS_NEXT) == 0)
545  return result;
546 
547  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
548  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
549  if ((byte & VARUINT_HAS_NEXT) == 0)
550  return result;
551 
552  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
553  return result;
554 }
555 
557 {
558  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
559  uint32_t result = byte & VARUINT_BYTE;
560  if ((byte & VARUINT_HAS_NEXT) == 0)
561  return result;
562 
563  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
564  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
565  if ((byte & VARUINT_HAS_NEXT) == 0)
566  return result;
567 
568  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
569  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
570  if ((byte & VARUINT_HAS_NEXT) == 0)
571  return result;
572 
573  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
574  return result;
575 }
576 
578 {
579  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
580  uint16_t result = byte & VARUINT_BYTE;
581  if ((byte & VARUINT_HAS_NEXT) == 0)
582  return result;
583 
584  result = static_cast<uint16_t>(result << 8U);
585  result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
586  return result;
587 }
588 
590 {
591  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
592  const bool sign = (byte & VARINT_SIGN_1) != 0;
593  uint64_t result = byte & VARINT_BYTE_1;
594  if ((byte & VARINT_HAS_NEXT_1) == 0)
595  return sign ? (result == 0 ? INT64_MIN : -static_cast<int64_t>(result)) : static_cast<int64_t>(result);
596 
597  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
598  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
599  if ((byte & VARINT_HAS_NEXT_N) == 0)
600  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
601 
602  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
603  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
604  if ((byte & VARINT_HAS_NEXT_N) == 0)
605  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
606 
607  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
608  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
609  if ((byte & VARINT_HAS_NEXT_N) == 0)
610  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
611 
612  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
613  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
614  if ((byte & VARINT_HAS_NEXT_N) == 0)
615  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
616 
617  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
618  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
619  if ((byte & VARINT_HAS_NEXT_N) == 0)
620  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
621 
622  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
623  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
624  if ((byte & VARINT_HAS_NEXT_N) == 0)
625  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
626 
627  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
628  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
629  if ((byte & VARINT_HAS_NEXT_N) == 0)
630  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
631 
632  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
633  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
634 }
635 
637 {
638  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
639  uint64_t result = byte & VARUINT_BYTE;
640  if ((byte & VARUINT_HAS_NEXT) == 0)
641  return result;
642 
643  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
644  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
645  if ((byte & VARUINT_HAS_NEXT) == 0)
646  return result;
647 
648  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
649  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
650  if ((byte & VARUINT_HAS_NEXT) == 0)
651  return result;
652 
653  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
654  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
655  if ((byte & VARUINT_HAS_NEXT) == 0)
656  return result;
657 
658  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
659  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
660  if ((byte & VARUINT_HAS_NEXT) == 0)
661  return result;
662 
663  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
664  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
665  if ((byte & VARUINT_HAS_NEXT) == 0)
666  return result;
667 
668  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
669  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
670  if ((byte & VARUINT_HAS_NEXT) == 0)
671  return result;
672 
673  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
674  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
675  if ((byte & VARUINT_HAS_NEXT) == 0)
676  return result;
677 
678  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
679  return result;
680 }
681 
683 {
684  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
685  uint32_t result = byte & VARUINT_BYTE;
686  if ((byte & VARUINT_HAS_NEXT) == 0)
687  return result;
688 
689  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
690  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
691  if ((byte & VARUINT_HAS_NEXT) == 0)
692  return result;
693 
694  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
695  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
696  if ((byte & VARUINT_HAS_NEXT) == 0)
697  return result;
698 
699  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
700  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
701  if ((byte & VARUINT_HAS_NEXT) == 0)
702  return result;
703 
704  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
705  if (result > VARSIZE_MAX_VALUE)
706  throw CppRuntimeException("BitStreamReader: Read value '")
707  << result << "' is out of range for varsize type!";
708 
709  return result;
710 }
711 
713 {
714  const uint16_t halfPrecisionFloatValue = static_cast<uint16_t>(readBitsImpl(m_context, 16));
715 
716  return convertUInt16ToFloat(halfPrecisionFloatValue);
717 }
718 
720 {
721  const uint32_t singlePrecisionFloatValue = static_cast<uint32_t>(readBitsImpl(m_context, 32));
722 
723  return convertUInt32ToFloat(singlePrecisionFloatValue);
724 }
725 
727 {
728 #ifdef ZSERIO_RUNTIME_64BIT
729  const uint64_t doublePrecisionFloatValue = static_cast<uint64_t>(readBitsImpl(m_context, 64));
730 #else
731  const uint64_t doublePrecisionFloatValue = readBits64Impl(m_context, 64);
732 #endif
733 
734  return convertUInt64ToDouble(doublePrecisionFloatValue);
735 }
736 
738 {
739  return readBitsImpl(m_context, 1) != 0;
740 }
741 
743 {
744  if (position > m_context.bufferBitSize)
745  throw CppRuntimeException("BitStreamReader: Reached eof(), setting of bit position failed!");
746 
747  m_context.bitIndex = (position / 8) * 8; // set to byte aligned position
748  m_context.cacheNumBits = 0; // invalidate cache
749  const uint8_t skip = static_cast<uint8_t>(position - m_context.bitIndex);
750  if (skip != 0)
751  readBits(skip);
752 }
753 
754 void BitStreamReader::alignTo(size_t alignment)
755 {
756  const BitPosType offset = getBitPosition() % alignment;
757  if (offset != 0)
758  {
759  const uint8_t skip = static_cast<uint8_t>(alignment - offset);
760  readBits64(skip);
761  }
762 }
763 
764 uint8_t BitStreamReader::readByte()
765 {
766  return static_cast<uint8_t>(readBitsImpl(m_context, 8));
767 }
768 
769 } // namespace zserio
void setBitPosition(BitPosType position)
void alignTo(size_t alignment)
uint64_t readBits64(uint8_t numBits=64)
BitStreamReader(const uint8_t *buffer, size_t bufferByteSize)
uint32_t readBits(uint8_t numBits=32)
int32_t readSignedBits(uint8_t numBits=32)
int64_t readSignedBits64(uint8_t numBits=64)
BitPosType getBitPosition() const
constexpr size_type size() const noexcept
Definition: Span.h:281
const_pointer const_iterator
Definition: Span.h:69
uint8_t numBits(uint64_t numValues)
float convertUInt32ToFloat(uint32_t float32Value)
Definition: FloatUtil.cpp:165
double convertUInt64ToDouble(uint64_t float64Value)
Definition: FloatUtil.cpp:179
float convertUInt16ToFloat(uint16_t float16Value)
Definition: FloatUtil.cpp:30
ReaderContext(Span< const uint8_t > readBuffer, size_t readBufferBitSize)