Coverage Report

Created: 2024-04-30 09:35

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
8
{
203
8
    throw CppRuntimeException("BitStreamReader: ReadBits #")
204
8
            << numBits << " is not valid, reading from stream failed!";
205
8
}
206
207
/** Checks numBits validity for 32-bit reads. */
208
inline void checkNumBits(uint8_t numBits)
209
7.83k
{
210
7.83k
    if (numBits > 32)
211
4
        throwNumBitsIsNotValid(numBits);
212
7.83k
}
213
214
/** Checks numBits validity for 64-bit reads. */
215
inline void checkNumBits64(uint8_t numBits)
216
5.58k
{
217
5.58k
    if (numBits > 64)
218
4
        throwNumBitsIsNotValid(numBits);
219
5.58k
}
220
221
/** Optimization which increases chances to inline loadCacheNext. */
222
inline void throwEof()
223
72
{
224
72
    throw CppRuntimeException("BitStreamReader: Reached eof(), reading from stream failed!");
225
72
}
226
227
/** Loads next 32/64 bits to 32/64 bit-cache. */
228
inline void loadCacheNext(ReaderContext& ctx, uint8_t numBits)
229
12.5k
{
230
12.5k
    static const uint8_t cacheBitSize = sizeof(BaseType) * 8;
231
232
    // ctx.bitIndex is always byte aligned and ctx.cacheNumBits is always zero in this call
233
12.5k
    const size_t byteIndex = ctx.bitIndex >> 3U;
234
12.5k
    if (ctx.bufferBitSize >= ctx.bitIndex + cacheBitSize)
235
8.39k
    {
236
8.39k
        ctx.cache =
237
8.39k
#ifdef ZSERIO_RUNTIME_64BIT
238
8.39k
                parse64(ctx.buffer.begin() + byteIndex);
239
#else
240
                parse32(ctx.buffer.begin() + byteIndex);
241
#endif
242
8.39k
        ctx.cacheNumBits = cacheBitSize;
243
8.39k
    }
244
4.11k
    else
245
4.11k
    {
246
4.11k
        if (ctx.bitIndex + numBits > ctx.bufferBitSize)
247
72
            throwEof();
248
249
4.11k
        ctx.cacheNumBits = static_cast<uint8_t>(ctx.bufferBitSize - ctx.bitIndex);
250
251
        // buffer must be always available in full bytes, even if some last bits are not used
252
4.11k
        const uint8_t alignedNumBits = static_cast<uint8_t>((ctx.cacheNumBits + 7U) & ~0x7U);
253
254
4.11k
        switch (alignedNumBits)
255
4.11k
        {
256
0
#ifdef ZSERIO_RUNTIME_64BIT
257
263
        case 64:
258
263
            ctx.cache = parse64(ctx.buffer.begin() + byteIndex);
259
263
            break;
260
350
        case 56:
261
350
            ctx.cache = parse56(ctx.buffer.begin() + byteIndex);
262
350
            break;
263
325
        case 48:
264
325
            ctx.cache = parse48(ctx.buffer.begin() + byteIndex);
265
325
            break;
266
459
        case 40:
267
459
            ctx.cache = parse40(ctx.buffer.begin() + byteIndex);
268
459
            break;
269
0
#endif
270
488
        case 32:
271
488
            ctx.cache = parse32(ctx.buffer.begin() + byteIndex);
272
488
            break;
273
356
        case 24:
274
356
            ctx.cache = parse24(ctx.buffer.begin() + byteIndex);
275
356
            break;
276
798
        case 16:
277
798
            ctx.cache = parse16(ctx.buffer.begin() + byteIndex);
278
798
            break;
279
1.00k
        default: // 8
280
1.00k
            ctx.cache = parse8(ctx.buffer.begin() + byteIndex);
281
1.00k
            break;
282
4.11k
        }
283
284
4.04k
        ctx.cache >>= static_cast<uint8_t>(alignedNumBits - ctx.cacheNumBits);
285
4.04k
    }
286
12.5k
}
287
288
/** Unchecked implementation of readBits. */
289
inline BaseType readBitsImpl(ReaderContext& ctx, uint8_t numBits)
290
63.4k
{
291
63.4k
    BaseType value = 0;
292
63.4k
    if (ctx.cacheNumBits < numBits)
293
12.5k
    {
294
        // read all remaining cache bits
295
12.5k
        value = ctx.cache & MASK_TABLE[ctx.cacheNumBits];
296
12.5k
        ctx.bitIndex += ctx.cacheNumBits;
297
12.5k
        numBits = static_cast<uint8_t>(numBits - ctx.cacheNumBits);
298
299
        // load next piece of buffer into cache
300
12.5k
        loadCacheNext(ctx, numBits);
301
302
        // add the remaining bits to the result
303
        // if numBits is sizeof(BaseType) * 8 here, value is already 0 (see MASK_TABLE[0])
304
12.5k
        if (numBits < sizeof(BaseType) * 8)
305
12.3k
            value <<= numBits;
306
12.5k
    }
307
63.4k
    value |= ((ctx.cache >> static_cast<uint8_t>(ctx.cacheNumBits - numBits)) & MASK_TABLE[numBits]);
308
63.4k
    ctx.cacheNumBits = static_cast<uint8_t>(ctx.cacheNumBits - numBits);
309
63.4k
    ctx.bitIndex += numBits;
310
311
63.4k
    return value;
312
63.4k
}
313
314
/** Unchecked version of readSignedBits. */
315
inline BaseSignedType readSignedBitsImpl(ReaderContext& ctx, uint8_t numBits)
316
3.42k
{
317
3.42k
    static const uint8_t typeSize = sizeof(BaseSignedType) * 8;
318
3.42k
    BaseType value = readBitsImpl(ctx, numBits);
319
320
    // Skip the signed overflow correction if numBits == typeSize.
321
    // In that case, the value that comes out the readBits function
322
    // is already correct.
323
3.42k
    if (numBits != 0 && 
numBits < typeSize3.42k
&&
324
3.42k
            
(value >= (static_cast<BaseType>(1) << static_cast<uint8_t>(numBits - 1)))2.91k
)
325
682
    {
326
682
        value -= static_cast<BaseType>(1) << numBits;
327
682
    }
328
329
3.42k
    return static_cast<BaseSignedType>(value);
330
3.42k
}
331
332
#ifndef ZSERIO_RUNTIME_64BIT
333
/** Unchecked implementation of readBits64. Always reads > 32bit! */
334
inline uint64_t readBits64Impl(ReaderContext& ctx, uint8_t numBits)
335
{
336
    // read the first 32 bits
337
    numBits = static_cast<uint8_t>(numBits - 32);
338
    uint64_t value = readBitsImpl(ctx, 32);
339
340
    // add the remaining bits
341
    value <<= numBits;
342
    value |= readBitsImpl(ctx, numBits);
343
344
    return value;
345
}
346
#endif
347
348
} // namespace
349
350
BitStreamReader::ReaderContext::ReaderContext(Span<const uint8_t> readBuffer, size_t readBufferBitSize) :
351
        buffer(readBuffer),
352
        bufferBitSize(readBufferBitSize),
353
        cache(0),
354
        cacheNumBits(0),
355
        bitIndex(0)
356
4.24k
{
357
4.24k
    if (buffer.size() > MAX_BUFFER_SIZE)
358
1
    {
359
1
        throw CppRuntimeException("BitStreamReader: Buffer size exceeded limit '")
360
1
                << MAX_BUFFER_SIZE << "' bytes!";
361
1
    }
362
4.24k
}
363
364
BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferByteSize) :
365
        BitStreamReader(Span<const uint8_t>(buffer, bufferByteSize))
366
15
{}
367
368
BitStreamReader::BitStreamReader(Span<const uint8_t> buffer) :
369
        m_context(buffer, buffer.size() * 8)
370
28
{}
371
372
BitStreamReader::BitStreamReader(Span<const uint8_t> buffer, size_t bufferBitSize) :
373
        m_context(buffer, bufferBitSize)
374
392
{
375
392
    if (buffer.size() < (bufferBitSize + 7) / 8)
376
1
    {
377
1
        throw CppRuntimeException("BitStreamReader: Wrong buffer bit size ('")
378
1
                << buffer.size() << "' < '" << (bufferBitSize + 7) / 8 << "')!";
379
1
    }
380
392
}
381
382
BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferBitSize, BitsTag) :
383
        m_context(Span<const uint8_t>(buffer, (bufferBitSize + 7) / 8), bufferBitSize)
384
3.82k
{}
385
386
uint32_t BitStreamReader::readBits(uint8_t numBits)
387
6.33k
{
388
6.33k
    checkNumBits(numBits);
389
390
6.33k
    return static_cast<uint32_t>(readBitsImpl(m_context, numBits));
391
6.33k
}
392
393
uint64_t BitStreamReader::readBits64(uint8_t numBits)
394
3.66k
{
395
3.66k
    checkNumBits64(numBits);
396
397
3.66k
#ifdef ZSERIO_RUNTIME_64BIT
398
3.66k
    return readBitsImpl(m_context, numBits);
399
#else
400
    if (numBits <= 32)
401
        return readBitsImpl(m_context, numBits);
402
403
    return readBits64Impl(m_context, numBits);
404
#endif
405
3.66k
}
406
407
int64_t BitStreamReader::readSignedBits64(uint8_t numBits)
408
1.92k
{
409
1.92k
    checkNumBits64(numBits);
410
411
1.92k
#ifdef ZSERIO_RUNTIME_64BIT
412
1.92k
    return readSignedBitsImpl(m_context, numBits);
413
#else
414
    if (numBits <= 32)
415
        return readSignedBitsImpl(m_context, numBits);
416
417
    int64_t value = static_cast<int64_t>(readBits64Impl(m_context, numBits));
418
419
    // Skip the signed overflow correction if numBits == 64.
420
    // In that case, the value that comes out the readBits function
421
    // is already correct.
422
    const bool needsSignExtension =
423
            numBits < 64 && (static_cast<uint64_t>(value) >= (UINT64_C(1) << (numBits - 1)));
424
    if (needsSignExtension)
425
        value -= UINT64_C(1) << numBits;
426
427
    return value;
428
#endif
429
1.92k
}
430
431
int32_t BitStreamReader::readSignedBits(uint8_t numBits)
432
1.50k
{
433
1.50k
    checkNumBits(numBits);
434
435
1.50k
    return static_cast<int32_t>(readSignedBitsImpl(m_context, numBits));
436
1.50k
}
437
438
int64_t BitStreamReader::readVarInt64()
439
2.34k
{
440
2.34k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
441
2.34k
    const bool sign = (byte & VARINT_SIGN_1) != 0;
442
2.34k
    uint64_t result = byte & VARINT_BYTE_1;
443
2.34k
    if ((byte & VARINT_HAS_NEXT_1) == 0)
444
347
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)284
;
445
446
1.99k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
447
1.99k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
448
1.99k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
449
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
450
451
1.71k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
452
1.71k
    result = static_cast<uint64_t>(result) << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
453
1.71k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
454
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
455
456
1.42k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
457
1.42k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
458
1.42k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
459
293
        return sign ? 
-static_cast<int64_t>(result)68
:
static_cast<int64_t>(result)225
;
460
461
1.13k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
462
1.13k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
463
1.13k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
464
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
465
466
852
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
467
852
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
468
852
    if ((byte & VARINT_HAS_NEXT_N) == 0)
469
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
470
471
568
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
472
568
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
473
568
    if ((byte & VARINT_HAS_NEXT_N) == 0)
474
284
        return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
475
476
284
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
477
284
    return sign ? 
-static_cast<int64_t>(result)63
:
static_cast<int64_t>(result)221
;
478
568
}
479
480
int32_t BitStreamReader::readVarInt32()
481
664
{
482
664
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
483
664
    const bool sign = (byte & VARINT_SIGN_1) != 0;
484
664
    uint32_t result = byte & VARINT_BYTE_1;
485
664
    if ((byte & VARINT_HAS_NEXT_1) == 0)
486
187
        return sign ? 
-static_cast<int32_t>(result)31
:
static_cast<int32_t>(result)156
;
487
488
477
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
489
477
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
490
477
    if ((byte & VARINT_HAS_NEXT_N) == 0)
491
156
        return sign ? 
-static_cast<int32_t>(result)31
:
static_cast<int32_t>(result)125
;
492
493
321
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
494
321
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
495
321
    if ((byte & VARINT_HAS_NEXT_N) == 0)
496
165
        return sign ? 
-static_cast<int32_t>(result)35
:
static_cast<int32_t>(result)130
;
497
498
156
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
499
156
    return sign ? 
-static_cast<int32_t>(result)31
:
static_cast<int32_t>(result)125
;
500
321
}
501
502
int16_t BitStreamReader::readVarInt16()
503
208
{
504
208
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
505
208
    const bool sign = (byte & VARINT_SIGN_1) != 0;
506
208
    uint16_t result = byte & VARINT_BYTE_1;
507
208
    if ((byte & VARINT_HAS_NEXT_1) == 0)
508
115
        return sign ? 
static_cast<int16_t>(-result)19
:
static_cast<int16_t>(result)96
;
509
510
93
    result = static_cast<uint16_t>(result << 8U);
511
93
    result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
512
93
    return sign ? 
static_cast<int16_t>(-result)16
:
static_cast<int16_t>(result)77
;
513
208
}
514
515
uint64_t BitStreamReader::readVarUInt64()
516
1.94k
{
517
1.94k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
518
1.94k
    uint64_t result = byte & VARUINT_BYTE;
519
1.94k
    if ((byte & VARUINT_HAS_NEXT) == 0)
520
445
        return result;
521
522
1.49k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
523
1.49k
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
524
1.49k
    if ((byte & VARUINT_HAS_NEXT) == 0)
525
192
        return result;
526
527
1.30k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
528
1.30k
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
529
1.30k
    if ((byte & VARUINT_HAS_NEXT) == 0)
530
322
        return result;
531
532
983
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
533
983
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
534
983
    if ((byte & VARUINT_HAS_NEXT) == 0)
535
222
        return result;
536
537
761
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
538
761
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
539
761
    if ((byte & VARUINT_HAS_NEXT) == 0)
540
191
        return result;
541
542
570
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
543
570
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
544
570
    if ((byte & VARUINT_HAS_NEXT) == 0)
545
190
        return result;
546
547
380
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
548
380
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
549
380
    if ((byte & VARUINT_HAS_NEXT) == 0)
550
190
        return result;
551
552
190
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
553
190
    return result;
554
380
}
555
556
uint32_t BitStreamReader::readVarUInt32()
557
478
{
558
478
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
559
478
    uint32_t result = byte & VARUINT_BYTE;
560
478
    if ((byte & VARUINT_HAS_NEXT) == 0)
561
125
        return result;
562
563
353
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
564
353
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
565
353
    if ((byte & VARUINT_HAS_NEXT) == 0)
566
96
        return result;
567
568
257
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
569
257
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
570
257
    if ((byte & VARUINT_HAS_NEXT) == 0)
571
162
        return result;
572
573
95
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
574
95
    return result;
575
257
}
576
577
uint16_t BitStreamReader::readVarUInt16()
578
178
{
579
178
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
580
178
    uint16_t result = byte & VARUINT_BYTE;
581
178
    if ((byte & VARUINT_HAS_NEXT) == 0)
582
100
        return result;
583
584
78
    result = static_cast<uint16_t>(result << 8U);
585
78
    result = static_cast<uint16_t>(result | readBitsImpl(m_context, 8)); // byte 2
586
78
    return result;
587
178
}
588
589
int64_t BitStreamReader::readVarInt()
590
3.10k
{
591
3.10k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
592
3.10k
    const bool sign = (byte & VARINT_SIGN_1) != 0;
593
3.10k
    uint64_t result = byte & VARINT_BYTE_1;
594
3.10k
    if ((byte & VARINT_HAS_NEXT_1) == 0)
595
570
        return sign ? 
(285
result == 0285
? INT64_MIN :
-static_cast<int64_t>(result)190
) :
static_cast<int64_t>(result)285
;
596
597
2.53k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
598
2.53k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
599
2.53k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
600
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
601
602
2.22k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
603
2.22k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
604
2.22k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
605
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
606
607
1.90k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
608
1.90k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
609
1.90k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
610
324
        return sign ? 
-static_cast<int64_t>(result)162
:
static_cast<int64_t>(result)162
;
611
612
1.58k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
613
1.58k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
614
1.58k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
615
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
616
617
1.26k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
618
1.26k
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
619
1.26k
    if ((byte & VARINT_HAS_NEXT_N) == 0)
620
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
621
622
949
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
623
949
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
624
949
    if ((byte & VARINT_HAS_NEXT_N) == 0)
625
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
626
627
633
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
628
633
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
629
633
    if ((byte & VARINT_HAS_NEXT_N) == 0)
630
316
        return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)158
;
631
632
317
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
633
317
    return sign ? 
-static_cast<int64_t>(result)158
:
static_cast<int64_t>(result)159
;
634
633
}
635
636
uint64_t BitStreamReader::readVarUInt()
637
1.55k
{
638
1.55k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
639
1.55k
    uint64_t result = byte & VARUINT_BYTE;
640
1.55k
    if ((byte & VARUINT_HAS_NEXT) == 0)
641
285
        return result;
642
643
1.27k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
644
1.27k
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
645
1.27k
    if ((byte & VARUINT_HAS_NEXT) == 0)
646
160
        return result;
647
648
1.11k
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
649
1.11k
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
650
1.11k
    if ((byte & VARUINT_HAS_NEXT) == 0)
651
164
        return result;
652
653
949
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
654
949
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
655
949
    if ((byte & VARUINT_HAS_NEXT) == 0)
656
158
        return result;
657
658
791
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
659
791
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
660
791
    if ((byte & VARUINT_HAS_NEXT) == 0)
661
158
        return result;
662
663
633
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
664
633
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
665
633
    if ((byte & VARUINT_HAS_NEXT) == 0)
666
158
        return result;
667
668
475
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 7
669
475
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
670
475
    if ((byte & VARUINT_HAS_NEXT) == 0)
671
158
        return result;
672
673
317
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 8
674
317
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
675
317
    if ((byte & VARUINT_HAS_NEXT) == 0)
676
158
        return result;
677
678
159
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 9
679
159
    return result;
680
317
}
681
682
uint32_t BitStreamReader::readVarSize()
683
2.65k
{
684
2.65k
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
685
2.65k
    uint32_t result = byte & VARUINT_BYTE;
686
2.65k
    if ((byte & VARUINT_HAS_NEXT) == 0)
687
2.08k
        return result;
688
689
577
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
690
577
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
691
577
    if ((byte & VARUINT_HAS_NEXT) == 0)
692
128
        return result;
693
694
449
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
695
449
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
696
449
    if ((byte & VARUINT_HAS_NEXT) == 0)
697
194
        return result;
698
699
255
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
700
255
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
701
255
    if ((byte & VARUINT_HAS_NEXT) == 0)
702
126
        return result;
703
704
129
    result = result << 8U | static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
705
129
    if (result > VARSIZE_MAX_VALUE)
706
2
        throw CppRuntimeException("BitStreamReader: Read value '")
707
2
                << result << "' is out of range for varsize type!";
708
709
127
    return result;
710
129
}
711
712
float BitStreamReader::readFloat16()
713
215
{
714
215
    const uint16_t halfPrecisionFloatValue = static_cast<uint16_t>(readBitsImpl(m_context, 16));
715
716
215
    return convertUInt16ToFloat(halfPrecisionFloatValue);
717
215
}
718
719
float BitStreamReader::readFloat32()
720
313
{
721
313
    const uint32_t singlePrecisionFloatValue = static_cast<uint32_t>(readBitsImpl(m_context, 32));
722
723
313
    return convertUInt32ToFloat(singlePrecisionFloatValue);
724
313
}
725
726
double BitStreamReader::readFloat64()
727
493
{
728
493
#ifdef ZSERIO_RUNTIME_64BIT
729
493
    const uint64_t doublePrecisionFloatValue = static_cast<uint64_t>(readBitsImpl(m_context, 64));
730
#else
731
    const uint64_t doublePrecisionFloatValue = readBits64Impl(m_context, 64);
732
#endif
733
734
493
    return convertUInt64ToDouble(doublePrecisionFloatValue);
735
493
}
736
737
bool BitStreamReader::readBool()
738
907
{
739
907
    return readBitsImpl(m_context, 1) != 0;
740
907
}
741
742
void BitStreamReader::setBitPosition(BitPosType position)
743
189
{
744
189
    if (position > m_context.bufferBitSize)
745
1
        throw CppRuntimeException("BitStreamReader: Reached eof(), setting of bit position failed!");
746
747
188
    m_context.bitIndex = (position / 8) * 8; // set to byte aligned position
748
188
    m_context.cacheNumBits = 0; // invalidate cache
749
188
    const uint8_t skip = static_cast<uint8_t>(position - m_context.bitIndex);
750
188
    if (skip != 0)
751
1
        readBits(skip);
752
188
}
753
754
void BitStreamReader::alignTo(size_t alignment)
755
4.73k
{
756
4.73k
    const BitPosType offset = getBitPosition() % alignment;
757
4.73k
    if (offset != 0)
758
2.45k
    {
759
2.45k
        const uint8_t skip = static_cast<uint8_t>(alignment - offset);
760
2.45k
        readBits64(skip);
761
2.45k
    }
762
4.73k
}
763
764
uint8_t BitStreamReader::readByte()
765
974
{
766
974
    return static_cast<uint8_t>(readBitsImpl(m_context, 8));
767
974
}
768
769
} // namespace zserio