Zserio C++ runtime library  1.0.0
Built for Zserio 2.13.0
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 <vector>
7 #include <type_traits>
8 
9 #include "zserio/Types.h"
10 #include "zserio/HashCodeUtil.h"
12 #include "zserio/Vector.h"
13 #include "zserio/Span.h"
14 
15 namespace zserio
16 {
17 
22 struct BitsTag
23 {};
24 
31 template <typename ALLOC = std::allocator<uint8_t>>
33 {
34 public:
35  static_assert(std::is_same<uint8_t, typename ALLOC::value_type>::value,
36  "Allocator with uint8_t value_type is required!");
37 
38  using allocator_type = ALLOC;
39 
46  {
47  return m_buffer.get_allocator();
48  }
49 
56 
62  explicit BasicBitBuffer(const ALLOC& allocator);
63 
70  explicit BasicBitBuffer(size_t bitSize, const ALLOC& allocator = ALLOC());
71 
78  explicit BasicBitBuffer(Span<const uint8_t> buffer, const ALLOC& allocator = ALLOC());
79 
89  explicit BasicBitBuffer(Span<const uint8_t> buffer, size_t bitSize, const ALLOC& allocator = ALLOC());
90 
96  explicit BasicBitBuffer(vector<uint8_t, ALLOC>&& buffer);
97 
106  explicit BasicBitBuffer(vector<uint8_t, ALLOC>&& buffer, size_t bitSize);
107 
115  explicit BasicBitBuffer(const uint8_t* buffer, size_t bitSize, const ALLOC& allocator = ALLOC());
116 
121  ~BasicBitBuffer() = default;
122 
123  BasicBitBuffer(const BasicBitBuffer<ALLOC>&) = default;
124  BasicBitBuffer(const BasicBitBuffer<ALLOC>& other, const ALLOC& allocator);
125  BasicBitBuffer& operator=(const BasicBitBuffer<ALLOC>&) = default;
126 
128  BasicBitBuffer(const BasicBitBuffer<ALLOC>&& other, const ALLOC& allocator);
129  BasicBitBuffer& operator=(BasicBitBuffer<ALLOC>&&) = default;
141  bool operator==(const BasicBitBuffer<ALLOC>& other) const;
142 
150  bool operator<(const BasicBitBuffer<ALLOC>& other) const;
151 
157  uint32_t hashCode() const;
158 
164  const uint8_t* getBuffer() const;
165 
171  uint8_t* getBuffer();
172 
178  size_t getBitSize() const;
179 
187  size_t getByteSize() const;
188 
194  const vector<uint8_t, ALLOC>& getBytes() const;
195 
201  Span<const uint8_t> getData() const;
202 
208  Span<uint8_t> getData();
209 
210 private:
211  uint8_t getMaskedLastByte() const;
212 
213  vector<uint8_t, ALLOC> m_buffer;
214  size_t m_bitSize;
215 };
216 
217 template <typename ALLOC>
219  m_buffer(ALLOC()), m_bitSize(0)
220 {
221 }
222 
223 template <typename ALLOC>
224 BasicBitBuffer<ALLOC>::BasicBitBuffer(const ALLOC& allocator) :
225  m_buffer(allocator), m_bitSize(0)
226 {
227 }
228 
229 template <typename ALLOC>
230 BasicBitBuffer<ALLOC>::BasicBitBuffer(size_t bitSize, const ALLOC& allocator) :
231  m_buffer((bitSize + 7) / 8, 0, allocator), m_bitSize(bitSize)
232 {
233 }
234 
235 template <typename ALLOC>
237  m_buffer(buffer.begin(), buffer.end(), allocator), m_bitSize(8 * buffer.size())
238 {
239 }
240 
241 template <typename ALLOC>
242 BasicBitBuffer<ALLOC>::BasicBitBuffer(Span<const uint8_t> buffer, size_t bitSize, const ALLOC& allocator) :
243  m_buffer(buffer.begin(), buffer.end(), allocator), m_bitSize(bitSize)
244 {
245  const size_t byteSize = (bitSize + 7) / 8;
246  if (buffer.size() < byteSize)
247  {
248  throw CppRuntimeException("BitBuffer: Bit size ") << bitSize <<
249  " out of range for given span byte size " << buffer.size() << "!";
250  }
251 }
252 
253 template <typename ALLOC>
255  m_buffer(std::move(buffer)), m_bitSize(8 * m_buffer.size())
256 {
257 }
258 
259 template <typename ALLOC>
261  m_buffer(std::move(buffer)), m_bitSize(bitSize)
262 {
263  const size_t byteSize = (bitSize + 7) / 8;
264  if (m_buffer.size() < byteSize)
265  {
266  throw CppRuntimeException("BitBuffer: Bit size ") << bitSize <<
267  " out of range for given vector byte size " << m_buffer.size() << "!";
268  }
269 }
270 
271 template <typename ALLOC>
272 BasicBitBuffer<ALLOC>::BasicBitBuffer(const uint8_t* buffer, size_t bitSize, const ALLOC& allocator) :
273  m_buffer(buffer, buffer + (bitSize + 7) / 8, allocator), m_bitSize(bitSize)
274 {
275 }
276 
277 template<typename ALLOC>
278 inline BasicBitBuffer<ALLOC>::BasicBitBuffer(const BasicBitBuffer<ALLOC>& other, const ALLOC& allocator) :
279  m_buffer(other.m_buffer, allocator), m_bitSize(other.m_bitSize)
280 {
281 }
282 
283 template<typename ALLOC>
284 inline BasicBitBuffer<ALLOC>::BasicBitBuffer(const BasicBitBuffer<ALLOC>&& other, const ALLOC& allocator) :
285  m_buffer(std::move(other.m_buffer), allocator), m_bitSize(other.m_bitSize)
286 {
287 }
288 
289 template <typename ALLOC>
291 {
292  if (this != &other)
293  {
294  if (m_bitSize != other.m_bitSize)
295  return false;
296 
297  const size_t byteSize = getByteSize();
298  if (byteSize > 0)
299  {
300  if (byteSize > 1)
301  {
302  if (memcmp(getBuffer(), other.getBuffer(), byteSize - 1) != 0)
303  return false;
304  }
305 
306  if (getMaskedLastByte() != other.getMaskedLastByte())
307  return false;
308  }
309  }
310 
311  return true;
312 }
313 
314 template <typename ALLOC>
316 {
317  const size_t byteSize1 = getByteSize();
318  const size_t byteSize2 = other.getByteSize();
319 
320  if (byteSize1 == 0)
321  return byteSize2 != 0;
322  if (byteSize2 == 0)
323  return false;
324 
325  using difference_type = typename vector<uint8_t, ALLOC>::iterator::difference_type;
326 
327  auto first1 = m_buffer.begin();
328  const auto last1 = first1 + static_cast<difference_type>(byteSize1 - 1);
329  auto first2 = other.m_buffer.begin();
330  const auto last2 = first2 + static_cast<difference_type>(byteSize2 - 1);
331  for (; (first1 != last1) && (first2 != last2); ++first1, ++first2)
332  {
333  if (*first1 < *first2)
334  return true;
335  if (*first2 < *first1)
336  return false;
337  }
338 
339  const auto lastValue1 = first1 != last1 ? *first1 : getMaskedLastByte();
340  const auto lastValue2 = first2 != last2 ? *first2 : other.getMaskedLastByte();
341  if (lastValue1 < lastValue2)
342  return true;
343  if (lastValue2 < lastValue1)
344  return false;
345 
346  return (first1 == last1) && (first2 != last2);
347 }
348 
349 template <typename ALLOC>
351 {
352  uint32_t result = ::zserio::HASH_SEED;
353  const size_t byteSize = getByteSize();
354  if (byteSize > 0)
355  {
356  if (byteSize > 1)
357  {
358  auto lastIt = m_buffer.begin() + static_cast<int>(byteSize) - 1;
359  for (auto it = m_buffer.begin(); it != lastIt; ++it)
360  result = calcHashCode(result, *it);
361  }
362  result = ::zserio::calcHashCode(result, getMaskedLastByte());
363  }
364 
365  return result;
366 }
367 
368 template <typename ALLOC>
369 const uint8_t* BasicBitBuffer<ALLOC>::getBuffer() const
370 {
371  return m_buffer.data();
372 }
373 
374 template <typename ALLOC>
376 {
377  return m_buffer.data();
378 }
379 
380 template <typename ALLOC>
382 {
383  return m_bitSize;
384 }
385 
386 template <typename ALLOC>
388 {
389  return (m_bitSize + 7) / 8;
390 }
391 
392 template <typename ALLOC>
394 {
395  return m_buffer;
396 }
397 
398 template <typename ALLOC>
400 {
401  return Span<const uint8_t>(m_buffer);
402 }
403 
404 template <typename ALLOC>
406 {
407  return Span<uint8_t>(m_buffer);
408 }
409 
410 template <typename ALLOC>
412 {
413  const size_t roundedByteSize = m_bitSize / 8;
414  const uint8_t lastByteBits = static_cast<uint8_t>(m_bitSize - 8 * roundedByteSize);
415 
416  return (lastByteBits == 0) ? m_buffer[roundedByteSize - 1] :
417  (m_buffer[roundedByteSize] & (0xFFU << (8U - lastByteBits)));
418 }
419 
422 
431 template <typename ALLOC>
432 CppRuntimeException& operator<<(CppRuntimeException& exception, const BasicBitBuffer<ALLOC>& bitBuffer)
433 {
434  return exception << "BitBuffer([...], " << bitBuffer.getBitSize() << ")";
435 }
436 
437 } // namespace zserio
438 
439 #endif // ifndef ZSERIO_BIT_BUFFER_H_INC
allocator_type get_allocator() const
Definition: BitBuffer.h:45
const vector< uint8_t, ALLOC > & getBytes() const
Definition: BitBuffer.h:393
const uint8_t * getBuffer() const
Definition: BitBuffer.h:369
bool operator==(const BasicBitBuffer< ALLOC > &other) const
Definition: BitBuffer.h:290
constexpr bool operator==(BasicStringView< CharT, Traits > lhs, BasicStringView< CharT, Traits > rhs) noexcept
Definition: StringView.h:817
constexpr size_type size() const noexcept
Definition: Span.h:276
uint32_t hashCode() const
Definition: BitBuffer.h:350
std::vector< T, RebindAlloc< ALLOC, T >> vector
Definition: Vector.h:16
size_t getBitSize() const
Definition: BitBuffer.h:381
size_t getByteSize() const
Definition: BitBuffer.h:387
std::enable_if< std::is_integral< T >::value &&(sizeof(T)<=4), uint32_t >::type calcHashCode(uint32_t seedValue, T value)
Definition: HashCodeUtil.h:43
Span< const uint8_t > getData() const
Definition: BitBuffer.h:399
bool operator<(const BasicBitBuffer< ALLOC > &other) const
Definition: BitBuffer.h:315