Commit ffdff2ba authored by nagayama15's avatar nagayama15

Add circular bit stream.

parent 8fd05c4a
#ifndef INCLUDE_NYKK_CIRCULARBITSTREAM_HPP
#define INCLUDE_NYKK_CIRCULARBITSTREAM_HPP
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <string_view>
#include <vector>
namespace nykk
{
class CircularBitStream
{
public:
static CircularBitStream from_string(std::string_view s)
{
return CircularBitStream { reinterpret_cast<const std::byte*>(s.data()), s.size() };
}
explicit CircularBitStream(const std::byte* pointer, std::size_t length)
: data_(pointer, pointer + length)
, bit_pos_(0)
{
assert(pointer != nullptr || length == 0);
}
// Uncopyable, movable.
CircularBitStream(const CircularBitStream&) =delete;
CircularBitStream(CircularBitStream&&) =default;
CircularBitStream& operator=(const CircularBitStream&) =delete;
CircularBitStream& operator=(CircularBitStream&&) =default;
~CircularBitStream() =default;
[[nodiscard]]
const std::byte* data() const noexcept
{
return data_.data();
}
[[nodiscard]]
std::size_t size_bytes() const noexcept
{
return data_.size();
}
[[nodiscard]]
std::size_t size_bits() const noexcept
{
return size_bytes() * 8;
}
[[nodiscard]]
std::size_t pos_bit() const noexcept
{
return bit_pos_;
}
std::uint64_t read(std::size_t size_bits)
{
assert(size_bits <= 64);
std::uint64_t data = 0;
for (std::size_t i = 0; i < size_bits; i++)
{
data |= read_bit() ? 1 << i : 0;
}
return data;
}
bool read_bit()
{
if (size_bits() == 0)
{
return false;
}
const std::byte value = data_[bit_pos_ >> 3] >> (bit_pos_ & 0x7);
if (++bit_pos_ >= size_bits())
{
bit_pos_ = 0;
}
return std::to_integer<bool>(value & std::byte {1});
}
private:
std::vector<std::byte> data_;
std::size_t bit_pos_;
};
}
#endif
#include "TestCircularBitStream.hpp"
#include "TestPermutationTable.hpp"
int main()
{
run_test_circular_bit_stream();
run_test_permutation_table();
}
#ifndef INCLUDE_TEST_TESTCIRCULARBITSTREAM_HPP
#define INCLUDE_TEST_TESTCIRCULARBITSTREAM_HPP
#include "../src/nykk/CircularBitStream.hpp"
#include <iostream>
inline void run_test_circular_bit_stream()
{
auto s = nykk::CircularBitStream::from_string(u8"\xab\xcd\xef\x98");
assert(s.size_bytes() == 4);
assert(s.size_bits() == 32);
assert(s.read_bit() == true);
assert(s.read_bit() == true);
assert(s.read_bit() == false);
assert(s.pos_bit() == 3);
assert(s.read(17) == 0x1f9b5);
assert(s.pos_bit() == 20);
assert(s.read(16) == 0xb98e);
assert(s.pos_bit() == 4);
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment