Skip to content

Commit

Permalink
update bit_span constructors and consume member
Browse files Browse the repository at this point in the history
Define a default constructor for `bit_span`. Update `consume` to return
a reference.

Change-Id: I08edcc3e240a44a04b09a8ba787030665134f3a8
  • Loading branch information
oliverlee committed Nov 22, 2023
1 parent 12dde2c commit fa67996
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 14 deletions.
35 changes: 21 additions & 14 deletions huffman/src/bit_span.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ namespace starflate::huffman {
/// A non-owning span of bits. Allows for iteration over the individual bits.
class bit_span : public std::ranges::view_interface<bit_span>
{
const std::byte* data_;
std::size_t bit_size_;
std::size_t init_bit_size_; // initial value of bit_size_
std::uint8_t bit_offset_; // always less than CHAR_BIT
const std::byte* data_{nullptr};
std::size_t bit_size_{};
std::uint8_t bit_offset_{}; // always less than CHAR_BIT

public:
/// An iterator over the bits in a bit_span.
Expand All @@ -39,7 +38,7 @@ class bit_span : public std::ranges::view_interface<bit_span>

iterator() = default;
constexpr iterator(const bit_span& parent, std::size_t offset)
: parent_(&parent), offset_(offset)
: parent_{&parent}, offset_{offset}
{
assert(offset_ <= std::numeric_limits<difference_type>::max());
}
Expand Down Expand Up @@ -74,6 +73,10 @@ class bit_span : public std::ranges::view_interface<bit_span>
operator<=>(const iterator&, const iterator&) = default;
};

/// Constructs an empty bit_span
///
bit_span() = default;

/// Constructs a bit_span from the given data.
///
/// @param data a pointer to the first byte of the data.
Expand All @@ -85,10 +88,7 @@ class bit_span : public std::ranges::view_interface<bit_span>
// NOLINTBEGIN(bugprone-easily-swappable-parameters)
constexpr bit_span(
const std::byte* data, std::size_t bit_size, std::uint8_t bit_offset = {})
: data_{data},
bit_size_{bit_size},
init_bit_size_{bit_size},
bit_offset_{bit_offset}
: data_{data}, bit_size_{bit_size}, bit_offset_{bit_offset}
// NOLINTEND(bugprone-easily-swappable-parameters)
{
assert(
Expand Down Expand Up @@ -145,16 +145,23 @@ class bit_span : public std::ranges::view_interface<bit_span>
/// Consumes the given number of bits. Advances the start of the view.
///
/// @pre n <= std::ranges::size(*this)
constexpr auto consume(std::size_t n) -> void
///
constexpr auto consume(std::size_t n) & -> bit_span&
{
assert(n <= bit_size_);
assert(n <= bit_size_); // pre
bit_size_ -= n;
// invariant
assert(bit_offset_ < CHAR_BIT);

const auto distance = bit_offset_ + n;
std::advance(data_, distance / CHAR_BIT);

bit_offset_ = static_cast<std::uint8_t>(distance % CHAR_BIT);

assert(bit_offset_ < CHAR_BIT); // post
return *this;
}
constexpr auto consume(std::size_t n) && -> bit_span&&
{
consume(n);
return std::move(*this);
}

/// Consumes bits until the start is aligned to a byte boundary.
Expand Down
22 changes: 22 additions & 0 deletions huffman/test/bit_span_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
auto main() -> int
{
using ::boost::ut::aborts;
using ::boost::ut::eq;
using ::boost::ut::expect;
using ::boost::ut::test;

Expand All @@ -31,6 +32,12 @@ auto main() -> int
})));
};

test("default constructible") = [] {
constexpr auto bits = huffman::bit_span{};

expect(eq(0, bits.size()));
};

test("indexable") = [] {
static constexpr auto data = huffman::byte_array(0b10101010, 0xff);
constexpr auto bs = huffman::bit_span{data};
Expand Down Expand Up @@ -114,6 +121,21 @@ auto main() -> int
}
} | std::views::iota(0UZ, 2UZ * (CHAR_BIT + 1UZ));

test("consume returns reference") = [] {
static constexpr auto data = std::byte{};

constexpr auto consumed_size = [] {
auto bits = huffman::bit_span{&data, CHAR_BIT};
return bits.consume(1).size();
}();

expect(eq(CHAR_BIT - 1, consumed_size));

constexpr auto consumed_bits =
huffman::bit_span{&data, CHAR_BIT}.consume(1);
expect(eq(CHAR_BIT - 1, consumed_bits.size()));
};

test("consume_to_byte_boundary") = [] {
static constexpr auto data = huffman::byte_array(0b10101010, 0b01010101);
huffman::bit_span span{data};
Expand Down

0 comments on commit fa67996

Please sign in to comment.