Zserio C++ runtime library  1.2.0
Built for Zserio 2.16.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 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  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>(readBitsImpl(m_context, numBits));
399 }
400 
402 {
403  checkNumBits64(numBits);
404 
405 #ifdef ZSERIO_RUNTIME_64BIT
406  return readBitsImpl(m_context, numBits);
407 #else
408  if (numBits <= 32)
409  {
410  return readBitsImpl(m_context, numBits);
411  }
412 
413  return readBits64Impl(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>(readBits64Impl(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 - 1)));
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  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
455  const bool sign = (byte & VARINT_SIGN_1) != 0;
456  uint64_t result = byte & VARINT_BYTE_1;
457  if ((byte & VARINT_HAS_NEXT_1) == 0)
458  {
459  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
460  }
461 
462  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
463  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
464  if ((byte & VARINT_HAS_NEXT_N) == 0)
465  {
466  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
467  }
468 
469  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
470  result = static_cast<uint64_t>(result) << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
471  if ((byte & VARINT_HAS_NEXT_N) == 0)
472  {
473  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
474  }
475 
476  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
477  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
478  if ((byte & VARINT_HAS_NEXT_N) == 0)
479  {
480  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
481  }
482 
483  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
484  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
485  if ((byte & VARINT_HAS_NEXT_N) == 0)
486  {
487  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
488  }
489 
490  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
491  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
492  if ((byte & VARINT_HAS_NEXT_N) == 0)
493  {
494  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
495  }
496 
497  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
498  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
499  if ((byte & VARINT_HAS_NEXT_N) == 0)
500  {
501  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
502  }
503 
504  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
505  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
506 }
507 
509 {
510  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
511  const bool sign = (byte & VARINT_SIGN_1) != 0;
512  uint32_t result = byte & VARINT_BYTE_1;
513  if ((byte & VARINT_HAS_NEXT_1) == 0)
514  {
515  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
516  }
517 
518  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
519  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
520  if ((byte & VARINT_HAS_NEXT_N) == 0)
521  {
522  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
523  }
524 
525  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
526  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
527  if ((byte & VARINT_HAS_NEXT_N) == 0)
528  {
529  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
530  }
531 
532  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
533  return sign ? -static_cast<int32_t>(result) : static_cast<int32_t>(result);
534 }
535 
537 {
538  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
539  const bool sign = (byte & VARINT_SIGN_1) != 0;
540  uint16_t result = byte & VARINT_BYTE_1;
541  if ((byte & VARINT_HAS_NEXT_1) == 0)
542  {
543  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
544  }
545 
546  result = static_cast<uint16_t>(result << 8U);
547  result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
548  return sign ? static_cast<int16_t>(-result) : static_cast<int16_t>(result);
549 }
550 
552 {
553  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
554  uint64_t result = byte & VARUINT_BYTE;
555  if ((byte & VARUINT_HAS_NEXT) == 0)
556  {
557  return result;
558  }
559 
560  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
561  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
562  if ((byte & VARUINT_HAS_NEXT) == 0)
563  {
564  return result;
565  }
566 
567  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
568  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
569  if ((byte & VARUINT_HAS_NEXT) == 0)
570  {
571  return result;
572  }
573 
574  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
575  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
576  if ((byte & VARUINT_HAS_NEXT) == 0)
577  {
578  return result;
579  }
580 
581  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
582  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
583  if ((byte & VARUINT_HAS_NEXT) == 0)
584  {
585  return result;
586  }
587 
588  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
589  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
590  if ((byte & VARUINT_HAS_NEXT) == 0)
591  {
592  return result;
593  }
594 
595  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
596  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
597  if ((byte & VARUINT_HAS_NEXT) == 0)
598  {
599  return result;
600  }
601 
602  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
603  return result;
604 }
605 
607 {
608  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
609  uint32_t result = byte & VARUINT_BYTE;
610  if ((byte & VARUINT_HAS_NEXT) == 0)
611  {
612  return result;
613  }
614 
615  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
616  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
617  if ((byte & VARUINT_HAS_NEXT) == 0)
618  {
619  return result;
620  }
621 
622  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
623  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
624  if ((byte & VARUINT_HAS_NEXT) == 0)
625  {
626  return result;
627  }
628 
629  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
630  return result;
631 }
632 
634 {
635  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
636  uint16_t result = byte & VARUINT_BYTE;
637  if ((byte & VARUINT_HAS_NEXT) == 0)
638  {
639  return result;
640  }
641 
642  result = static_cast<uint16_t>(result << 8U);
643  result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
644  return result;
645 }
646 
648 {
649  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
650  const bool sign = (byte & VARINT_SIGN_1) != 0;
651  uint64_t result = byte & VARINT_BYTE_1;
652  if ((byte & VARINT_HAS_NEXT_1) == 0)
653  {
654  return sign ? (result == 0 ? INT64_MIN : -static_cast<int64_t>(result)) : static_cast<int64_t>(result);
655  }
656 
657  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
658  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
659  if ((byte & VARINT_HAS_NEXT_N) == 0)
660  {
661  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
662  }
663 
664  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
665  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
666  if ((byte & VARINT_HAS_NEXT_N) == 0)
667  {
668  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
669  }
670 
671  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
672  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
673  if ((byte & VARINT_HAS_NEXT_N) == 0)
674  {
675  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
676  }
677 
678  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
679  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
680  if ((byte & VARINT_HAS_NEXT_N) == 0)
681  {
682  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
683  }
684 
685  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
686  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
687  if ((byte & VARINT_HAS_NEXT_N) == 0)
688  {
689  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
690  }
691 
692  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
693  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
694  if ((byte & VARINT_HAS_NEXT_N) == 0)
695  {
696  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
697  }
698 
699  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
700  result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
701  if ((byte & VARINT_HAS_NEXT_N) == 0)
702  {
703  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
704  }
705 
706  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
707  return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
708 }
709 
711 {
712  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
713  uint64_t result = byte & VARUINT_BYTE;
714  if ((byte & VARUINT_HAS_NEXT) == 0)
715  {
716  return result;
717  }
718 
719  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
720  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
721  if ((byte & VARUINT_HAS_NEXT) == 0)
722  {
723  return result;
724  }
725 
726  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
727  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
728  if ((byte & VARUINT_HAS_NEXT) == 0)
729  {
730  return result;
731  }
732 
733  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
734  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
735  if ((byte & VARUINT_HAS_NEXT) == 0)
736  {
737  return result;
738  }
739 
740  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
741  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
742  if ((byte & VARUINT_HAS_NEXT) == 0)
743  {
744  return result;
745  }
746 
747  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
748  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
749  if ((byte & VARUINT_HAS_NEXT) == 0)
750  {
751  return result;
752  }
753 
754  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
755  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
756  if ((byte & VARUINT_HAS_NEXT) == 0)
757  {
758  return result;
759  }
760 
761  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
762  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
763  if ((byte & VARUINT_HAS_NEXT) == 0)
764  {
765  return result;
766  }
767 
768  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
769  return result;
770 }
771 
773 {
774  uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
775  uint32_t result = byte & VARUINT_BYTE;
776  if ((byte & VARUINT_HAS_NEXT) == 0)
777  {
778  return result;
779  }
780 
781  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
782  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
783  if ((byte & VARUINT_HAS_NEXT) == 0)
784  {
785  return result;
786  }
787 
788  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
789  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
790  if ((byte & VARUINT_HAS_NEXT) == 0)
791  {
792  return result;
793  }
794 
795  byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
796  result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
797  if ((byte & VARUINT_HAS_NEXT) == 0)
798  {
799  return result;
800  }
801 
802  result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
803  if (result > VARSIZE_MAX_VALUE)
804  {
805  throw CppRuntimeException("BitStreamReader: Read value '")
806  << result << "' is out of range for varsize type!";
807  }
808 
809  return result;
810 }
811 
813 {
814  const uint16_t halfPrecisionFloatValue = static_cast<uint16_t>(readBitsImpl(m_context, 16));
815 
816  return convertUInt16ToFloat(halfPrecisionFloatValue);
817 }
818 
820 {
821  const uint32_t singlePrecisionFloatValue = static_cast<uint32_t>(readBitsImpl(m_context, 32));
822 
823  return convertUInt32ToFloat(singlePrecisionFloatValue);
824 }
825 
827 {
828 #ifdef ZSERIO_RUNTIME_64BIT
829  const uint64_t doublePrecisionFloatValue = static_cast<uint64_t>(readBitsImpl(m_context, 64));
830 #else
831  const uint64_t doublePrecisionFloatValue = readBits64Impl(m_context, 64);
832 #endif
833 
834  return convertUInt64ToDouble(doublePrecisionFloatValue);
835 }
836 
838 {
839  return readBitsImpl(m_context, 1) != 0;
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)readBits(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)readBits64(skip);
865  }
866 }
867 
868 uint8_t BitStreamReader::readByte()
869 {
870  return static_cast<uint8_t>(readBitsImpl(m_context, 8));
871 }
872 
873 } // 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: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)