|
|
@ -12,6 +12,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
namespace detail
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Provides a string container for the huffman compressor.
|
|
|
|
|
|
|
|
// Using this allows for automatic string data length measurement, as
|
|
|
|
|
|
|
|
// well as implementation of the _huffman suffix.
|
|
|
|
template<unsigned long int N>
|
|
|
|
template<unsigned long int N>
|
|
|
|
struct huffman_string_container {
|
|
|
|
struct huffman_string_container {
|
|
|
|
char data[N];
|
|
|
|
char data[N];
|
|
|
@ -32,14 +35,18 @@ namespace detail
|
|
|
|
* minimal run-time interface for decompressing the data.
|
|
|
|
* minimal run-time interface for decompressing the data.
|
|
|
|
* @tparam data The string of data to be compressed.
|
|
|
|
* @tparam data The string of data to be compressed.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
template<detail::huffman_string_container data>
|
|
|
|
template<auto data>
|
|
|
|
requires(data.size() > 0)
|
|
|
|
requires(
|
|
|
|
|
|
|
|
std::same_as<decltype(data),
|
|
|
|
|
|
|
|
const detail::huffman_string_container<data.size()>> &&
|
|
|
|
|
|
|
|
data.size() > 0)
|
|
|
|
class huffman_compressor
|
|
|
|
class huffman_compressor
|
|
|
|
{
|
|
|
|
{
|
|
|
|
using size_t = long int;
|
|
|
|
using size_t = long int;
|
|
|
|
using usize_t = unsigned long int;
|
|
|
|
using usize_t = unsigned long int;
|
|
|
|
|
|
|
|
|
|
|
|
// Note: class internals need to be defined before the public interface.
|
|
|
|
// Note: class internals need to be defined before the public interface.
|
|
|
|
|
|
|
|
// See the bottom of the class definition for usage.
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
// Node structure used to build a tree for calculating Huffman codes.
|
|
|
|
// Node structure used to build a tree for calculating Huffman codes.
|
|
|
|
struct node {
|
|
|
|
struct node {
|
|
|
@ -316,6 +323,16 @@ public:
|
|
|
|
friend class huffman_compressor;
|
|
|
|
friend class huffman_compressor;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Stick the forward_iterator check here just so it's run
|
|
|
|
|
|
|
|
consteval huffman_compressor() noexcept
|
|
|
|
|
|
|
|
requires (std::forward_iterator<decode_info>)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if constexpr (bytes_saved() > 0) {
|
|
|
|
|
|
|
|
build_decode_tree();
|
|
|
|
|
|
|
|
compress();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto begin() const noexcept {
|
|
|
|
auto begin() const noexcept {
|
|
|
|
return decode_info(this);
|
|
|
|
return decode_info(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -325,14 +342,11 @@ public:
|
|
|
|
auto cbegin() const noexcept { begin(); }
|
|
|
|
auto cbegin() const noexcept { begin(); }
|
|
|
|
auto cend() const noexcept { end(); }
|
|
|
|
auto cend() const noexcept { end(); }
|
|
|
|
|
|
|
|
|
|
|
|
// Stick the requires clause here just so it's run
|
|
|
|
auto size() const noexcept {
|
|
|
|
consteval huffman_compressor() noexcept
|
|
|
|
if constexpr (bytes_saved() > 0)
|
|
|
|
requires (std::forward_iterator<decode_info>)
|
|
|
|
return compressed_size();
|
|
|
|
{
|
|
|
|
else
|
|
|
|
if constexpr (bytes_saved() > 0) {
|
|
|
|
return uncompressed_size();
|
|
|
|
build_decode_tree();
|
|
|
|
|
|
|
|
compress();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|