src/zserio/BitStreamWriter.cpp
Line | Count | 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 | | BitStreamWriter::BitStreamWriter(uint8_t* buffer, size_t bufferBitSize, BitsTag) : |
117 | | m_buffer(buffer, (bufferBitSize + 7) / 8), |
118 | | m_bitIndex(0), |
119 | | m_bufferBitSize(bufferBitSize) |
120 | 1 | {} |
121 | | |
122 | | BitStreamWriter::BitStreamWriter(uint8_t* buffer, size_t bufferByteSize) : |
123 | | BitStreamWriter(Span<uint8_t>(buffer, bufferByteSize)) |
124 | 3.40k | {} |
125 | | |
126 | | BitStreamWriter::BitStreamWriter(Span<uint8_t> buffer) : |
127 | | m_buffer(buffer), |
128 | | m_bitIndex(0), |
129 | | m_bufferBitSize(buffer.size() * 8) |
130 | 3.41k | {} |
131 | | |
132 | | BitStreamWriter::BitStreamWriter(Span<uint8_t> buffer, size_t bufferBitSize) : |
133 | | m_buffer(buffer), |
134 | | m_bitIndex(0), |
135 | | m_bufferBitSize(bufferBitSize) |
136 | 471 | { |
137 | 471 | if (buffer.size() < (bufferBitSize + 7) / 8) |
138 | 1 | { |
139 | 1 | throw CppRuntimeException("BitStreamWriter: Wrong buffer bit size ('") << buffer.size() << |
140 | 1 | "' < '" << (bufferBitSize + 7) / 8 << "')!"; |
141 | 1 | } |
142 | 471 | } |
143 | | |
144 | | void BitStreamWriter::writeBits(uint32_t data, uint8_t numBits) |
145 | 8.85k | { |
146 | 8.85k | if (numBits > sizeof(uint32_t) * 8 || data > MAX_U32_VALUES[numBits]8.85k ) |
147 | 34 | { |
148 | 34 | throw CppRuntimeException("BitStreamWriter: Writing of ") << numBits << "-bits value '" << data << |
149 | 34 | "' failed!"; |
150 | 34 | } |
151 | | |
152 | 8.81k | writeUnsignedBits(data, numBits); |
153 | 8.81k | } |
154 | | |
155 | | void BitStreamWriter::writeBits64(uint64_t data, uint8_t numBits) |
156 | 4.35k | { |
157 | 4.35k | if (numBits > sizeof(uint64_t) * 8 || data > MAX_U64_VALUES[numBits]4.35k ) |
158 | 66 | { |
159 | 66 | throw CppRuntimeException("BitStreamWriter: Writing of ") << numBits << "-bits value '" << data << |
160 | 66 | "' failed!"; |
161 | 66 | } |
162 | | |
163 | 4.28k | writeUnsignedBits64(data, numBits); |
164 | 4.28k | } |
165 | | |
166 | | void BitStreamWriter::writeSignedBits(int32_t data, uint8_t numBits) |
167 | 1.62k | { |
168 | 1.62k | if (numBits > sizeof(int32_t) * 8 || data < MIN_I32_VALUES[numBits]1.62k || data > MAX_I32_VALUES[numBits]1.59k ) |
169 | 65 | { |
170 | 65 | throw CppRuntimeException("BitStreamWriter: Writing of ") << numBits << "-bits value '" << data << |
171 | 65 | "' failed!"; |
172 | 65 | } |
173 | | |
174 | 1.56k | writeUnsignedBits(static_cast<uint32_t>(data) & MAX_U32_VALUES[numBits], numBits); |
175 | 1.56k | } |
176 | | |
177 | | void BitStreamWriter::writeSignedBits64(int64_t data, uint8_t numBits) |
178 | 2.18k | { |
179 | 2.18k | if (numBits > sizeof(int64_t) * 8 || data < MIN_I64_VALUES[numBits]2.18k || data > MAX_I64_VALUES[numBits]2.12k ) |
180 | 129 | { |
181 | 129 | throw CppRuntimeException("BitStreamWriter: Writing of ") << numBits << "-bits value '" << data << |
182 | 129 | "' failed!"; |
183 | 129 | } |
184 | | |
185 | 2.05k | writeUnsignedBits64(static_cast<uint64_t>(data) & MAX_U64_VALUES[numBits], numBits); |
186 | 2.05k | } |
187 | | |
188 | | void BitStreamWriter::writeVarInt64(int64_t data) |
189 | 4.42k | { |
190 | 4.42k | writeSignedVarNum(data, 8, zserio::bitSizeOfVarInt64(data) / 8); |
191 | 4.42k | } |
192 | | |
193 | | void BitStreamWriter::writeVarInt32(int32_t data) |
194 | 1.19k | { |
195 | 1.19k | writeSignedVarNum(data, 4, zserio::bitSizeOfVarInt32(data) / 8); |
196 | 1.19k | } |
197 | | |
198 | | void BitStreamWriter::writeVarInt16(int16_t data) |
199 | 344 | { |
200 | 344 | writeSignedVarNum(data, 2, zserio::bitSizeOfVarInt16(data) / 8); |
201 | 344 | } |
202 | | |
203 | | void BitStreamWriter::writeVarUInt64(uint64_t data) |
204 | 3.14k | { |
205 | 3.14k | writeUnsignedVarNum(data, 8, zserio::bitSizeOfVarUInt64(data) / 8); |
206 | 3.14k | } |
207 | | |
208 | | void BitStreamWriter::writeVarUInt32(uint32_t data) |
209 | 820 | { |
210 | 820 | writeUnsignedVarNum(data, 4, zserio::bitSizeOfVarUInt32(data) / 8); |
211 | 820 | } |
212 | | |
213 | | void BitStreamWriter::writeVarUInt16(uint16_t data) |
214 | 284 | { |
215 | 284 | writeUnsignedVarNum(data, 2, zserio::bitSizeOfVarUInt16(data) / 8); |
216 | 284 | } |
217 | | |
218 | | void BitStreamWriter::writeVarInt(int64_t data) |
219 | 5.50k | { |
220 | 5.50k | if (data == INT64_MIN) |
221 | 159 | writeBits(0x80, 8); // INT64_MIN is encoded as -0 |
222 | 5.34k | else |
223 | 5.34k | writeSignedVarNum(data, 9, zserio::bitSizeOfVarInt(data) / 8); |
224 | 5.50k | } |
225 | | |
226 | | void BitStreamWriter::writeVarUInt(uint64_t data) |
227 | 2.75k | { |
228 | 2.75k | writeUnsignedVarNum(data, 9, zserio::bitSizeOfVarUInt(data) / 8); |
229 | 2.75k | } |
230 | | |
231 | | void BitStreamWriter::writeVarSize(uint32_t data) |
232 | 3.11k | { |
233 | 3.11k | writeUnsignedVarNum(data, 5, zserio::bitSizeOfVarSize(data) / 8); |
234 | 3.11k | } |
235 | | |
236 | | void BitStreamWriter::writeFloat16(float data) |
237 | 305 | { |
238 | 305 | const uint16_t halfPrecisionFloat = convertFloatToUInt16(data); |
239 | 305 | writeUnsignedBits(halfPrecisionFloat, 16); |
240 | 305 | } |
241 | | |
242 | | void BitStreamWriter::writeFloat32(float data) |
243 | 499 | { |
244 | 499 | const uint32_t singlePrecisionFloat = convertFloatToUInt32(data); |
245 | 499 | writeUnsignedBits(singlePrecisionFloat, 32); |
246 | 499 | } |
247 | | |
248 | | void BitStreamWriter::writeFloat64(double data) |
249 | 859 | { |
250 | 859 | const uint64_t doublePrecisionFloat = convertDoubleToUInt64(data); |
251 | 859 | writeUnsignedBits64(doublePrecisionFloat, 64); |
252 | 859 | } |
253 | | |
254 | | void BitStreamWriter::writeBytes(Span<const uint8_t> data) |
255 | 99 | { |
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 | 52 | { |
262 | | // we are not aligned to byte |
263 | 180 | for (size_t i = 0; i < len; ++i128 ) |
264 | 128 | writeBits(data[i], 8); |
265 | 52 | } |
266 | 47 | else |
267 | 47 | { |
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 | 47 | } |
273 | 99 | } |
274 | | |
275 | | void BitStreamWriter::writeString(StringView data) |
276 | 161 | { |
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 | 78 | { |
283 | | // we are not aligned to byte |
284 | 1.54k | for (size_t i = 0; i < len; ++i1.47k ) |
285 | 1.47k | writeBits(static_cast<uint8_t>(data[i]), 8); |
286 | 78 | } |
287 | 83 | else |
288 | 83 | { |
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 | 83 | } |
294 | 161 | } |
295 | | |
296 | | void BitStreamWriter::writeBool(bool data) |
297 | 909 | { |
298 | 909 | writeBits((data ? 1391 : 0518 ), 1); |
299 | 909 | } |
300 | | |
301 | | void BitStreamWriter::setBitPosition(BitPosType position) |
302 | 704 | { |
303 | 704 | if (hasWriteBuffer()) |
304 | 695 | checkCapacity(position); |
305 | | |
306 | 704 | m_bitIndex = position; |
307 | 704 | } |
308 | | |
309 | | void BitStreamWriter::alignTo(size_t alignment) |
310 | 4.73k | { |
311 | 4.73k | const BitPosType offset = getBitPosition() % alignment; |
312 | 4.73k | if (offset != 0) |
313 | 2.46k | { |
314 | 2.46k | const uint8_t skip = static_cast<uint8_t>(alignment - offset); |
315 | 2.46k | writeBits64(0, skip); |
316 | 2.46k | } |
317 | 4.73k | } |
318 | | |
319 | | const uint8_t* BitStreamWriter::getWriteBuffer() const |
320 | 515 | { |
321 | 515 | return m_buffer.data(); |
322 | 515 | } |
323 | | |
324 | | Span<const uint8_t> BitStreamWriter::getBuffer() const |
325 | 18 | { |
326 | 18 | return m_buffer; |
327 | 18 | } |
328 | | |
329 | | void BitStreamWriter::writeUnsignedBits(uint32_t data, uint8_t numBits) |
330 | 103k | { |
331 | 103k | if (!hasWriteBuffer()) |
332 | 37.3k | { |
333 | 37.3k | m_bitIndex += numBits; |
334 | 37.3k | return; |
335 | 37.3k | } |
336 | | |
337 | 66.4k | checkCapacity(m_bitIndex + numBits); |
338 | | |
339 | 66.4k | uint8_t restNumBits = numBits; |
340 | 66.4k | const uint8_t bitsUsed = m_bitIndex & 0x07U; |
341 | 66.4k | uint8_t bitsFree = 8 - bitsUsed; |
342 | 66.4k | size_t byteIndex = m_bitIndex / 8; |
343 | | |
344 | 66.4k | if (restNumBits > bitsFree) |
345 | 46.3k | { |
346 | | // first part |
347 | 46.3k | const uint8_t shiftNum = restNumBits - bitsFree; |
348 | 46.3k | const uint8_t maskedByte = m_buffer[byteIndex] & ~(0xFFU >> bitsUsed); |
349 | 46.3k | m_buffer[byteIndex++] = maskedByte | static_cast<uint8_t>(data >> shiftNum); |
350 | 46.3k | restNumBits -= bitsFree; |
351 | | |
352 | | // middle parts |
353 | 64.3k | while (restNumBits >= 8) |
354 | 18.0k | { |
355 | 18.0k | restNumBits -= 8; |
356 | 18.0k | m_buffer[byteIndex++] = static_cast<uint8_t>((data >> restNumBits) & MAX_U32_VALUES[8]); |
357 | 18.0k | } |
358 | | |
359 | | // reset bits free |
360 | 46.3k | bitsFree = 8; |
361 | 46.3k | } |
362 | | |
363 | | // last part |
364 | 66.4k | if (restNumBits > 0) |
365 | 64.2k | { |
366 | 64.2k | const uint8_t shiftNum = bitsFree - restNumBits; |
367 | 64.2k | const uint32_t mask = MAX_U32_VALUES[restNumBits]; |
368 | 64.2k | const uint8_t maskedByte = m_buffer[byteIndex] & |
369 | 64.2k | static_cast<uint8_t>(~static_cast<uint8_t>(mask << shiftNum)); |
370 | 64.2k | m_buffer[byteIndex] = maskedByte | static_cast<uint8_t>((data & mask) << shiftNum); |
371 | 64.2k | } |
372 | | |
373 | 66.4k | m_bitIndex += numBits; |
374 | 66.4k | } |
375 | | |
376 | | inline void BitStreamWriter::writeUnsignedBits64(uint64_t data, uint8_t numBits) |
377 | 7.20k | { |
378 | 7.20k | if (numBits <= 32) |
379 | 4.04k | { |
380 | 4.04k | writeUnsignedBits(static_cast<uint32_t>(data), numBits); |
381 | 4.04k | } |
382 | 3.16k | else |
383 | 3.16k | { |
384 | 3.16k | writeUnsignedBits(static_cast<uint32_t>(data >> 32U), numBits - 32); |
385 | 3.16k | writeUnsignedBits(static_cast<uint32_t>(data), 32); |
386 | 3.16k | } |
387 | 7.20k | } |
388 | | |
389 | | inline void BitStreamWriter::writeSignedVarNum(int64_t value, size_t maxVarBytes, size_t numVarBytes) |
390 | 11.3k | { |
391 | 11.3k | const uint64_t absValue = static_cast<uint64_t>(value < 0 ? -value3.92k : value7.37k ); |
392 | 11.3k | writeVarNum(absValue, true, value < 0, maxVarBytes, numVarBytes); |
393 | 11.3k | } |
394 | | |
395 | | inline void BitStreamWriter::writeUnsignedVarNum(uint64_t value, size_t maxVarBytes, size_t numVarBytes) |
396 | 10.1k | { |
397 | 10.1k | writeVarNum(value, false, false, maxVarBytes, numVarBytes); |
398 | 10.1k | } |
399 | | |
400 | | inline void BitStreamWriter::writeVarNum(uint64_t value, bool hasSign, bool isNegative, size_t maxVarBytes, |
401 | | size_t numVarBytes) |
402 | 21.4k | { |
403 | 21.4k | static const std::array<uint64_t, 8> bitMasks = { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; |
404 | 21.4k | const bool hasMaxByteRange = (numVarBytes == maxVarBytes); |
405 | | |
406 | 103k | for (size_t i = 0; i < numVarBytes; i++81.9k ) |
407 | 81.9k | { |
408 | 81.9k | uint8_t byte = 0x00; |
409 | 81.9k | uint8_t numBits = 8; |
410 | 81.9k | const bool hasNextByte = (i < numVarBytes - 1); |
411 | 81.9k | const bool hasSignBit = (hasSign && i == 048.6k ); |
412 | 81.9k | if (hasSignBit) |
413 | 11.3k | { |
414 | 11.3k | if (isNegative) |
415 | 3.92k | byte |= 0x80U; |
416 | 11.3k | numBits--; |
417 | 11.3k | } |
418 | 81.9k | if (hasNextByte) |
419 | 60.5k | { |
420 | 60.5k | numBits--; |
421 | 60.5k | byte |= (0x01U << numBits); // use bit 6 if signed bit is present, use bit 7 otherwise |
422 | 60.5k | } |
423 | 21.4k | else // this is the last byte |
424 | 21.4k | { |
425 | 21.4k | if (!hasMaxByteRange) // next byte indicator is not used in last byte in case of max byte range |
426 | 18.8k | numBits--; |
427 | 21.4k | } |
428 | | |
429 | 81.9k | const size_t shiftBits = (numVarBytes - (i + 1)) * 7 + ((hasMaxByteRange && hasNextByte17.7k ) ? 115.1k : 066.8k ); |
430 | 81.9k | byte |= static_cast<uint8_t>((value >> shiftBits) & bitMasks[numBits - 1]); |
431 | 81.9k | writeUnsignedBits(byte, 8); |
432 | 81.9k | } |
433 | 21.4k | } |
434 | | |
435 | | inline void BitStreamWriter::throwInsufficientCapacityException() const |
436 | 71 | { |
437 | 71 | throw InsufficientCapacityException("BitStreamWriter: Reached end of bit buffer!"); |
438 | 71 | } |
439 | | |
440 | | inline void BitStreamWriter::checkCapacity(size_t bitSize) const |
441 | 67.1k | { |
442 | 67.1k | if (bitSize > m_bufferBitSize) |
443 | 71 | throwInsufficientCapacityException(); |
444 | 67.1k | } |
445 | | |
446 | | } // namespace zserio |