src/zserio/BitStreamWriter.cpp
Line | Count | Source |
1 | | #include <algorithm> |
2 | | #include <array> |
3 | | #include <cstring> |
4 | | #include <fstream> |
5 | | |
6 | | #include "zserio/BitSizeOfCalculator.h" |
7 | | #include "zserio/BitStreamWriter.h" |
8 | | #include "zserio/CppRuntimeException.h" |
9 | | #include "zserio/FloatUtil.h" |
10 | | |
11 | | namespace zserio |
12 | | { |
13 | | |
14 | | static const std::array<uint32_t, 33> MAX_U32_VALUES = { |
15 | | 0x00U, |
16 | | 0x0001U, |
17 | | 0x0003U, |
18 | | 0x0007U, |
19 | | 0x000fU, |
20 | | 0x001fU, |
21 | | 0x003fU, |
22 | | 0x007fU, |
23 | | 0x00ffU, |
24 | | 0x01ffU, |
25 | | 0x03ffU, |
26 | | 0x07ffU, |
27 | | 0x0fffU, |
28 | | 0x1fffU, |
29 | | 0x3fffU, |
30 | | 0x7fffU, |
31 | | 0xffffU, |
32 | | 0x0001ffffU, |
33 | | 0x0003ffffU, |
34 | | 0x0007ffffU, |
35 | | 0x000fffffU, |
36 | | 0x001fffffU, |
37 | | 0x003fffffU, |
38 | | 0x007fffffU, |
39 | | 0x00ffffffU, |
40 | | 0x01ffffffU, |
41 | | 0x03ffffffU, |
42 | | 0x07ffffffU, |
43 | | 0x0fffffffU, |
44 | | 0x1fffffffU, |
45 | | 0x3fffffffU, |
46 | | 0x7fffffffU, |
47 | | 0xffffffffU, |
48 | | }; |
49 | | |
50 | | static const std::array<int32_t, 33> MIN_I32_VALUES = { |
51 | | 0, |
52 | | -0x0001, |
53 | | -0x0002, |
54 | | -0x0004, |
55 | | -0x0008, |
56 | | -0x0010, |
57 | | -0x0020, |
58 | | -0x0040, |
59 | | -0x0080, |
60 | | -0x0100, |
61 | | -0x0200, |
62 | | -0x0400, |
63 | | -0x0800, |
64 | | -0x1000, |
65 | | -0x2000, |
66 | | -0x4000, |
67 | | -0x8000, |
68 | | -0x00010000, |
69 | | -0x00020000, |
70 | | -0x00040000, |
71 | | -0x00080000, |
72 | | -0x00100000, |
73 | | -0x00200000, |
74 | | -0x00400000, |
75 | | -0x00800000, |
76 | | -0x01000000, |
77 | | -0x02000000, |
78 | | -0x04000000, |
79 | | -0x08000000, |
80 | | -0x10000000, |
81 | | -0x20000000, |
82 | | -0x40000000, |
83 | | INT32_MIN, |
84 | | }; |
85 | | |
86 | | static const std::array<int32_t, 33> MAX_I32_VALUES = { |
87 | | 0x00, |
88 | | 0x0000, |
89 | | 0x0001, |
90 | | 0x0003, |
91 | | 0x0007, |
92 | | 0x000f, |
93 | | 0x001f, |
94 | | 0x003f, |
95 | | 0x007f, |
96 | | 0x00ff, |
97 | | 0x01ff, |
98 | | 0x03ff, |
99 | | 0x07ff, |
100 | | 0x0fff, |
101 | | 0x1fff, |
102 | | 0x3fff, |
103 | | 0x7fff, |
104 | | 0x0000ffff, |
105 | | 0x0001ffff, |
106 | | 0x0003ffff, |
107 | | 0x0007ffff, |
108 | | 0x000fffff, |
109 | | 0x001fffff, |
110 | | 0x003fffff, |
111 | | 0x007fffff, |
112 | | 0x00ffffff, |
113 | | 0x01ffffff, |
114 | | 0x03ffffff, |
115 | | 0x07ffffff, |
116 | | 0x0fffffff, |
117 | | 0x1fffffff, |
118 | | 0x3fffffff, |
119 | | 0x7fffffff, |
120 | | }; |
121 | | |
122 | | static const std::array<uint64_t, 65> MAX_U64_VALUES = { |
123 | | 0x00ULL, |
124 | | 0x0001ULL, |
125 | | 0x0003ULL, |
126 | | 0x0007ULL, |
127 | | 0x000fULL, |
128 | | 0x001fULL, |
129 | | 0x003fULL, |
130 | | 0x007fULL, |
131 | | 0x00ffULL, |
132 | | 0x01ffULL, |
133 | | 0x03ffULL, |
134 | | 0x07ffULL, |
135 | | 0x0fffULL, |
136 | | 0x1fffULL, |
137 | | 0x3fffULL, |
138 | | 0x7fffULL, |
139 | | 0xffffULL, |
140 | | 0x0001ffffULL, |
141 | | 0x0003ffffULL, |
142 | | 0x0007ffffULL, |
143 | | 0x000fffffULL, |
144 | | 0x001fffffULL, |
145 | | 0x003fffffULL, |
146 | | 0x007fffffULL, |
147 | | 0x00ffffffULL, |
148 | | 0x01ffffffULL, |
149 | | 0x03ffffffULL, |
150 | | 0x07ffffffULL, |
151 | | 0x0fffffffULL, |
152 | | 0x1fffffffULL, |
153 | | 0x3fffffffULL, |
154 | | 0x7fffffffULL, |
155 | | 0xffffffffULL, |
156 | | 0x0001ffffffffULL, |
157 | | 0x0003ffffffffULL, |
158 | | 0x0007ffffffffULL, |
159 | | 0x000fffffffffULL, |
160 | | 0x001fffffffffULL, |
161 | | 0x003fffffffffULL, |
162 | | 0x007fffffffffULL, |
163 | | 0x00ffffffffffULL, |
164 | | 0x01ffffffffffULL, |
165 | | 0x03ffffffffffULL, |
166 | | 0x07ffffffffffULL, |
167 | | 0x0fffffffffffULL, |
168 | | 0x1fffffffffffULL, |
169 | | 0x3fffffffffffULL, |
170 | | 0x7fffffffffffULL, |
171 | | 0xffffffffffffULL, |
172 | | 0x0001ffffffffffffULL, |
173 | | 0x0003ffffffffffffULL, |
174 | | 0x0007ffffffffffffULL, |
175 | | 0x000fffffffffffffULL, |
176 | | 0x001fffffffffffffULL, |
177 | | 0x003fffffffffffffULL, |
178 | | 0x007fffffffffffffULL, |
179 | | 0x00ffffffffffffffULL, |
180 | | 0x01ffffffffffffffULL, |
181 | | 0x03ffffffffffffffULL, |
182 | | 0x07ffffffffffffffULL, |
183 | | 0x0fffffffffffffffULL, |
184 | | 0x1fffffffffffffffULL, |
185 | | 0x3fffffffffffffffULL, |
186 | | 0x7fffffffffffffffULL, |
187 | | 0xffffffffffffffffULL, |
188 | | }; |
189 | | |
190 | | static const std::array<int64_t, 65> MIN_I64_VALUES = { |
191 | | 0LL, |
192 | | -0x0001LL, |
193 | | -0x0002LL, |
194 | | -0x0004LL, |
195 | | -0x0008LL, |
196 | | -0x0010LL, |
197 | | -0x0020LL, |
198 | | -0x0040LL, |
199 | | -0x0080LL, |
200 | | -0x0100LL, |
201 | | -0x0200LL, |
202 | | -0x0400LL, |
203 | | -0x0800LL, |
204 | | -0x1000LL, |
205 | | -0x2000LL, |
206 | | -0x4000LL, |
207 | | -0x8000LL, |
208 | | -0x00010000LL, |
209 | | -0x00020000LL, |
210 | | -0x00040000LL, |
211 | | -0x00080000LL, |
212 | | -0x00100000LL, |
213 | | -0x00200000LL, |
214 | | -0x00400000LL, |
215 | | -0x00800000LL, |
216 | | -0x01000000LL, |
217 | | -0x02000000LL, |
218 | | -0x04000000LL, |
219 | | -0x08000000LL, |
220 | | -0x10000000LL, |
221 | | -0x20000000LL, |
222 | | -0x40000000LL, |
223 | | -0x80000000LL, |
224 | | -0x000100000000LL, |
225 | | -0x000200000000LL, |
226 | | -0x000400000000LL, |
227 | | -0x000800000000LL, |
228 | | -0x001000000000LL, |
229 | | -0x002000000000LL, |
230 | | -0x004000000000LL, |
231 | | -0x008000000000LL, |
232 | | -0x010000000000LL, |
233 | | -0x020000000000LL, |
234 | | -0x040000000000LL, |
235 | | -0x080000000000LL, |
236 | | -0x100000000000LL, |
237 | | -0x200000000000LL, |
238 | | -0x400000000000LL, |
239 | | -0x800000000000LL, |
240 | | -0x0001000000000000LL, |
241 | | -0x0002000000000000LL, |
242 | | -0x0004000000000000LL, |
243 | | -0x0008000000000000LL, |
244 | | -0x0010000000000000LL, |
245 | | -0x0020000000000000LL, |
246 | | -0x0040000000000000LL, |
247 | | -0x0080000000000000LL, |
248 | | -0x0100000000000000LL, |
249 | | -0x0200000000000000LL, |
250 | | -0x0400000000000000LL, |
251 | | -0x0800000000000000LL, |
252 | | -0x1000000000000000LL, |
253 | | -0x2000000000000000LL, |
254 | | -0x4000000000000000LL, |
255 | | INT64_MIN, |
256 | | }; |
257 | | |
258 | | static const std::array<int64_t, 65> MAX_I64_VALUES = { |
259 | | 0x00LL, |
260 | | 0x0000LL, |
261 | | 0x0001LL, |
262 | | 0x0003LL, |
263 | | 0x0007LL, |
264 | | 0x000fLL, |
265 | | 0x001fLL, |
266 | | 0x003fLL, |
267 | | 0x007fLL, |
268 | | 0x00ffLL, |
269 | | 0x01ffLL, |
270 | | 0x03ffLL, |
271 | | 0x07ffLL, |
272 | | 0x0fffLL, |
273 | | 0x1fffLL, |
274 | | 0x3fffLL, |
275 | | 0x7fffLL, |
276 | | 0x0000ffffLL, |
277 | | 0x0001ffffLL, |
278 | | 0x0003ffffLL, |
279 | | 0x0007ffffLL, |
280 | | 0x000fffffLL, |
281 | | 0x001fffffLL, |
282 | | 0x003fffffLL, |
283 | | 0x007fffffLL, |
284 | | 0x00ffffffLL, |
285 | | 0x01ffffffLL, |
286 | | 0x03ffffffLL, |
287 | | 0x07ffffffLL, |
288 | | 0x0fffffffLL, |
289 | | 0x1fffffffLL, |
290 | | 0x3fffffffLL, |
291 | | 0x7fffffffLL, |
292 | | 0x0000ffffffffLL, |
293 | | 0x0001ffffffffLL, |
294 | | 0x0003ffffffffLL, |
295 | | 0x0007ffffffffLL, |
296 | | 0x000fffffffffLL, |
297 | | 0x001fffffffffLL, |
298 | | 0x003fffffffffLL, |
299 | | 0x007fffffffffLL, |
300 | | 0x00ffffffffffLL, |
301 | | 0x01ffffffffffLL, |
302 | | 0x03ffffffffffLL, |
303 | | 0x07ffffffffffLL, |
304 | | 0x0fffffffffffLL, |
305 | | 0x1fffffffffffLL, |
306 | | 0x3fffffffffffLL, |
307 | | 0x7fffffffffffLL, |
308 | | 0x0000ffffffffffffLL, |
309 | | 0x0001ffffffffffffLL, |
310 | | 0x0003ffffffffffffLL, |
311 | | 0x0007ffffffffffffLL, |
312 | | 0x000fffffffffffffLL, |
313 | | 0x001fffffffffffffLL, |
314 | | 0x003fffffffffffffLL, |
315 | | 0x007fffffffffffffLL, |
316 | | 0x00ffffffffffffffLL, |
317 | | 0x01ffffffffffffffLL, |
318 | | 0x03ffffffffffffffLL, |
319 | | 0x07ffffffffffffffLL, |
320 | | 0x0fffffffffffffffLL, |
321 | | 0x1fffffffffffffffLL, |
322 | | 0x3fffffffffffffffLL, |
323 | | 0x7fffffffffffffffLL, |
324 | | }; |
325 | | |
326 | | BitStreamWriter::BitStreamWriter(uint8_t* buffer, size_t bufferBitSize, BitsTag) : |
327 | | m_buffer(buffer, (bufferBitSize + 7) / 8), |
328 | | m_bitIndex(0), |
329 | | m_bufferBitSize(bufferBitSize) |
330 | 1 | {} |
331 | | |
332 | | BitStreamWriter::BitStreamWriter(uint8_t* buffer, size_t bufferByteSize) : |
333 | | BitStreamWriter(Span<uint8_t>(buffer, bufferByteSize)) |
334 | 3.40k | {} |
335 | | |
336 | | BitStreamWriter::BitStreamWriter(Span<uint8_t> buffer) : |
337 | | m_buffer(buffer), |
338 | | m_bitIndex(0), |
339 | | m_bufferBitSize(buffer.size() * 8) |
340 | 3.41k | {} |
341 | | |
342 | | BitStreamWriter::BitStreamWriter(Span<uint8_t> buffer, size_t bufferBitSize) : |
343 | | m_buffer(buffer), |
344 | | m_bitIndex(0), |
345 | | m_bufferBitSize(bufferBitSize) |
346 | 471 | { |
347 | 471 | if (buffer.size() < (bufferBitSize + 7) / 8) |
348 | 1 | { |
349 | 1 | throw CppRuntimeException("BitStreamWriter: Wrong buffer bit size ('") |
350 | 1 | << buffer.size() << "' < '" << (bufferBitSize + 7) / 8 << "')!"; |
351 | 1 | } |
352 | 471 | } |
353 | | |
354 | | void BitStreamWriter::writeBits(uint32_t data, uint8_t numBits) |
355 | 8.44k | { |
356 | 8.44k | if (numBits == 0 || numBits > sizeof(uint32_t) * 88.43k || data > MAX_U32_VALUES[numBits]8.43k ) |
357 | 37 | { |
358 | 37 | throw CppRuntimeException("BitStreamWriter: Writing of ") |
359 | 37 | << numBits << "-bits value '" << data << "' failed!"; |
360 | 37 | } |
361 | | |
362 | 8.40k | writeUnsignedBits(data, numBits); |
363 | 8.40k | } |
364 | | |
365 | | void BitStreamWriter::writeBits64(uint64_t data, uint8_t numBits) |
366 | 4.35k | { |
367 | 4.35k | if (numBits == 0 || numBits > sizeof(uint64_t) * 84.35k || data > MAX_U64_VALUES[numBits]4.35k ) |
368 | 69 | { |
369 | 69 | throw CppRuntimeException("BitStreamWriter: Writing of ") |
370 | 69 | << numBits << "-bits value '" << data << "' failed!"; |
371 | 69 | } |
372 | | |
373 | 4.28k | writeUnsignedBits64(data, numBits); |
374 | 4.28k | } |
375 | | |
376 | | void BitStreamWriter::writeSignedBits(int32_t data, uint8_t numBits) |
377 | 1.63k | { |
378 | 1.63k | if (numBits == 0 || numBits > sizeof(int32_t) * 81.63k || data < MIN_I32_VALUES[numBits]1.62k || |
379 | 1.63k | data > MAX_I32_VALUES[numBits]1.59k ) |
380 | 68 | { |
381 | 68 | throw CppRuntimeException("BitStreamWriter: Writing of ") |
382 | 68 | << numBits << "-bits value '" << data << "' failed!"; |
383 | 68 | } |
384 | | |
385 | 1.56k | writeUnsignedBits(static_cast<uint32_t>(data) & MAX_U32_VALUES[numBits], numBits); |
386 | 1.56k | } |
387 | | |
388 | | void BitStreamWriter::writeSignedBits64(int64_t data, uint8_t numBits) |
389 | 2.18k | { |
390 | 2.18k | if (numBits == 0 || numBits > sizeof(int64_t) * 82.18k || data < MIN_I64_VALUES[numBits]2.18k || |
391 | 2.18k | data > MAX_I64_VALUES[numBits]2.12k ) |
392 | 132 | { |
393 | 132 | throw CppRuntimeException("BitStreamWriter: Writing of ") |
394 | 132 | << numBits << "-bits value '" << data << "' failed!"; |
395 | 132 | } |
396 | | |
397 | 2.05k | writeUnsignedBits64(static_cast<uint64_t>(data) & MAX_U64_VALUES[numBits], numBits); |
398 | 2.05k | } |
399 | | |
400 | | void BitStreamWriter::writeVarInt64(int64_t data) |
401 | 4.42k | { |
402 | 4.42k | writeSignedVarNum(data, 8, zserio::bitSizeOfVarInt64(data) / 8); |
403 | 4.42k | } |
404 | | |
405 | | void BitStreamWriter::writeVarInt32(int32_t data) |
406 | 1.19k | { |
407 | 1.19k | writeSignedVarNum(data, 4, zserio::bitSizeOfVarInt32(data) / 8); |
408 | 1.19k | } |
409 | | |
410 | | void BitStreamWriter::writeVarInt16(int16_t data) |
411 | 344 | { |
412 | 344 | writeSignedVarNum(data, 2, zserio::bitSizeOfVarInt16(data) / 8); |
413 | 344 | } |
414 | | |
415 | | void BitStreamWriter::writeVarUInt64(uint64_t data) |
416 | 3.14k | { |
417 | 3.14k | writeUnsignedVarNum(data, 8, zserio::bitSizeOfVarUInt64(data) / 8); |
418 | 3.14k | } |
419 | | |
420 | | void BitStreamWriter::writeVarUInt32(uint32_t data) |
421 | 820 | { |
422 | 820 | writeUnsignedVarNum(data, 4, zserio::bitSizeOfVarUInt32(data) / 8); |
423 | 820 | } |
424 | | |
425 | | void BitStreamWriter::writeVarUInt16(uint16_t data) |
426 | 284 | { |
427 | 284 | writeUnsignedVarNum(data, 2, zserio::bitSizeOfVarUInt16(data) / 8); |
428 | 284 | } |
429 | | |
430 | | void BitStreamWriter::writeVarInt(int64_t data) |
431 | 5.50k | { |
432 | 5.50k | if (data == INT64_MIN) |
433 | 159 | { |
434 | 159 | writeBits(0x80, 8); // INT64_MIN is encoded as -0 |
435 | 159 | } |
436 | 5.34k | else |
437 | 5.34k | { |
438 | 5.34k | writeSignedVarNum(data, 9, zserio::bitSizeOfVarInt(data) / 8); |
439 | 5.34k | } |
440 | 5.50k | } |
441 | | |
442 | | void BitStreamWriter::writeVarUInt(uint64_t data) |
443 | 2.75k | { |
444 | 2.75k | writeUnsignedVarNum(data, 9, zserio::bitSizeOfVarUInt(data) / 8); |
445 | 2.75k | } |
446 | | |
447 | | void BitStreamWriter::writeVarSize(uint32_t data) |
448 | 3.11k | { |
449 | 3.11k | writeUnsignedVarNum(data, 5, zserio::bitSizeOfVarSize(data) / 8); |
450 | 3.11k | } |
451 | | |
452 | | void BitStreamWriter::writeFloat16(float data) |
453 | 305 | { |
454 | 305 | const uint16_t halfPrecisionFloat = convertFloatToUInt16(data); |
455 | 305 | writeUnsignedBits(halfPrecisionFloat, 16); |
456 | 305 | } |
457 | | |
458 | | void BitStreamWriter::writeFloat32(float data) |
459 | 499 | { |
460 | 499 | const uint32_t singlePrecisionFloat = convertFloatToUInt32(data); |
461 | 499 | writeUnsignedBits(singlePrecisionFloat, 32); |
462 | 499 | } |
463 | | |
464 | | void BitStreamWriter::writeFloat64(double data) |
465 | 859 | { |
466 | 859 | const uint64_t doublePrecisionFloat = convertDoubleToUInt64(data); |
467 | 859 | writeUnsignedBits64(doublePrecisionFloat, 64); |
468 | 859 | } |
469 | | |
470 | | void BitStreamWriter::writeBytes(Span<const uint8_t> data) |
471 | 99 | { |
472 | 99 | const size_t len = data.size(); |
473 | 99 | writeVarSize(convertSizeToUInt32(len)); |
474 | | |
475 | 99 | const BitPosType beginBitPosition = getBitPosition(); |
476 | 99 | if ((beginBitPosition & 0x07U) != 0) |
477 | 52 | { |
478 | | // we are not aligned to byte |
479 | 180 | for (size_t i = 0; i < len; ++i128 ) |
480 | 128 | { |
481 | 128 | writeBits(data[i], 8); |
482 | 128 | } |
483 | 52 | } |
484 | 47 | else |
485 | 47 | { |
486 | | // we are aligned to bytes |
487 | 47 | setBitPosition(beginBitPosition + len * 8); |
488 | 47 | if (hasWriteBuffer()) |
489 | 45 | { |
490 | 45 | std::copy(data.begin(), data.end(), m_buffer.begin() + beginBitPosition / 8); |
491 | 45 | } |
492 | 47 | } |
493 | 99 | } |
494 | | |
495 | | void BitStreamWriter::writeString(StringView data) |
496 | 161 | { |
497 | 161 | const size_t len = data.size(); |
498 | 161 | writeVarSize(convertSizeToUInt32(len)); |
499 | | |
500 | 161 | const BitPosType beginBitPosition = getBitPosition(); |
501 | 161 | if ((beginBitPosition & 0x07U) != 0) |
502 | 78 | { |
503 | | // we are not aligned to byte |
504 | 1.54k | for (size_t i = 0; i < len; ++i1.47k ) |
505 | 1.47k | { |
506 | 1.47k | writeBits(static_cast<uint8_t>(data[i]), 8); |
507 | 1.47k | } |
508 | 78 | } |
509 | 83 | else |
510 | 83 | { |
511 | | // we are aligned to bytes |
512 | 83 | setBitPosition(beginBitPosition + len * 8); |
513 | 83 | if (hasWriteBuffer()) |
514 | 80 | { |
515 | 80 | std::copy(data.begin(), data.begin() + len, m_buffer.data() + beginBitPosition / 8); |
516 | 80 | } |
517 | 83 | } |
518 | 161 | } |
519 | | |
520 | | void BitStreamWriter::writeBool(bool data) |
521 | 909 | { |
522 | 909 | writeBits((data ? 1391 : 0518 ), 1); |
523 | 909 | } |
524 | | |
525 | | void BitStreamWriter::setBitPosition(BitPosType position) |
526 | 704 | { |
527 | 704 | if (hasWriteBuffer()) |
528 | 695 | { |
529 | 695 | checkCapacity(position); |
530 | 695 | } |
531 | | |
532 | 704 | m_bitIndex = position; |
533 | 704 | } |
534 | | |
535 | | void BitStreamWriter::alignTo(size_t alignment) |
536 | 4.73k | { |
537 | 4.73k | const BitPosType offset = getBitPosition() % alignment; |
538 | 4.73k | if (offset != 0) |
539 | 2.46k | { |
540 | 2.46k | const uint8_t skip = static_cast<uint8_t>(alignment - offset); |
541 | 2.46k | writeBits64(0, skip); |
542 | 2.46k | } |
543 | 4.73k | } |
544 | | |
545 | | const uint8_t* BitStreamWriter::getWriteBuffer() const |
546 | 515 | { |
547 | 515 | return m_buffer.data(); |
548 | 515 | } |
549 | | |
550 | | Span<const uint8_t> BitStreamWriter::getBuffer() const |
551 | 18 | { |
552 | 18 | return m_buffer; |
553 | 18 | } |
554 | | |
555 | | void BitStreamWriter::writeUnsignedBits(uint32_t data, uint8_t numBits) |
556 | 103k | { |
557 | 103k | if (!hasWriteBuffer()) |
558 | 37.3k | { |
559 | 37.3k | m_bitIndex += numBits; |
560 | 37.3k | return; |
561 | 37.3k | } |
562 | | |
563 | 65.9k | checkCapacity(m_bitIndex + numBits); |
564 | | |
565 | 65.9k | uint8_t restNumBits = numBits; |
566 | 65.9k | const uint8_t bitsUsed = m_bitIndex & 0x07U; |
567 | 65.9k | uint8_t bitsFree = static_cast<uint8_t>(8 - bitsUsed); |
568 | 65.9k | size_t byteIndex = m_bitIndex / 8; |
569 | | |
570 | 65.9k | if (restNumBits > bitsFree) |
571 | 46.3k | { |
572 | | // first part |
573 | 46.3k | const uint8_t shiftNum = static_cast<uint8_t>(restNumBits - bitsFree); |
574 | 46.3k | const uint8_t maskedByte = static_cast<uint8_t>(m_buffer[byteIndex] & ~(0xFFU >> bitsUsed)); |
575 | 46.3k | m_buffer[byteIndex++] = static_cast<uint8_t>(maskedByte | (data >> shiftNum)); |
576 | 46.3k | restNumBits = static_cast<uint8_t>(restNumBits - bitsFree); |
577 | | |
578 | | // middle parts |
579 | 64.3k | while (restNumBits >= 8) |
580 | 18.0k | { |
581 | 18.0k | restNumBits = static_cast<uint8_t>(restNumBits - 8); |
582 | 18.0k | m_buffer[byteIndex++] = static_cast<uint8_t>((data >> restNumBits) & MAX_U32_VALUES[8]); |
583 | 18.0k | } |
584 | | |
585 | | // reset bits free |
586 | 46.3k | bitsFree = 8; |
587 | 46.3k | } |
588 | | |
589 | | // last part |
590 | 65.9k | if (restNumBits > 0) |
591 | 64.2k | { |
592 | 64.2k | const uint8_t shiftNum = static_cast<uint8_t>(bitsFree - restNumBits); |
593 | 64.2k | const uint32_t mask = MAX_U32_VALUES[restNumBits]; |
594 | 64.2k | const uint8_t maskedByte = |
595 | 64.2k | m_buffer[byteIndex] & static_cast<uint8_t>(~static_cast<uint8_t>(mask << shiftNum)); |
596 | 64.2k | m_buffer[byteIndex] = static_cast<uint8_t>(maskedByte | ((data & mask) << shiftNum)); |
597 | 64.2k | } |
598 | | |
599 | 65.9k | m_bitIndex += numBits; |
600 | 65.9k | } |
601 | | |
602 | | inline void BitStreamWriter::writeUnsignedBits64(uint64_t data, uint8_t numBits) |
603 | 7.20k | { |
604 | 7.20k | if (numBits <= 32) |
605 | 4.04k | { |
606 | 4.04k | writeUnsignedBits(static_cast<uint32_t>(data), numBits); |
607 | 4.04k | } |
608 | 3.16k | else |
609 | 3.16k | { |
610 | 3.16k | writeUnsignedBits(static_cast<uint32_t>(data >> 32U), static_cast<uint8_t>(numBits - 32)); |
611 | 3.16k | writeUnsignedBits(static_cast<uint32_t>(data), 32); |
612 | 3.16k | } |
613 | 7.20k | } |
614 | | |
615 | | inline void BitStreamWriter::writeSignedVarNum(int64_t value, size_t maxVarBytes, size_t numVarBytes) |
616 | 11.3k | { |
617 | 11.3k | const uint64_t absValue = static_cast<uint64_t>(value < 0 ? -value3.92k : value7.37k ); |
618 | 11.3k | writeVarNum(absValue, true, value < 0, maxVarBytes, numVarBytes); |
619 | 11.3k | } |
620 | | |
621 | | inline void BitStreamWriter::writeUnsignedVarNum(uint64_t value, size_t maxVarBytes, size_t numVarBytes) |
622 | 10.1k | { |
623 | 10.1k | writeVarNum(value, false, false, maxVarBytes, numVarBytes); |
624 | 10.1k | } |
625 | | |
626 | | inline void BitStreamWriter::writeVarNum( |
627 | | uint64_t value, bool hasSign, bool isNegative, size_t maxVarBytes, size_t numVarBytes) |
628 | 21.4k | { |
629 | 21.4k | static const std::array<uint64_t, 8> bitMasks = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF}; |
630 | 21.4k | const bool hasMaxByteRange = (numVarBytes == maxVarBytes); |
631 | | |
632 | 103k | for (size_t i = 0; i < numVarBytes; i++81.9k ) |
633 | 81.9k | { |
634 | 81.9k | uint8_t byte = 0x00; |
635 | 81.9k | uint8_t numBits = 8; |
636 | 81.9k | const bool hasNextByte = (i < numVarBytes - 1); |
637 | 81.9k | const bool hasSignBit = (hasSign && i == 048.6k ); |
638 | 81.9k | if (hasSignBit) |
639 | 11.3k | { |
640 | 11.3k | if (isNegative) |
641 | 3.92k | { |
642 | 3.92k | byte |= 0x80U; |
643 | 3.92k | } |
644 | 11.3k | numBits--; |
645 | 11.3k | } |
646 | 81.9k | if (hasNextByte) |
647 | 60.5k | { |
648 | 60.5k | numBits--; |
649 | 60.5k | const uint8_t add = static_cast<uint8_t>(0x01U << numBits); |
650 | 60.5k | byte = static_cast<uint8_t>(byte | add); // use bit 6 if signed bit is present, use bit 7 otherwise |
651 | 60.5k | } |
652 | 21.4k | else // this is the last byte |
653 | 21.4k | { |
654 | 21.4k | if (!hasMaxByteRange) // next byte indicator is not used in last byte in case of max byte range |
655 | 18.8k | { |
656 | 18.8k | numBits--; |
657 | 18.8k | } |
658 | 21.4k | } |
659 | | |
660 | 81.9k | const size_t shiftBits = (numVarBytes - (i + 1)) * 7 + ((hasMaxByteRange && hasNextByte17.7k ) ? 115.1k : 066.8k ); |
661 | 81.9k | const uint8_t add = static_cast<uint8_t>((value >> shiftBits) & bitMasks[numBits - 1U]); |
662 | 81.9k | byte = static_cast<uint8_t>(byte | add); |
663 | 81.9k | writeUnsignedBits(byte, 8); |
664 | 81.9k | } |
665 | 21.4k | } |
666 | | |
667 | | inline void BitStreamWriter::throwInsufficientCapacityException() const |
668 | 71 | { |
669 | 71 | throw InsufficientCapacityException("BitStreamWriter: Reached end of bit buffer!"); |
670 | 71 | } |
671 | | |
672 | | inline void BitStreamWriter::checkCapacity(size_t bitSize) const |
673 | 66.6k | { |
674 | 66.6k | if (bitSize > m_bufferBitSize) |
675 | 71 | { |
676 | 71 | throwInsufficientCapacityException(); |
677 | 71 | } |
678 | 66.6k | } |
679 | | |
680 | | } // namespace zserio |