Zserio C++17 runtime library  1.1.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 readUnsignedBitsImpl(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 = readUnsignedBitsImpl(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 readUnsignedBits64Impl(ReaderContext& ctx, uint8_t numBits)
343 {
344  // read the first 32 bits
345  numBits = static_cast<uint8_t>(numBits - 32);
346  uint64_t value = readUnsignedBitsImpl(ctx, 32);
347 
348  // add the remaining bits
349  value <<= numBits;
350  value |= readUnsignedBitsImpl(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  maxArrayPreallocation(maxArrayPrealloc),
365  bitIndex(0)
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>(readUnsignedBitsImpl(m_context, numBits));
404 }
405 
407 {
408  checkNumBits64(numBits);
409 
410 #ifdef ZSERIO_RUNTIME_64BIT
411  return readUnsignedBitsImpl(m_context, numBits);
412 #else
413  if (numBits <= 32)
414  {
415  return readUnsignedBitsImpl(m_context, numBits);
416  }
417 
418  return readUnsignedBits64Impl(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>(readUnsignedBits64Impl(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 - 1U)));
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  return readUnsignedBitsImpl(m_context, 1) != 0;
460 }
461 
463 {
464  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
465  const bool sign = (byte & VARINT_SIGN_1) != 0;
466  uint16_t result = byte & VARINT_BYTE_1;
467  if ((byte & VARINT_HAS_NEXT_1) == 0)
468  {
469  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
470  }
471 
472  result = static_cast<uint16_t>(result << 8U);
473  result = static_cast<uint16_t>(result | readUnsignedBitsImpl(m_context, 8)); // byte 2
474  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
475 }
476 
478 {
479  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
480  const bool sign = (byte & VARINT_SIGN_1) != 0;
481  uint32_t result = byte & VARINT_BYTE_1;
482  if ((byte & VARINT_HAS_NEXT_1) == 0)
483  {
484  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
485  }
486 
487  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
488  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
489  if ((byte & VARINT_HAS_NEXT_N) == 0)
490  {
491  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
492  }
493 
494  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
495  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
496  if ((byte & VARINT_HAS_NEXT_N) == 0)
497  {
498  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
499  }
500 
501  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
502  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
503 }
504 
506 {
507  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
508  const bool sign = (byte & VARINT_SIGN_1) != 0;
509  uint64_t result = byte & VARINT_BYTE_1;
510  if ((byte & VARINT_HAS_NEXT_1) == 0)
511  {
512  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
513  }
514 
515  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
516  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
517  if ((byte & VARINT_HAS_NEXT_N) == 0)
518  {
519  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
520  }
521 
522  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
523  result = static_cast<uint64_t>(result) << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
524  if ((byte & VARINT_HAS_NEXT_N) == 0)
525  {
526  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
527  }
528 
529  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
530  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
531  if ((byte & VARINT_HAS_NEXT_N) == 0)
532  {
533  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
534  }
535 
536  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 5
537  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
538  if ((byte & VARINT_HAS_NEXT_N) == 0)
539  {
540  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
541  }
542 
543  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 6
544  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
545  if ((byte & VARINT_HAS_NEXT_N) == 0)
546  {
547  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
548  }
549 
550  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 7
551  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
552  if ((byte & VARINT_HAS_NEXT_N) == 0)
553  {
554  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
555  }
556 
557  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 8
558  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
559 }
560 
562 {
563  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
564  const bool sign = (byte & VARINT_SIGN_1) != 0;
565  uint64_t result = byte & VARINT_BYTE_1;
566  if ((byte & VARINT_HAS_NEXT_1) == 0)
567  {
568  return sign ? (result == 0 ? INT64_MIN : -static_cast<int64_t>(result)) : static_cast<int64_t>(result);
569  }
570 
571  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
572  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
573  if ((byte & VARINT_HAS_NEXT_N) == 0)
574  {
575  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
576  }
577 
578  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
579  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
580  if ((byte & VARINT_HAS_NEXT_N) == 0)
581  {
582  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
583  }
584 
585  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
586  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
587  if ((byte & VARINT_HAS_NEXT_N) == 0)
588  {
589  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
590  }
591 
592  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 5
593  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
594  if ((byte & VARINT_HAS_NEXT_N) == 0)
595  {
596  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
597  }
598 
599  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 6
600  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
601  if ((byte & VARINT_HAS_NEXT_N) == 0)
602  {
603  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
604  }
605 
606  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 7
607  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
608  if ((byte & VARINT_HAS_NEXT_N) == 0)
609  {
610  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
611  }
612 
613  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 8
614  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
615  if ((byte & VARINT_HAS_NEXT_N) == 0)
616  {
617  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
618  }
619 
620  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 9
621  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
622 }
623 
625 {
626  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
627  uint16_t result = byte & VARUINT_BYTE;
628  if ((byte & VARUINT_HAS_NEXT) == 0)
629  {
630  return result;
631  }
632 
633  result = static_cast<uint16_t>(result << 8U);
634  result = static_cast<uint16_t>(result | readUnsignedBitsImpl(m_context, 8)); // byte 2
635  return result;
636 }
637 
639 {
640  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
641  uint32_t result = byte & VARUINT_BYTE;
642  if ((byte & VARUINT_HAS_NEXT) == 0)
643  {
644  return result;
645  }
646 
647  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
648  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
649  if ((byte & VARUINT_HAS_NEXT) == 0)
650  {
651  return result;
652  }
653 
654  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
655  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
656  if ((byte & VARUINT_HAS_NEXT) == 0)
657  {
658  return result;
659  }
660 
661  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
662  return result;
663 }
664 
666 {
667  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
668  uint64_t result = byte & VARUINT_BYTE;
669  if ((byte & VARUINT_HAS_NEXT) == 0)
670  {
671  return result;
672  }
673 
674  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
675  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
676  if ((byte & VARUINT_HAS_NEXT) == 0)
677  {
678  return result;
679  }
680 
681  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
682  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
683  if ((byte & VARUINT_HAS_NEXT) == 0)
684  {
685  return result;
686  }
687 
688  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
689  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
690  if ((byte & VARUINT_HAS_NEXT) == 0)
691  {
692  return result;
693  }
694 
695  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 5
696  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
697  if ((byte & VARUINT_HAS_NEXT) == 0)
698  {
699  return result;
700  }
701 
702  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 6
703  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
704  if ((byte & VARUINT_HAS_NEXT) == 0)
705  {
706  return result;
707  }
708 
709  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 7
710  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
711  if ((byte & VARUINT_HAS_NEXT) == 0)
712  {
713  return result;
714  }
715 
716  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 8
717  return result;
718 }
719 
721 {
722  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
723  uint64_t result = byte & VARUINT_BYTE;
724  if ((byte & VARUINT_HAS_NEXT) == 0)
725  {
726  return result;
727  }
728 
729  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
730  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
731  if ((byte & VARUINT_HAS_NEXT) == 0)
732  {
733  return result;
734  }
735 
736  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
737  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
738  if ((byte & VARUINT_HAS_NEXT) == 0)
739  {
740  return result;
741  }
742 
743  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
744  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
745  if ((byte & VARUINT_HAS_NEXT) == 0)
746  {
747  return result;
748  }
749 
750  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 5
751  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
752  if ((byte & VARUINT_HAS_NEXT) == 0)
753  {
754  return result;
755  }
756 
757  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 6
758  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
759  if ((byte & VARUINT_HAS_NEXT) == 0)
760  {
761  return result;
762  }
763 
764  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 7
765  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
766  if ((byte & VARUINT_HAS_NEXT) == 0)
767  {
768  return result;
769  }
770 
771  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 8
772  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
773  if ((byte & VARUINT_HAS_NEXT) == 0)
774  {
775  return result;
776  }
777 
778  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 9
779  return result;
780 }
781 
783 {
784  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
785  uint32_t result = byte & VARUINT_BYTE;
786  if ((byte & VARUINT_HAS_NEXT) == 0)
787  {
788  return result;
789  }
790 
791  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
792  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
793  if ((byte & VARUINT_HAS_NEXT) == 0)
794  {
795  return result;
796  }
797 
798  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
799  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
800  if ((byte & VARUINT_HAS_NEXT) == 0)
801  {
802  return result;
803  }
804 
805  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
806  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
807  if ((byte & VARUINT_HAS_NEXT) == 0)
808  {
809  return result;
810  }
811 
812  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 5
813  if (result > VARSIZE_MAX_VALUE)
814  {
815  throw CppRuntimeException("BitStreamReader: Read value '")
816  << result << "' is out of range for varsize type!";
817  }
818 
819  return result;
820 }
821 
823 {
824  const uint16_t halfPrecisionFloatValue = static_cast<uint16_t>(readUnsignedBitsImpl(m_context, 16));
825 
826  return convertUInt16ToFloat(halfPrecisionFloatValue);
827 }
828 
830 {
831  const uint32_t singlePrecisionFloatValue = static_cast<uint32_t>(readUnsignedBitsImpl(m_context, 32));
832 
833  return convertUInt32ToFloat(singlePrecisionFloatValue);
834 }
835 
837 {
838 #ifdef ZSERIO_RUNTIME_64BIT
839  const uint64_t doublePrecisionFloatValue = static_cast<uint64_t>(readUnsignedBitsImpl(m_context, 64));
840 #else
841  const uint64_t doublePrecisionFloatValue = readUnsignedBits64Impl(m_context, 64);
842 #endif
843 
844  return convertUInt64ToDouble(doublePrecisionFloatValue);
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)readUnsignedBits32(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)readUnsignedBits64(skip);
870  }
871 }
872 
873 uint8_t BitStreamReader::readByte()
874 {
875  return static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8));
876 }
877 
878 } // namespace zserio
void setBitPosition(BitPosType position)
void alignTo(size_t alignment)
uint32_t readUnsignedBits32(uint8_t numBits=32)
uint64_t readUnsignedBits64(uint8_t numBits=64)
int64_t readSignedBits64(uint8_t numBits=64)
int32_t readSignedBits32(uint8_t numBits=32)
BitStreamReader(const uint8_t *buffer, size_t bufferByteSize, ArrayPreallocation maxArrayPrealloc={})
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)
detail::BoolWrapper Bool
Definition: Types.h:732
detail::VarIntWrapper< uint64_t, detail::VarIntType::VAR > VarUInt
Definition: Types.h:888
detail::FloatWrapper< float, detail::FloatType::FLOAT16 > Float16
Definition: Types.h:892
detail::FloatWrapper< float, detail::FloatType::FLOAT32 > Float32
Definition: Types.h:893
detail::VarIntWrapper< int32_t, detail::VarIntType::VAR32 > VarInt32
Definition: Types.h:881
float convertUInt32ToFloat(uint32_t float32Value)
Definition: FloatUtil.cpp:169
detail::VarIntWrapper< uint16_t, detail::VarIntType::VAR16 > VarUInt16
Definition: Types.h:885
double convertUInt64ToDouble(uint64_t float64Value)
Definition: FloatUtil.cpp:185
detail::VarIntWrapper< uint64_t, detail::VarIntType::VAR64 > VarUInt64
Definition: Types.h:887
detail::VarIntWrapper< int16_t, detail::VarIntType::VAR16 > VarInt16
Definition: Types.h:880
detail::FloatWrapper< double, detail::FloatType::FLOAT64 > Float64
Definition: Types.h:894
detail::VarIntWrapper< uint32_t, detail::VarIntType::VAR32 > VarUInt32
Definition: Types.h:886
float convertUInt16ToFloat(uint16_t float16Value)
Definition: FloatUtil.cpp:32
detail::VarIntWrapper< int64_t, detail::VarIntType::VAR > VarInt
Definition: Types.h:883
detail::VarIntWrapper< int64_t, detail::VarIntType::VAR64 > VarInt64
Definition: Types.h:882
detail::VarIntWrapper< uint32_t, detail::VarIntType::VARSIZE > VarSize
Definition: Types.h:890
ReaderContext(Span< const uint8_t > readBuffer, size_t readBufferBitSize, size_t maxArrayPrealloc)