Verified Commit dfdcaaa2 authored by nagayama15's avatar nagayama15

feat(stream): add CircularBitStreamReader

parent 2363ea59
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define INCLUDE_kyut_BitStreamWriter_hpp #define INCLUDE_kyut_BitStreamWriter_hpp
#include <cassert> #include <cassert>
#include <cstdint>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
......
#ifndef INCLUDE_kyut_CircularBitStreamReader_hpp
#define INCLUDE_kyut_CircularBitStreamReader_hpp
#include <cassert>
#include <cstdint>
#include <string_view>
#include <vector>
namespace kyut {
class CircularBitStreamReader {
public:
explicit CircularBitStreamReader(std::vector<std::uint8_t>&& data)
: data_(std::move(data))
, pos_bits_(0) {
}
explicit CircularBitStreamReader(std::string_view data)
: data_(reinterpret_cast<const std::uint8_t*>(data.data()), reinterpret_cast<const std::uint8_t*>(data.data() + data.size()))
, pos_bits_(0) {
}
// Uncopyable and unmovable
CircularBitStreamReader(const CircularBitStreamReader&) = delete;
CircularBitStreamReader(CircularBitStreamReader&&) = delete;
CircularBitStreamReader& operator=(const CircularBitStreamReader&) = delete;
CircularBitStreamReader& operator=(CircularBitStreamReader&&) = delete;
~CircularBitStreamReader() noexcept = default;
std::uint64_t read(std::size_t size_bits) {
std::uint64_t x = 0;
for (std::size_t i = 0; i < size_bits; i++) {
x <<= 1;
x |= read_bit() ? 1 : 0;
}
return x;
}
bool read_bit() {
const auto n = pos_bits_ >> 3;
const auto k = pos_bits_ & 7;
const auto bit = (data_[n] >> (7 - k)) & 1;
pos_bits_++;
pos_bits_ %= size_bits();
return bit != 0;
}
std::size_t size_bytes() const noexcept {
return data_.size();
}
std::size_t size_bits() const noexcept {
return size_bytes() * 8;
}
std::size_t position_bits() const noexcept {
return pos_bits_;
}
private:
std::vector<std::uint8_t> data_;
std::size_t pos_bits_;
};
} // namespace kyut
#endif // INCLUDE_kyut_CircularBitStreamReader_hpp
...@@ -2,6 +2,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test") ...@@ -2,6 +2,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test")
add_executable(test_kyut add_executable(test_kyut
test_BitStreamWriter.cpp test_BitStreamWriter.cpp
test_CircularBitStreamReader.cpp
) )
target_link_libraries(test_kyut target_link_libraries(test_kyut
......
#include "kyut/CircularBitStreamReader.hpp"
#include <gtest/gtest.h>
TEST(kyut, CircularBitStreamReader) {
kyut::CircularBitStreamReader r{"\x89\xAB\xCD\xEF"};
std::uint64_t a;
EXPECT_EQ(r.size_bytes(), 4);
EXPECT_EQ(r.size_bits(), 32);
EXPECT_EQ(r.position_bits(), 0);
a = r.read(4);
EXPECT_EQ(a, 0x8);
EXPECT_EQ(r.position_bits(), 4);
a = r.read(12);
EXPECT_EQ(a, 0x9AB);
EXPECT_EQ(r.position_bits(), 16);
a = r.read(20);
EXPECT_EQ(a, 0xCDEF8);
EXPECT_EQ(r.position_bits(), 4);
}
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