Coverage Report

Created: 2024-07-18 11:41

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
        {
97
32.7k
            break;
98
32.7k
        }
99
79.8k
        byteSize++;
100
79.8k
    }
101
102
32.7k
    if (byteSize > maxValues.size())
103
14
    {
104
14
        throw CppRuntimeException("BitSizeOfCalculator: Value '")
105
14
                << value << "' is out of range for " << varIntName << "!";
106
14
    }
107
108
32.7k
    return byteSize * 8;
109
32.7k
}
110
111
template <typename T>
112
static uint64_t convertToAbsValue(T value)
113
13.6k
{
114
13.6k
    return static_cast<uint64_t>((value < 0) ? 
-value4.62k
:
value9.05k
);
115
13.6k
}
116
117
size_t bitSizeOfVarInt16(int16_t value)
118
492
{
119
492
    return bitSizeOfVarIntImpl(convertToAbsValue(value), VARIN16_MAX_VALUES, "varint16");
120
492
}
121
122
size_t bitSizeOfVarInt32(int32_t value)
123
1.47k
{
124
1.47k
    return bitSizeOfVarIntImpl(convertToAbsValue(value), VARINT32_MAX_VALUES, "varint32");
125
1.47k
}
126
127
size_t bitSizeOfVarInt64(int64_t value)
128
4.98k
{
129
4.98k
    return bitSizeOfVarIntImpl(convertToAbsValue(value), VARINT64_MAX_VALUES, "varint64");
130
4.98k
}
131
132
size_t bitSizeOfVarUInt16(uint16_t value)
133
428
{
134
428
    return bitSizeOfVarIntImpl(value, VARUINT16_MAX_VALUES, "varuint16");
135
428
}
136
137
size_t bitSizeOfVarUInt32(uint32_t value)
138
1.09k
{
139
1.09k
    return bitSizeOfVarIntImpl(value, VARUINT32_MAX_VALUES, "varuint32");
140
1.09k
}
141
142
size_t bitSizeOfVarUInt64(uint64_t value)
143
6.08k
{
144
6.08k
    return bitSizeOfVarIntImpl(value, VARUINT64_MAX_VALUES, "varuint64");
145
6.08k
}
146
147
size_t bitSizeOfVarInt(int64_t value)
148
6.79k
{
149
6.79k
    if (value == INT64_MIN)
150
65
    {
151
65
        return 8; // INT64_MIN is stored as -0
152
65
    }
153
154
6.73k
    return bitSizeOfVarIntImpl(convertToAbsValue(value), VARINT_MAX_VALUES, "varint");
155
6.79k
}
156
157
size_t bitSizeOfVarUInt(uint64_t value)
158
3.49k
{
159
3.49k
    return bitSizeOfVarIntImpl(value, VARUINT_MAX_VALUES, "varuint");
160
3.49k
}
161
162
size_t bitSizeOfVarSize(uint32_t value)
163
8.01k
{
164
8.01k
    return bitSizeOfVarIntImpl(value, VARSIZE_MAX_VALUES, "varsize");
165
8.01k
}
166
167
size_t bitSizeOfBytes(Span<const uint8_t> bytesValue)
168
135
{
169
135
    const size_t bytesSize = bytesValue.size();
170
171
    // the bytes consists of varsize for size followed by the bytes
172
135
    return bitSizeOfVarSize(convertSizeToUInt32(bytesSize)) + bytesSize * 8;
173
135
}
174
175
size_t bitSizeOfString(StringView stringValue)
176
231
{
177
231
    const size_t stringSize = stringValue.size();
178
179
    // the string consists of varsize for size followed by the UTF-8 encoded string
180
231
    return bitSizeOfVarSize(convertSizeToUInt32(stringSize)) + stringSize * 8;
181
231
}
182
183
} // namespace zserio