Zserio C++ runtime library  1.4.0
Built for Zserio 2.18.1
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 "bitIndex + numBits" overflows
16 const size_t MAX_BUFFER_SIZE = std::numeric_limits<size_t>::max() / 8 - sizeof(size_t);
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 == 0 || numBits > 32)
211  {
212  throwNumBitsIsNotValid(numBits);
213  }
214 }
215 
217 inline void checkNumBits64(uint8_t numBits)
218 {
219  if (numBits == 0 || numBits > 64)
220  {
221  throwNumBitsIsNotValid(numBits);
222  }
223 }
224 
226 inline void throwEof()
227 {
228  throw CppRuntimeException("BitStreamReader: Reached eof(), reading from stream failed!");
229 }
230 
232 inline void loadCacheNext(ReaderContext& ctx, uint8_t numBits)
233 {
234  static const uint8_t cacheBitSize = sizeof(BaseType) * 8;
235 
236  // ctx.bitIndex is always byte aligned and ctx.cacheNumBits is always zero in this call
237  const size_t byteIndex = ctx.bitIndex >> 3U;
238  if (ctx.bufferBitSize >= ctx.bitIndex + cacheBitSize)
239  {
240  ctx.cache =
241 #ifdef ZSERIO_RUNTIME_64BIT
242  parse64(ctx.buffer.begin() + byteIndex);
243 #else
244  parse32(ctx.buffer.begin() + byteIndex);
245 #endif
246  ctx.cacheNumBits = cacheBitSize;
247  }
248  else
249  {
250  if (ctx.bitIndex + numBits > ctx.bufferBitSize)
251  {
252  throwEof();
253  }
254 
255  ctx.cacheNumBits = static_cast<uint8_t>(ctx.bufferBitSize - ctx.bitIndex);
256 
257  // buffer must be always available in full bytes, even if some last bits are not used
258  const uint8_t alignedNumBits = static_cast<uint8_t>((ctx.cacheNumBits + 7U) & ~0x7U);
259 
260  switch (alignedNumBits)
261  {
262 #ifdef ZSERIO_RUNTIME_64BIT
263  case 64:
264  ctx.cache = parse64(ctx.buffer.begin() + byteIndex);
265  break;
266  case 56:
267  ctx.cache = parse56(ctx.buffer.begin() + byteIndex);
268  break;
269  case 48:
270  ctx.cache = parse48(ctx.buffer.begin() + byteIndex);
271  break;
272  case 40:
273  ctx.cache = parse40(ctx.buffer.begin() + byteIndex);
274  break;
275 #endif
276  case 32:
277  ctx.cache = parse32(ctx.buffer.begin() + byteIndex);
278  break;
279  case 24:
280  ctx.cache = parse24(ctx.buffer.begin() + byteIndex);
281  break;
282  case 16:
283  ctx.cache = parse16(ctx.buffer.begin() + byteIndex);
284  break;
285  default: // 8
286  ctx.cache = parse8(ctx.buffer.begin() + byteIndex);
287  break;
288  }
289 
290  ctx.cache >>= static_cast<uint8_t>(alignedNumBits - ctx.cacheNumBits);
291  }
292 }
293 
295 inline BaseType readBitsImpl(ReaderContext& ctx, uint8_t numBits)
296 {
297  BaseType value = 0;
298  if (ctx.cacheNumBits < numBits)
299  {
300  // read all remaining cache bits
301  value = ctx.cache & MASK_TABLE[ctx.cacheNumBits];
302  ctx.bitIndex += ctx.cacheNumBits;
303  numBits = static_cast<uint8_t>(numBits - ctx.cacheNumBits);
304 
305  // load next piece of buffer into cache
306  loadCacheNext(ctx, numBits);
307 
308  // add the remaining bits to the result
309  // if numBits is sizeof(BaseType) * 8 here, value is already 0 (see MASK_TABLE[0])
310  if (numBits < sizeof(BaseType) * 8)
311  {
312  value <<= numBits;
313  }
314  }
315  value |= ((ctx.cache >> static_cast<uint8_t>(ctx.cacheNumBits - numBits)) & MASK_TABLE[numBits]);
316  ctx.cacheNumBits = static_cast<uint8_t>(ctx.cacheNumBits - numBits);
317  ctx.bitIndex += numBits;
318 
319  return value;
320 }
321 
323 inline BaseSignedType readSignedBitsImpl(ReaderContext& ctx, uint8_t numBits)
324 {
325  static const uint8_t typeSize = sizeof(BaseSignedType) * 8;
326  BaseType value = readBitsImpl(ctx, numBits);
327 
328  // Skip the signed overflow correction if numBits == typeSize.
329  // In that case, the value that comes out the readBits function
330  // is already correct.
331  if (numBits != 0 && numBits < typeSize &&
332  (value >= (static_cast<BaseType>(1) << static_cast<uint8_t>(numBits - 1))))
333  {
334  value -= static_cast<BaseType>(1) << numBits;
335  }
336 
337  return static_cast<BaseSignedType>(value);
338 }
339 
340 #ifndef ZSERIO_RUNTIME_64BIT
342 inline uint64_t readBits64Impl(ReaderContext& ctx, uint8_t numBits)
343 {
344  // read the first 32 bits
345  numBits = static_cast<uint8_t>(numBits - 32);
346  uint64_t value = readBitsImpl(ctx, 32);
347 
348  // add the remaining bits
349  value <<= numBits;
350  value |= readBitsImpl(ctx, numBits);
351 
352  return value;
353 }
354 #endif
355 
356 } // namespace
357 
359  Span<const uint8_t> readBuffer, size_t readBufferBitSize, size_t maxArrayPrealloc) :
360  buffer(readBuffer),
361  bufferBitSize(readBufferBitSize),
362  cache(0),
363  cacheNumBits(0),
364  bitIndex(0),
365  maxArrayPreallocation(maxArrayPrealloc)
366 {
367  if (buffer.size() > MAX_BUFFER_SIZE)
368  {
369  throw CppRuntimeException("BitStreamReader: Buffer size exceeded limit '")
370  << MAX_BUFFER_SIZE << "' bytes!";
371  }
372 }
373 
375  const uint8_t* buffer, size_t bufferByteSize, ArrayPreallocation maxArrayPrealloc) :
376  BitStreamReader(Span<const uint8_t>(buffer, bufferByteSize), maxArrayPrealloc)
377 {}
378 
380  m_context(buffer, buffer.size() * 8, maxArrayPrealloc)
381 {}
382 
384  Span<const uint8_t> buffer, size_t bufferBitSize, ArrayPreallocation maxArrayPrealloc) :
385  m_context(buffer, bufferBitSize, maxArrayPrealloc)
386 {
387  if (buffer.size() < (bufferBitSize + 7) / 8)
388  {
389  throw CppRuntimeException("BitStreamReader: Wrong buffer bit size ('")
390  << buffer.size() << "' < '" << (bufferBitSize + 7) / 8 << "')!";
391  }
392 }
393 
395  const uint8_t* buffer, size_t bufferBitSize, BitsTag, ArrayPreallocation maxArrayPrealloc) :
396  m_context(Span<const uint8_t>(buffer, (bufferBitSize + 7) / 8), bufferBitSize, maxArrayPrealloc)
397 {}
398 
400 {
401  checkNumBits(numBits);
402 
403  return static_cast<uint32_t>(readBitsImpl(m_context, numBits));
404 }
405 
407 {
408  checkNumBits64(numBits);
409 
410 #ifdef ZSERIO_RUNTIME_64BIT
411  return readBitsImpl(m_context, numBits);
412 #else
413  if (numBits <= 32)
414  {
415  return readBitsImpl(m_context, numBits);
416  }
417 
418  return readBits64Impl(m_context, numBits);
419 #endif
420 }
421 
423 {
424  checkNumBits64(numBits);
425 
426 #ifdef ZSERIO_RUNTIME_64BIT
427  return readSignedBitsImpl(m_context, numBits);
428 #else
429  if (numBits <= 32)
430  {
431  return readSignedBitsImpl(m_context, numBits);
432  }
433 
434  int64_t value = static_cast<int64_t>(readBits64Impl(m_context, numBits));
435 
436  // Skip the signed overflow correction if numBits == 64.
437  // In that case, the value that comes out the readBits function
438  // is already correct.
439  const bool needsSignExtension =
440  numBits < 64 && (static_cast<uint64_t>(value) >= (UINT64_C(1) << (numBits - 1)));
441  if (needsSignExtension)
442  {
443  value = static_cast<int64_t>(static_cast<uint64_t>(value) - (UINT64_C(1) << numBits));
444  }
445 
446  return value;
447 #endif
448 }
449 
451 {
452  checkNumBits(numBits);
453 
454  return static_cast<int32_t>(readSignedBitsImpl(m_context, numBits));
455 }
456 
458 {
459  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
460  const bool sign = (byte & VARINT_SIGN_1) != 0;
461  uint64_t result = byte & VARINT_BYTE_1;
462  if ((byte & VARINT_HAS_NEXT_1) == 0)
463  {
464  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
465  }
466 
467  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
468  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
469  if ((byte & VARINT_HAS_NEXT_N) == 0)
470  {
471  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
472  }
473 
474  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
475  result = static_cast<uint64_t>(result) << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
476  if ((byte & VARINT_HAS_NEXT_N) == 0)
477  {
478  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
479  }
480 
481  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
482  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
483  if ((byte & VARINT_HAS_NEXT_N) == 0)
484  {
485  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
486  }
487 
488  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
489  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
490  if ((byte & VARINT_HAS_NEXT_N) == 0)
491  {
492  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
493  }
494 
495  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
496  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
497  if ((byte & VARINT_HAS_NEXT_N) == 0)
498  {
499  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
500  }
501 
502  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
503  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
504  if ((byte & VARINT_HAS_NEXT_N) == 0)
505  {
506  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
507  }
508 
509  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
510  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
511 }
512 
514 {
515  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
516  const bool sign = (byte & VARINT_SIGN_1) != 0;
517  uint32_t result = byte & VARINT_BYTE_1;
518  if ((byte & VARINT_HAS_NEXT_1) == 0)
519  {
520  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
521  }
522 
523  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
524  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
525  if ((byte & VARINT_HAS_NEXT_N) == 0)
526  {
527  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
528  }
529 
530  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
531  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
532  if ((byte & VARINT_HAS_NEXT_N) == 0)
533  {
534  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
535  }
536 
537  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
538  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
539 }
540 
542 {
543  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
544  const bool sign = (byte & VARINT_SIGN_1) != 0;
545  uint16_t result = byte & VARINT_BYTE_1;
546  if ((byte & VARINT_HAS_NEXT_1) == 0)
547  {
548  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
549  }
550 
551  result = static_cast<uint16_t>(result << 8U);
552  result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
553  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
554 }
555 
557 {
558  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
559  uint64_t result = byte & VARUINT_BYTE;
560  if ((byte & VARUINT_HAS_NEXT) == 0)
561  {
562  return result;
563  }
564 
565  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
566  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
567  if ((byte & VARUINT_HAS_NEXT) == 0)
568  {
569  return result;
570  }
571 
572  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
573  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
574  if ((byte & VARUINT_HAS_NEXT) == 0)
575  {
576  return result;
577  }
578 
579  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
580  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
581  if ((byte & VARUINT_HAS_NEXT) == 0)
582  {
583  return result;
584  }
585 
586  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
587  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
588  if ((byte & VARUINT_HAS_NEXT) == 0)
589  {
590  return result;
591  }
592 
593  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
594  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
595  if ((byte & VARUINT_HAS_NEXT) == 0)
596  {
597  return result;
598  }
599 
600  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
601  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
602  if ((byte & VARUINT_HAS_NEXT) == 0)
603  {
604  return result;
605  }
606 
607  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
608  return result;
609 }
610 
612 {
613  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
614  uint32_t result = byte & VARUINT_BYTE;
615  if ((byte & VARUINT_HAS_NEXT) == 0)
616  {
617  return result;
618  }
619 
620  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
621  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
622  if ((byte & VARUINT_HAS_NEXT) == 0)
623  {
624  return result;
625  }
626 
627  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
628  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
629  if ((byte & VARUINT_HAS_NEXT) == 0)
630  {
631  return result;
632  }
633 
634  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
635  return result;
636 }
637 
639 {
640  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
641  uint16_t result = byte & VARUINT_BYTE;
642  if ((byte & VARUINT_HAS_NEXT) == 0)
643  {
644  return result;
645  }
646 
647  result = static_cast<uint16_t>(result << 8U);
648  result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
649  return result;
650 }
651 
653 {
654  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
655  const bool sign = (byte & VARINT_SIGN_1) != 0;
656  uint64_t result = byte & VARINT_BYTE_1;
657  if ((byte & VARINT_HAS_NEXT_1) == 0)
658  {
659  return sign ? (result == 0 ? INT64_MIN : -static_cast<int64_t>(result)) : static_cast<int64_t>(result);
660  }
661 
662  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
663  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
664  if ((byte & VARINT_HAS_NEXT_N) == 0)
665  {
666  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
667  }
668 
669  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
670  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
671  if ((byte & VARINT_HAS_NEXT_N) == 0)
672  {
673  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
674  }
675 
676  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
677  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
678  if ((byte & VARINT_HAS_NEXT_N) == 0)
679  {
680  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
681  }
682 
683  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
684  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
685  if ((byte & VARINT_HAS_NEXT_N) == 0)
686  {
687  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
688  }
689 
690  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
691  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
692  if ((byte & VARINT_HAS_NEXT_N) == 0)
693  {
694  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
695  }
696 
697  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
698  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
699  if ((byte & VARINT_HAS_NEXT_N) == 0)
700  {
701  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
702  }
703 
704  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
705  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
706  if ((byte & VARINT_HAS_NEXT_N) == 0)
707  {
708  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
709  }
710 
711  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
712  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
713 }
714 
716 {
717  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
718  uint64_t result = byte & VARUINT_BYTE;
719  if ((byte & VARUINT_HAS_NEXT) == 0)
720  {
721  return result;
722  }
723 
724  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
725  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
726  if ((byte & VARUINT_HAS_NEXT) == 0)
727  {
728  return result;
729  }
730 
731  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
732  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
733  if ((byte & VARUINT_HAS_NEXT) == 0)
734  {
735  return result;
736  }
737 
738  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
739  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
740  if ((byte & VARUINT_HAS_NEXT) == 0)
741  {
742  return result;
743  }
744 
745  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
746  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
747  if ((byte & VARUINT_HAS_NEXT) == 0)
748  {
749  return result;
750  }
751 
752  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
753  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
754  if ((byte & VARUINT_HAS_NEXT) == 0)
755  {
756  return result;
757  }
758 
759  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
760  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
761  if ((byte & VARUINT_HAS_NEXT) == 0)
762  {
763  return result;
764  }
765 
766  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
767  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
768  if ((byte & VARUINT_HAS_NEXT) == 0)
769  {
770  return result;
771  }
772 
773  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
774  return result;
775 }
776 
778 {
779  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
780  uint32_t result = byte & VARUINT_BYTE;
781  if ((byte & VARUINT_HAS_NEXT) == 0)
782  {
783  return result;
784  }
785 
786  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
787  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
788  if ((byte & VARUINT_HAS_NEXT) == 0)
789  {
790  return result;
791  }
792 
793  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
794  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
795  if ((byte & VARUINT_HAS_NEXT) == 0)
796  {
797  return result;
798  }
799 
800  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
801  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
802  if ((byte & VARUINT_HAS_NEXT) == 0)
803  {
804  return result;
805  }
806 
807  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
808  if (result > VARSIZE_MAX_VALUE)
809  {
810  throw CppRuntimeException("BitStreamReader: Read value '")
811  << result << "' is out of range for varsize type!";
812  }
813 
814  return result;
815 }
816 
818 {
819  const uint16_t halfPrecisionFloatValue = static_cast<uint16_t>(readBitsImpl(m_context, 16));
820 
821  return convertUInt16ToFloat(halfPrecisionFloatValue);
822 }
823 
825 {
826  const uint32_t singlePrecisionFloatValue = static_cast<uint32_t>(readBitsImpl(m_context, 32));
827 
828  return convertUInt32ToFloat(singlePrecisionFloatValue);
829 }
830 
832 {
833 #ifdef ZSERIO_RUNTIME_64BIT
834  const uint64_t doublePrecisionFloatValue = static_cast<uint64_t>(readBitsImpl(m_context, 64));
835 #else
836  const uint64_t doublePrecisionFloatValue = readBits64Impl(m_context, 64);
837 #endif
838 
839  return convertUInt64ToDouble(doublePrecisionFloatValue);
840 }
841 
843 {
844  return readBitsImpl(m_context, 1) != 0;
845 }
846 
848 {
849  if (position > m_context.bufferBitSize)
850  {
851  throw CppRuntimeException("BitStreamReader: Reached eof(), setting of bit position failed!");
852  }
853 
854  m_context.bitIndex = (position / 8) * 8; // set to byte aligned position
855  m_context.cacheNumBits = 0; // invalidate cache
856  const uint8_t skip = static_cast<uint8_t>(position - m_context.bitIndex);
857  if (skip != 0)
858  {
859  (void)readBits(skip);
860  }
861 }
862 
863 void BitStreamReader::alignTo(size_t alignment)
864 {
865  const BitPosType offset = getBitPosition() % alignment;
866  if (offset != 0)
867  {
868  const uint8_t skip = static_cast<uint8_t>(alignment - offset);
869  (void)readBits64(skip);
870  }
871 }
872 
873 uint8_t BitStreamReader::readByte()
874 {
875  return static_cast<uint8_t>(readBitsImpl(m_context, 8));
876 }
877 
878 } // namespace zserio
void setBitPosition(BitPosType position)
void alignTo(size_t alignment)
uint64_t readBits64(uint8_t numBits=64)
uint32_t readBits(uint8_t numBits=32)
int32_t readSignedBits(uint8_t numBits=32)
int64_t readSignedBits64(uint8_t numBits=64)
BitStreamReader(const uint8_t *buffer, size_t bufferByteSize, ArrayPreallocation maxArrayPrealloc={})
BitPosType getBitPosition() const
constexpr size_type size() const noexcept
Definition: Span.h:283
const_pointer const_iterator
Definition: Span.h:71
uint8_t numBits(uint64_t numValues)
float convertUInt32ToFloat(uint32_t float32Value)
Definition: FloatUtil.cpp:169
double convertUInt64ToDouble(uint64_t float64Value)
Definition: FloatUtil.cpp:185
float convertUInt16ToFloat(uint16_t float16Value)
Definition: FloatUtil.cpp:32
ReaderContext(Span< const uint8_t > readBuffer, size_t readBufferBitSize, size_t maxArrayPrealloc)