Zserio C++ runtime library  1.0.1
Built for Zserio 2.14.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 <cstring>
7 
8 #include "zserio/BitBuffer.h"
9 #include "zserio/RebindAlloc.h"
10 #include "zserio/Span.h"
11 #include "zserio/String.h"
12 #include "zserio/Types.h"
13 #include "zserio/Vector.h"
14 
15 namespace zserio
16 {
17 
22 {
23 public:
25  using BitPosType = size_t;
26 
31  {
38  explicit ReaderContext(Span<const uint8_t> readBuffer, size_t readBufferBitSize);
39 
43  ~ReaderContext() = default;
44 
49  ReaderContext(const ReaderContext&) = delete;
51 
52  ReaderContext(const ReaderContext&&) = delete;
61  uintptr_t cache;
62  uint8_t cacheNumBits;
65  };
66 
73  explicit BitStreamReader(const uint8_t* buffer, size_t bufferByteSize);
74 
80  explicit BitStreamReader(Span<const uint8_t> buffer);
81 
88  explicit BitStreamReader(Span<const uint8_t> buffer, size_t bufferBitSize);
89 
96  explicit BitStreamReader(const uint8_t* buffer, size_t bufferBitSize, BitsTag);
97 
103  template <typename ALLOC>
104  explicit BitStreamReader(const BasicBitBuffer<ALLOC>& bitBuffer) :
105  BitStreamReader(bitBuffer.getData(), bitBuffer.getBitSize())
106  {}
107 
111  ~BitStreamReader() = default;
112 
120  uint32_t readBits(uint8_t numBits = 32);
121 
129  uint64_t readBits64(uint8_t numBits = 64);
130 
138  int32_t readSignedBits(uint8_t numBits = 32);
139 
147  int64_t readSignedBits64(uint8_t numBits = 64);
148 
154  int64_t readVarInt64();
155 
161  int32_t readVarInt32();
162 
168  int16_t readVarInt16();
169 
175  uint64_t readVarUInt64();
176 
182  uint32_t readVarUInt32();
183 
189  uint16_t readVarUInt16();
190 
196  int64_t readVarInt();
197 
203  uint64_t readVarUInt();
204 
210  uint32_t readVarSize();
211 
217  float readFloat16();
218 
224  float readFloat32();
225 
231  double readFloat64();
232 
240  template <typename ALLOC = std::allocator<uint8_t>>
241  vector<uint8_t, ALLOC> readBytes(const ALLOC& alloc = ALLOC())
242  {
243  const size_t len = static_cast<size_t>(readVarSize());
244  const BitPosType beginBitPosition = getBitPosition();
245  if ((beginBitPosition & 0x07U) != 0)
246  {
247  // we are not aligned to byte
248  vector<uint8_t, ALLOC> value{alloc};
249  value.reserve(len);
250  for (size_t i = 0; i < len; ++i)
251  value.push_back(readByte());
252  return value;
253  }
254  else
255  {
256  // we are aligned to byte
257  setBitPosition(beginBitPosition + len * 8);
258  Span<const uint8_t>::iterator beginIt = m_context.buffer.begin() + beginBitPosition / 8;
259  return vector<uint8_t, ALLOC>(beginIt, beginIt + len, alloc);
260  }
261  }
262 
270  template <typename ALLOC = std::allocator<char>>
271  string<ALLOC> readString(const ALLOC& alloc = ALLOC())
272  {
273  const size_t len = static_cast<size_t>(readVarSize());
274  const BitPosType beginBitPosition = getBitPosition();
275  if ((beginBitPosition & 0x07U) != 0)
276  {
277  // we are not aligned to byte
278  string<ALLOC> value{alloc};
279  value.reserve(len);
280  for (size_t i = 0; i < len; ++i)
281  value.push_back(static_cast<char>(readByte()));
282  return value;
283  }
284  else
285  {
286  // we are aligned to byte
287  setBitPosition(beginBitPosition + len * 8);
288  Span<const uint8_t>::iterator beginIt = m_context.buffer.begin() + beginBitPosition / 8;
289  return string<ALLOC>(beginIt, beginIt + len, alloc);
290  }
291  }
292 
298  bool readBool();
299 
307  template <typename ALLOC = std::allocator<uint8_t>>
309  {
310  const size_t bitSize = static_cast<size_t>(readVarSize());
311  const size_t numBytesToRead = bitSize / 8;
312  const uint8_t numRestBits = static_cast<uint8_t>(bitSize - numBytesToRead * 8);
313  BasicBitBuffer<RebindAlloc<ALLOC, uint8_t>> bitBuffer(bitSize, allocator);
314  Span<uint8_t> buffer = bitBuffer.getData();
315  const BitPosType beginBitPosition = getBitPosition();
316  const Span<uint8_t>::iterator itEnd = buffer.begin() + numBytesToRead;
317  if ((beginBitPosition & 0x07U) != 0)
318  {
319  // we are not aligned to byte
320  for (Span<uint8_t>::iterator it = buffer.begin(); it != itEnd; ++it)
321  *it = static_cast<uint8_t>(readBits(8));
322  }
323  else
324  {
325  // we are aligned to byte
326  setBitPosition(beginBitPosition + numBytesToRead * 8);
327  Span<const uint8_t>::const_iterator sourceIt = m_context.buffer.begin() + beginBitPosition / 8;
328  std::copy(sourceIt, sourceIt + numBytesToRead, buffer.begin());
329  }
330 
331  if (numRestBits > 0)
332  *itEnd = static_cast<uint8_t>(readBits(numRestBits) << (8U - numRestBits));
333 
334  return bitBuffer;
335  }
336 
343  {
344  return m_context.bitIndex;
345  }
346 
352  void setBitPosition(BitPosType position);
353 
359  void alignTo(size_t alignment);
360 
366  size_t getBufferBitSize() const
367  {
368  return m_context.bufferBitSize;
369  }
370 
371 private:
372  uint8_t readByte();
373 
374  ReaderContext m_context;
375 };
376 
377 } // namespace zserio
378 
379 #endif // ifndef ZSERIO_BIT_STREAM_READER_H_INC
Span< const uint8_t > getData() const
Definition: BitBuffer.h:401
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)
BitStreamReader(const BasicBitBuffer< ALLOC > &bitBuffer)
BasicBitBuffer< RebindAlloc< ALLOC, uint8_t > > readBitBuffer(const ALLOC &allocator=ALLOC())
size_t getBufferBitSize() const
string< ALLOC > readString(const ALLOC &alloc=ALLOC())
vector< uint8_t, ALLOC > readBytes(const ALLOC &alloc=ALLOC())
int32_t readSignedBits(uint8_t numBits=32)
int64_t readSignedBits64(uint8_t numBits=64)
BitPosType getBitPosition() const
constexpr iterator begin() const noexcept
Definition: Span.h:200
uint8_t numBits(uint64_t numValues)
std::basic_string< char, std::char_traits< char >, RebindAlloc< ALLOC, char > > string
Definition: String.h:17
std::vector< T, RebindAlloc< ALLOC, T > > vector
Definition: Vector.h:17
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