Coverage Report

Created: 2024-07-18 11:41

src/zserio/BitStreamReader.cpp
Line
Count
Source (jump to first uncovered line)
1
#include <array>
2
#include <limits>
3
4
#include "zserio/BitStreamReader.h"
5
#include "zserio/CppRuntimeException.h"
6
#include "zserio/FloatUtil.h"
7
#include "zserio/RuntimeArch.h"
8
9
namespace zserio
10
{
11
12
namespace
13
{
14
15
// max size calculated to prevent overflows in internal comparisons
16
const size_t MAX_BUFFER_SIZE = std::numeric_limits<size_t>::max() / 8 - 4;
17
18
using BitPosType = BitStreamReader::BitPosType;
19
using ReaderContext = BitStreamReader::ReaderContext;
20
21
#ifdef ZSERIO_RUNTIME_64BIT
22
using BaseType = uint64_t;
23
using BaseSignedType = int64_t;
24
#else
25
using BaseType = uint32_t;
26
using BaseSignedType = int32_t;
27
#endif
28
29
#ifdef ZSERIO_RUNTIME_64BIT
30
const std::array<BaseType, 65> MASK_TABLE = {
31
        UINT64_C(0x00),
32
        UINT64_C(0x0001),
33
        UINT64_C(0x0003),
34
        UINT64_C(0x0007),
35
        UINT64_C(0x000f),
36
        UINT64_C(0x001f),
37
        UINT64_C(0x003f),
38
        UINT64_C(0x007f),
39
        UINT64_C(0x00ff),
40
        UINT64_C(0x01ff),
41
        UINT64_C(0x03ff),
42
        UINT64_C(0x07ff),
43
        UINT64_C(0x0fff),
44
        UINT64_C(0x1fff),
45
        UINT64_C(0x3fff),
46
        UINT64_C(0x7fff),
47
        UINT64_C(0xffff),
48
        UINT64_C(0x0001ffff),
49
        UINT64_C(0x0003ffff),
50
        UINT64_C(0x0007ffff),
51
        UINT64_C(0x000fffff),
52
        UINT64_C(0x001fffff),
53
        UINT64_C(0x003fffff),
54
        UINT64_C(0x007fffff),
55
        UINT64_C(0x00ffffff),
56
        UINT64_C(0x01ffffff),
57
        UINT64_C(0x03ffffff),
58
        UINT64_C(0x07ffffff),
59
        UINT64_C(0x0fffffff),
60
        UINT64_C(0x1fffffff),
61
        UINT64_C(0x3fffffff),
62
        UINT64_C(0x7fffffff),
63
        UINT64_C(0xffffffff),
64
65
        UINT64_C(0x00000001ffffffff),
66
        UINT64_C(0x00000003ffffffff),
67
        UINT64_C(0x00000007ffffffff),
68
        UINT64_C(0x0000000fffffffff),
69
        UINT64_C(0x0000001fffffffff),
70
        UINT64_C(0x0000003fffffffff),
71
        UINT64_C(0x0000007fffffffff),
72
        UINT64_C(0x000000ffffffffff),
73
        UINT64_C(0x000001ffffffffff),
74
        UINT64_C(0x000003ffffffffff),
75
        UINT64_C(0x000007ffffffffff),
76
        UINT64_C(0x00000fffffffffff),
77
        UINT64_C(0x00001fffffffffff),
78
        UINT64_C(0x00003fffffffffff),
79
        UINT64_C(0x00007fffffffffff),
80
        UINT64_C(0x0000ffffffffffff),
81
        UINT64_C(0x0001ffffffffffff),
82
        UINT64_C(0x0003ffffffffffff),
83
        UINT64_C(0x0007ffffffffffff),
84
        UINT64_C(0x000fffffffffffff),
85
        UINT64_C(0x001fffffffffffff),
86
        UINT64_C(0x003fffffffffffff),
87
        UINT64_C(0x007fffffffffffff),
88
        UINT64_C(0x00ffffffffffffff),
89
        UINT64_C(0x01ffffffffffffff),
90
        UINT64_C(0x03ffffffffffffff),
91
        UINT64_C(0x07ffffffffffffff),
92
        UINT64_C(0x0fffffffffffffff),
93
        UINT64_C(0x1fffffffffffffff),
94
        UINT64_C(0x3fffffffffffffff),
95
        UINT64_C(0x7fffffffffffffff),
96
        UINT64_C(0xffffffffffffffff),
97
};
98
#else
99
const std::array<BaseType, 33> MASK_TABLE = {
100
        UINT32_C(0x00),
101
        UINT32_C(0x0001),
102
        UINT32_C(0x0003),
103
        UINT32_C(0x0007),
104
        UINT32_C(0x000f),
105
        UINT32_C(0x001f),
106
        UINT32_C(0x003f),
107
        UINT32_C(0x007f),
108
        UINT32_C(0x00ff),
109
        UINT32_C(0x01ff),
110
        UINT32_C(0x03ff),
111
        UINT32_C(0x07ff),
112
        UINT32_C(0x0fff),
113
        UINT32_C(0x1fff),
114
        UINT32_C(0x3fff),
115
        UINT32_C(0x7fff),
116
        UINT32_C(0xffff),
117
        UINT32_C(0x0001ffff),
118
        UINT32_C(0x0003ffff),
119
        UINT32_C(0x0007ffff),
120
        UINT32_C(0x000fffff),
121
        UINT32_C(0x001fffff),
122
        UINT32_C(0x003fffff),
123
        UINT32_C(0x007fffff),
124
        UINT32_C(0x00ffffff),
125
        UINT32_C(0x01ffffff),
126
        UINT32_C(0x03ffffff),
127
        UINT32_C(0x07ffffff),
128
        UINT32_C(0x0fffffff),
129
        UINT32_C(0x1fffffff),
130
        UINT32_C(0x3fffffff),
131
        UINT32_C(0x7fffffff),
132
        UINT32_C(0xffffffff),
133
};
134
#endif
135
136
const uint8_t VARINT_SIGN_1 = UINT8_C(0x80);
137
const uint8_t VARINT_BYTE_1 = UINT8_C(0x3f);
138
const uint8_t VARINT_BYTE_N = UINT8_C(0x7f);
139
const uint8_t VARINT_HAS_NEXT_1 = UINT8_C(0x40);
140
const uint8_t VARINT_HAS_NEXT_N = UINT8_C(0x80);
141
142
const uint8_t VARUINT_BYTE = UINT8_C(0x7f);
143
const uint8_t VARUINT_HAS_NEXT = UINT8_C(0x80);
144
145
const uint32_t VARSIZE_MAX_VALUE = (UINT32_C(1) << 31U) - 1;
146
147
#ifdef ZSERIO_RUNTIME_64BIT
148
inline BaseType parse64(Span<const uint8_t>::const_iterator bufferIt)
149
8.66k
{
150
8.66k
    return static_cast<BaseType>(*bufferIt) << 56U | static_cast<BaseType>(*(bufferIt + 1)) << 48U |
151
8.66k
            static_cast<BaseType>(*(bufferIt + 2)) << 40U | static_cast<BaseType>(*(bufferIt + 3)) << 32U |
152
8.66k
            static_cast<BaseType>(*(bufferIt + 4)) << 24U | static_cast<BaseType>(*(bufferIt + 5)) << 16U |
153
8.66k
            static_cast<BaseType>(*(bufferIt + 6)) << 8U | static_cast<BaseType>(*(bufferIt + 7));
154
8.66k
}
155
156
inline BaseType parse56(Span<const uint8_t>::const_iterator bufferIt)
157
350
{
158
350
    return static_cast<BaseType>(*bufferIt) << 48U | static_cast<BaseType>(*(bufferIt + 1)) << 40U |
159
350
            static_cast<BaseType>(*(bufferIt + 2)) << 32U | static_cast<BaseType>(*(bufferIt + 3)) << 24U |
160
350
            static_cast<BaseType>(*(bufferIt + 4)) << 16U | static_cast<BaseType>(*(bufferIt + 5)) << 8U |
161
350
            static_cast<BaseType>(*(bufferIt + 6));
162
350
}
163
164
inline BaseType parse48(Span<const uint8_t>::const_iterator bufferIt)
165
325
{
166
325
    return static_cast<BaseType>(*bufferIt) << 40U | static_cast<BaseType>(*(bufferIt + 1)) << 32U |
167
325
            static_cast<BaseType>(*(bufferIt + 2)) << 24U | static_cast<BaseType>(*(bufferIt + 3)) << 16U |
168
325
            static_cast<BaseType>(*(bufferIt + 4)) << 8U | static_cast<BaseType>(*(bufferIt + 5));
169
325
}
170
171
inline BaseType parse40(Span<const uint8_t>::const_iterator bufferIt)
172
459
{
173
459
    return static_cast<BaseType>(*bufferIt) << 32U | static_cast<BaseType>(*(bufferIt + 1)) << 24U |
174
459
            static_cast<BaseType>(*(bufferIt + 2)) << 16U | static_cast<BaseType>(*(bufferIt + 3)) << 8U |
175
459
            static_cast<BaseType>(*(bufferIt + 4));
176
459
}
177
#endif
178
inline BaseType parse32(Span<const uint8_t>::const_iterator bufferIt)
179
488
{
180
488
    return static_cast<BaseType>(*bufferIt) << 24U | static_cast<BaseType>(*(bufferIt + 1)) << 16U |
181
488
            static_cast<BaseType>(*(bufferIt + 2)) << 8U | static_cast<BaseType>(*(bufferIt + 3));
182
488
}
183
184
inline BaseType parse24(Span<const uint8_t>::const_iterator bufferIt)
185
356
{
186
356
    return static_cast<BaseType>(*bufferIt) << 16U | static_cast<BaseType>(*(bufferIt + 1)) << 8U |
187
356
            static_cast<BaseType>(*(bufferIt + 2));
188
356
}
189
190
inline BaseType parse16(Span<const uint8_t>::const_iterator bufferIt)
191
798
{
192
798
    return static_cast<BaseType>(*bufferIt) << 8U | static_cast<BaseType>(*(bufferIt + 1));
193
798
}
194
195
inline BaseType parse8(Span<const uint8_t>::const_iterator bufferIt)
196
1.00k
{
197
1.00k
    return static_cast<BaseType>(*bufferIt);
198
1.00k
}
199
200
/** Optimization which increases chances to inline checkNumBits and checkNumBits64. */
201
inline void throwNumBitsIsNotValid(uint8_t numBits)
202
12
{
203
12
    throw CppRuntimeException("BitStreamReader: ReadBits #")
204
12
            << numBits << " is not valid, reading from stream failed!";
205
12
}
206
207
/** Checks numBits validity for 32-bit reads. */
208
inline void checkNumBits(uint8_t numBits)
209
7.42k
{
210
7.42k
    if (numBits == 0 || 
numBits > 327.42k
)
211
6
    {
212
6
        throwNumBitsIsNotValid(numBits);
213
6
    }
214
7.42k
}
215
216
/** Checks numBits validity for 64-bit reads. */
217
inline void checkNumBits64(uint8_t numBits)
218
5.58k
{
219
5.58k
    if (numBits == 0 || 
numBits > 645.58k
)
220
6
    {
221
6
        throwNumBitsIsNotValid(numBits);
222
6
    }
223
5.58k
}
224
225
/** Optimization which increases chances to inline loadCacheNext. */
226
inline void throwEof()
227
72
{
228
72
    throw CppRuntimeException("BitStreamReader: Reached eof(), reading from stream failed!");
229
72
}
230
231
/** Loads next 32/64 bits to 32/64 bit-cache. */
232
inline void loadCacheNext(ReaderContext& ctx, uint8_t numBits)
233
12.5k
{
234
12.5k
    static const uint8_t cacheBitSize = sizeof(BaseType) * 8;
235
236
    // ctx.bitIndex is always byte aligned and ctx.cacheNumBits is always zero in this call
237
12.5k
    const size_t byteIndex = ctx.bitIndex >> 3U;
238
12.5k
    if (ctx.bufferBitSize >= ctx.bitIndex + cacheBitSize)
239
8.39k
    {
240
8.39k
        ctx.cache =
241
8.39k
#ifdef ZSERIO_RUNTIME_64BIT
242
8.39k
                parse64(ctx.buffer.begin() + byteIndex);
243
#else
244
                parse32(ctx.buffer.begin() + byteIndex);
245
#endif
246
8.39k
        ctx.cacheNumBits = cacheBitSize;
247
8.39k
    }
248
4.11k
    else
249
4.11k
    {
250
4.11k
        if (ctx.bitIndex + numBits > ctx.bufferBitSize)
251
72
        {
252
72
            throwEof();
253
72
        }
254
255
4.11k
        ctx.cacheNumBits = static_cast<uint8_t>(ctx.bufferBitSize - ctx.bitIndex);
256
257
        // buffer must be always available in full bytes, even if some last bits are not used
258
4.11k
        const uint8_t alignedNumBits = static_cast<uint8_t>((ctx.cacheNumBits + 7U) & ~0x7U);
259
260
4.11k
        switch (alignedNumBits)
261
4.11k
        {
262
0
#ifdef ZSERIO_RUNTIME_64BIT
263
263
        case 64:
264
263
            ctx.cache = parse64(ctx.buffer.begin() + byteIndex);
265
263
            break;
266
350
        case 56:
267
350
            ctx.cache = parse56(ctx.buffer.begin() + byteIndex);
268
350
            break;
269
325
        case 48:
270
325
            ctx.cache = parse48(ctx.buffer.begin() + byteIndex);
271
325
            break;
272
459
        case 40:
273
459
            ctx.cache = parse40(ctx.buffer.begin() + byteIndex);
274
459
            break;
275
0
#endif
276
488
        case 32:
277
488
            ctx.cache = parse32(ctx.buffer.begin() + byteIndex);
278
488
            break;
279
356
        case 24:
280
356
            ctx.cache = parse24(ctx.buffer.begin() + byteIndex);
281
356
            break;
282
798
        case 16:
283
798
            ctx.cache = parse16(ctx.buffer.begin() + byteIndex);
284
798
            break;
285
1.00k
        default: // 8
286
1.00k
            ctx.cache = parse8(ctx.buffer.begin() + byteIndex);
287
1.00k
            break;
288
4.11k
        }
289
290
4.04k
        ctx.cache >>= static_cast<uint8_t>(alignedNumBits - ctx.cacheNumBits);
291
4.04k
    }
292
12.5k
}
293
294
/** Unchecked implementation of readBits. */
295
inline BaseType readBitsImpl(ReaderContext& ctx, uint8_t numBits)
296
63.0k
{
297
63.0k
    BaseType value = 0;
298
63.0k
    if (ctx.cacheNumBits < numBits)
299
12.5k
    {
300
        // read all remaining cache bits
301
12.5k
        value = ctx.cache & MASK_TABLE[ctx.cacheNumBits];
302
12.5k
        ctx.bitIndex += ctx.cacheNumBits;
303
12.5k
        numBits = static_cast<uint8_t>(numBits - ctx.cacheNumBits);
304
305
        // load next piece of buffer into cache
306
12.5k
        loadCacheNext(ctx, numBits);
307
308
        // add the remaining bits to the result
309
        // if numBits is sizeof(BaseType) * 8 here, value is already 0 (see MASK_TABLE[0])
310
12.5k
        if (numBits < sizeof(BaseType) * 8)
311
12.3k
        {
312
12.3k
            value <<= numBits;
313
12.3k
        }
314
12.5k
    }
315
63.0k
    value |= ((ctx.cache >> static_cast<uint8_t>(ctx.cacheNumBits - numBits)) & MASK_TABLE[numBits]);
316
63.0k
    ctx.cacheNumBits = static_cast<uint8_t>(ctx.cacheNumBits - numBits);
317
63.0k
    ctx.bitIndex += numBits;
318
319
63.0k
    return value;
320
63.0k
}
321
322
/** Unchecked version of readSignedBits. */
323
inline BaseSignedType readSignedBitsImpl(ReaderContext& ctx, uint8_t numBits)
324
3.42k
{
325
3.42k
    static const uint8_t typeSize = sizeof(BaseSignedType) * 8;
326
3.42k
    BaseType value = readBitsImpl(ctx, numBits);
327
328
    // Skip the signed overflow correction if numBits == typeSize.
329
    // In that case, the value that comes out the readBits function
330
    // is already correct.
331
3.42k
    if (numBits != 0 && numBits < typeSize &&
332
3.42k
            
(value >= (static_cast<BaseType>(1) << static_cast<uint8_t>(numBits - 1)))2.91k
)
333
682
    {
334
682
        value -= static_cast<BaseType>(1) << numBits;
335
682
    }
336
337
3.42k
    return static_cast<BaseSignedType>(value);
338
3.42k
}
339
340
#ifndef ZSERIO_RUNTIME_64BIT
341
/** Unchecked implementation of readBits64. Always reads > 32bit! */
342
inline uint64_t readBits64Impl(ReaderContext& ctx, uint8_t numBits)
343
{
344
    // read the first 32 bits
345
    numBits = static_cast<uint8_t>(numBits - 32);
346
    uint64_t value = readBitsImpl(ctx, 32);
347
348
    // add the remaining bits
349
    value <<= numBits;
350
    value |= readBitsImpl(ctx, numBits);
351
352
    return value;
353
}
354
#endif
355
356
} // namespace
357
358
BitStreamReader::ReaderContext::ReaderContext(Span<const uint8_t> readBuffer, size_t readBufferBitSize) :
359
        buffer(readBuffer),
360
        bufferBitSize(readBufferBitSize),
361
        cache(0),
362
        cacheNumBits(0),
363
        bitIndex(0)
364
4.24k
{
365
4.24k
    if (buffer.size() > MAX_BUFFER_SIZE)
366
1
    {
367
1
        throw CppRuntimeException("BitStreamReader: Buffer size exceeded limit '")
368
1
                << MAX_BUFFER_SIZE << "' bytes!";
369
1
    }
370
4.24k
}
371
372
BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferByteSize) :
373
        BitStreamReader(Span<const uint8_t>(buffer, bufferByteSize))
374
15
{}
375
376
BitStreamReader::BitStreamReader(Span<const uint8_t> buffer) :
377
        m_context(buffer, buffer.size() * 8)
378
28
{}
379
380
BitStreamReader::BitStreamReader(Span<const uint8_t> buffer, size_t bufferBitSize) :
381
        m_context(buffer, bufferBitSize)
382
392
{
383
392
    if (buffer.size() < (bufferBitSize + 7) / 8)
384
1
    {
385
1
        throw CppRuntimeException("BitStreamReader: Wrong buffer bit size ('")
386
1
                << buffer.size() << "' < '" << (bufferBitSize + 7) / 8 << "')!";
387
1
    }
388
392
}
389
390
BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferBitSize, BitsTag) :
391
        m_context(Span<const uint8_t>(buffer, (bufferBitSize + 7) / 8), bufferBitSize)
392
3.82k
{}
393
394
uint32_t BitStreamReader::readBits(uint8_t numBits)
395
5.92k
{
396
5.92k
    checkNumBits(numBits);
397
398
5.92k
    return static_cast<uint32_t>(readBitsImpl(m_context, numBits));
399
5.92k
}
400
401
uint64_t BitStreamReader::readBits64(uint8_t numBits)
402
3.65k
{
403
3.65k
    checkNumBits64(numBits);
404
405
3.65k
#ifdef ZSERIO_RUNTIME_64BIT
406
3.65k
    return readBitsImpl(m_context, numBits);
407
#else
408
    if (numBits <= 32)
409
    {
410
        return readBitsImpl(m_context, numBits);
411
    }
412
413
    return readBits64Impl(m_context, numBits);
414
#endif
415
3.65k
}
416
417
int64_t BitStreamReader::readSignedBits64(uint8_t numBits)
418
1.92k
{
419
1.92k
    checkNumBits64(numBits);
420
421
1.92k
#ifdef ZSERIO_RUNTIME_64BIT
422
1.92k
    return readSignedBitsImpl(m_context, numBits);
423
#else
424
    if (numBits <= 32)
425
    {
426
        return readSignedBitsImpl(m_context, numBits);
427
    }
428
429
    int64_t value = static_cast<int64_t>(readBits64Impl(m_context, numBits));
430
431
    // Skip the signed overflow correction if numBits == 64.
432
    // In that case, the value that comes out the readBits function
433
    // is already correct.
434
    const bool needsSignExtension =
435
            numBits < 64 && (static_cast<uint64_t>(value) >= (UINT64_C(1) << (numBits - 1)));
436
    if (needsSignExtension)
437
    {
438
        value = static_cast<int64_t>(static_cast<uint64_t>(value) - (UINT64_C(1) << numBits));
439
    }
440
441
    return value;
442
#endif
443
1.92k
}
444
445
int32_t BitStreamReader::readSignedBits(uint8_t numBits)
446
1.50k
{
447
1.50k
    checkNumBits(numBits);
448
449
1.50k
    return static_cast<int32_t>(readSignedBitsImpl(m_context, numBits));
450
1.50k
}
451
452
int64_t BitStreamReader::readVarInt64()
453
2.34k
{
454
2.34k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
455
2.34k
    const bool sign = (byte & VARINT_SIGN_1) != 0;
456
2.34k
    uint64_t result = byte & VARINT_BYTE_1;
457
2.34k
    if ((byte & VARINT_HAS_NEXT_1) == 0)
458
347
    {
459
347
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)284
;
460
347
    }
461
462
1.99k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
463
1.99k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
464
1.99k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
465
284
    {
466
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
467
284
    }
468
469
1.71k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
470
1.71k
    result = static_cast<uint64_t>(result) << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
471
1.71k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
472
284
    {
473
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
474
284
    }
475
476
1.42k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
477
1.42k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
478
1.42k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
479
293
    {
480
293
        return sign ? 
-static_cast<int64_t>(result)68
:
static_cast<int64_t>(result)225
;
481
293
    }
482
483
1.13k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
484
1.13k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
485
1.13k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
486
284
    {
487
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
488
284
    }
489
490
852
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
491
852
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
492
852
    if ((byte & VARINT_HAS_NEXT_N) == 0)
493
284
    {
494
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
495
284
    }
496
497
568
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
498
568
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
499
568
    if ((byte & VARINT_HAS_NEXT_N) == 0)
500
284
    {
501
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
502
284
    }
503
504
284
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
505
284
    return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
506
568
}
507
508
int32_t BitStreamReader::readVarInt32()
509
664
{
510
664
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
511
664
    const bool sign = (byte & VARINT_SIGN_1) != 0;
512
664
    uint32_t result = byte & VARINT_BYTE_1;
513
664
    if ((byte & VARINT_HAS_NEXT_1) == 0)
514
187
    {
515
187
        return sign ? 
-static_cast<int32_t>(result)31
:
static_cast<int32_t>(result)156
;
516
187
    }
517
518
477
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
519
477
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
520
477
    if ((byte & VARINT_HAS_NEXT_N) == 0)
521
156
    {
522
156
        return sign ? 
-static_cast<int32_t>(result)31
:
static_cast<int32_t>(result)125
;
523
156
    }
524
525
321
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
526
321
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
527
321
    if ((byte & VARINT_HAS_NEXT_N) == 0)
528
165
    {
529
165
        return sign ? 
-static_cast<int32_t>(result)35
:
static_cast<int32_t>(result)130
;
530
165
    }
531
532
156
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
533
156
    return sign ? 
-static_cast<int32_t>(result)31
:
static_cast<int32_t>(result)125
;
534
321
}
535
536
int16_t BitStreamReader::readVarInt16()
537
208
{
538
208
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
539
208
    const bool sign = (byte & VARINT_SIGN_1) != 0;
540
208
    uint16_t result = byte & VARINT_BYTE_1;
541
208
    if ((byte & VARINT_HAS_NEXT_1) == 0)
542
115
    {
543
115
        return sign ? 
static_cast<int16_t>(-result)19
:
static_cast<int16_t>(result)96
;
544
115
    }
545
546
93
    result = static_cast<uint16_t>(result << 8U);
547
93
    result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
548
93
    return sign ? 
static_cast<int16_t>(-result)16
:
static_cast<int16_t>(result)77
;
549
208
}
550
551
uint64_t BitStreamReader::readVarUInt64()
552
1.94k
{
553
1.94k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
554
1.94k
    uint64_t result = byte & VARUINT_BYTE;
555
1.94k
    if ((byte & VARUINT_HAS_NEXT) == 0)
556
445
    {
557
445
        return result;
558
445
    }
559
560
1.49k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
561
1.49k
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
562
1.49k
    if ((byte & VARUINT_HAS_NEXT) == 0)
563
192
    {
564
192
        return result;
565
192
    }
566
567
1.30k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
568
1.30k
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
569
1.30k
    if ((byte & VARUINT_HAS_NEXT) == 0)
570
322
    {
571
322
        return result;
572
322
    }
573
574
983
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
575
983
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
576
983
    if ((byte & VARUINT_HAS_NEXT) == 0)
577
222
    {
578
222
        return result;
579
222
    }
580
581
761
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
582
761
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
583
761
    if ((byte & VARUINT_HAS_NEXT) == 0)
584
191
    {
585
191
        return result;
586
191
    }
587
588
570
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
589
570
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
590
570
    if ((byte & VARUINT_HAS_NEXT) == 0)
591
190
    {
592
190
        return result;
593
190
    }
594
595
380
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
596
380
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
597
380
    if ((byte & VARUINT_HAS_NEXT) == 0)
598
190
    {
599
190
        return result;
600
190
    }
601
602
190
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
603
190
    return result;
604
380
}
605
606
uint32_t BitStreamReader::readVarUInt32()
607
478
{
608
478
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
609
478
    uint32_t result = byte & VARUINT_BYTE;
610
478
    if ((byte & VARUINT_HAS_NEXT) == 0)
611
125
    {
612
125
        return result;
613
125
    }
614
615
353
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
616
353
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
617
353
    if ((byte & VARUINT_HAS_NEXT) == 0)
618
96
    {
619
96
        return result;
620
96
    }
621
622
257
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
623
257
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
624
257
    if ((byte & VARUINT_HAS_NEXT) == 0)
625
162
    {
626
162
        return result;
627
162
    }
628
629
95
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
630
95
    return result;
631
257
}
632
633
uint16_t BitStreamReader::readVarUInt16()
634
178
{
635
178
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
636
178
    uint16_t result = byte & VARUINT_BYTE;
637
178
    if ((byte & VARUINT_HAS_NEXT) == 0)
638
100
    {
639
100
        return result;
640
100
    }
641
642
78
    result = static_cast<uint16_t>(result << 8U);
643
78
    result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
644
78
    return result;
645
178
}
646
647
int64_t BitStreamReader::readVarInt()
648
3.10k
{
649
3.10k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
650
3.10k
    const bool sign = (byte & VARINT_SIGN_1) != 0;
651
3.10k
    uint64_t result = byte & VARINT_BYTE_1;
652
3.10k
    if ((byte & VARINT_HAS_NEXT_1) == 0)
653
570
    {
654
570
        return sign ? 
(285
result == 0285
? INT64_MIN :
-static_cast<int64_t>(result)190
) :
static_cast<int64_t>(result)285
;
655
570
    }
656
657
2.53k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
658
2.53k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
659
2.53k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
660
316
    {
661
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
662
316
    }
663
664
2.22k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
665
2.22k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
666
2.22k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
667
316
    {
668
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
669
316
    }
670
671
1.90k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
672
1.90k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
673
1.90k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
674
324
    {
675
324
        return sign ? 
-static_cast<int64_t>(result)162
:
static_cast<int64_t>(result)162
;
676
324
    }
677
678
1.58k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
679
1.58k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
680
1.58k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
681
316
    {
682
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
683
316
    }
684
685
1.26k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
686
1.26k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
687
1.26k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
688
316
    {
689
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
690
316
    }
691
692
949
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
693
949
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
694
949
    if ((byte & VARINT_HAS_NEXT_N) == 0)
695
316
    {
696
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
697
316
    }
698
699
633
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
700
633
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
701
633
    if ((byte & VARINT_HAS_NEXT_N) == 0)
702
316
    {
703
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
704
316
    }
705
706
317
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
707
317
    return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)159
;
708
633
}
709
710
uint64_t BitStreamReader::readVarUInt()
711
1.55k
{
712
1.55k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
713
1.55k
    uint64_t result = byte & VARUINT_BYTE;
714
1.55k
    if ((byte & VARUINT_HAS_NEXT) == 0)
715
285
    {
716
285
        return result;
717
285
    }
718
719
1.27k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
720
1.27k
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
721
1.27k
    if ((byte & VARUINT_HAS_NEXT) == 0)
722
160
    {
723
160
        return result;
724
160
    }
725
726
1.11k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
727
1.11k
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
728
1.11k
    if ((byte & VARUINT_HAS_NEXT) == 0)
729
164
    {
730
164
        return result;
731
164
    }
732
733
949
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
734
949
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
735
949
    if ((byte & VARUINT_HAS_NEXT) == 0)
736
158
    {
737
158
        return result;
738
158
    }
739
740
791
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
741
791
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
742
791
    if ((byte & VARUINT_HAS_NEXT) == 0)
743
158
    {
744
158
        return result;
745
158
    }
746
747
633
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
748
633
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
749
633
    if ((byte & VARUINT_HAS_NEXT) == 0)
750
158
    {
751
158
        return result;
752
158
    }
753
754
475
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
755
475
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
756
475
    if ((byte & VARUINT_HAS_NEXT) == 0)
757
158
    {
758
158
        return result;
759
158
    }
760
761
317
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
762
317
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
763
317
    if ((byte & VARUINT_HAS_NEXT) == 0)
764
158
    {
765
158
        return result;
766
158
    }
767
768
159
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
769
159
    return result;
770
317
}
771
772
uint32_t BitStreamReader::readVarSize()
773
2.65k
{
774
2.65k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
775
2.65k
    uint32_t result = byte & VARUINT_BYTE;
776
2.65k
    if ((byte & VARUINT_HAS_NEXT) == 0)
777
2.08k
    {
778
2.08k
        return result;
779
2.08k
    }
780
781
577
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
782
577
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
783
577
    if ((byte & VARUINT_HAS_NEXT) == 0)
784
128
    {
785
128
        return result;
786
128
    }
787
788
449
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
789
449
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
790
449
    if ((byte & VARUINT_HAS_NEXT) == 0)
791
194
    {
792
194
        return result;
793
194
    }
794
795
255
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
796
255
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
797
255
    if ((byte & VARUINT_HAS_NEXT) == 0)
798
126
    {
799
126
        return result;
800
126
    }
801
802
129
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
803
129
    if (result > VARSIZE_MAX_VALUE)
804
2
    {
805
2
        throw CppRuntimeException("BitStreamReader: Read value '")
806
2
                << result << "' is out of range for varsize type!";
807
2
    }
808
809
127
    return result;
810
129
}
811
812
float BitStreamReader::readFloat16()
813
215
{
814
215
    const uint16_t halfPrecisionFloatValue = static_cast<uint16_t>(readBitsImpl(m_context, 16));
815
816
215
    return convertUInt16ToFloat(halfPrecisionFloatValue);
817
215
}
818
819
float BitStreamReader::readFloat32()
820
313
{
821
313
    const uint32_t singlePrecisionFloatValue = static_cast<uint32_t>(readBitsImpl(m_context, 32));
822
823
313
    return convertUInt32ToFloat(singlePrecisionFloatValue);
824
313
}
825
826
double BitStreamReader::readFloat64()
827
493
{
828
493
#ifdef ZSERIO_RUNTIME_64BIT
829
493
    const uint64_t doublePrecisionFloatValue = static_cast<uint64_t>(readBitsImpl(m_context, 64));
830
#else
831
    const uint64_t doublePrecisionFloatValue = readBits64Impl(m_context, 64);
832
#endif
833
834
493
    return convertUInt64ToDouble(doublePrecisionFloatValue);
835
493
}
836
837
bool BitStreamReader::readBool()
838
907
{
839
907
    return readBitsImpl(m_context, 1) != 0;
840
907
}
841
842
void BitStreamReader::setBitPosition(BitPosType position)
843
189
{
844
189
    if (position > m_context.bufferBitSize)
845
1
    {
846
1
        throw CppRuntimeException("BitStreamReader: Reached eof(), setting of bit position failed!");
847
1
    }
848
849
188
    m_context.bitIndex = (position / 8) * 8; // set to byte aligned position
850
188
    m_context.cacheNumBits = 0; // invalidate cache
851
188
    const uint8_t skip = static_cast<uint8_t>(position - m_context.bitIndex);
852
188
    if (skip != 0)
853
1
    {
854
1
        (void)readBits(skip);
855
1
    }
856
188
}
857
858
void BitStreamReader::alignTo(size_t alignment)
859
4.73k
{
860
4.73k
    const BitPosType offset = getBitPosition() % alignment;
861
4.73k
    if (offset != 0)
862
2.45k
    {
863
2.45k
        const uint8_t skip = static_cast<uint8_t>(alignment - offset);
864
2.45k
        (void)readBits64(skip);
865
2.45k
    }
866
4.73k
}
867
868
uint8_t BitStreamReader::readByte()
869
974
{
870
974
    return static_cast<uint8_t>(readBitsImpl(m_context, 8));
871
974
}
872
873
} // namespace zserio