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