GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#include <cstring> |
||
2 |
#include <fstream> |
||
3 |
#include <array> |
||
4 |
#include <algorithm> |
||
5 |
|||
6 |
#include "zserio/CppRuntimeException.h" |
||
7 |
#include "zserio/BitSizeOfCalculator.h" |
||
8 |
#include "zserio/FloatUtil.h" |
||
9 |
#include "zserio/BitStreamWriter.h" |
||
10 |
|||
11 |
namespace zserio |
||
12 |
{ |
||
13 |
|||
14 |
static const std::array<uint32_t, 33> MAX_U32_VALUES = |
||
15 |
{ |
||
16 |
0x00U, |
||
17 |
0x0001U, 0x0003U, 0x0007U, 0x000fU, |
||
18 |
0x001fU, 0x003fU, 0x007fU, 0x00ffU, |
||
19 |
0x01ffU, 0x03ffU, 0x07ffU, 0x0fffU, |
||
20 |
0x1fffU, 0x3fffU, 0x7fffU, 0xffffU, |
||
21 |
0x0001ffffU, 0x0003ffffU, 0x0007ffffU, 0x000fffffU, |
||
22 |
0x001fffffU, 0x003fffffU, 0x007fffffU, 0x00ffffffU, |
||
23 |
0x01ffffffU, 0x03ffffffU, 0x07ffffffU, 0x0fffffffU, |
||
24 |
0x1fffffffU, 0x3fffffffU, 0x7fffffffU, 0xffffffffU, |
||
25 |
}; |
||
26 |
|||
27 |
static const std::array<int32_t, 33> MIN_I32_VALUES = |
||
28 |
{ |
||
29 |
0, |
||
30 |
-0x0001, -0x0002, -0x0004, -0x0008, |
||
31 |
-0x0010, -0x0020, -0x0040, -0x0080, |
||
32 |
-0x0100, -0x0200, -0x0400, -0x0800, |
||
33 |
-0x1000, -0x2000, -0x4000, -0x8000, |
||
34 |
-0x00010000, -0x00020000, -0x00040000, -0x00080000, |
||
35 |
-0x00100000, -0x00200000, -0x00400000, -0x00800000, |
||
36 |
-0x01000000, -0x02000000, -0x04000000, -0x08000000, |
||
37 |
-0x10000000, -0x20000000, -0x40000000, INT32_MIN |
||
38 |
}; |
||
39 |
|||
40 |
static const std::array<int32_t, 33> MAX_I32_VALUES = |
||
41 |
{ |
||
42 |
0x00, |
||
43 |
0x0000, 0x0001, 0x0003, 0x0007, |
||
44 |
0x000f, 0x001f, 0x003f, 0x007f, |
||
45 |
0x00ff, 0x01ff, 0x03ff, 0x07ff, |
||
46 |
0x0fff, 0x1fff, 0x3fff, 0x7fff, |
||
47 |
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, |
||
48 |
0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, |
||
49 |
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, |
||
50 |
0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff |
||
51 |
}; |
||
52 |
|||
53 |
static const std::array<uint64_t, 65> MAX_U64_VALUES = |
||
54 |
{ |
||
55 |
0x00ULL, |
||
56 |
0x0001ULL, 0x0003ULL, 0x0007ULL, 0x000fULL, |
||
57 |
0x001fULL, 0x003fULL, 0x007fULL, 0x00ffULL, |
||
58 |
0x01ffULL, 0x03ffULL, 0x07ffULL, 0x0fffULL, |
||
59 |
0x1fffULL, 0x3fffULL, 0x7fffULL, 0xffffULL, |
||
60 |
0x0001ffffULL, 0x0003ffffULL, 0x0007ffffULL, 0x000fffffULL, |
||
61 |
0x001fffffULL, 0x003fffffULL, 0x007fffffULL, 0x00ffffffULL, |
||
62 |
0x01ffffffULL, 0x03ffffffULL, 0x07ffffffULL, 0x0fffffffULL, |
||
63 |
0x1fffffffULL, 0x3fffffffULL, 0x7fffffffULL, 0xffffffffULL, |
||
64 |
0x0001ffffffffULL, 0x0003ffffffffULL, 0x0007ffffffffULL, 0x000fffffffffULL, |
||
65 |
0x001fffffffffULL, 0x003fffffffffULL, 0x007fffffffffULL, 0x00ffffffffffULL, |
||
66 |
0x01ffffffffffULL, 0x03ffffffffffULL, 0x07ffffffffffULL, 0x0fffffffffffULL, |
||
67 |
0x1fffffffffffULL, 0x3fffffffffffULL, 0x7fffffffffffULL, 0xffffffffffffULL, |
||
68 |
0x0001ffffffffffffULL, 0x0003ffffffffffffULL, 0x0007ffffffffffffULL, 0x000fffffffffffffULL, |
||
69 |
0x001fffffffffffffULL, 0x003fffffffffffffULL, 0x007fffffffffffffULL, 0x00ffffffffffffffULL, |
||
70 |
0x01ffffffffffffffULL, 0x03ffffffffffffffULL, 0x07ffffffffffffffULL, 0x0fffffffffffffffULL, |
||
71 |
0x1fffffffffffffffULL, 0x3fffffffffffffffULL, 0x7fffffffffffffffULL, 0xffffffffffffffffULL |
||
72 |
}; |
||
73 |
|||
74 |
static const std::array<int64_t, 65> MIN_I64_VALUES = |
||
75 |
{ |
||
76 |
0LL, |
||
77 |
-0x0001LL, -0x0002LL, -0x0004LL, -0x0008LL, |
||
78 |
-0x0010LL, -0x0020LL, -0x0040LL, -0x0080LL, |
||
79 |
-0x0100LL, -0x0200LL, -0x0400LL, -0x0800LL, |
||
80 |
-0x1000LL, -0x2000LL, -0x4000LL, -0x8000LL, |
||
81 |
-0x00010000LL, -0x00020000LL, -0x00040000LL, -0x00080000LL, |
||
82 |
-0x00100000LL, -0x00200000LL, -0x00400000LL, -0x00800000LL, |
||
83 |
-0x01000000LL, -0x02000000LL, -0x04000000LL, -0x08000000LL, |
||
84 |
-0x10000000LL, -0x20000000LL, -0x40000000LL, -0x80000000LL, |
||
85 |
-0x000100000000LL, -0x000200000000LL, -0x000400000000LL, -0x000800000000LL, |
||
86 |
-0x001000000000LL, -0x002000000000LL, -0x004000000000LL, -0x008000000000LL, |
||
87 |
-0x010000000000LL, -0x020000000000LL, -0x040000000000LL, -0x080000000000LL, |
||
88 |
-0x100000000000LL, -0x200000000000LL, -0x400000000000LL, -0x800000000000LL, |
||
89 |
-0x0001000000000000LL, -0x0002000000000000LL, -0x0004000000000000LL, -0x0008000000000000LL, |
||
90 |
-0x0010000000000000LL, -0x0020000000000000LL, -0x0040000000000000LL, -0x0080000000000000LL, |
||
91 |
-0x0100000000000000LL, -0x0200000000000000LL, -0x0400000000000000LL, -0x0800000000000000LL, |
||
92 |
-0x1000000000000000LL, -0x2000000000000000LL, -0x4000000000000000LL, INT64_MIN |
||
93 |
}; |
||
94 |
|||
95 |
static const std::array<int64_t, 65> MAX_I64_VALUES = |
||
96 |
{ |
||
97 |
0x00LL, |
||
98 |
0x0000LL, 0x0001LL, 0x0003LL, 0x0007LL, |
||
99 |
0x000fLL, 0x001fLL, 0x003fLL, 0x007fLL, |
||
100 |
0x00ffLL, 0x01ffLL, 0x03ffLL, 0x07ffLL, |
||
101 |
0x0fffLL, 0x1fffLL, 0x3fffLL, 0x7fffLL, |
||
102 |
0x0000ffffLL, 0x0001ffffLL, 0x0003ffffLL, 0x0007ffffLL, |
||
103 |
0x000fffffLL, 0x001fffffLL, 0x003fffffLL, 0x007fffffLL, |
||
104 |
0x00ffffffLL, 0x01ffffffLL, 0x03ffffffLL, 0x07ffffffLL, |
||
105 |
0x0fffffffLL, 0x1fffffffLL, 0x3fffffffLL, 0x7fffffffLL, |
||
106 |
0x0000ffffffffLL, 0x0001ffffffffLL, 0x0003ffffffffLL, 0x0007ffffffffLL, |
||
107 |
0x000fffffffffLL, 0x001fffffffffLL, 0x003fffffffffLL, 0x007fffffffffLL, |
||
108 |
0x00ffffffffffLL, 0x01ffffffffffLL, 0x03ffffffffffLL, 0x07ffffffffffLL, |
||
109 |
0x0fffffffffffLL, 0x1fffffffffffLL, 0x3fffffffffffLL, 0x7fffffffffffLL, |
||
110 |
0x0000ffffffffffffLL, 0x0001ffffffffffffLL, 0x0003ffffffffffffLL, 0x0007ffffffffffffLL, |
||
111 |
0x000fffffffffffffLL, 0x001fffffffffffffLL, 0x003fffffffffffffLL, 0x007fffffffffffffLL, |
||
112 |
0x00ffffffffffffffLL, 0x01ffffffffffffffLL, 0x03ffffffffffffffLL, 0x07ffffffffffffffLL, |
||
113 |
0x0fffffffffffffffLL, 0x1fffffffffffffffLL, 0x3fffffffffffffffLL, 0x7fffffffffffffffLL |
||
114 |
}; |
||
115 |
|||
116 |
1 |
BitStreamWriter::BitStreamWriter(uint8_t* buffer, size_t bufferBitSize, BitsTag) : |
|
117 |
1 |
m_buffer(buffer, (bufferBitSize + 7) / 8), |
|
118 |
m_bitIndex(0), |
||
119 |
1 |
m_bufferBitSize(bufferBitSize) |
|
120 |
1 |
{} |
|
121 |
|||
122 |
3409 |
BitStreamWriter::BitStreamWriter(uint8_t* buffer, size_t bufferByteSize) : |
|
123 |
3409 |
BitStreamWriter(Span<uint8_t>(buffer, bufferByteSize)) |
|
124 |
3409 |
{} |
|
125 |
|||
126 |
3410 |
BitStreamWriter::BitStreamWriter(Span<uint8_t> buffer) : |
|
127 |
m_buffer(buffer), |
||
128 |
m_bitIndex(0), |
||
129 |
3410 |
m_bufferBitSize(buffer.size() * 8) |
|
130 |
3410 |
{} |
|
131 |
|||
132 |
471 |
BitStreamWriter::BitStreamWriter(Span<uint8_t> buffer, size_t bufferBitSize) : |
|
133 |
m_buffer(buffer), |
||
134 |
m_bitIndex(0), |
||
135 |
471 |
m_bufferBitSize(bufferBitSize) |
|
136 |
{ |
||
137 |
✓✓ | 471 |
if (buffer.size() < (bufferBitSize + 7) / 8) |
138 |
{ |
||
139 |
✓✗✓✗ |
2 |
throw CppRuntimeException("BitStreamWriter: Wrong buffer bit size ('") << buffer.size() << |
140 |
✓✗✓✗ ✓✗ |
3 |
"' < '" << (bufferBitSize + 7) / 8 << "')!"; |
141 |
} |
||
142 |
470 |
} |
|
143 |
|||
144 |
8852 |
void BitStreamWriter::writeBits(uint32_t data, uint8_t numBits) |
|
145 |
{ |
||
146 |
✓✓✓✓ ✓✓ |
8852 |
if (numBits > sizeof(uint32_t) * 8 || data > MAX_U32_VALUES[numBits]) |
147 |
{ |
||
148 |
✓✗✓✗ ✓✗✓✗ |
68 |
throw CppRuntimeException("BitStreamWriter: Writing of ") << numBits << "-bits value '" << data << |
149 |
✓✗ | 102 |
"' failed!"; |
150 |
} |
||
151 |
|||
152 |
8818 |
writeUnsignedBits(data, numBits); |
|
153 |
8813 |
} |
|
154 |
|||
155 |
4355 |
void BitStreamWriter::writeBits64(uint64_t data, uint8_t numBits) |
|
156 |
{ |
||
157 |
✓✓✓✓ ✓✓ |
4355 |
if (numBits > sizeof(uint64_t) * 8 || data > MAX_U64_VALUES[numBits]) |
158 |
{ |
||
159 |
✓✗✓✗ ✓✗✓✗ |
132 |
throw CppRuntimeException("BitStreamWriter: Writing of ") << numBits << "-bits value '" << data << |
160 |
✓✗ | 198 |
"' failed!"; |
161 |
} |
||
162 |
|||
163 |
4289 |
writeUnsignedBits64(data, numBits); |
|
164 |
4224 |
} |
|
165 |
|||
166 |
1629 |
void BitStreamWriter::writeSignedBits(int32_t data, uint8_t numBits) |
|
167 |
{ |
||
168 |
✓✓✓✓ ✓✓✓✓ |
1629 |
if (numBits > sizeof(int32_t) * 8 || data < MIN_I32_VALUES[numBits] || data > MAX_I32_VALUES[numBits]) |
169 |
{ |
||
170 |
✓✗✓✗ ✓✗✓✗ |
130 |
throw CppRuntimeException("BitStreamWriter: Writing of ") << numBits << "-bits value '" << data << |
171 |
✓✗ | 195 |
"' failed!"; |
172 |
} |
||
173 |
|||
174 |
1564 |
writeUnsignedBits(static_cast<uint32_t>(data) & MAX_U32_VALUES[numBits], numBits); |
|
175 |
1564 |
} |
|
176 |
|||
177 |
2186 |
void BitStreamWriter::writeSignedBits64(int64_t data, uint8_t numBits) |
|
178 |
{ |
||
179 |
✓✓✓✓ ✓✓✓✓ |
2186 |
if (numBits > sizeof(int64_t) * 8 || data < MIN_I64_VALUES[numBits] || data > MAX_I64_VALUES[numBits]) |
180 |
{ |
||
181 |
✓✗✓✗ ✓✗✓✗ |
258 |
throw CppRuntimeException("BitStreamWriter: Writing of ") << numBits << "-bits value '" << data << |
182 |
✓✗ | 387 |
"' failed!"; |
183 |
} |
||
184 |
|||
185 |
2057 |
writeUnsignedBits64(static_cast<uint64_t>(data) & MAX_U64_VALUES[numBits], numBits); |
|
186 |
2057 |
} |
|
187 |
|||
188 |
4424 |
void BitStreamWriter::writeVarInt64(int64_t data) |
|
189 |
{ |
||
190 |
4424 |
writeSignedVarNum(data, 8, zserio::bitSizeOfVarInt64(data) / 8); |
|
191 |
4423 |
} |
|
192 |
|||
193 |
1192 |
void BitStreamWriter::writeVarInt32(int32_t data) |
|
194 |
{ |
||
195 |
1192 |
writeSignedVarNum(data, 4, zserio::bitSizeOfVarInt32(data) / 8); |
|
196 |
1191 |
} |
|
197 |
|||
198 |
344 |
void BitStreamWriter::writeVarInt16(int16_t data) |
|
199 |
{ |
||
200 |
344 |
writeSignedVarNum(data, 2, zserio::bitSizeOfVarInt16(data) / 8); |
|
201 |
343 |
} |
|
202 |
|||
203 |
3140 |
void BitStreamWriter::writeVarUInt64(uint64_t data) |
|
204 |
{ |
||
205 |
3140 |
writeUnsignedVarNum(data, 8, zserio::bitSizeOfVarUInt64(data) / 8); |
|
206 |
3139 |
} |
|
207 |
|||
208 |
820 |
void BitStreamWriter::writeVarUInt32(uint32_t data) |
|
209 |
{ |
||
210 |
820 |
writeUnsignedVarNum(data, 4, zserio::bitSizeOfVarUInt32(data) / 8); |
|
211 |
819 |
} |
|
212 |
|||
213 |
284 |
void BitStreamWriter::writeVarUInt16(uint16_t data) |
|
214 |
{ |
||
215 |
284 |
writeUnsignedVarNum(data, 2, zserio::bitSizeOfVarUInt16(data) / 8); |
|
216 |
283 |
} |
|
217 |
|||
218 |
5503 |
void BitStreamWriter::writeVarInt(int64_t data) |
|
219 |
{ |
||
220 |
✓✓ | 5503 |
if (data == INT64_MIN) |
221 |
159 |
writeBits(0x80, 8); // INT64_MIN is encoded as -0 |
|
222 |
else |
||
223 |
5344 |
writeSignedVarNum(data, 9, zserio::bitSizeOfVarInt(data) / 8); |
|
224 |
5503 |
} |
|
225 |
|||
226 |
2757 |
void BitStreamWriter::writeVarUInt(uint64_t data) |
|
227 |
{ |
||
228 |
2757 |
writeUnsignedVarNum(data, 9, zserio::bitSizeOfVarUInt(data) / 8); |
|
229 |
2757 |
} |
|
230 |
|||
231 |
3113 |
void BitStreamWriter::writeVarSize(uint32_t data) |
|
232 |
{ |
||
233 |
3113 |
writeUnsignedVarNum(data, 5, zserio::bitSizeOfVarSize(data) / 8); |
|
234 |
3112 |
} |
|
235 |
|||
236 |
305 |
void BitStreamWriter::writeFloat16(float data) |
|
237 |
{ |
||
238 |
305 |
const uint16_t halfPrecisionFloat = convertFloatToUInt16(data); |
|
239 |
305 |
writeUnsignedBits(halfPrecisionFloat, 16); |
|
240 |
305 |
} |
|
241 |
|||
242 |
499 |
void BitStreamWriter::writeFloat32(float data) |
|
243 |
{ |
||
244 |
499 |
const uint32_t singlePrecisionFloat = convertFloatToUInt32(data); |
|
245 |
499 |
writeUnsignedBits(singlePrecisionFloat, 32); |
|
246 |
499 |
} |
|
247 |
|||
248 |
859 |
void BitStreamWriter::writeFloat64(double data) |
|
249 |
{ |
||
250 |
859 |
const uint64_t doublePrecisionFloat = convertDoubleToUInt64(data); |
|
251 |
859 |
writeUnsignedBits64(doublePrecisionFloat, 64); |
|
252 |
859 |
} |
|
253 |
|||
254 |
99 |
void BitStreamWriter::writeBytes(Span<const uint8_t> data) |
|
255 |
{ |
||
256 |
99 |
const size_t len = data.size(); |
|
257 |
99 |
writeVarSize(convertSizeToUInt32(len)); |
|
258 |
|||
259 |
99 |
const BitPosType beginBitPosition = getBitPosition(); |
|
260 |
✓✓ | 99 |
if ((beginBitPosition & 0x07U) != 0) |
261 |
{ |
||
262 |
// we are not aligned to byte |
||
263 |
✓✓ | 180 |
for (size_t i = 0; i < len; ++i) |
264 |
128 |
writeBits(data[i], 8); |
|
265 |
} |
||
266 |
else |
||
267 |
{ |
||
268 |
// we are aligned to bytes |
||
269 |
47 |
setBitPosition(beginBitPosition + len * 8); |
|
270 |
✓✓ | 47 |
if (hasWriteBuffer()) |
271 |
45 |
std::copy(data.begin(), data.end(), m_buffer.begin() + beginBitPosition / 8); |
|
272 |
} |
||
273 |
99 |
} |
|
274 |
|||
275 |
161 |
void BitStreamWriter::writeString(StringView data) |
|
276 |
{ |
||
277 |
161 |
const size_t len = data.size(); |
|
278 |
161 |
writeVarSize(convertSizeToUInt32(len)); |
|
279 |
|||
280 |
161 |
const BitPosType beginBitPosition = getBitPosition(); |
|
281 |
✓✓ | 161 |
if ((beginBitPosition & 0x07U) != 0) |
282 |
{ |
||
283 |
// we are not aligned to byte |
||
284 |
✓✓ | 1548 |
for (size_t i = 0; i < len; ++i) |
285 |
1470 |
writeBits(static_cast<uint8_t>(data[i]), 8); |
|
286 |
} |
||
287 |
else |
||
288 |
{ |
||
289 |
// we are aligned to bytes |
||
290 |
83 |
setBitPosition(beginBitPosition + len * 8); |
|
291 |
✓✓ | 83 |
if (hasWriteBuffer()) |
292 |
80 |
std::copy(data.begin(), data.begin() + len, m_buffer.data() + beginBitPosition / 8); |
|
293 |
} |
||
294 |
161 |
} |
|
295 |
|||
296 |
909 |
void BitStreamWriter::writeBool(bool data) |
|
297 |
{ |
||
298 |
✓✓ | 909 |
writeBits((data ? 1 : 0), 1); |
299 |
909 |
} |
|
300 |
|||
301 |
704 |
void BitStreamWriter::setBitPosition(BitPosType position) |
|
302 |
{ |
||
303 |
✓✓ | 704 |
if (hasWriteBuffer()) |
304 |
695 |
checkCapacity(position); |
|
305 |
|||
306 |
703 |
m_bitIndex = position; |
|
307 |
703 |
} |
|
308 |
|||
309 |
4736 |
void BitStreamWriter::alignTo(size_t alignment) |
|
310 |
{ |
||
311 |
4736 |
const BitPosType offset = getBitPosition() % alignment; |
|
312 |
✓✓ | 4736 |
if (offset != 0) |
313 |
{ |
||
314 |
2465 |
const uint8_t skip = static_cast<uint8_t>(alignment - offset); |
|
315 |
2465 |
writeBits64(0, skip); |
|
316 |
} |
||
317 |
4736 |
} |
|
318 |
|||
319 |
515 |
const uint8_t* BitStreamWriter::getWriteBuffer() const |
|
320 |
{ |
||
321 |
515 |
return m_buffer.data(); |
|
322 |
} |
||
323 |
|||
324 |
18 |
Span<const uint8_t> BitStreamWriter::getBuffer() const |
|
325 |
{ |
||
326 |
18 |
return m_buffer; |
|
327 |
} |
||
328 |
|||
329 |
103734 |
void BitStreamWriter::writeUnsignedBits(uint32_t data, uint8_t numBits) |
|
330 |
{ |
||
331 |
✓✓ | 103734 |
if (!hasWriteBuffer()) |
332 |
{ |
||
333 |
37321 |
m_bitIndex += numBits; |
|
334 |
37321 |
return; |
|
335 |
} |
||
336 |
|||
337 |
66413 |
checkCapacity(m_bitIndex + numBits); |
|
338 |
|||
339 |
66343 |
uint8_t restNumBits = numBits; |
|
340 |
66343 |
const uint8_t bitsUsed = m_bitIndex & 0x07U; |
|
341 |
66343 |
uint8_t bitsFree = 8 - bitsUsed; |
|
342 |
66343 |
size_t byteIndex = m_bitIndex / 8; |
|
343 |
|||
344 |
✓✓ | 66343 |
if (restNumBits > bitsFree) |
345 |
{ |
||
346 |
// first part |
||
347 |
46360 |
const uint8_t shiftNum = restNumBits - bitsFree; |
|
348 |
46360 |
const uint8_t maskedByte = m_buffer[byteIndex] & ~(0xFFU >> bitsUsed); |
|
349 |
46360 |
m_buffer[byteIndex++] = maskedByte | static_cast<uint8_t>(data >> shiftNum); |
|
350 |
46360 |
restNumBits -= bitsFree; |
|
351 |
|||
352 |
// middle parts |
||
353 |
✓✓ | 82370 |
while (restNumBits >= 8) |
354 |
{ |
||
355 |
18005 |
restNumBits -= 8; |
|
356 |
18005 |
m_buffer[byteIndex++] = static_cast<uint8_t>((data >> restNumBits) & MAX_U32_VALUES[8]); |
|
357 |
} |
||
358 |
|||
359 |
// reset bits free |
||
360 |
46360 |
bitsFree = 8; |
|
361 |
} |
||
362 |
|||
363 |
// last part |
||
364 |
✓✓ | 66343 |
if (restNumBits > 0) |
365 |
{ |
||
366 |
64200 |
const uint8_t shiftNum = bitsFree - restNumBits; |
|
367 |
64200 |
const uint32_t mask = MAX_U32_VALUES[restNumBits]; |
|
368 |
64200 |
const uint8_t maskedByte = m_buffer[byteIndex] & |
|
369 |
64200 |
static_cast<uint8_t>(~static_cast<uint8_t>(mask << shiftNum)); |
|
370 |
64200 |
m_buffer[byteIndex] = maskedByte | static_cast<uint8_t>((data & mask) << shiftNum); |
|
371 |
} |
||
372 |
|||
373 |
66343 |
m_bitIndex += numBits; |
|
374 |
} |
||
375 |
|||
376 |
7205 |
inline void BitStreamWriter::writeUnsignedBits64(uint64_t data, uint8_t numBits) |
|
377 |
{ |
||
378 |
✓✓ | 7205 |
if (numBits <= 32) |
379 |
{ |
||
380 |
4045 |
writeUnsignedBits(static_cast<uint32_t>(data), numBits); |
|
381 |
} |
||
382 |
else |
||
383 |
{ |
||
384 |
3160 |
writeUnsignedBits(static_cast<uint32_t>(data >> 32U), numBits - 32); |
|
385 |
3160 |
writeUnsignedBits(static_cast<uint32_t>(data), 32); |
|
386 |
} |
||
387 |
7140 |
} |
|
388 |
|||
389 |
11301 |
inline void BitStreamWriter::writeSignedVarNum(int64_t value, size_t maxVarBytes, size_t numVarBytes) |
|
390 |
{ |
||
391 |
11301 |
const uint64_t absValue = static_cast<uint64_t>(value < 0 ? -value : value); |
|
392 |
11301 |
writeVarNum(absValue, true, value < 0, maxVarBytes, numVarBytes); |
|
393 |
11301 |
} |
|
394 |
|||
395 |
10110 |
inline void BitStreamWriter::writeUnsignedVarNum(uint64_t value, size_t maxVarBytes, size_t numVarBytes) |
|
396 |
{ |
||
397 |
10110 |
writeVarNum(value, false, false, maxVarBytes, numVarBytes); |
|
398 |
10110 |
} |
|
399 |
|||
400 |
21411 |
inline void BitStreamWriter::writeVarNum(uint64_t value, bool hasSign, bool isNegative, size_t maxVarBytes, |
|
401 |
size_t numVarBytes) |
||
402 |
{ |
||
403 |
static const std::array<uint64_t, 8> bitMasks = { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; |
||
404 |
21411 |
const bool hasMaxByteRange = (numVarBytes == maxVarBytes); |
|
405 |
|||
406 |
✓✓ | 103386 |
for (size_t i = 0; i < numVarBytes; i++) |
407 |
{ |
||
408 |
81975 |
uint8_t byte = 0x00; |
|
409 |
81975 |
uint8_t numBits = 8; |
|
410 |
81975 |
const bool hasNextByte = (i < numVarBytes - 1); |
|
411 |
✓✓✓✓ |
81975 |
const bool hasSignBit = (hasSign && i == 0); |
412 |
✓✓ | 81975 |
if (hasSignBit) |
413 |
{ |
||
414 |
✓✓ | 11301 |
if (isNegative) |
415 |
3922 |
byte |= 0x80U; |
|
416 |
11301 |
numBits--; |
|
417 |
} |
||
418 |
✓✓ | 81975 |
if (hasNextByte) |
419 |
{ |
||
420 |
60564 |
numBits--; |
|
421 |
60564 |
byte |= (0x01U << numBits); // use bit 6 if signed bit is present, use bit 7 otherwise |
|
422 |
} |
||
423 |
else // this is the last byte |
||
424 |
{ |
||
425 |
✓✓ | 21411 |
if (!hasMaxByteRange) // next byte indicator is not used in last byte in case of max byte range |
426 |
18801 |
numBits--; |
|
427 |
} |
||
428 |
|||
429 |
✓✓✓✓ |
81975 |
const size_t shiftBits = (numVarBytes - (i + 1)) * 7 + ((hasMaxByteRange && hasNextByte) ? 1 : 0); |
430 |
81975 |
byte |= static_cast<uint8_t>((value >> shiftBits) & bitMasks[numBits - 1]); |
|
431 |
81975 |
writeUnsignedBits(byte, 8); |
|
432 |
} |
||
433 |
21411 |
} |
|
434 |
|||
435 |
71 |
inline void BitStreamWriter::throwInsufficientCapacityException() const |
|
436 |
{ |
||
437 |
✓✗ | 71 |
throw InsufficientCapacityException("BitStreamWriter: Reached end of bit buffer!"); |
438 |
} |
||
439 |
|||
440 |
67108 |
inline void BitStreamWriter::checkCapacity(size_t bitSize) const |
|
441 |
{ |
||
442 |
✓✓ | 67108 |
if (bitSize > m_bufferBitSize) |
443 |
71 |
throwInsufficientCapacityException(); |
|
444 |
67037 |
} |
|
445 |
|||
446 |
} // namespace zserio |
Generated by: GCOVR (Version 4.2) |