Zserio C++17 runtime library  1.1.0
Built for Zserio 2.18.1
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 
32  };
33 
35  using BitPosType = size_t;
36 
43  explicit BitStreamWriter(uint8_t* buffer, size_t bufferBitSize, BitsTag);
44 
51  explicit BitStreamWriter(uint8_t* buffer, size_t bufferByteSize);
52 
58  explicit BitStreamWriter(Span<uint8_t> buffer);
59 
66  explicit BitStreamWriter(Span<uint8_t> buffer, size_t bufferBitSize);
67 
73  template <typename ALLOC>
74  explicit BitStreamWriter(BasicBitBuffer<ALLOC>& bitBuffer) :
75  BitStreamWriter(bitBuffer.getData(), bitBuffer.getBitSize())
76  {}
77 
81  ~BitStreamWriter() = default;
82 
87  BitStreamWriter(const BitStreamWriter&) = delete;
89 
90  BitStreamWriter(const BitStreamWriter&&) = delete;
102  void writeUnsignedBits32(uint32_t data, uint8_t numBits = 32);
103 
110  void writeUnsignedBits64(uint64_t data, uint8_t numBits = 64);
111 
118  void writeSignedBits32(int32_t data, uint8_t numBits = 32);
119 
126  void writeSignedBits64(int64_t data, uint8_t numBits = 64);
127 
133  void writeBool(Bool data);
134 
140  void writeVarInt16(VarInt16 data);
141 
147  void writeVarInt32(VarInt32 data);
148 
154  void writeVarInt64(VarInt64 data);
155 
161  void writeVarInt(VarInt data);
162 
168  void writeVarUInt16(VarUInt16 data);
169 
175  void writeVarUInt32(VarUInt32 data);
176 
182  void writeVarUInt64(VarUInt64 data);
183 
189  void writeVarUInt(VarUInt data);
190 
196  void writeVarSize(VarSize data);
197 
203  void writeFloat16(Float16 data);
204 
210  void writeFloat32(Float32 data);
211 
217  void writeFloat64(Float64 data);
218 
224  void writeBytes(BytesView data);
225 
231  void writeString(std::string_view data);
232 
238  template <typename ALLOC>
239  void writeBitBuffer(const BasicBitBuffer<ALLOC>& bitBuffer)
240  {
241  const VarSize bitSize = fromCheckedValue<VarSize>(convertSizeToUInt32(bitBuffer.getBitSize()));
242  writeVarSize(bitSize);
243 
244  Span<const uint8_t> buffer = bitBuffer.getData();
245  size_t numBytesToWrite = bitSize / 8;
246  const uint8_t numRestBits = static_cast<uint8_t>(bitSize - numBytesToWrite * 8);
247  const BitPosType beginBitPosition = getBitPosition();
248  const Span<const uint8_t>::iterator itEnd = buffer.begin() + numBytesToWrite;
249  if ((beginBitPosition & 0x07U) != 0)
250  {
251  // we are not aligned to byte
252  for (Span<const uint8_t>::iterator it = buffer.begin(); it != itEnd; ++it)
253  {
254  writeUnsignedBits32Impl(*it, 8);
255  }
256  }
257  else
258  {
259  // we are aligned to byte
260  setBitPosition(beginBitPosition + numBytesToWrite * 8);
261  if (hasWriteBuffer())
262  {
263  (void)std::copy(buffer.begin(), buffer.begin() + numBytesToWrite,
264  m_buffer.data() + beginBitPosition / 8);
265  }
266  }
267 
268  if (numRestBits > 0)
269  {
270  writeUnsignedBits32Impl(static_cast<uint32_t>(*itEnd) >> (8U - numRestBits), numRestBits);
271  }
272  }
273 
280  {
281  return m_bitIndex;
282  }
283 
289  void setBitPosition(BitPosType position);
290 
296  void alignTo(size_t alignment);
297 
303  bool hasWriteBuffer() const
304  {
305  return m_buffer.data() != nullptr;
306  }
307 
313  const uint8_t* getWriteBuffer() const;
314 
321 
327  size_t getBufferBitSize() const
328  {
329  return m_bufferBitSize;
330  }
331 
332 private:
333  void writeUnsignedBits32Impl(uint32_t data, uint8_t numBits);
334  void writeUnsignedBits64Impl(uint64_t data, uint8_t numBits);
335  void writeSignedVarNum(int64_t value, size_t maxVarBytes, size_t numVarBytes);
336  void writeUnsignedVarNum(uint64_t value, size_t maxVarBytes, size_t numVarBytes);
337  void writeVarNum(uint64_t value, bool hasSign, bool isNegative, size_t maxVarBytes, size_t numVarBytes);
338 
339  void checkCapacity(size_t bitSize) const;
340  void throwInsufficientCapacityException() const;
341 
342  Span<uint8_t> m_buffer;
343  size_t m_bitIndex;
344  size_t m_bufferBitSize;
345 };
346 
347 namespace detail
348 {
349 
350 inline void write(BitStreamWriter& writer, Bool value)
351 {
352  writer.writeBool(value);
353 }
354 
355 template <BitSize BIT_SIZE, bool IS_SIGNED>
356 void write(BitStreamWriter& writer, FixedIntWrapper<BIT_SIZE, IS_SIGNED> value)
357 {
358  using ValueType = typename FixedIntWrapper<BIT_SIZE, IS_SIGNED>::ValueType;
359 
360  static_assert(BIT_SIZE != 0, "Variable dynamic bit fields not allowed here!");
361  if constexpr (sizeof(ValueType) <= 4)
362  {
363  if constexpr (std::is_signed_v<ValueType>)
364  {
365  writer.writeSignedBits32(value, BIT_SIZE);
366  }
367  else
368  {
369  writer.writeUnsignedBits32(value, BIT_SIZE);
370  }
371  }
372  else
373  {
374  if constexpr (std::is_signed_v<ValueType>)
375  {
376  writer.writeSignedBits64(value, BIT_SIZE);
377  }
378  else
379  {
380  writer.writeUnsignedBits64(value, BIT_SIZE);
381  }
382  }
383 }
384 
385 template <typename T>
386 void write(BitStreamWriter& writer, DynIntWrapper<T> value, uint8_t numBits)
387 {
388  if constexpr (sizeof(T) <= 4)
389  {
390  if constexpr (std::is_signed_v<T>)
391  {
392  writer.writeSignedBits32(value, numBits);
393  }
394  else
395  {
396  writer.writeUnsignedBits32(value, numBits);
397  }
398  }
399  else
400  {
401  if constexpr (std::is_signed_v<T>)
402  {
403  writer.writeSignedBits64(value, numBits);
404  }
405  else
406  {
407  writer.writeUnsignedBits64(value, numBits);
408  }
409  }
410 }
411 
412 inline void write(BitStreamWriter& writer, VarInt16 value)
413 {
414  writer.writeVarInt16(value);
415 }
416 
417 inline void write(BitStreamWriter& writer, VarInt32 value)
418 {
419  writer.writeVarInt32(value);
420 }
421 
422 inline void write(BitStreamWriter& writer, VarInt64 value)
423 {
424  writer.writeVarInt64(value);
425 }
426 
427 inline void write(BitStreamWriter& writer, VarInt value)
428 {
429  writer.writeVarInt(value);
430 }
431 
432 inline void write(BitStreamWriter& writer, VarUInt16 value)
433 {
434  writer.writeVarUInt16(value);
435 }
436 
437 inline void write(BitStreamWriter& writer, VarUInt32 value)
438 {
439  writer.writeVarUInt32(value);
440 }
441 
442 inline void write(BitStreamWriter& writer, VarUInt64 value)
443 {
444  writer.writeVarUInt64(value);
445 }
446 
447 inline void write(BitStreamWriter& writer, VarUInt value)
448 {
449  writer.writeVarUInt(value);
450 }
451 
452 inline void write(BitStreamWriter& writer, VarSize value)
453 {
454  writer.writeVarSize(value);
455 }
456 
457 inline void write(BitStreamWriter& writer, Float16 value)
458 {
459  writer.writeFloat16(value);
460 }
461 
462 inline void write(BitStreamWriter& writer, Float32 value)
463 {
464  writer.writeFloat32(value);
465 }
466 
467 inline void write(BitStreamWriter& writer, Float64 value)
468 {
469  writer.writeFloat64(value);
470 }
471 
472 inline void write(BitStreamWriter& writer, BytesView value)
473 {
474  writer.writeBytes(value);
475 }
476 
477 inline void write(BitStreamWriter& writer, std::string_view value)
478 {
479  writer.writeString(value);
480 }
481 
482 template <typename ALLOC>
483 inline void write(BitStreamWriter& writer, const BasicBitBufferView<ALLOC>& value)
484 {
485  writer.writeBitBuffer(value.get());
486 }
487 
488 } // namespace detail
489 
490 } // namespace zserio
491 
492 #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