96 lines
2.6 KiB
C++

#pragma once
#include "byte_buffer.h"
#include <cstddef>
#include <cstdint>
#include <limits>
#include <type_traits>
namespace bitstream
{
struct fixed_policy
{
/**
* @brief Construct a stream pointing to the given byte array with @p num_bytes size
* @param bytes The byte array to serialize to/from. Must be 4-byte aligned and the size must be a multiple of 4
* @param num_bytes The number of bytes in the array
*/
fixed_policy(void* buffer, uint32_t num_bits) noexcept :
m_Buffer(static_cast<uint32_t*>(buffer)),
m_NumBitsSerialized(0),
m_TotalBits(num_bits) {}
/**
* @brief Construct a stream pointing to the given @p buffer
* @param buffer The buffer to serialize to/from
* @param num_bits The maximum number of bits that we can read
*/
template<size_t Size>
fixed_policy(byte_buffer<Size>& buffer, uint32_t num_bits) noexcept :
m_Buffer(reinterpret_cast<uint32_t*>(buffer.Bytes)),
m_NumBitsSerialized(0),
m_TotalBits(num_bits) {}
/**
* @brief Construct a stream pointing to the given @p buffer
* @param buffer The buffer to serialize to/from
*/
template<size_t Size>
fixed_policy(byte_buffer<Size>& buffer) noexcept :
m_Buffer(reinterpret_cast<uint32_t*>(buffer.Bytes)),
m_NumBitsSerialized(0),
m_TotalBits(Size * 8) {}
uint32_t* get_buffer() const noexcept { return m_Buffer; }
// TODO: Transition sizes to size_t
uint32_t get_num_bits_serialized() const noexcept { return m_NumBitsSerialized; }
bool can_serialize_bits(uint32_t num_bits) const noexcept { return m_NumBitsSerialized + num_bits <= m_TotalBits; }
uint32_t get_total_bits() const noexcept { return m_TotalBits; }
bool extend(uint32_t num_bits) noexcept
{
if (!can_serialize_bits(num_bits))
return false;
m_NumBitsSerialized += num_bits;
return true;
}
uint32_t* m_Buffer;
// TODO: Transition sizes to size_t
uint32_t m_NumBitsSerialized;
uint32_t m_TotalBits;
};
template<typename T>
struct growing_policy
{
growing_policy(T& container) noexcept :
m_Buffer(container),
m_NumBitsSerialized(0) {}
uint32_t* get_buffer() const noexcept { return m_Buffer.data(); }
uint32_t get_num_bits_serialized() const noexcept { return m_NumBitsSerialized; }
bool can_serialize_bits(uint32_t num_bits) const noexcept { return true; }
uint32_t get_total_bits() const noexcept { return (std::numeric_limits<uint32_t>::max)(); }
bool extend(uint32_t num_bits)
{
m_NumBitsSerialized += num_bits;
uint32_t num_bytes = (m_NumBitsSerialized - 1) / 8U + 1;
m_Buffer.resize(num_bytes);
return true;
}
T& m_Buffer;
uint32_t m_NumBitsSerialized;
};
}