GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/zserio/BitStreamReader.cpp Lines: 367 367 100.0 %
Date: 2023-12-13 14:51:09 Branches: 194 216 89.8 %

Line Branch Exec Source
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
8662
    inline BaseType parse64(Span<const uint8_t>::const_iterator bufferIt)
86
    {
87
17324
        return static_cast<BaseType>(*bufferIt) << 56U |
88
17324
               static_cast<BaseType>(*(bufferIt + 1)) << 48U |
89
17324
               static_cast<BaseType>(*(bufferIt + 2)) << 40U |
90
17324
               static_cast<BaseType>(*(bufferIt + 3)) << 32U |
91
17324
               static_cast<BaseType>(*(bufferIt + 4)) << 24U |
92
17324
               static_cast<BaseType>(*(bufferIt + 5)) << 16U |
93
17324
               static_cast<BaseType>(*(bufferIt + 6)) << 8U |
94
17324
               static_cast<BaseType>(*(bufferIt + 7));
95
    }
96
97
350
    inline BaseType parse56(Span<const uint8_t>::const_iterator bufferIt)
98
    {
99
700
        return static_cast<BaseType>(*bufferIt) << 48U |
100
700
               static_cast<BaseType>(*(bufferIt + 1)) << 40U |
101
700
               static_cast<BaseType>(*(bufferIt + 2)) << 32U |
102
700
               static_cast<BaseType>(*(bufferIt + 3)) << 24U |
103
700
               static_cast<BaseType>(*(bufferIt + 4)) << 16U |
104
700
               static_cast<BaseType>(*(bufferIt + 5)) << 8U |
105
700
               static_cast<BaseType>(*(bufferIt + 6));
106
    }
107
108
325
    inline BaseType parse48(Span<const uint8_t>::const_iterator bufferIt)
109
    {
110
650
        return static_cast<BaseType>(*bufferIt) << 40U |
111
650
               static_cast<BaseType>(*(bufferIt + 1)) << 32U |
112
650
               static_cast<BaseType>(*(bufferIt + 2)) << 24U |
113
650
               static_cast<BaseType>(*(bufferIt + 3)) << 16U |
114
650
               static_cast<BaseType>(*(bufferIt + 4)) << 8U |
115
650
               static_cast<BaseType>(*(bufferIt + 5));
116
    }
117
118
459
    inline BaseType parse40(Span<const uint8_t>::const_iterator bufferIt)
119
    {
120
918
        return static_cast<BaseType>(*bufferIt) << 32U |
121
918
               static_cast<BaseType>(*(bufferIt + 1)) << 24U |
122
918
               static_cast<BaseType>(*(bufferIt + 2)) << 16U |
123
918
               static_cast<BaseType>(*(bufferIt + 3)) << 8U |
124
918
               static_cast<BaseType>(*(bufferIt + 4));
125
    }
126
#endif
127
488
    inline BaseType parse32(Span<const uint8_t>::const_iterator bufferIt)
128
    {
129
976
        return static_cast<BaseType>(*bufferIt) << 24U |
130
976
               static_cast<BaseType>(*(bufferIt + 1)) << 16U |
131
976
               static_cast<BaseType>(*(bufferIt + 2)) << 8U |
132
976
               static_cast<BaseType>(*(bufferIt + 3));
133
    }
134
135
356
    inline BaseType parse24(Span<const uint8_t>::const_iterator bufferIt)
136
    {
137
712
        return static_cast<BaseType>(*bufferIt) << 16U |
138
712
               static_cast<BaseType>(*(bufferIt + 1)) << 8U |
139
712
               static_cast<BaseType>(*(bufferIt + 2));
140
    }
141
142
798
    inline BaseType parse16(Span<const uint8_t>::const_iterator bufferIt)
143
    {
144
1596
        return static_cast<BaseType>(*bufferIt) << 8U |
145
1596
               static_cast<BaseType>(*(bufferIt + 1));
146
    }
147
148
1006
    inline BaseType parse8(Span<const uint8_t>::const_iterator bufferIt)
149
    {
150
1006
        return static_cast<BaseType>(*bufferIt);
151
    }
152
153
    /** Optimization which increases chances to inline checkNumBits and checkNumBits64. */
154
8
    inline void throwNumBitsIsNotValid(uint8_t numBits)
155
    {
156

16
        throw CppRuntimeException("BitStreamReader: ReadBits #") << numBits <<
157
24
                " is not valid, reading from stream failed!";
158
    }
159
160
    /** Checks numBits validity for 32-bit reads. */
161
7838
    inline void checkNumBits(uint8_t numBits)
162
    {
163
7838
        if (numBits > 32)
164
4
            throwNumBitsIsNotValid(numBits);
165
7834
    }
166
167
    /** Checks numBits validity for 64-bit reads. */
168
5589
    inline void checkNumBits64(uint8_t numBits)
169
    {
170
5589
        if (numBits > 64)
171
4
            throwNumBitsIsNotValid(numBits);
172
5585
    }
173
174
    /** Optimization which increases chances to inline loadCacheNext. */
175
72
    inline void throwEof()
176
    {
177
72
        throw CppRuntimeException("BitStreamReader: Reached eof(), reading from stream failed!");
178
    }
179
180
    /** Loads next 32/64 bits to 32/64 bit-cache. */
181
12516
    inline void loadCacheNext(ReaderContext& ctx, uint8_t numBits)
182
    {
183
        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
12516
        const size_t byteIndex = ctx.bitIndex >> 3U;
187
12516
        if (ctx.bufferBitSize >= ctx.bitIndex + cacheBitSize)
188
        {
189
            ctx.cache =
190
#ifdef ZSERIO_RUNTIME_64BIT
191
8399
                    parse64(ctx.buffer.begin() + byteIndex);
192
#else
193
                    parse32(ctx.buffer.begin() + byteIndex);
194
#endif
195
8399
            ctx.cacheNumBits = cacheBitSize;
196
        }
197
        else
198
        {
199
4117
            if (ctx.bitIndex + numBits > ctx.bufferBitSize)
200
72
                throwEof();
201
202
4045
            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
4045
            const uint8_t alignedNumBits = (ctx.cacheNumBits + 7U) & ~0x7U;
206
207


4045
            switch (alignedNumBits)
208
            {
209
#ifdef ZSERIO_RUNTIME_64BIT
210
            case 64:
211
263
                ctx.cache = parse64(ctx.buffer.begin() + byteIndex);
212
263
                break;
213
            case 56:
214
350
                ctx.cache = parse56(ctx.buffer.begin() + byteIndex);
215
350
                break;
216
            case 48:
217
325
                ctx.cache = parse48(ctx.buffer.begin() + byteIndex);
218
325
                break;
219
            case 40:
220
459
                ctx.cache = parse40(ctx.buffer.begin() + byteIndex);
221
459
                break;
222
#endif
223
            case 32:
224
488
                ctx.cache = parse32(ctx.buffer.begin() + byteIndex);
225
488
                break;
226
            case 24:
227
356
                ctx.cache = parse24(ctx.buffer.begin() + byteIndex);
228
356
                break;
229
            case 16:
230
798
                ctx.cache = parse16(ctx.buffer.begin() + byteIndex);
231
798
                break;
232
            default: // 8
233
1006
                ctx.cache = parse8(ctx.buffer.begin() + byteIndex);
234
1006
                break;
235
            }
236
237
4045
            ctx.cache >>= static_cast<uint8_t>(alignedNumBits - ctx.cacheNumBits);
238
        }
239
12444
    }
240
241
    /** Unchecked implementation of readBits. */
242
63482
    inline BaseType readBitsImpl(ReaderContext& ctx, uint8_t numBits)
243
    {
244
63482
        BaseType value = 0;
245
63482
        if (ctx.cacheNumBits < numBits)
246
        {
247
            // read all remaining cache bits
248
12516
            value = ctx.cache & MASK_TABLE[ctx.cacheNumBits];
249
12516
            ctx.bitIndex += ctx.cacheNumBits;
250
12516
            numBits -= ctx.cacheNumBits;
251
252
            // load next piece of buffer into cache
253
12516
            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
12444
            if (numBits < sizeof(BaseType) * 8)
258
12385
                value <<= numBits;
259
        }
260
63410
        value |= ((ctx.cache >> static_cast<uint8_t>(ctx.cacheNumBits - numBits)) & MASK_TABLE[numBits]);
261
63410
        ctx.cacheNumBits -= numBits;
262
63410
        ctx.bitIndex += numBits;
263
264
63410
        return value;
265
    }
266
267
    /** Unchecked version of readSignedBits. */
268
3428
    inline BaseSignedType readSignedBitsImpl(ReaderContext& ctx, uint8_t numBits)
269
    {
270
        static const uint8_t typeSize = sizeof(BaseSignedType) * 8;
271
3428
        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

6341
        if (numBits != 0 && numBits < typeSize &&
277
2913
                (value >= (static_cast<BaseType>(1) << static_cast<uint8_t>(numBits - 1))))
278
        {
279
682
            value -= static_cast<BaseType>(1) << numBits;
280
        }
281
282
3428
        return static_cast<BaseSignedType>(value);
283
    }
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
4245
BitStreamReader::ReaderContext::ReaderContext(Span<const uint8_t> readBuffer, size_t readBufferBitSize)
303
:   buffer(readBuffer),
304
    bufferBitSize(readBufferBitSize),
305
    cache(0),
306
    cacheNumBits(0),
307
4245
    bitIndex(0)
308
{
309
4245
    if (buffer.size() > MAX_BUFFER_SIZE)
310
    {
311

2
        throw CppRuntimeException("BitStreamReader: Buffer size exceeded limit '") << MAX_BUFFER_SIZE <<
312
3
                "' bytes!";
313
    }
314
4244
}
315
316
15
BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferByteSize) :
317
16
        BitStreamReader(Span<const uint8_t>(buffer, bufferByteSize))
318
14
{}
319
320
28
BitStreamReader::BitStreamReader(Span<const uint8_t> buffer) :
321
28
        m_context(buffer, buffer.size() * 8)
322
27
{}
323
324
392
BitStreamReader::BitStreamReader(Span<const uint8_t> buffer, size_t bufferBitSize) :
325
392
        m_context(buffer, bufferBitSize)
326
{
327
392
    if (buffer.size() < (bufferBitSize + 7) / 8)
328
    {
329

2
        throw CppRuntimeException("BitStreamReader: Wrong buffer bit size ('") << buffer.size() <<
330

3
                "' < '" << (bufferBitSize + 7) / 8 << "')!";
331
    }
332
391
}
333
334
3825
BitStreamReader::BitStreamReader(const uint8_t* buffer, size_t bufferBitSize, BitsTag) :
335
3825
        m_context(Span<const uint8_t>(buffer, (bufferBitSize + 7) / 8), bufferBitSize)
336
3825
{}
337
338
6335
uint32_t BitStreamReader::readBits(uint8_t numBits)
339
{
340
6335
    checkNumBits(numBits);
341
342
6333
    return static_cast<uint32_t>(readBitsImpl(m_context, numBits));
343
}
344
345
3660
uint64_t BitStreamReader::readBits64(uint8_t numBits)
346
{
347
3660
    checkNumBits64(numBits);
348
349
#ifdef ZSERIO_RUNTIME_64BIT
350
3658
    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
}
358
359
1929
int64_t BitStreamReader::readSignedBits64(uint8_t numBits)
360
{
361
1929
    checkNumBits64(numBits);
362
363
#ifdef ZSERIO_RUNTIME_64BIT
364
1927
    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
}
382
383
1503
int32_t BitStreamReader::readSignedBits(uint8_t numBits)
384
{
385
1503
    checkNumBits(numBits);
386
387
1501
    return static_cast<int32_t>(readSignedBitsImpl(m_context, numBits));
388
}
389
390
2344
int64_t BitStreamReader::readVarInt64()
391
{
392
2344
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
393
2344
    const bool sign = (byte & VARINT_SIGN_1) != 0;
394
2344
    uint64_t result = byte & VARINT_BYTE_1;
395
2344
    if ((byte & VARINT_HAS_NEXT_1) == 0)
396
347
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
397
398
1997
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
399
1997
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
400
1997
    if ((byte & VARINT_HAS_NEXT_N) == 0)
401
284
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
402
403
1713
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
404
1713
    result = static_cast<uint64_t>(result) << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
405
1713
    if ((byte & VARINT_HAS_NEXT_N) == 0)
406
284
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
407
408
1429
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
409
1429
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
410
1429
    if ((byte & VARINT_HAS_NEXT_N) == 0)
411
293
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
412
413
1136
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
414
1136
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
415
1136
    if ((byte & VARINT_HAS_NEXT_N) == 0)
416
284
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
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) : static_cast<int64_t>(result);
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) : static_cast<int64_t>(result);
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) : static_cast<int64_t>(result);
430
}
431
432
664
int32_t BitStreamReader::readVarInt32()
433
{
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) : static_cast<int32_t>(result);
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) : static_cast<int32_t>(result);
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) : static_cast<int32_t>(result);
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) : static_cast<int32_t>(result);
452
}
453
454
208
int16_t BitStreamReader::readVarInt16()
455
{
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) : static_cast<int16_t>(result);
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) : static_cast<int16_t>(result);
464
}
465
466
1942
uint64_t BitStreamReader::readVarUInt64()
467
{
468
1942
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
469
1942
    uint64_t result = byte & VARUINT_BYTE;
470
1942
    if ((byte & VARUINT_HAS_NEXT) == 0)
471
445
        return result;
472
473
1497
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
474
1497
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
475
1497
    if ((byte & VARUINT_HAS_NEXT) == 0)
476
192
        return result;
477
478
1305
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
479
1305
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
480
1305
    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
}
506
507
478
uint32_t BitStreamReader::readVarUInt32()
508
{
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
}
527
528
178
uint16_t BitStreamReader::readVarUInt16()
529
{
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
}
538
539
3107
int64_t BitStreamReader::readVarInt()
540
{
541
3107
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
542
3107
    const bool sign = (byte & VARINT_SIGN_1) != 0;
543
3107
    uint64_t result = byte & VARINT_BYTE_1;
544
3107
    if ((byte & VARINT_HAS_NEXT_1) == 0)
545

570
        return sign ? (result == 0 ? INT64_MIN : -static_cast<int64_t>(result)) : static_cast<int64_t>(result);
546
547
2537
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
548
2537
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
549
2537
    if ((byte & VARINT_HAS_NEXT_N) == 0)
550
316
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
551
552
2221
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
553
2221
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
554
2221
    if ((byte & VARINT_HAS_NEXT_N) == 0)
555
316
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
556
557
1905
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 4
558
1905
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
559
1905
    if ((byte & VARINT_HAS_NEXT_N) == 0)
560
324
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
561
562
1581
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 5
563
1581
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
564
1581
    if ((byte & VARINT_HAS_NEXT_N) == 0)
565
316
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
566
567
1265
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 6
568
1265
    result = result << 7U | static_cast<uint8_t>(byte & VARINT_BYTE_N);
569
1265
    if ((byte & VARINT_HAS_NEXT_N) == 0)
570
316
        return sign ? -static_cast<int64_t>(result) : static_cast<int64_t>(result);
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) : static_cast<int64_t>(result);
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) : static_cast<int64_t>(result);
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) : static_cast<int64_t>(result);
584
}
585
586
1558
uint64_t BitStreamReader::readVarUInt()
587
{
588
1558
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
589
1558
    uint64_t result = byte & VARUINT_BYTE;
590
1558
    if ((byte & VARUINT_HAS_NEXT) == 0)
591
285
        return result;
592
593
1273
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 2
594
1273
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
595
1273
    if ((byte & VARUINT_HAS_NEXT) == 0)
596
160
        return result;
597
598
1113
    byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 3
599
1113
    result = result << 7U | static_cast<uint8_t>(byte & VARUINT_BYTE);
600
1113
    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
}
631
632
2659
uint32_t BitStreamReader::readVarSize()
633
{
634
2659
    uint8_t byte = static_cast<uint8_t>(readBitsImpl(m_context, 8)); // byte 1
635
2659
    uint32_t result = byte & VARUINT_BYTE;
636
2659
    if ((byte & VARUINT_HAS_NEXT) == 0)
637
2082
        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

4
        throw CppRuntimeException("BitStreamReader: Read value '") << result <<
657
6
                "' is out of range for varsize type!";
658
659
127
    return result;
660
}
661
662
215
float BitStreamReader::readFloat16()
663
{
664
215
    const uint16_t halfPrecisionFloatValue = static_cast<uint16_t>(readBitsImpl(m_context, 16));
665
666
215
    return convertUInt16ToFloat(halfPrecisionFloatValue);
667
}
668
669
313
float BitStreamReader::readFloat32()
670
{
671
313
    const uint32_t singlePrecisionFloatValue = static_cast<uint32_t>(readBitsImpl(m_context, 32));
672
673
313
    return convertUInt32ToFloat(singlePrecisionFloatValue);
674
}
675
676
493
double BitStreamReader::readFloat64()
677
{
678
#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
}
686
687
907
bool BitStreamReader::readBool()
688
{
689
907
    return readBitsImpl(m_context, 1) != 0;
690
}
691
692
189
void BitStreamReader::setBitPosition(BitPosType position)
693
{
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
4732
void BitStreamReader::alignTo(size_t alignment)
705
{
706
4732
    const BitPosType offset = getBitPosition() % alignment;
707
4732
    if (offset != 0)
708
    {
709
2455
        const uint8_t skip = static_cast<uint8_t>(alignment - offset);
710
2455
        readBits64(skip);
711
    }
712
4732
}
713
714
974
uint8_t BitStreamReader::readByte()
715
{
716
974
    return static_cast<uint8_t>(readBitsImpl(m_context, 8));
717
}
718
719
} // namespace zserio