Zserio C++17 runtime library  0.5.0
Built for Zserio 2.17.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 == 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  buffer(readBuffer),
360  bufferBitSize(readBufferBitSize),
361  cache(0),
362  cacheNumBits(0),
363  bitIndex(0)
364 {
365  if (buffer.size() > MAX_BUFFER_SIZE)
366  {
367  throw CppRuntimeException("BitStreamReader: Buffer size exceeded limit '")
368  << MAX_BUFFER_SIZE << "' bytes!";
369  }
370 }
371 
372 BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferByteSize) :
373  BitStreamReader(Span<const uint8_t>(buffer, bufferByteSize))
374 {}
375 
377  m_context(buffer, buffer.size() * 8)
378 {}
379 
381  m_context(buffer, bufferBitSize)
382 {
383  if (buffer.size() < (bufferBitSize + 7) / 8)
384  {
385  throw CppRuntimeException("BitStreamReader: Wrong buffer bit size ('")
386  << buffer.size() << "' < '" << (bufferBitSize + 7) / 8 << "')!";
387  }
388 }
389 
390 BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferBitSize, BitsTag) :
391  m_context(Span<const uint8_t>(buffer, (bufferBitSize + 7) / 8), bufferBitSize)
392 {}
393 
395 {
396  checkNumBits(numBits);
397 
398  return static_cast<uint32_t>(readUnsignedBitsImpl(m_context, numBits));
399 }
400 
402 {
403  checkNumBits64(numBits);
404 
405 #ifdef ZSERIO_RUNTIME_64BIT
406  return readUnsignedBitsImpl(m_context, numBits);
407 #else
408  if (numBits <= 32)
409  {
410  return readUnsignedBitsImpl(m_context, numBits);
411  }
412 
413  return readUnsignedBits64Impl(m_context, numBits);
414 #endif
415 }
416 
418 {
419  checkNumBits64(numBits);
420 
421 #ifdef ZSERIO_RUNTIME_64BIT
422  return readSignedBitsImpl(m_context, numBits);
423 #else
424  if (numBits <= 32)
425  {
426  return readSignedBitsImpl(m_context, numBits);
427  }
428 
429  int64_t value = static_cast<int64_t>(readUnsignedBits64Impl(m_context, numBits));
430 
431  // Skip the signed overflow correction if numBits == 64.
432  // In that case, the value that comes out the readBits function
433  // is already correct.
434  const bool needsSignExtension =
435  numBits < 64 && (static_cast<uint64_t>(value) >= (UINT64_C(1) << (numBits - 1U)));
436  if (needsSignExtension)
437  {
438  value = static_cast<int64_t>(static_cast<uint64_t>(value) - (UINT64_C(1) << numBits));
439  }
440 
441  return value;
442 #endif
443 }
444 
446 {
447  checkNumBits(numBits);
448 
449  return static_cast<int32_t>(readSignedBitsImpl(m_context, numBits));
450 }
451 
453 {
454  return readUnsignedBitsImpl(m_context, 1) != 0;
455 }
456 
458 {
459  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
460  const bool sign = (byte & VARINT_SIGN_1) != 0;
461  uint16_t result = byte & VARINT_BYTE_1;
462  if ((byte & VARINT_HAS_NEXT_1) == 0)
463  {
464  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
465  }
466 
467  result = static_cast<uint16_t>(result << 8U);
468  result = static_cast<uint16_t>(result | readUnsignedBitsImpl(m_context, 8)); // byte 2
469  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
470 }
471 
473 {
474  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
475  const bool sign = (byte & VARINT_SIGN_1) != 0;
476  uint32_t result = byte & VARINT_BYTE_1;
477  if ((byte & VARINT_HAS_NEXT_1) == 0)
478  {
479  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
480  }
481 
482  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
483  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
484  if ((byte & VARINT_HAS_NEXT_N) == 0)
485  {
486  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
487  }
488 
489  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
490  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
491  if ((byte & VARINT_HAS_NEXT_N) == 0)
492  {
493  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
494  }
495 
496  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
497  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
498 }
499 
501 {
502  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
503  const bool sign = (byte & VARINT_SIGN_1) != 0;
504  uint64_t result = byte & VARINT_BYTE_1;
505  if ((byte & VARINT_HAS_NEXT_1) == 0)
506  {
507  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
508  }
509 
510  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
511  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
512  if ((byte & VARINT_HAS_NEXT_N) == 0)
513  {
514  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
515  }
516 
517  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
518  result = static_cast<uint64_t>(result) << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
519  if ((byte & VARINT_HAS_NEXT_N) == 0)
520  {
521  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
522  }
523 
524  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
525  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
526  if ((byte & VARINT_HAS_NEXT_N) == 0)
527  {
528  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
529  }
530 
531  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 5
532  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
533  if ((byte & VARINT_HAS_NEXT_N) == 0)
534  {
535  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
536  }
537 
538  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 6
539  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
540  if ((byte & VARINT_HAS_NEXT_N) == 0)
541  {
542  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
543  }
544 
545  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 7
546  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
547  if ((byte & VARINT_HAS_NEXT_N) == 0)
548  {
549  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
550  }
551 
552  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 8
553  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
554 }
555 
557 {
558  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
559  const bool sign = (byte & VARINT_SIGN_1) != 0;
560  uint64_t result = byte & VARINT_BYTE_1;
561  if ((byte & VARINT_HAS_NEXT_1) == 0)
562  {
563  return sign ? (result == 0 ? INT64_MIN : -static_cast<int64_t>(result)) : static_cast<int64_t>(result);
564  }
565 
566  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
567  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
568  if ((byte & VARINT_HAS_NEXT_N) == 0)
569  {
570  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
571  }
572 
573  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
574  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
575  if ((byte & VARINT_HAS_NEXT_N) == 0)
576  {
577  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
578  }
579 
580  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
581  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
582  if ((byte & VARINT_HAS_NEXT_N) == 0)
583  {
584  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
585  }
586 
587  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 5
588  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
589  if ((byte & VARINT_HAS_NEXT_N) == 0)
590  {
591  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
592  }
593 
594  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 6
595  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
596  if ((byte & VARINT_HAS_NEXT_N) == 0)
597  {
598  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
599  }
600 
601  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 7
602  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
603  if ((byte & VARINT_HAS_NEXT_N) == 0)
604  {
605  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
606  }
607 
608  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 8
609  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
610  if ((byte & VARINT_HAS_NEXT_N) == 0)
611  {
612  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
613  }
614 
615  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 9
616  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
617 }
618 
620 {
621  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
622  uint16_t result = byte & VARUINT_BYTE;
623  if ((byte & VARUINT_HAS_NEXT) == 0)
624  {
625  return result;
626  }
627 
628  result = static_cast<uint16_t>(result << 8U);
629  result = static_cast<uint16_t>(result | readUnsignedBitsImpl(m_context, 8)); // byte 2
630  return result;
631 }
632 
634 {
635  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
636  uint32_t result = byte & VARUINT_BYTE;
637  if ((byte & VARUINT_HAS_NEXT) == 0)
638  {
639  return result;
640  }
641 
642  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
643  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
644  if ((byte & VARUINT_HAS_NEXT) == 0)
645  {
646  return result;
647  }
648 
649  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
650  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
651  if ((byte & VARUINT_HAS_NEXT) == 0)
652  {
653  return result;
654  }
655 
656  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
657  return result;
658 }
659 
661 {
662  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 1
663  uint64_t result = byte & VARUINT_BYTE;
664  if ((byte & VARUINT_HAS_NEXT) == 0)
665  {
666  return result;
667  }
668 
669  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 2
670  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
671  if ((byte & VARUINT_HAS_NEXT) == 0)
672  {
673  return result;
674  }
675 
676  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 3
677  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
678  if ((byte & VARUINT_HAS_NEXT) == 0)
679  {
680  return result;
681  }
682 
683  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 4
684  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
685  if ((byte & VARUINT_HAS_NEXT) == 0)
686  {
687  return result;
688  }
689 
690  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 5
691  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
692  if ((byte & VARUINT_HAS_NEXT) == 0)
693  {
694  return result;
695  }
696 
697  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 6
698  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
699  if ((byte & VARUINT_HAS_NEXT) == 0)
700  {
701  return result;
702  }
703 
704  byte = static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 7
705  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
706  if ((byte & VARUINT_HAS_NEXT) == 0)
707  {
708  return result;
709  }
710 
711  result = result << 8U | static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8)); // byte 8
712  return result;
713 }
714 
716 {
717  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(m_context, 8)); // byte 9
774  return result;
775 }
776 
778 {
779  uint8_t byte = static_cast<uint8_t>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(m_context, 16));
820 
821  return convertUInt16ToFloat(halfPrecisionFloatValue);
822 }
823 
825 {
826  const uint32_t singlePrecisionFloatValue = static_cast<uint32_t>(readUnsignedBitsImpl(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>(readUnsignedBitsImpl(m_context, 64));
835 #else
836  const uint64_t doublePrecisionFloatValue = readUnsignedBits64Impl(m_context, 64);
837 #endif
838 
839  return convertUInt64ToDouble(doublePrecisionFloatValue);
840 }
841 
843 {
844  if (position > m_context.bufferBitSize)
845  {
846  throw CppRuntimeException("BitStreamReader: Reached eof(), setting of bit position failed!");
847  }
848 
849  m_context.bitIndex = (position / 8) * 8; // set to byte aligned position
850  m_context.cacheNumBits = 0; // invalidate cache
851  const uint8_t skip = static_cast<uint8_t>(position - m_context.bitIndex);
852  if (skip != 0)
853  {
854  (void)readUnsignedBits32(skip);
855  }
856 }
857 
858 void BitStreamReader::alignTo(size_t alignment)
859 {
860  const BitPosType offset = getBitPosition() % alignment;
861  if (offset != 0)
862  {
863  const uint8_t skip = static_cast<uint8_t>(alignment - offset);
864  (void)readUnsignedBits64(skip);
865  }
866 }
867 
868 uint8_t BitStreamReader::readByte()
869 {
870  return static_cast<uint8_t>(readUnsignedBitsImpl(m_context, 8));
871 }
872 
873 } // namespace zserio
void setBitPosition(BitPosType position)
void alignTo(size_t alignment)
BitStreamReader(const uint8_t *buffer, size_t bufferByteSize)
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)
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)