Zserio C++17 runtime library 1.3.0
Built for Zserio 2.20.0
Loading...
Searching...
No Matches
BitBuffer.h
Go to the documentation of this file.
1#ifndef ZSERIO_BIT_BUFFER_H_INC
2#define ZSERIO_BIT_BUFFER_H_INC
3
4#include <cstddef>
5#include <cstring>
6#include <functional>
7#include <string_view>
8#include <type_traits>
9#include <vector>
10
11#include "zserio/BitSize.h"
13#include "zserio/HashCodeUtil.h"
15#include "zserio/Span.h"
16#include "zserio/Traits.h"
17
18namespace zserio
19{
20
25struct BitsTag
26{};
27
34template <typename ALLOC = std::allocator<uint8_t>>
36{
37public:
38 static_assert(std::is_same<uint8_t, typename ALLOC::value_type>::value,
39 "Allocator with uint8_t value_type is required!");
40
42
49 {
50 return m_buffer.get_allocator();
51 }
52
59
65 explicit BasicBitBuffer(const ALLOC& allocator);
66
73 explicit BasicBitBuffer(size_t bitSize, const ALLOC& allocator = {});
74
81 explicit BasicBitBuffer(Span<const uint8_t> buffer, const ALLOC& allocator = {});
82
92 explicit BasicBitBuffer(Span<const uint8_t> buffer, size_t bitSize, const ALLOC& allocator = {});
93
99 explicit BasicBitBuffer(std::vector<uint8_t, ALLOC>&& buffer);
100
109 explicit BasicBitBuffer(std::vector<uint8_t, ALLOC>&& buffer, size_t bitSize);
110
115
120
125 ~BasicBitBuffer() = default;
126
129
143 bool operator==(const BasicBitBuffer& other) const;
144
152 bool operator!=(const BasicBitBuffer& other) const
153 {
154 return !(*this == other);
155 }
156
165 bool operator<(const BasicBitBuffer& other) const;
166
174 bool operator>(const BasicBitBuffer& other) const
175 {
176 return other < *this;
177 }
178
186 bool operator<=(const BasicBitBuffer& other) const
187 {
188 return !(other < *this);
189 }
190
198 bool operator>=(const BasicBitBuffer& other) const
199 {
200 return !(*this < other);
201 }
202
209
215 const uint8_t* getBuffer() const;
216
223
229 size_t getBitSize() const;
230
238 size_t getByteSize() const;
239
245 const std::vector<uint8_t, ALLOC>& getBytes() const;
246
253
260
261private:
262 uint8_t getMaskedLastByte() const;
263
264 std::vector<uint8_t, ALLOC> m_buffer;
265 size_t m_bitSize;
266};
267
268template <typename ALLOC>
270 m_buffer(ALLOC()),
271 m_bitSize(0)
272{}
273
274template <typename ALLOC>
276 m_buffer(allocator),
277 m_bitSize(0)
278{}
279
280template <typename ALLOC>
282 m_buffer((bitSize + 7) / 8, 0, allocator),
283 m_bitSize(bitSize)
284{}
285
286template <typename ALLOC>
288 m_buffer(buffer.begin(), buffer.end(), allocator),
289 m_bitSize(8 * buffer.size())
290{}
291
292template <typename ALLOC>
294 m_buffer(buffer.begin(), buffer.end(), allocator),
295 m_bitSize(bitSize)
296{
297 const size_t byteSize = (bitSize + 7) / 8;
298 if (buffer.size() < byteSize)
299 {
300 throw CppRuntimeException("BitBuffer: Bit size ")
301 << bitSize << " out of range for given span byte size " << buffer.size() << "!";
302 }
303}
304
305template <typename ALLOC>
306BasicBitBuffer<ALLOC>::BasicBitBuffer(std::vector<uint8_t, ALLOC>&& buffer) :
307 m_buffer(std::move(buffer)),
308 m_bitSize(8 * m_buffer.size())
309{}
310
311template <typename ALLOC>
312BasicBitBuffer<ALLOC>::BasicBitBuffer(std::vector<uint8_t, ALLOC>&& buffer, size_t bitSize) :
313 m_buffer(std::move(buffer)),
314 m_bitSize(bitSize)
315{
316 const size_t byteSize = (bitSize + 7) / 8;
317 if (m_buffer.size() < byteSize)
318 {
319 throw CppRuntimeException("BitBuffer: Bit size ")
320 << bitSize << " out of range for given vector byte size " << m_buffer.size() << "!";
321 }
322}
323
324template <typename ALLOC>
326 m_buffer(other.m_buffer, allocator),
327 m_bitSize(other.m_bitSize)
328{}
329
330template <typename ALLOC>
332 m_buffer(std::move(other.m_buffer), allocator),
333 m_bitSize(other.m_bitSize)
334{}
335
336template <typename ALLOC>
338{
339 if (this != &other)
340 {
341 if (m_bitSize != other.m_bitSize)
342 {
343 return false;
344 }
345
346 const size_t byteSize = getByteSize();
347 if (byteSize > 0)
348 {
349 if (byteSize > 1)
350 {
351 if (std::memcmp(getBuffer(), other.getBuffer(), byteSize - 1) != 0)
352 {
353 return false;
354 }
355 }
356
357 if (getMaskedLastByte() != other.getMaskedLastByte())
358 {
359 return false;
360 }
361 }
362 }
363
364 return true;
365}
366
367template <typename ALLOC>
369{
370 const size_t byteSize1 = getByteSize();
371 const size_t byteSize2 = other.getByteSize();
372
373 if (byteSize1 == 0)
374 {
375 return byteSize2 != 0;
376 }
377 if (byteSize2 == 0)
378 {
379 return false;
380 }
381
382 using DifferenceType = typename std::vector<uint8_t, ALLOC>::iterator::difference_type;
383
384 auto first1 = m_buffer.begin();
385 const auto last1 = first1 + static_cast<DifferenceType>(byteSize1 - 1);
386 auto first2 = other.m_buffer.begin();
387 const auto last2 = first2 + static_cast<DifferenceType>(byteSize2 - 1);
388 for (; (first1 != last1) && (first2 != last2); ++first1, ++first2)
389 {
390 if (*first1 < *first2)
391 {
392 return true;
393 }
394 if (*first2 < *first1)
395 {
396 return false;
397 }
398 }
399
400 const auto lastValue1 = first1 != last1 ? *first1 : getMaskedLastByte();
401 const auto lastValue2 = first2 != last2 ? *first2 : other.getMaskedLastByte();
403 {
404 return true;
405 }
407 {
408 return false;
409 }
410
411 return m_bitSize < other.m_bitSize;
412}
413
414template <typename ALLOC>
416{
417 uint32_t result = HASH_SEED;
418 const size_t byteSize = getByteSize();
419 if (byteSize > 0)
420 {
421 if (byteSize > 1)
422 {
423 auto lastIt = m_buffer.begin() + static_cast<int>(byteSize) - 1;
424 for (auto it = m_buffer.begin(); it != lastIt; ++it)
425 {
427 }
428 }
429 result = calcHashCode(result, getMaskedLastByte());
430 }
431
432 return result;
433}
434
435template <typename ALLOC>
437{
438 return m_buffer.data();
439}
440
441template <typename ALLOC>
443{
444 return m_buffer.data();
445}
446
447template <typename ALLOC>
449{
450 return m_bitSize;
451}
452
453template <typename ALLOC>
455{
456 return (m_bitSize + 7) / 8;
457}
458
459template <typename ALLOC>
460const std::vector<uint8_t, ALLOC>& BasicBitBuffer<ALLOC>::getBytes() const
461{
462 return m_buffer;
463}
464
465template <typename ALLOC>
470
471template <typename ALLOC>
476
477template <typename ALLOC>
479{
480 const size_t roundedByteSize = m_bitSize / 8;
481 const uint8_t lastByteBits = static_cast<uint8_t>(m_bitSize - 8 * roundedByteSize);
482
483 return (lastByteBits == 0)
484 ? m_buffer[roundedByteSize - 1]
485 : static_cast<uint8_t>(m_buffer[roundedByteSize] & (0xFFU << (8U - lastByteBits)));
486}
487
490
492template <typename ALLOC>
493using BasicBitBufferView = std::reference_wrapper<const BasicBitBuffer<ALLOC>>;
494
496using BitBufferView = std::reference_wrapper<const BitBuffer>;
497
498template <typename ALLOC>
503
507template <typename ALLOC>
509{
510 return lhs.get() == rhs.get();
511}
512
513template <typename ALLOC>
515{
516 return lhs.get() != rhs.get();
517}
518
519template <typename ALLOC>
521{
522 return lhs.get() < rhs.get();
523}
524
525template <typename ALLOC>
527{
528 return lhs.get() > rhs.get();
529}
530
531template <typename ALLOC>
533{
534 return lhs.get() <= rhs.get();
535}
536
537template <typename ALLOC>
539{
540 return lhs.get() >= rhs.get();
541}
542
553template <typename ALLOC>
555{
556 return exception << "BitBuffer([...], " << bitBuffer.getBitSize() << ")";
557}
558
567template <typename ALLOC>
572
573namespace detail
574{
575
576template <typename ALLOC>
577void validate(const BasicBitBufferView<ALLOC>&, std::string_view)
578{
579 // always valid
580}
581
582template <typename ALLOC>
583BitSize bitSizeOf(const BasicBitBufferView<ALLOC>& bitBufferView, BitSize = 0)
584{
585 const BasicBitBuffer<ALLOC>& bitBuffer = bitBufferView.get();
586 const VarSize bitBufferSize = fromCheckedValue<VarSize>(convertSizeToUInt32(bitBuffer.getBitSize()));
587
588 // bit buffer consists of varsize for bit size followed by the bits
589 return bitSizeOf(bitBufferSize) + bitBufferSize;
590}
591
592template <typename ALLOC>
593BitSize initializeOffsets(const BasicBitBufferView<ALLOC>& bitBufferView, BitSize bitPosition)
594{
595 return bitSizeof(bitBufferView, bitPosition);
596}
597
598} // namespace detail
599
600} // namespace zserio
601
602namespace std
603{
604
608template <typename ALLOC>
609struct hash<zserio::BasicBitBuffer<ALLOC>>
610{
611 size_t operator()(const zserio::BasicBitBuffer<ALLOC>& bitBuffer) const
612 {
613 return static_cast<size_t>(bitBuffer.hashCode());
614 }
615};
616
620template <typename ALLOC>
621struct hash<zserio::BasicBitBufferView<ALLOC>>
622{
623 size_t operator()(const zserio::BasicBitBufferView<ALLOC>& bitBuffer) const
624 {
625 return static_cast<size_t>(bitBuffer.get().hashCode());
626 }
627};
628
629} // namespace std
630
631#endif // ifndef ZSERIO_BIT_BUFFER_H_INC
size_t getByteSize() const
Definition BitBuffer.h:454
BasicBitBuffer(const BasicBitBuffer &other, const ALLOC &allocator)
Definition BitBuffer.h:325
ALLOC get_allocator() const
Definition BitBuffer.h:48
bool operator<=(const BasicBitBuffer &other) const
Definition BitBuffer.h:186
BasicBitBuffer(std::vector< uint8_t, ALLOC > &&buffer)
Definition BitBuffer.h:306
BasicBitBuffer(Span< const uint8_t > buffer, const ALLOC &allocator={})
Definition BitBuffer.h:287
bool operator>(const BasicBitBuffer &other) const
Definition BitBuffer.h:174
BasicBitBuffer & operator=(const BasicBitBuffer &)=default
BasicBitBuffer(BasicBitBuffer &&)=default
BasicBitBuffer(const BasicBitBuffer &)=default
Span< const uint8_t > getData() const
Definition BitBuffer.h:466
size_t getBitSize() const
Definition BitBuffer.h:448
uint32_t hashCode() const
Definition BitBuffer.h:415
BasicBitBuffer(size_t bitSize, const ALLOC &allocator={})
Definition BitBuffer.h:281
BasicBitBuffer(std::vector< uint8_t, ALLOC > &&buffer, size_t bitSize)
Definition BitBuffer.h:312
bool operator>=(const BasicBitBuffer &other) const
Definition BitBuffer.h:198
bool operator==(const BasicBitBuffer &other) const
Definition BitBuffer.h:337
bool operator<(const BasicBitBuffer &other) const
Definition BitBuffer.h:368
BasicBitBuffer & operator=(BasicBitBuffer &&)=default
uint8_t * getBuffer()
Definition BitBuffer.h:442
const std::vector< uint8_t, ALLOC > & getBytes() const
Definition BitBuffer.h:460
Span< uint8_t > getData()
Definition BitBuffer.h:472
const uint8_t * getBuffer() const
Definition BitBuffer.h:436
BasicBitBuffer(const ALLOC &allocator)
Definition BitBuffer.h:275
BasicBitBuffer(Span< const uint8_t > buffer, size_t bitSize, const ALLOC &allocator={})
Definition BitBuffer.h:293
bool operator!=(const BasicBitBuffer &other) const
Definition BitBuffer.h:152
BasicBitBuffer(BasicBitBuffer &&other, const ALLOC &allocator)
Definition BitBuffer.h:331
bool operator>(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
Definition BitBuffer.h:526
bool operator==(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
Definition BitBuffer.h:508
unsigned int BitSize
Definition BitSize.h:8
CppRuntimeException & operator<<(CppRuntimeException &exception, const BasicBitBuffer< ALLOC > &bitBuffer)
Definition BitBuffer.h:554
std::reference_wrapper< const BitBuffer > BitBufferView
Definition BitBuffer.h:496
bool operator<(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
Definition BitBuffer.h:520
uint32_t calcHashCode(uint32_t seedValue, const ArrayView< T, ARRAY_TRAITS > &array)
Definition ArrayView.h:882
uint32_t convertSizeToUInt32(size_t value)
bool operator<=(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
Definition BitBuffer.h:532
bool operator>=(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
Definition BitBuffer.h:538
std::reference_wrapper< const BasicBitBuffer< ALLOC > > BasicBitBufferView
Definition BitBuffer.h:493
bool operator!=(const BasicBitBufferView< ALLOC > &lhs, const BasicBitBufferView< ALLOC > &rhs)
Definition BitBuffer.h:514
detail::VarIntWrapper< uint32_t, detail::VarIntType::VARSIZE > VarSize
Definition Types.h:890
size_t operator()(const zserio::BasicBitBufferView< ALLOC > &bitBuffer) const
Definition BitBuffer.h:623
size_t operator()(const zserio::BasicBitBuffer< ALLOC > &bitBuffer) const
Definition BitBuffer.h:611