Coverage Report

Created: 2024-07-18 11:41

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