Zserio C++17 runtime library  0.5.0
Built for Zserio 2.17.0
BitStreamWriter.h
Go to the documentation of this file.
1 #ifndef ZSERIO_BIT_STREAM_WRITER_H_INC
2 #define ZSERIO_BIT_STREAM_WRITER_H_INC
3 
4 #include <algorithm>
5 #include <cstddef>
6 #include <string_view>
7 #include <type_traits>
8 
9 #include "zserio/BitBuffer.h"
10 #include "zserio/Bytes.h"
12 #include "zserio/SizeConvertUtil.h"
13 #include "zserio/String.h"
14 #include "zserio/Types.h"
15 
16 namespace zserio
17 {
18 
23 {
24 public:
27  {
28  public:
30  };
31 
33  using BitPosType = size_t;
34 
41  explicit BitStreamWriter(uint8_t* buffer, size_t bufferBitSize, BitsTag);
42 
49  explicit BitStreamWriter(uint8_t* buffer, size_t bufferByteSize);
50 
56  explicit BitStreamWriter(Span<uint8_t> buffer);
57 
64  explicit BitStreamWriter(Span<uint8_t> buffer, size_t bufferBitSize);
65 
71  template <typename ALLOC>
72  explicit BitStreamWriter(BasicBitBuffer<ALLOC>& bitBuffer) :
73  BitStreamWriter(bitBuffer.getData(), bitBuffer.getBitSize())
74  {}
75 
79  ~BitStreamWriter() = default;
80 
85  BitStreamWriter(const BitStreamWriter&) = delete;
87 
88  BitStreamWriter(const BitStreamWriter&&) = delete;
100  void writeUnsignedBits32(uint32_t data, uint8_t numBits = 32);
101 
108  void writeUnsignedBits64(uint64_t data, uint8_t numBits = 64);
109 
116  void writeSignedBits32(int32_t data, uint8_t numBits = 32);
117 
124  void writeSignedBits64(int64_t data, uint8_t numBits = 64);
125 
131  void writeBool(Bool data);
132 
138  void writeVarInt16(VarInt16 data);
139 
145  void writeVarInt32(VarInt32 data);
146 
152  void writeVarInt64(VarInt64 data);
153 
159  void writeVarInt(VarInt data);
160 
166  void writeVarUInt16(VarUInt16 data);
167 
173  void writeVarUInt32(VarUInt32 data);
174 
180  void writeVarUInt64(VarUInt64 data);
181 
187  void writeVarUInt(VarUInt data);
188 
194  void writeVarSize(VarSize data);
195 
201  void writeFloat16(Float16 data);
202 
208  void writeFloat32(Float32 data);
209 
215  void writeFloat64(Float64 data);
216 
222  void writeBytes(BytesView data);
223 
229  void writeString(std::string_view data);
230 
236  template <typename ALLOC>
237  void writeBitBuffer(const BasicBitBuffer<ALLOC>& bitBuffer)
238  {
239  const VarSize bitSize = fromCheckedValue<VarSize>(convertSizeToUInt32(bitBuffer.getBitSize()));
240  writeVarSize(bitSize);
241 
242  Span<const uint8_t> buffer = bitBuffer.getData();
243  size_t numBytesToWrite = bitSize / 8;
244  const uint8_t numRestBits = static_cast<uint8_t>(bitSize - numBytesToWrite * 8);
245  const BitPosType beginBitPosition = getBitPosition();
246  const Span<const uint8_t>::iterator itEnd = buffer.begin() + numBytesToWrite;
247  if ((beginBitPosition & 0x07U) != 0)
248  {
249  // we are not aligned to byte
250  for (Span<const uint8_t>::iterator it = buffer.begin(); it != itEnd; ++it)
251  {
252  writeUnsignedBits32Impl(*it, 8);
253  }
254  }
255  else
256  {
257  // we are aligned to byte
258  setBitPosition(beginBitPosition + numBytesToWrite * 8);
259  if (hasWriteBuffer())
260  {
261  (void)std::copy(buffer.begin(), buffer.begin() + numBytesToWrite,
262  m_buffer.data() + beginBitPosition / 8);
263  }
264  }
265 
266  if (numRestBits > 0)
267  {
268  writeUnsignedBits32Impl(static_cast<uint32_t>(*itEnd) >> (8U - numRestBits), numRestBits);
269  }
270  }
271 
278  {
279  return m_bitIndex;
280  }
281 
287  void setBitPosition(BitPosType position);
288 
294  void alignTo(size_t alignment);
295 
301  bool hasWriteBuffer() const
302  {
303  return m_buffer.data() != nullptr;
304  }
305 
311  const uint8_t* getWriteBuffer() const;
312 
319 
325  size_t getBufferBitSize() const
326  {
327  return m_bufferBitSize;
328  }
329 
330 private:
331  void writeUnsignedBits32Impl(uint32_t data, uint8_t numBits);
332  void writeUnsignedBits64Impl(uint64_t data, uint8_t numBits);
333  void writeSignedVarNum(int64_t value, size_t maxVarBytes, size_t numVarBytes);
334  void writeUnsignedVarNum(uint64_t value, size_t maxVarBytes, size_t numVarBytes);
335  void writeVarNum(uint64_t value, bool hasSign, bool isNegative, size_t maxVarBytes, size_t numVarBytes);
336 
337  void checkCapacity(size_t bitSize) const;
338  void throwInsufficientCapacityException() const;
339 
340  Span<uint8_t> m_buffer;
341  size_t m_bitIndex;
342  size_t m_bufferBitSize;
343 };
344 
345 namespace detail
346 {
347 
348 inline void write(BitStreamWriter& writer, Bool value)
349 {
350  writer.writeBool(value);
351 }
352 
353 template <BitSize BIT_SIZE, bool IS_SIGNED>
354 void write(BitStreamWriter& writer, FixedIntWrapper<BIT_SIZE, IS_SIGNED> value)
355 {
356  using ValueType = typename FixedIntWrapper<BIT_SIZE, IS_SIGNED>::ValueType;
357 
358  static_assert(BIT_SIZE != 0, "Variable dynamic bit fields not allowed here!");
359  if constexpr (sizeof(ValueType) <= 4)
360  {
361  if constexpr (std::is_signed_v<ValueType>)
362  {
363  writer.writeSignedBits32(value, BIT_SIZE);
364  }
365  else
366  {
367  writer.writeUnsignedBits32(value, BIT_SIZE);
368  }
369  }
370  else
371  {
372  if constexpr (std::is_signed_v<ValueType>)
373  {
374  writer.writeSignedBits64(value, BIT_SIZE);
375  }
376  else
377  {
378  writer.writeUnsignedBits64(value, BIT_SIZE);
379  }
380  }
381 }
382 
383 template <typename T>
384 void write(BitStreamWriter& writer, DynIntWrapper<T> value, uint8_t numBits)
385 {
386  if constexpr (sizeof(T) <= 4)
387  {
388  if constexpr (std::is_signed_v<T>)
389  {
390  writer.writeSignedBits32(value, numBits);
391  }
392  else
393  {
394  writer.writeUnsignedBits32(value, numBits);
395  }
396  }
397  else
398  {
399  if constexpr (std::is_signed_v<T>)
400  {
401  writer.writeSignedBits64(value, numBits);
402  }
403  else
404  {
405  writer.writeUnsignedBits64(value, numBits);
406  }
407  }
408 }
409 
410 inline void write(BitStreamWriter& writer, VarInt16 value)
411 {
412  writer.writeVarInt16(value);
413 }
414 
415 inline void write(BitStreamWriter& writer, VarInt32 value)
416 {
417  writer.writeVarInt32(value);
418 }
419 
420 inline void write(BitStreamWriter& writer, VarInt64 value)
421 {
422  writer.writeVarInt64(value);
423 }
424 
425 inline void write(BitStreamWriter& writer, VarInt value)
426 {
427  writer.writeVarInt(value);
428 }
429 
430 inline void write(BitStreamWriter& writer, VarUInt16 value)
431 {
432  writer.writeVarUInt16(value);
433 }
434 
435 inline void write(BitStreamWriter& writer, VarUInt32 value)
436 {
437  writer.writeVarUInt32(value);
438 }
439 
440 inline void write(BitStreamWriter& writer, VarUInt64 value)
441 {
442  writer.writeVarUInt64(value);
443 }
444 
445 inline void write(BitStreamWriter& writer, VarUInt value)
446 {
447  writer.writeVarUInt(value);
448 }
449 
450 inline void write(BitStreamWriter& writer, VarSize value)
451 {
452  writer.writeVarSize(value);
453 }
454 
455 inline void write(BitStreamWriter& writer, Float16 value)
456 {
457  writer.writeFloat16(value);
458 }
459 
460 inline void write(BitStreamWriter& writer, Float32 value)
461 {
462  writer.writeFloat32(value);
463 }
464 
465 inline void write(BitStreamWriter& writer, Float64 value)
466 {
467  writer.writeFloat64(value);
468 }
469 
470 inline void write(BitStreamWriter& writer, BytesView value)
471 {
472  writer.writeBytes(value);
473 }
474 
475 inline void write(BitStreamWriter& writer, std::string_view value)
476 {
477  writer.writeString(value);
478 }
479 
480 template <typename ALLOC>
481 inline void write(BitStreamWriter& writer, const BasicBitBufferView<ALLOC>& value)
482 {
483  writer.writeBitBuffer(value.get());
484 }
485 
486 } // namespace detail
487 
488 } // namespace zserio
489 
490 #endif // ifndef ZSERIO_BIT_STREAM_WRITER_H_INC
Span< const uint8_t > getData() const
Definition: BitBuffer.h:465
size_t getBitSize() const
Definition: BitBuffer.h:447
void writeVarUInt16(VarUInt16 data)
Span< const uint8_t > getBuffer() const
void writeVarInt32(VarInt32 data)
void writeFloat64(Float64 data)
void writeVarUInt64(VarUInt64 data)
size_t getBufferBitSize() const
BitPosType getBitPosition() const
void writeVarInt16(VarInt16 data)
const uint8_t * getWriteBuffer() const
void writeSignedBits64(int64_t data, uint8_t numBits=64)
BitStreamWriter(const BitStreamWriter &&)=delete
void writeVarInt64(VarInt64 data)
BitStreamWriter(const BitStreamWriter &)=delete
BitStreamWriter & operator=(const BitStreamWriter &)=delete
void writeUnsignedBits32(uint32_t data, uint8_t numBits=32)
void writeFloat32(Float32 data)
void writeSignedBits32(int32_t data, uint8_t numBits=32)
void writeVarUInt(VarUInt data)
void writeBytes(BytesView data)
void writeUnsignedBits64(uint64_t data, uint8_t numBits=64)
void writeBitBuffer(const BasicBitBuffer< ALLOC > &bitBuffer)
BitStreamWriter(BasicBitBuffer< ALLOC > &bitBuffer)
BitStreamWriter(uint8_t *buffer, size_t bufferBitSize, BitsTag)
BitStreamWriter & operator=(BitStreamWriter &&)=delete
void writeString(std::string_view data)
void writeFloat16(Float16 data)
void writeVarUInt32(VarUInt32 data)
void writeVarSize(VarSize data)
void writeVarInt(VarInt data)
void setBitPosition(BitPosType position)
void alignTo(size_t alignment)
CppRuntimeException(const char *message="")
constexpr pointer data() const noexcept
Definition: Span.h:271
constexpr iterator begin() const noexcept
Definition: Span.h:200
uint8_t numBits(uint64_t numValues)
Span< const uint8_t > BytesView
Definition: Bytes.h:30
detail::BoolWrapper Bool
Definition: Types.h:732
detail::VarIntWrapper< uint64_t, detail::VarIntType::VAR > VarUInt
Definition: Types.h:888
detail::FloatWrapper< float, detail::FloatType::FLOAT16 > Float16
Definition: Types.h:892
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
uint32_t convertSizeToUInt32(size_t value)
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