Zserio C++17 runtime library 1.3.0
Built for Zserio 2.20.0
Loading...
Searching...
No Matches
BitStreamWriter.cpp
Go to the documentation of this file.
2#include "zserio/FloatUtil.h"
3
4namespace zserio
5{
6
7static const std::array<uint32_t, 33> MAX_U32_VALUES = {
8 0x00U,
9 0x0001U,
10 0x0003U,
11 0x0007U,
12 0x000fU,
13 0x001fU,
14 0x003fU,
15 0x007fU,
16 0x00ffU,
17 0x01ffU,
18 0x03ffU,
19 0x07ffU,
20 0x0fffU,
21 0x1fffU,
22 0x3fffU,
23 0x7fffU,
24 0xffffU,
25 0x0001ffffU,
26 0x0003ffffU,
27 0x0007ffffU,
28 0x000fffffU,
29 0x001fffffU,
30 0x003fffffU,
31 0x007fffffU,
32 0x00ffffffU,
33 0x01ffffffU,
34 0x03ffffffU,
35 0x07ffffffU,
36 0x0fffffffU,
37 0x1fffffffU,
38 0x3fffffffU,
39 0x7fffffffU,
40 0xffffffffU,
41};
42
43static const std::array<int32_t, 33> MIN_I32_VALUES = {
44 0,
45 -0x0001,
46 -0x0002,
47 -0x0004,
48 -0x0008,
49 -0x0010,
50 -0x0020,
51 -0x0040,
52 -0x0080,
53 -0x0100,
54 -0x0200,
55 -0x0400,
56 -0x0800,
57 -0x1000,
58 -0x2000,
59 -0x4000,
60 -0x8000,
61 -0x00010000,
62 -0x00020000,
63 -0x00040000,
64 -0x00080000,
65 -0x00100000,
66 -0x00200000,
67 -0x00400000,
68 -0x00800000,
69 -0x01000000,
70 -0x02000000,
71 -0x04000000,
72 -0x08000000,
73 -0x10000000,
74 -0x20000000,
75 -0x40000000,
76 INT32_MIN,
77};
78
79static const std::array<int32_t, 33> MAX_I32_VALUES = {
80 0x00,
81 0x0000,
82 0x0001,
83 0x0003,
84 0x0007,
85 0x000f,
86 0x001f,
87 0x003f,
88 0x007f,
89 0x00ff,
90 0x01ff,
91 0x03ff,
92 0x07ff,
93 0x0fff,
94 0x1fff,
95 0x3fff,
96 0x7fff,
97 0x0000ffff,
98 0x0001ffff,
99 0x0003ffff,
100 0x0007ffff,
101 0x000fffff,
102 0x001fffff,
103 0x003fffff,
104 0x007fffff,
105 0x00ffffff,
106 0x01ffffff,
107 0x03ffffff,
108 0x07ffffff,
109 0x0fffffff,
110 0x1fffffff,
111 0x3fffffff,
112 0x7fffffff,
113};
114
115static const std::array<uint64_t, 65> MAX_U64_VALUES = {
116 0x00ULL,
117 0x0001ULL,
118 0x0003ULL,
119 0x0007ULL,
120 0x000fULL,
121 0x001fULL,
122 0x003fULL,
123 0x007fULL,
124 0x00ffULL,
125 0x01ffULL,
126 0x03ffULL,
127 0x07ffULL,
128 0x0fffULL,
129 0x1fffULL,
130 0x3fffULL,
131 0x7fffULL,
132 0xffffULL,
133 0x0001ffffULL,
134 0x0003ffffULL,
135 0x0007ffffULL,
136 0x000fffffULL,
137 0x001fffffULL,
138 0x003fffffULL,
139 0x007fffffULL,
140 0x00ffffffULL,
141 0x01ffffffULL,
142 0x03ffffffULL,
143 0x07ffffffULL,
144 0x0fffffffULL,
145 0x1fffffffULL,
146 0x3fffffffULL,
147 0x7fffffffULL,
148 0xffffffffULL,
149 0x0001ffffffffULL,
150 0x0003ffffffffULL,
151 0x0007ffffffffULL,
152 0x000fffffffffULL,
153 0x001fffffffffULL,
154 0x003fffffffffULL,
155 0x007fffffffffULL,
156 0x00ffffffffffULL,
157 0x01ffffffffffULL,
158 0x03ffffffffffULL,
159 0x07ffffffffffULL,
160 0x0fffffffffffULL,
161 0x1fffffffffffULL,
162 0x3fffffffffffULL,
163 0x7fffffffffffULL,
164 0xffffffffffffULL,
165 0x0001ffffffffffffULL,
166 0x0003ffffffffffffULL,
167 0x0007ffffffffffffULL,
168 0x000fffffffffffffULL,
169 0x001fffffffffffffULL,
170 0x003fffffffffffffULL,
171 0x007fffffffffffffULL,
172 0x00ffffffffffffffULL,
173 0x01ffffffffffffffULL,
174 0x03ffffffffffffffULL,
175 0x07ffffffffffffffULL,
176 0x0fffffffffffffffULL,
177 0x1fffffffffffffffULL,
178 0x3fffffffffffffffULL,
179 0x7fffffffffffffffULL,
180 0xffffffffffffffffULL,
181};
182
183static const std::array<int64_t, 65> MIN_I64_VALUES = {
184 0LL,
185 -0x0001LL,
186 -0x0002LL,
187 -0x0004LL,
188 -0x0008LL,
189 -0x0010LL,
190 -0x0020LL,
191 -0x0040LL,
192 -0x0080LL,
193 -0x0100LL,
194 -0x0200LL,
195 -0x0400LL,
196 -0x0800LL,
197 -0x1000LL,
198 -0x2000LL,
199 -0x4000LL,
200 -0x8000LL,
201 -0x00010000LL,
202 -0x00020000LL,
203 -0x00040000LL,
204 -0x00080000LL,
205 -0x00100000LL,
206 -0x00200000LL,
207 -0x00400000LL,
208 -0x00800000LL,
209 -0x01000000LL,
210 -0x02000000LL,
211 -0x04000000LL,
212 -0x08000000LL,
213 -0x10000000LL,
214 -0x20000000LL,
215 -0x40000000LL,
216 -0x80000000LL,
217 -0x000100000000LL,
218 -0x000200000000LL,
219 -0x000400000000LL,
220 -0x000800000000LL,
221 -0x001000000000LL,
222 -0x002000000000LL,
223 -0x004000000000LL,
224 -0x008000000000LL,
225 -0x010000000000LL,
226 -0x020000000000LL,
227 -0x040000000000LL,
228 -0x080000000000LL,
229 -0x100000000000LL,
230 -0x200000000000LL,
231 -0x400000000000LL,
232 -0x800000000000LL,
233 -0x0001000000000000LL,
234 -0x0002000000000000LL,
235 -0x0004000000000000LL,
236 -0x0008000000000000LL,
237 -0x0010000000000000LL,
238 -0x0020000000000000LL,
239 -0x0040000000000000LL,
240 -0x0080000000000000LL,
241 -0x0100000000000000LL,
242 -0x0200000000000000LL,
243 -0x0400000000000000LL,
244 -0x0800000000000000LL,
245 -0x1000000000000000LL,
246 -0x2000000000000000LL,
247 -0x4000000000000000LL,
248 INT64_MIN,
249};
250
251static const std::array<int64_t, 65> MAX_I64_VALUES = {
252 0x00LL,
253 0x0000LL,
254 0x0001LL,
255 0x0003LL,
256 0x0007LL,
257 0x000fLL,
258 0x001fLL,
259 0x003fLL,
260 0x007fLL,
261 0x00ffLL,
262 0x01ffLL,
263 0x03ffLL,
264 0x07ffLL,
265 0x0fffLL,
266 0x1fffLL,
267 0x3fffLL,
268 0x7fffLL,
269 0x0000ffffLL,
270 0x0001ffffLL,
271 0x0003ffffLL,
272 0x0007ffffLL,
273 0x000fffffLL,
274 0x001fffffLL,
275 0x003fffffLL,
276 0x007fffffLL,
277 0x00ffffffLL,
278 0x01ffffffLL,
279 0x03ffffffLL,
280 0x07ffffffLL,
281 0x0fffffffLL,
282 0x1fffffffLL,
283 0x3fffffffLL,
284 0x7fffffffLL,
285 0x0000ffffffffLL,
286 0x0001ffffffffLL,
287 0x0003ffffffffLL,
288 0x0007ffffffffLL,
289 0x000fffffffffLL,
290 0x001fffffffffLL,
291 0x003fffffffffLL,
292 0x007fffffffffLL,
293 0x00ffffffffffLL,
294 0x01ffffffffffLL,
295 0x03ffffffffffLL,
296 0x07ffffffffffLL,
297 0x0fffffffffffLL,
298 0x1fffffffffffLL,
299 0x3fffffffffffLL,
300 0x7fffffffffffLL,
301 0x0000ffffffffffffLL,
302 0x0001ffffffffffffLL,
303 0x0003ffffffffffffLL,
304 0x0007ffffffffffffLL,
305 0x000fffffffffffffLL,
306 0x001fffffffffffffLL,
307 0x003fffffffffffffLL,
308 0x007fffffffffffffLL,
309 0x00ffffffffffffffLL,
310 0x01ffffffffffffffLL,
311 0x03ffffffffffffffLL,
312 0x07ffffffffffffffLL,
313 0x0fffffffffffffffLL,
314 0x1fffffffffffffffLL,
315 0x3fffffffffffffffLL,
316 0x7fffffffffffffffLL,
317};
318
320
321BitStreamWriter::BitStreamWriter(uint8_t* buffer, size_t bufferBitSize, BitsTag) :
322 m_buffer(buffer, (bufferBitSize + 7) / 8),
323 m_bitIndex(0),
324 m_bufferBitSize(bufferBitSize)
325{}
326
330
332 m_buffer(buffer),
333 m_bitIndex(0),
334 m_bufferBitSize(buffer.size() * 8)
335{}
336
337BitStreamWriter::BitStreamWriter(Span<uint8_t> buffer, size_t bufferBitSize) :
338 m_buffer(buffer),
339 m_bitIndex(0),
340 m_bufferBitSize(bufferBitSize)
341{
342 if (buffer.size() < (bufferBitSize + 7) / 8)
343 {
344 throw CppRuntimeException("BitStreamWriter: Wrong buffer bit size ('")
345 << buffer.size() << "' < '" << (bufferBitSize + 7) / 8 << "')!";
346 }
347}
348
350{
351 if (numBits == 0 || numBits > sizeof(uint32_t) * 8 || data > MAX_U32_VALUES[numBits])
352 {
353 throw CppRuntimeException("BitStreamWriter: Writing of ")
354 << numBits << "-bits value '" << data << "' failed!";
355 }
356
357 writeUnsignedBits32Impl(data, numBits);
358}
359
361{
362 if (numBits == 0 || numBits > sizeof(uint64_t) * 8 || data > MAX_U64_VALUES[numBits])
363 {
364 throw CppRuntimeException("BitStreamWriter: Writing of ")
365 << numBits << "-bits value '" << data << "' failed!";
366 }
367
368 writeUnsignedBits64Impl(data, numBits);
369}
370
372{
373 if (numBits == 0 || numBits > sizeof(int32_t) * 8 || data < MIN_I32_VALUES[numBits] ||
374 data > MAX_I32_VALUES[numBits])
375 {
376 throw CppRuntimeException("BitStreamWriter: Writing of ")
377 << numBits << "-bits value '" << data << "' failed!";
378 }
379
380 writeUnsignedBits32Impl(static_cast<uint32_t>(data) & MAX_U32_VALUES[numBits], numBits);
381}
382
384{
385 if (numBits == 0 || numBits > sizeof(int64_t) * 8 || data < MIN_I64_VALUES[numBits] ||
386 data > MAX_I64_VALUES[numBits])
387 {
388 throw CppRuntimeException("BitStreamWriter: Writing of ")
389 << numBits << "-bits value '" << data << "' failed!";
390 }
391
392 writeUnsignedBits64Impl(static_cast<uint64_t>(data) & MAX_U64_VALUES[numBits], numBits);
393}
394
396{
397 writeUnsignedBits32Impl((data ? 1 : 0), 1);
398}
399
401{
402 writeSignedVarNum(data, 2, detail::bitSizeOf(data) / 8);
403}
404
406{
407 writeSignedVarNum(data, 4, detail::bitSizeOf(data) / 8);
408}
409
411{
412 writeSignedVarNum(data, 8, detail::bitSizeOf(data) / 8);
413}
414
416{
417 if (data == INT64_MIN)
418 {
419 writeUnsignedBits32Impl(0x80, 8); // INT64_MIN is encoded as -0
420 }
421 else
422 {
423 writeSignedVarNum(data, 9, detail::bitSizeOf(data) / 8);
424 }
425}
426
428{
429 writeUnsignedVarNum(data, 2, detail::bitSizeOf(data) / 8);
430}
431
433{
434 writeUnsignedVarNum(data, 4, detail::bitSizeOf(data) / 8);
435}
436
438{
439 writeUnsignedVarNum(data, 8, detail::bitSizeOf(data) / 8);
440}
441
443{
444 writeUnsignedVarNum(data, 9, detail::bitSizeOf(data) / 8);
445}
446
448{
449 writeUnsignedVarNum(data, 5, detail::bitSizeOf(data) / 8);
450}
451
453{
455 writeUnsignedBits32Impl(halfPrecisionFloat, 16);
456}
457
459{
461 writeUnsignedBits32Impl(singlePrecisionFloat, 32);
462}
463
469
471{
474
476 if ((beginBitPosition & 0x07U) != 0)
477 {
478 // we are not aligned to byte
479 for (size_t i = 0; i < len; ++i)
480 {
481 writeUnsignedBits32Impl(data[i], 8);
482 }
483 }
484 else
485 {
486 // we are aligned to bytes
488 if (hasWriteBuffer())
489 {
490 (void)std::copy(data.begin(), data.end(), m_buffer.begin() + beginBitPosition / 8);
491 }
492 }
493}
494
495void BitStreamWriter::writeString(std::string_view data)
496{
499
501 if ((beginBitPosition & 0x07U) != 0)
502 {
503 // we are not aligned to byte
504 for (size_t i = 0; i < len; ++i)
505 {
506 // TODO[Mi-L@]: can we use unchecked here?!
507 writeUnsignedBits32(static_cast<uint8_t>(std::char_traits<char>::to_int_type(data[i])), 8);
508 }
509 }
510 else
511 {
512 // we are aligned to bytes
514 if (hasWriteBuffer())
515 {
516 (void)std::copy(data.begin(), data.begin() + len, m_buffer.data() + beginBitPosition / 8);
517 }
518 }
519}
520
522{
523 if (hasWriteBuffer())
524 {
525 checkCapacity(position);
526 }
527
528 m_bitIndex = position;
529}
530
531void BitStreamWriter::alignTo(size_t alignment)
532{
533 const BitPosType offset = getBitPosition() % alignment;
534 if (offset != 0)
535 {
536 const uint8_t skip = static_cast<uint8_t>(alignment - offset);
538 }
539}
540
542{
543 return m_buffer.data();
544}
545
547{
548 return m_buffer;
549}
550
551void BitStreamWriter::writeUnsignedBits32Impl(uint32_t data, uint8_t numBits)
552{
553 if (!hasWriteBuffer())
554 {
555 m_bitIndex += numBits;
556 return;
557 }
558
559 checkCapacity(m_bitIndex + numBits);
560
561 uint8_t restNumBits = numBits;
562 const uint8_t bitsUsed = m_bitIndex & 0x07U;
563 uint8_t bitsFree = static_cast<uint8_t>(8 - bitsUsed);
564 size_t byteIndex = m_bitIndex / 8;
565
566 if (restNumBits > bitsFree)
567 {
568 // first part
569 const uint8_t shiftNum = static_cast<uint8_t>(restNumBits - bitsFree);
570 const uint8_t maskedByte = static_cast<uint8_t>(m_buffer[byteIndex] & ~(0xFFU >> bitsUsed));
571 m_buffer[byteIndex++] = static_cast<uint8_t>(maskedByte | (data >> shiftNum));
572 restNumBits = static_cast<uint8_t>(restNumBits - bitsFree);
573
574 // middle parts
575 while (restNumBits >= 8)
576 {
577 restNumBits = static_cast<uint8_t>(restNumBits - 8);
578 m_buffer[byteIndex++] = static_cast<uint8_t>((data >> restNumBits) & MAX_U32_VALUES[8]);
579 }
580
581 // reset bits free
582 bitsFree = 8;
583 }
584
585 // last part
586 if (restNumBits > 0)
587 {
588 const uint8_t shiftNum = static_cast<uint8_t>(bitsFree - restNumBits);
589 const uint32_t mask = MAX_U32_VALUES[restNumBits];
590 const uint8_t maskedByte =
591 m_buffer[byteIndex] & static_cast<uint8_t>(~static_cast<uint8_t>(mask << shiftNum));
592 m_buffer[byteIndex] = static_cast<uint8_t>(maskedByte | ((data & mask) << shiftNum));
593 }
594
595 m_bitIndex += numBits;
596}
597
598inline void BitStreamWriter::writeUnsignedBits64Impl(uint64_t data, uint8_t numBits)
599{
600 if (numBits <= 32)
601 {
602 writeUnsignedBits32Impl(static_cast<uint32_t>(data), numBits);
603 }
604 else
605 {
606 writeUnsignedBits32Impl(static_cast<uint32_t>(data >> 32U), static_cast<uint8_t>(numBits - 32));
607 writeUnsignedBits32Impl(static_cast<uint32_t>(data), 32);
608 }
609}
610
611inline void BitStreamWriter::writeSignedVarNum(int64_t value, size_t maxVarBytes, size_t numVarBytes)
612{
613 const uint64_t absValue = static_cast<uint64_t>(value < 0 ? -value : value);
614 writeVarNum(absValue, true, value < 0, maxVarBytes, numVarBytes);
615}
616
617inline void BitStreamWriter::writeUnsignedVarNum(uint64_t value, size_t maxVarBytes, size_t numVarBytes)
618{
619 writeVarNum(value, false, false, maxVarBytes, numVarBytes);
620}
621
622inline void BitStreamWriter::writeVarNum(
623 uint64_t value, bool hasSign, bool isNegative, size_t maxVarBytes, size_t numVarBytes)
624{
625 static const std::array<uint64_t, 8> bitMasks = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
626 const bool hasMaxByteRange = (numVarBytes == maxVarBytes);
627
628 for (size_t i = 0; i < numVarBytes; i++)
629 {
630 uint8_t byte = 0x00;
631 uint8_t numBits = 8;
632 const bool hasNextByte = (i < numVarBytes - 1);
633 const bool hasSignBit = (hasSign && i == 0);
634 if (hasSignBit)
635 {
636 if (isNegative)
637 {
638 byte |= 0x80U;
639 }
640 numBits--;
641 }
642 if (hasNextByte)
643 {
644 numBits--;
645 const uint8_t add = static_cast<uint8_t>(0x01U << numBits);
646 byte = static_cast<uint8_t>(byte | add); // use bit 6 if signed bit is present, use bit 7 otherwise
647 }
648 else // this is the last byte
649 {
650 if (!hasMaxByteRange) // next byte indicator is not used in last byte in case of max byte range
651 {
652 numBits--;
653 }
654 }
655
656 const size_t shiftBits = (numVarBytes - (i + 1)) * 7 + ((hasMaxByteRange && hasNextByte) ? 1 : 0);
657 const uint8_t add = static_cast<uint8_t>((value >> shiftBits) & bitMasks[numBits - 1U]);
658 byte = static_cast<uint8_t>(byte | add);
659 writeUnsignedBits32Impl(byte, 8);
660 }
661}
662
663inline void BitStreamWriter::throwInsufficientCapacityException() const
664{
665 throw InsufficientCapacityException("BitStreamWriter: Reached end of bit buffer!");
666}
667
668inline void BitStreamWriter::checkCapacity(size_t bitSize) const
669{
670 if (bitSize > m_bufferBitSize)
671 {
672 throwInsufficientCapacityException();
673 }
674}
675
676} // namespace zserio
void writeVarUInt16(VarUInt16 data)
Span< const uint8_t > getBuffer() const
void writeVarInt32(VarInt32 data)
void writeFloat64(Float64 data)
void writeVarUInt64(VarUInt64 data)
BitPosType getBitPosition() const
void writeVarInt16(VarInt16 data)
const uint8_t * getWriteBuffer() const
void writeSignedBits64(int64_t data, uint8_t numBits=64)
void writeVarInt64(VarInt64 data)
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)
BitStreamWriter(uint8_t *buffer, size_t bufferBitSize, BitsTag)
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)
constexpr size_type size() const noexcept
Definition Span.h:281
constexpr pointer data() const noexcept
Definition Span.h:271
constexpr iterator end() const noexcept
Definition Span.h:210
constexpr iterator begin() const noexcept
Definition Span.h:200
uint8_t numBits(uint64_t numValues)
uint64_t convertDoubleToUInt64(double float64)
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
uint32_t convertFloatToUInt32(float float32)
detail::VarIntWrapper< uint16_t, detail::VarIntType::VAR16 > VarUInt16
Definition Types.h:885
detail::VarIntWrapper< uint64_t, detail::VarIntType::VAR64 > VarUInt64
Definition Types.h:887
uint16_t convertFloatToUInt16(float float32)
Definition FloatUtil.cpp:83
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