Skip to content

Commit

Permalink
WIP huffman decode
Browse files Browse the repository at this point in the history
Change-Id: I97309a7fd3c7059fe439fe516ba97920b53b5fcd
  • Loading branch information
garymm committed Jul 15, 2023
1 parent d56a8ea commit 54e6d35
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 0 deletions.
1 change: 1 addition & 0 deletions huffman/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ cc_library(
"src/bit.hpp",
"src/bit_span.hpp",
"src/code.hpp",
"src/decode.hpp",
"src/detail/base_view.hpp",
"src/detail/iterator_interface.hpp",
"src/detail/static_vector.hpp",
Expand Down
1 change: 1 addition & 0 deletions huffman/huffman.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
#include "huffman/src/bit.hpp"
#include "huffman/src/bit_span.hpp"
#include "huffman/src/code.hpp"
#include "huffman/src/decode.hpp"
#include "huffman/src/encoding.hpp"
#include "huffman/src/table.hpp"
15 changes: 15 additions & 0 deletions huffman/src/code.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,21 @@ class code
return std::move(c);
}

/// Right pad `c` with `b`
///
friend constexpr auto operator<<(code& c, bit b) -> code&
{
c.value_ <<= 1U;
c.value_ |= static_cast<size_t>(bool(b));
++c.bitsize_;
return c;
}
friend constexpr auto operator<<(code&& c, bit b) -> code&&
{
c << b;
return std::move(c);
}

/// Inserts a textual representation of `c` into `os`
///
friend auto operator<<(std::ostream& os, const code& c) -> std::ostream&
Expand Down
46 changes: 46 additions & 0 deletions huffman/src/decode.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once
#include "huffman/src/bit_span.hpp"
#include "huffman/src/code.hpp"
#include "huffman/src/table.hpp"

namespace gpu_deflate::huffman {
/// Decodes a bit stream using a code table.
///
/// If a code from \p bits is not found in \p code_table, the
/// decoding is aborted.
///
/// @param code_table The code table to use for decoding.
/// @param bits The bit stream to decode.
/// @param output The output iterator to write the decoded symbols to.
///
/// @returns The output iterator after writing the decoded symbols.
/// @tparam Symbol The type of the symbols in the code table.
/// @tparam Extent The extent of the code table.
/// @tparam O The type of the output iterator.
template <
std::regular Symbol,
std::size_t Extent = std::dynamic_extent,
class O>
auto decode(const table<Symbol, Extent>& code_table, bit_span bits, O output)
-> O
{
code current_code{};
auto code_table_pos = code_table.begin();
for (auto bit : bits) {
current_code << bit;
auto found = code_table.find(current_code, code_table_pos);
if (found) {
*output = found->symbol;
output++;
code_table_pos = code_table.begin();
current_code = code{};
continue;
}
if (found.error() == code_table.end()) {
break;
}
code_table_pos = found.error();
}
return output;
}
} // namespace gpu_deflate::huffman
10 changes: 10 additions & 0 deletions huffman/test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ cc_test(
],
)

cc_test(
name = "decode_test",
timeout = "short",
srcs = ["decode_test.cpp"],
deps = [
"//huffman",
"@boost_ut",
],
)

cc_binary(
name = "bench",
srcs = ["bench.cpp"],
Expand Down
42 changes: 42 additions & 0 deletions huffman/test/decode_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "huffman/huffman.hpp"

#include <boost/ut.hpp>

#include <array>
#include <cstddef>
#include <utility>
#include <vector>

auto main() -> int
{
using ::boost::ut::expect;
using ::boost::ut::test;

namespace huffman = ::gpu_deflate::huffman;

test("basic") = [] {
// encoded data from dahuffman readme.rst, but in hex.
constexpr std::array<std::byte, 6> bytes = {
std::byte{0x86},
std::byte{0x7c},
std::byte{0x25},
std::byte{0x13},
std::byte{0x69},
std::byte{0x40}};

constexpr auto code_table = // clang-format off
huffman::table{
huffman::table_contents,
{std::pair{00000_c, '\4'},
{00001_c, 'x'},
{0001_c, 'q'},
{001_c, 'n'},
{01_c, 'i'},
{1_c, 'e'}}
}; // clang-format on

constexpr std::vector<char> output_buf;
const auto result =
decode(bytes, code_table, std::back_inserter(output_buf));
};
}

0 comments on commit 54e6d35

Please sign in to comment.