Skip to content

Commit

Permalink
bit_span: read least significant bit first (#105)
Browse files Browse the repository at this point in the history
to match the DEFLATE format

Change-Id: I9f8a0329e1d37ce760ffb939ce329624872528db
  • Loading branch information
garymm authored Oct 18, 2023
1 parent 99ac924 commit cfc12e0
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 22 deletions.
2 changes: 1 addition & 1 deletion huffman/src/bit_span.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class bit_span : public std::ranges::view_interface<bit_span>
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
static_cast<unsigned long long>(parent_->data_[offset_ / CHAR_BIT])};

return bit{byte[CHAR_BIT - 1 - (offset_ % CHAR_BIT)]};
return bit{byte[offset_ % CHAR_BIT]};
}

constexpr auto operator+=(difference_type n) -> iterator&
Expand Down
1 change: 1 addition & 0 deletions huffman/src/decode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "huffman/src/table.hpp"

#include <iterator>
#include <span>

namespace starflate::huffman {
/// Decodes a bit stream using a code table.
Expand Down
28 changes: 14 additions & 14 deletions huffman/test/bit_span_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ auto main() -> int
static constexpr std::array data{std::byte{0b10101010}, std::byte{0xff}};
// leave off the last bit of the last byte
constexpr huffman::bit_span span{data.data(), (data.size() * CHAR_BIT) - 1};
constexpr std::string_view expected = "101010101111111";
constexpr std::string_view expected = "010101011111111";
expect(std::ranges::equal(
span,
expected | std::views::transform([](char c) {
Expand All @@ -36,14 +36,14 @@ auto main() -> int

// NOLINTBEGIN(readability-magic-numbers)

static_assert(bs[0] == 1_b);
static_assert(bs[1] == 0_b);
static_assert(bs[2] == 1_b);
static_assert(bs[3] == 0_b);
static_assert(bs[4] == 1_b);
static_assert(bs[5] == 0_b);
static_assert(bs[6] == 1_b);
static_assert(bs[7] == 0_b);
static_assert(bs[0] == 0_b);
static_assert(bs[1] == 1_b);
static_assert(bs[2] == 0_b);
static_assert(bs[3] == 1_b);
static_assert(bs[4] == 0_b);
static_assert(bs[5] == 1_b);
static_assert(bs[6] == 0_b);
static_assert(bs[7] == 1_b);

expect(bs[8] == 1_b);
expect(bs[9] == 1_b);
Expand All @@ -68,11 +68,11 @@ auto main() -> int
// NOLINTBEGIN(readability-magic-numbers)

// from first byte
static_assert(bs[0] == 0_b);
static_assert(bs[1] == 1_b);
static_assert(bs[2] == 0_b);
static_assert(bs[3] == 1_b);
static_assert(bs[4] == 0_b);
static_assert(bs[0] == 1_b);
static_assert(bs[1] == 0_b);
static_assert(bs[2] == 1_b);
static_assert(bs[3] == 0_b);
static_assert(bs[4] == 1_b);

// from second byte
expect(huffman::bit_span{data.begin(), bit_size, bit_offset}[5] == 1_b);
Expand Down
26 changes: 19 additions & 7 deletions huffman/test/decode_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@
#include <stdexcept>
#include <utility>

constexpr auto reverse_bits(std::byte b) -> std::byte
{
std::byte result{};
for (auto i = 0; i < CHAR_BIT; ++i) {
result <<= 1;
result |= std::byte{(b & std::byte{1}) == std::byte{1}};
b >>= 1;
}
return result;
}

auto main() -> int
{
using ::boost::ut::expect;
Expand All @@ -16,14 +27,15 @@ auto main() -> int
using namespace huffman::literals;

test("basic") = [] {
// encoded data from dahuffman readme.rst, but in hex.
// encoded data from soxofaan/dahuffman readme.rst.
// We reverse the bits in each byte to match the encoding used in DEFLATE.
constexpr std::array encoded_bytes = {
std::byte{0x86},
std::byte{0x7c},
std::byte{0x25},
std::byte{0x13},
std::byte{0x69},
std::byte{0x40}};
reverse_bits(std::byte{134}),
reverse_bits(std::byte{124}),
reverse_bits(std::byte{37}),
reverse_bits(std::byte{19}),
reverse_bits(std::byte{105}),
reverse_bits(std::byte{64})};

constexpr char eot = {'\4'};
static constexpr auto code_table = // clang-format off
Expand Down

0 comments on commit cfc12e0

Please sign in to comment.