Zserio C++17 runtime library  0.5.0
Built for Zserio 2.17.0
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:
24  using BitPosType = size_t;
25 
30  {
37  explicit ReaderContext(Span<const uint8_t> readBuffer, size_t readBufferBitSize);
38 
42  ~ReaderContext() = default;
43 
48  ReaderContext(const ReaderContext&) = delete;
50 
51  ReaderContext(const ReaderContext&&) = delete;
60  uintptr_t cache;
61  uint8_t cacheNumBits;
64  };
65 
72  explicit BitStreamReader(const uint8_t* buffer, size_t bufferByteSize);
73 
79  explicit BitStreamReader(Span<const uint8_t> buffer);
80 
87  explicit BitStreamReader(Span<const uint8_t> buffer, size_t bufferBitSize);
88 
95  explicit BitStreamReader(const uint8_t* buffer, size_t bufferBitSize, BitsTag);
96 
102  template <typename ALLOC>
103  explicit BitStreamReader(const BasicBitBuffer<ALLOC>& bitBuffer) :
104  BitStreamReader(bitBuffer.getData(), bitBuffer.getBitSize())
105  {}
106 
110  ~BitStreamReader() = default;
111 
119  uint32_t readUnsignedBits32(uint8_t numBits = 32);
120 
128  uint64_t readUnsignedBits64(uint8_t numBits = 64);
129 
137  int32_t readSignedBits32(uint8_t numBits = 32);
138 
146  int64_t readSignedBits64(uint8_t numBits = 64);
147 
153  Bool readBool();
154 
161 
168 
175 
181  VarInt readVarInt();
182 
189 
196 
203 
210 
217 
224 
231 
238 
246  template <typename ALLOC = std::allocator<uint8_t>>
247  BasicBytes<ALLOC> readBytes(const ALLOC& alloc = ALLOC())
248  {
249  const size_t len = static_cast<size_t>(readVarSize());
250  const BitPosType beginBitPosition = getBitPosition();
251  if ((beginBitPosition & 0x07U) != 0)
252  {
253  // we are not aligned to byte
254  Vector<uint8_t, ALLOC> value{alloc};
255  value.reserve(len);
256  for (size_t i = 0; i < len; ++i)
257  {
258  value.push_back(readByte());
259  }
260  return value;
261  }
262  else
263  {
264  // we are aligned to byte
265  setBitPosition(beginBitPosition + len * 8);
266  Span<const uint8_t>::iterator beginIt = m_context.buffer.begin() + beginBitPosition / 8;
267  return BasicBytes<ALLOC>(beginIt, beginIt + len, alloc);
268  }
269  }
270 
278  template <typename ALLOC = std::allocator<char>>
279  BasicString<ALLOC> readString(const ALLOC& alloc = ALLOC())
280  {
281  const size_t len = static_cast<size_t>(readVarSize());
282  const BitPosType beginBitPosition = getBitPosition();
283  if ((beginBitPosition & 0x07U) != 0)
284  {
285  // we are not aligned to byte
286  BasicString<ALLOC> value{alloc};
287  value.reserve(len);
288  for (size_t i = 0; i < len; ++i)
289  {
290  const char readCharacter = std::char_traits<char>::to_char_type(
291  static_cast<std::char_traits<char>::int_type>(readByte()));
292  value.push_back(readCharacter);
293  }
294  return value;
295  }
296  else
297  {
298  // we are aligned to byte
299  setBitPosition(beginBitPosition + len * 8);
300  Span<const uint8_t>::iterator beginIt = m_context.buffer.begin() + beginBitPosition / 8;
301  return BasicString<ALLOC>(beginIt, beginIt + len, alloc);
302  }
303  }
304 
312  template <typename ALLOC = std::allocator<uint8_t>>
314  {
315  const size_t bitSize = static_cast<size_t>(readVarSize());
316  const size_t numBytesToRead = bitSize / 8;
317  const uint8_t numRestBits = static_cast<uint8_t>(bitSize - numBytesToRead * 8);
318  BasicBitBuffer<RebindAlloc<ALLOC, uint8_t>> bitBuffer(bitSize, allocator);
319  Span<uint8_t> buffer = bitBuffer.getData();
320  const BitPosType beginBitPosition = getBitPosition();
321  const Span<uint8_t>::iterator itEnd = buffer.begin() + numBytesToRead;
322  if ((beginBitPosition & 0x07U) != 0)
323  {
324  // we are not aligned to byte
325  for (Span<uint8_t>::iterator it = buffer.begin(); it != itEnd; ++it)
326  {
327  *it = static_cast<uint8_t>(readUnsignedBits32(8));
328  }
329  }
330  else
331  {
332  // we are aligned to byte
333  setBitPosition(beginBitPosition + numBytesToRead * 8);
334  Span<const uint8_t>::const_iterator sourceIt = m_context.buffer.begin() + beginBitPosition / 8;
335  (void)std::copy(sourceIt, sourceIt + numBytesToRead, buffer.begin());
336  }
337 
338  if (numRestBits > 0)
339  {
340  *itEnd = static_cast<uint8_t>(readUnsignedBits32(numRestBits) << (8U - numRestBits));
341  }
342 
343  return bitBuffer;
344  }
345 
352  {
353  return m_context.bitIndex;
354  }
355 
361  void setBitPosition(BitPosType position);
362 
368  void alignTo(size_t alignment);
369 
375  size_t getBufferBitSize() const
376  {
377  return m_context.bufferBitSize;
378  }
379 
380 private:
381  uint8_t readByte();
382 
383  ReaderContext m_context;
384 };
385 
386 namespace detail
387 {
388 
389 inline void read(BitStreamReader& reader, Bool& value)
390 {
391  value = reader.readBool();
392 }
393 
394 template <BitSize BIT_SIZE, bool IS_SIGNED>
395 void read(BitStreamReader& reader, FixedIntWrapper<BIT_SIZE, IS_SIGNED>& value)
396 {
397  using ValueType = typename FixedIntWrapper<BIT_SIZE, IS_SIGNED>::ValueType;
398  // TODO[Mi-L@]: implement on the reader to get rid of the numBits check
399  if constexpr (sizeof(ValueType) <= 4)
400  {
401  if constexpr (std::is_signed_v<ValueType>)
402  {
403  value = static_cast<ValueType>(reader.readSignedBits32(BIT_SIZE));
404  }
405  else
406  {
407  value = static_cast<ValueType>(reader.readUnsignedBits32(BIT_SIZE));
408  }
409  }
410  else
411  {
412  if constexpr (std::is_signed_v<ValueType>)
413  {
414  value = static_cast<ValueType>(reader.readSignedBits64(BIT_SIZE));
415  }
416  else
417  {
418  value = static_cast<ValueType>(reader.readUnsignedBits64(BIT_SIZE));
419  }
420  }
421 }
422 
423 template <typename T>
424 void read(BitStreamReader& reader, DynIntWrapper<T>& value, uint8_t numBits)
425 {
426  if constexpr (sizeof(T) <= 4)
427  {
428  if constexpr (std::is_signed_v<T>)
429  {
430  value = static_cast<T>(reader.readSignedBits32(numBits));
431  }
432  else
433  {
434  value = static_cast<T>(reader.readUnsignedBits32(numBits));
435  }
436  }
437  else
438  {
439  if constexpr (std::is_signed_v<T>)
440  {
441  value = static_cast<T>(reader.readSignedBits64(numBits));
442  }
443  else
444  {
445  value = static_cast<T>(reader.readUnsignedBits64(numBits));
446  }
447  }
448 }
449 
450 inline void read(BitStreamReader& reader, VarInt16& value)
451 {
452  value = reader.readVarInt16();
453 }
454 
455 inline void read(BitStreamReader& reader, VarInt32& value)
456 {
457  value = reader.readVarInt32();
458 }
459 
460 inline void read(BitStreamReader& reader, VarInt64& value)
461 {
462  value = reader.readVarInt64();
463 }
464 
465 inline void read(BitStreamReader& reader, VarInt& value)
466 {
467  value = reader.readVarInt();
468 }
469 
470 inline void read(BitStreamReader& reader, VarUInt16& value)
471 {
472  value = reader.readVarUInt16();
473 }
474 
475 inline void read(BitStreamReader& reader, VarUInt32& value)
476 {
477  value = reader.readVarUInt32();
478 }
479 
480 inline void read(BitStreamReader& reader, VarUInt64& value)
481 {
482  value = reader.readVarUInt64();
483 }
484 
485 inline void read(BitStreamReader& reader, VarUInt& value)
486 {
487  value = reader.readVarUInt();
488 }
489 
490 inline void read(BitStreamReader& reader, VarSize& value)
491 {
492  value = reader.readVarSize();
493 }
494 
495 inline void read(BitStreamReader& reader, Float16& value)
496 {
497  value = reader.readFloat16();
498 }
499 
500 inline void read(BitStreamReader& reader, Float32& value)
501 {
502  value = reader.readFloat32();
503 }
504 
505 inline void read(BitStreamReader& reader, Float64& value)
506 {
507  value = reader.readFloat64();
508 }
509 
510 template <typename ALLOC>
511 inline void read(BitStreamReader& reader, BasicBytes<ALLOC>& value)
512 {
513  value = reader.readBytes(value.get_allocator());
514 }
515 
516 template <typename ALLOC>
517 inline void read(BitStreamReader& reader, zserio::BasicString<ALLOC>& value)
518 {
519  value = reader.readString(value.get_allocator());
520 }
521 
522 template <typename ALLOC>
523 inline void read(BitStreamReader& reader, BasicBitBuffer<ALLOC>& value)
524 {
525  value = reader.readBitBuffer(value.get_allocator());
526 }
527 
528 } // namespace detail
529 
530 } // namespace zserio
531 
532 #endif // ifndef ZSERIO_BIT_STREAM_READER_H_INC
Span< const uint8_t > getData() const
Definition: BitBuffer.h:465
void setBitPosition(BitPosType position)
void alignTo(size_t alignment)
BitStreamReader(const uint8_t *buffer, size_t bufferByteSize)
uint32_t readUnsignedBits32(uint8_t numBits=32)
BitStreamReader(const BasicBitBuffer< ALLOC > &bitBuffer)
BasicBitBuffer< RebindAlloc< ALLOC, uint8_t > > readBitBuffer(const ALLOC &allocator=ALLOC())
uint64_t readUnsignedBits64(uint8_t numBits=64)
size_t getBufferBitSize() const
int64_t readSignedBits64(uint8_t numBits=64)
int32_t readSignedBits32(uint8_t numBits=32)
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)
ReaderContext & operator=(const ReaderContext &&)=delete
ReaderContext(const ReaderContext &&)=delete
ReaderContext & operator=(const ReaderContext &)=delete
ReaderContext(const ReaderContext &)=delete