Coverage Report

Created: 2024-04-30 09:35

src/zserio/BitSizeOfCalculator.cpp
Line
Count
Source
1
#include <array>
2
#include <limits>
3
4
#include "zserio/BitSizeOfCalculator.h"
5
#include "zserio/CppRuntimeException.h"
6
7
namespace zserio
8
{
9
10
static const std::array<uint64_t, 2> VARIN16_MAX_VALUES = {
11
        (UINT64_C(1) << (6)) - 1,
12
        (UINT64_C(1) << (6 + 8)) - 1,
13
};
14
15
static const std::array<uint64_t, 4> VARINT32_MAX_VALUES = {
16
        (UINT64_C(1) << (6)) - 1,
17
        (UINT64_C(1) << (6 + 7)) - 1,
18
        (UINT64_C(1) << (6 + 7 + 7)) - 1,
19
        (UINT64_C(1) << (6 + 7 + 7 + 8)) - 1,
20
};
21
22
static const std::array<uint64_t, 8> VARINT64_MAX_VALUES = {
23
        (UINT64_C(1) << (6)) - 1,
24
        (UINT64_C(1) << (6 + 7)) - 1,
25
        (UINT64_C(1) << (6 + 7 + 7)) - 1,
26
        (UINT64_C(1) << (6 + 7 + 7 + 7)) - 1,
27
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7)) - 1,
28
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7)) - 1,
29
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7 + 7)) - 1,
30
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1,
31
};
32
33
static const std::array<uint64_t, 2> VARUINT16_MAX_VALUES = {
34
        (UINT64_C(1) << (7)) - 1,
35
        (UINT64_C(1) << (7 + 8)) - 1,
36
};
37
38
static const std::array<uint64_t, 4> VARUINT32_MAX_VALUES = {
39
        (UINT64_C(1) << (7)) - 1,
40
        (UINT64_C(1) << (7 + 7)) - 1,
41
        (UINT64_C(1) << (7 + 7 + 7)) - 1,
42
        (UINT64_C(1) << (7 + 7 + 7 + 8)) - 1,
43
};
44
45
static const std::array<uint64_t, 8> VARUINT64_MAX_VALUES = {
46
        (UINT64_C(1) << (7)) - 1,
47
        (UINT64_C(1) << (7 + 7)) - 1,
48
        (UINT64_C(1) << (7 + 7 + 7)) - 1,
49
        (UINT64_C(1) << (7 + 7 + 7 + 7)) - 1,
50
        (UINT64_C(1) << (7 + 7 + 7 + 7 + 7)) - 1,
51
        (UINT64_C(1) << (7 + 7 + 7 + 7 + 7 + 7)) - 1,
52
        (UINT64_C(1) << (7 + 7 + 7 + 7 + 7 + 7 + 7)) - 1,
53
        (UINT64_C(1) << (7 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1,
54
};
55
56
static const std::array<uint64_t, 9> VARINT_MAX_VALUES = {
57
        (UINT64_C(1) << (6)) - 1,
58
        (UINT64_C(1) << (6 + 7)) - 1,
59
        (UINT64_C(1) << (6 + 7 + 7)) - 1,
60
        (UINT64_C(1) << (6 + 7 + 7 + 7)) - 1,
61
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7)) - 1,
62
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7)) - 1,
63
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7 + 7)) - 1,
64
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 7)) - 1,
65
        (UINT64_C(1) << (6 + 7 + 7 + 7 + 7 + 7 + 7 + 7 + 8)) - 1,
66
};
67
68
static const std::array<uint64_t, 9> VARUINT_MAX_VALUES = {
69
        (UINT64_C(1) << (7)) - 1,
70
        (UINT64_C(1) << (7 + 7)) - 1,
71
        (UINT64_C(1) << (7 + 7 + 7)) - 1,
72
        (UINT64_C(1) << (7 + 7 + 7 + 7)) - 1,
73
        (UINT64_C(1) << (7 + 7 + 7 + 7 + 7)) - 1,
74
        (UINT64_C(1) << (7 + 7 + 7 + 7 + 7 + 7)) - 1,
75
        (UINT64_C(1) << (7 + 7 + 7 + 7 + 7 + 7 + 7)) - 1,
76
        (UINT64_C(1) << (7 + 7 + 7 + 7 + 7 + 7 + 7 + 7)) - 1,
77
        UINT64_MAX,
78
};
79
80
static const std::array<uint64_t, 5> VARSIZE_MAX_VALUES = {
81
        (UINT64_C(1) << (7)) - 1,
82
        (UINT64_C(1) << (7 + 7)) - 1,
83
        (UINT64_C(1) << (7 + 7 + 7)) - 1,
84
        (UINT64_C(1) << (7 + 7 + 7 + 7)) - 1,
85
        (UINT64_C(1) << (2 + 7 + 7 + 7 + 8)) - 1,
86
};
87
88
template <std::size_t SIZE>
89
static size_t bitSizeOfVarIntImpl(
90
        uint64_t value, const std::array<uint64_t, SIZE>& maxValues, const char* varIntName)
91
32.7k
{
92
32.7k
    size_t byteSize = 1;
93
32.7k
    for (uint64_t maxValue : maxValues)
94
112k
    {
95
112k
        if (value <= maxValue)
96
32.7k
            break;
97
79.8k
        byteSize++;
98
79.8k
    }
99
100
32.7k
    if (byteSize > maxValues.size())
101
14
    {
102
14
        throw CppRuntimeException("BitSizeOfCalculator: Value '")
103
14
                << value << "' is out of range for " << varIntName << "!";
104
14
    }
105
106
32.7k
    return byteSize * 8;
107
32.7k
}
108
109
template <typename T>
110
static uint64_t convertToAbsValue(T value)
111
13.6k
{
112
13.6k
    return static_cast<uint64_t>((value < 0) ? 
-value4.62k
:
value9.05k
);
113
13.6k
}
114
115
size_t bitSizeOfVarInt16(int16_t value)
116
492
{
117
492
    return bitSizeOfVarIntImpl(convertToAbsValue(value), VARIN16_MAX_VALUES, "varint16");
118
492
}
119
120
size_t bitSizeOfVarInt32(int32_t value)
121
1.47k
{
122
1.47k
    return bitSizeOfVarIntImpl(convertToAbsValue(value), VARINT32_MAX_VALUES, "varint32");
123
1.47k
}
124
125
size_t bitSizeOfVarInt64(int64_t value)
126
4.98k
{
127
4.98k
    return bitSizeOfVarIntImpl(convertToAbsValue(value), VARINT64_MAX_VALUES, "varint64");
128
4.98k
}
129
130
size_t bitSizeOfVarUInt16(uint16_t value)
131
428
{
132
428
    return bitSizeOfVarIntImpl(value, VARUINT16_MAX_VALUES, "varuint16");
133
428
}
134
135
size_t bitSizeOfVarUInt32(uint32_t value)
136
1.09k
{
137
1.09k
    return bitSizeOfVarIntImpl(value, VARUINT32_MAX_VALUES, "varuint32");
138
1.09k
}
139
140
size_t bitSizeOfVarUInt64(uint64_t value)
141
6.08k
{
142
6.08k
    return bitSizeOfVarIntImpl(value, VARUINT64_MAX_VALUES, "varuint64");
143
6.08k
}
144
145
size_t bitSizeOfVarInt(int64_t value)
146
6.79k
{
147
6.79k
    if (value == INT64_MIN)
148
65
        return 8; // INT64_MIN is stored as -0
149
150
6.73k
    return bitSizeOfVarIntImpl(convertToAbsValue(value), VARINT_MAX_VALUES, "varint");
151
6.79k
}
152
153
size_t bitSizeOfVarUInt(uint64_t value)
154
3.49k
{
155
3.49k
    return bitSizeOfVarIntImpl(value, VARUINT_MAX_VALUES, "varuint");
156
3.49k
}
157
158
size_t bitSizeOfVarSize(uint32_t value)
159
8.01k
{
160
8.01k
    return bitSizeOfVarIntImpl(value, VARSIZE_MAX_VALUES, "varsize");
161
8.01k
}
162
163
size_t bitSizeOfBytes(Span<const uint8_t> bytesValue)
164
135
{
165
135
    const size_t bytesSize = bytesValue.size();
166
167
    // the bytes consists of varsize for size followed by the bytes
168
135
    return bitSizeOfVarSize(convertSizeToUInt32(bytesSize)) + bytesSize * 8;
169
135
}
170
171
size_t bitSizeOfString(StringView stringValue)
172
231
{
173
231
    const size_t stringSize = stringValue.size();
174
175
    // the string consists of varsize for size followed by the UTF-8 encoded string
176
231
    return bitSizeOfVarSize(convertSizeToUInt32(stringSize)) + stringSize * 8;
177
231
}
178
179
} // namespace zserio