Zserio C++17 runtime library  1.1.0
Built for Zserio 2.18.1
BitStreamReader.h
Go to the documentation of this file.
1 #ifndef ZSERIO_BIT_STREAM_READER_H_INC
2 #define ZSERIO_BIT_STREAM_READER_H_INC
3 
4 #include <algorithm>
5 #include <cstddef>
6 #include <type_traits>
7 
8 #include "zserio/BitBuffer.h"
9 #include "zserio/Bytes.h"
10 #include "zserio/RebindAlloc.h"
11 #include "zserio/String.h"
12 #include "zserio/Types.h"
13 
14 namespace zserio
15 {
16 
21 {
22 public:
23  static constexpr size_t MAX_INITIAL_ARRAY_ALLOCATION = 128 * 1024;
24 
30  {}
36  explicit ArrayPreallocation(size_t alloc) :
37  allocation(alloc)
38  {}
42  operator size_t() const
43  {
44  return allocation;
45  }
46 
47 private:
48  size_t allocation;
49 };
50 
55 {
56 public:
58  using BitPosType = size_t;
59 
64  {
71  explicit ReaderContext(
72  Span<const uint8_t> readBuffer, size_t readBufferBitSize, size_t maxArrayPrealloc);
73 
77  ~ReaderContext() = default;
78 
83  ReaderContext(const ReaderContext&) = delete;
85 
86  ReaderContext(const ReaderContext&&) = delete;
95  uintptr_t cache;
96  uint8_t cacheNumBits;
97  const size_t maxArrayPreallocation;
100  };
101 
109  explicit BitStreamReader(
110  const uint8_t* buffer, size_t bufferByteSize, ArrayPreallocation maxArrayPrealloc = {});
111 
118  explicit BitStreamReader(Span<const uint8_t> buffer, ArrayPreallocation maxArrayPrealloc = {});
119 
127  explicit BitStreamReader(
128  Span<const uint8_t> buffer, size_t bufferBitSize, ArrayPreallocation maxArrayPrealloc = {});
129 
137  explicit BitStreamReader(
138  const uint8_t* buffer, size_t bufferBitSize, BitsTag, ArrayPreallocation maxArrayPrealloc = {});
139 
146  template <typename ALLOC>
147  explicit BitStreamReader(const BasicBitBuffer<ALLOC>& bitBuffer, ArrayPreallocation maxArrayPrealloc = {}) :
148  BitStreamReader(bitBuffer.getData(), bitBuffer.getBitSize(), maxArrayPrealloc)
149  {}
150 
154  ~BitStreamReader() = default;
155 
163  uint32_t readUnsignedBits32(uint8_t numBits = 32);
164 
172  uint64_t readUnsignedBits64(uint8_t numBits = 64);
173 
181  int32_t readSignedBits32(uint8_t numBits = 32);
182 
190  int64_t readSignedBits64(uint8_t numBits = 64);
191 
197  Bool readBool();
198 
205 
212 
219 
225  VarInt readVarInt();
226 
233 
240 
247 
254 
261 
268 
275 
282 
290  template <typename ALLOC = std::allocator<uint8_t>>
291  BasicBytes<ALLOC> readBytes(const ALLOC& alloc = ALLOC())
292  {
293  const size_t len = static_cast<size_t>(readVarSize());
294  const BitPosType beginBitPosition = getBitPosition();
295  if (beginBitPosition + 8ULL * len > getBufferBitSize())
296  {
297  throw CppRuntimeException("BitStreamReader: Byte array size exceeds available buffer!");
298  }
299  if ((beginBitPosition & 0x07U) != 0)
300  {
301  // we are not aligned to byte
302  Vector<uint8_t, ALLOC> value{alloc};
303  value.reserve(len);
304  for (size_t i = 0; i < len; ++i)
305  {
306  value.push_back(readByte());
307  }
308  return value;
309  }
310  else
311  {
312  // we are aligned to byte
313  setBitPosition(beginBitPosition + len * 8);
314  Span<const uint8_t>::iterator beginIt = m_context.buffer.begin() + beginBitPosition / 8;
315  return BasicBytes<ALLOC>(beginIt, beginIt + len, alloc);
316  }
317  }
318 
326  template <typename ALLOC = std::allocator<char>>
327  BasicString<ALLOC> readString(const ALLOC& alloc = ALLOC())
328  {
329  const size_t len = static_cast<size_t>(readVarSize());
330  const BitPosType beginBitPosition = getBitPosition();
331  if (beginBitPosition + 8ULL * len > getBufferBitSize())
332  {
333  throw CppRuntimeException("BitStreamReader: Byte array size exceeds available buffer!");
334  }
335  if ((beginBitPosition & 0x07U) != 0)
336  {
337  // we are not aligned to byte
338  BasicString<ALLOC> value{alloc};
339  value.reserve(len);
340  for (size_t i = 0; i < len; ++i)
341  {
342  const char readCharacter = std::char_traits<char>::to_char_type(
343  static_cast<std::char_traits<char>::int_type>(readByte()));
344  value.push_back(readCharacter);
345  }
346  return value;
347  }
348  else
349  {
350  // we are aligned to byte
351  setBitPosition(beginBitPosition + len * 8);
352  Span<const uint8_t>::iterator beginIt = m_context.buffer.begin() + beginBitPosition / 8;
353  return BasicString<ALLOC>(beginIt, beginIt + len, alloc);
354  }
355  }
356 
364  template <typename ALLOC = std::allocator<uint8_t>>
366  {
367  const size_t bitSize = static_cast<size_t>(readVarSize());
368  const BitPosType beginBitPosition = getBitPosition();
369  if (beginBitPosition + static_cast<uint64_t>(bitSize) > getBufferBitSize())
370  {
371  throw CppRuntimeException("BitStreamReader: Byte array size exceeds available buffer!");
372  }
373  const size_t numBytesToRead = bitSize / 8;
374  const uint8_t numRestBits = static_cast<uint8_t>(bitSize - numBytesToRead * 8);
375  BasicBitBuffer<RebindAlloc<ALLOC, uint8_t>> bitBuffer(bitSize, allocator);
376  Span<uint8_t> buffer = bitBuffer.getData();
377  const Span<uint8_t>::iterator itEnd = buffer.begin() + numBytesToRead;
378  if ((beginBitPosition & 0x07U) != 0)
379  {
380  // we are not aligned to byte
381  for (Span<uint8_t>::iterator it = buffer.begin(); it != itEnd; ++it)
382  {
383  *it = static_cast<uint8_t>(readUnsignedBits32(8));
384  }
385  }
386  else
387  {
388  // we are aligned to byte
389  setBitPosition(beginBitPosition + numBytesToRead * 8);
390  Span<const uint8_t>::const_iterator sourceIt = m_context.buffer.begin() + beginBitPosition / 8;
391  (void)std::copy(sourceIt, sourceIt + numBytesToRead, buffer.begin());
392  }
393 
394  if (numRestBits > 0)
395  {
396  *itEnd = static_cast<uint8_t>(readUnsignedBits32(numRestBits) << (8U - numRestBits));
397  }
398 
399  return bitBuffer;
400  }
401 
408  {
409  return m_context.bitIndex;
410  }
411 
417  void setBitPosition(BitPosType position);
418 
424  void alignTo(size_t alignment);
425 
431  size_t getBufferBitSize() const
432  {
433  return m_context.bufferBitSize;
434  }
435 
442  {
443  return m_context.maxArrayPreallocation;
444  }
445 
446 private:
447  uint8_t readByte();
448 
449  ReaderContext m_context;
450 };
451 
452 namespace detail
453 {
454 
455 inline void read(BitStreamReader& reader, Bool& value)
456 {
457  value = reader.readBool();
458 }
459 
460 template <BitSize BIT_SIZE, bool IS_SIGNED>
461 void read(BitStreamReader& reader, FixedIntWrapper<BIT_SIZE, IS_SIGNED>& value)
462 {
463  using ValueType = typename FixedIntWrapper<BIT_SIZE, IS_SIGNED>::ValueType;
464  // TODO[Mi-L@]: implement on the reader to get rid of the numBits check
465  if constexpr (sizeof(ValueType) <= 4)
466  {
467  if constexpr (std::is_signed_v<ValueType>)
468  {
469  value = static_cast<ValueType>(reader.readSignedBits32(BIT_SIZE));
470  }
471  else
472  {
473  value = static_cast<ValueType>(reader.readUnsignedBits32(BIT_SIZE));
474  }
475  }
476  else
477  {
478  if constexpr (std::is_signed_v<ValueType>)
479  {
480  value = static_cast<ValueType>(reader.readSignedBits64(BIT_SIZE));
481  }
482  else
483  {
484  value = static_cast<ValueType>(reader.readUnsignedBits64(BIT_SIZE));
485  }
486  }
487 }
488 
489 template <typename T>
490 void read(BitStreamReader& reader, DynIntWrapper<T>& value, uint8_t numBits)
491 {
492  if constexpr (sizeof(T) <= 4)
493  {
494  if constexpr (std::is_signed_v<T>)
495  {
496  value = static_cast<T>(reader.readSignedBits32(numBits));
497  }
498  else
499  {
500  value = static_cast<T>(reader.readUnsignedBits32(numBits));
501  }
502  }
503  else
504  {
505  if constexpr (std::is_signed_v<T>)
506  {
507  value = static_cast<T>(reader.readSignedBits64(numBits));
508  }
509  else
510  {
511  value = static_cast<T>(reader.readUnsignedBits64(numBits));
512  }
513  }
514 }
515 
516 inline void read(BitStreamReader& reader, VarInt16& value)
517 {
518  value = reader.readVarInt16();
519 }
520 
521 inline void read(BitStreamReader& reader, VarInt32& value)
522 {
523  value = reader.readVarInt32();
524 }
525 
526 inline void read(BitStreamReader& reader, VarInt64& value)
527 {
528  value = reader.readVarInt64();
529 }
530 
531 inline void read(BitStreamReader& reader, VarInt& value)
532 {
533  value = reader.readVarInt();
534 }
535 
536 inline void read(BitStreamReader& reader, VarUInt16& value)
537 {
538  value = reader.readVarUInt16();
539 }
540 
541 inline void read(BitStreamReader& reader, VarUInt32& value)
542 {
543  value = reader.readVarUInt32();
544 }
545 
546 inline void read(BitStreamReader& reader, VarUInt64& value)
547 {
548  value = reader.readVarUInt64();
549 }
550 
551 inline void read(BitStreamReader& reader, VarUInt& value)
552 {
553  value = reader.readVarUInt();
554 }
555 
556 inline void read(BitStreamReader& reader, VarSize& value)
557 {
558  value = reader.readVarSize();
559 }
560 
561 inline void read(BitStreamReader& reader, Float16& value)
562 {
563  value = reader.readFloat16();
564 }
565 
566 inline void read(BitStreamReader& reader, Float32& value)
567 {
568  value = reader.readFloat32();
569 }
570 
571 inline void read(BitStreamReader& reader, Float64& value)
572 {
573  value = reader.readFloat64();
574 }
575 
576 template <typename ALLOC>
577 inline void read(BitStreamReader& reader, BasicBytes<ALLOC>& value)
578 {
579  value = reader.readBytes(value.get_allocator());
580 }
581 
582 template <typename ALLOC>
583 inline void read(BitStreamReader& reader, zserio::BasicString<ALLOC>& value)
584 {
585  value = reader.readString(value.get_allocator());
586 }
587 
588 template <typename ALLOC>
589 inline void read(BitStreamReader& reader, BasicBitBuffer<ALLOC>& value)
590 {
591  value = reader.readBitBuffer(value.get_allocator());
592 }
593 
594 } // namespace detail
595 
596 } // namespace zserio
597 
598 #endif // ifndef ZSERIO_BIT_STREAM_READER_H_INC
static constexpr size_t MAX_INITIAL_ARRAY_ALLOCATION
ArrayPreallocation(size_t alloc)
Span< const uint8_t > getData() const
Definition: BitBuffer.h:465
size_t getBitSize() const
Definition: BitBuffer.h:447
void setBitPosition(BitPosType position)
void alignTo(size_t alignment)
uint32_t readUnsignedBits32(uint8_t numBits=32)
size_t getMaxArrayPreallocation() const
BasicBitBuffer< RebindAlloc< ALLOC, uint8_t > > readBitBuffer(const ALLOC &allocator=ALLOC())
uint64_t readUnsignedBits64(uint8_t numBits=64)
BitStreamReader(const BasicBitBuffer< ALLOC > &bitBuffer, ArrayPreallocation maxArrayPrealloc={})
size_t getBufferBitSize() const
int64_t readSignedBits64(uint8_t numBits=64)
int32_t readSignedBits32(uint8_t numBits=32)
BitStreamReader(const uint8_t *buffer, size_t bufferByteSize, ArrayPreallocation maxArrayPrealloc={})
BasicString< ALLOC > readString(const ALLOC &alloc=ALLOC())
BasicBytes< ALLOC > readBytes(const ALLOC &alloc=ALLOC())
BitPosType getBitPosition() const
constexpr iterator begin() const noexcept
Definition: Span.h:200
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
std::basic_string< char, std::char_traits< char >, ALLOC > BasicString
Definition: String.h:17
detail::FloatWrapper< float, detail::FloatType::FLOAT16 > Float16
Definition: Types.h:892
std::vector< T, ALLOC > Vector
Definition: Vector.h:13
std::vector< uint8_t, ALLOC > BasicBytes
Definition: Bytes.h:20
detail::FloatWrapper< float, detail::FloatType::FLOAT32 > Float32
Definition: Types.h:893
detail::VarIntWrapper< int32_t, detail::VarIntType::VAR32 > VarInt32
Definition: Types.h:881
detail::VarIntWrapper< uint16_t, detail::VarIntType::VAR16 > VarUInt16
Definition: Types.h:885
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
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)
ReaderContext & operator=(const ReaderContext &&)=delete
ReaderContext(const ReaderContext &&)=delete
ReaderContext & operator=(const ReaderContext &)=delete
ReaderContext(const ReaderContext &)=delete