Coverage Report

Created: 2023-12-13 14:58

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