diff --git a/include/consteval_huffman/consteval_huffman.hpp b/include/consteval_huffman/consteval_huffman.hpp index 7884e2f..0c41913 100644 --- a/include/consteval_huffman/consteval_huffman.hpp +++ b/include/consteval_huffman/consteval_huffman.hpp @@ -17,13 +17,15 @@ 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 + template + requires(std::same_as, char> || + std::same_as, unsigned char>) struct huffman_string_container { - char data[N]; - consteval huffman_string_container(const char (&s)[N]) noexcept { + T data[N]; + consteval huffman_string_container(const T (&s)[N]) noexcept { std::copy(s, s + N, data); } - consteval operator const char *() const noexcept { + consteval operator const T *() const noexcept { return data; } consteval auto size() const noexcept { @@ -35,12 +37,13 @@ namespace detail /** * Compresses the given data string using Huffman coding, providing a * minimal run-time interface for decompressing the data. - * @tparam data The string of data to be compressed. + * @tparam raw_data The string of data to be compressed. */ template requires( std::same_as, - detail::huffman_string_container> && + detail::huffman_string_container, + raw_data.size()>> && raw_data.size() > 0) class huffman_compressor { @@ -167,8 +170,9 @@ private: size_t bytes = 1, bits = 0; for (usize_t i = 0; i < raw_data.size(); i++) { + auto c = static_cast(raw_data[i]); auto leaf = std::find_if(tree.begin(), tree.end(), - [c = raw_data[i]](const auto& n) { return n.value == c; }); + [c](const auto& n) { return n.value == c; }); while (leaf->parent != -1) { if (++bits == 8) @@ -197,8 +201,9 @@ private: // Compress data backwards, because we obtain the Huffman codes backwards // as we traverse towards the parent node. for (auto i = raw_data.size(); i > 0; i--) { + auto c = static_cast(raw_data[i - 1]); auto leaf = std::find_if(tree.begin(), tree.end(), - [c = raw_data[i - 1]](auto& n) { return n.value == c; }); + [c](auto& n) { return n.value == c; }); while (leaf->parent != -1) { auto parent = tree.begin() + leaf->parent; @@ -282,7 +287,9 @@ public: } bool operator==(const decoder& other) const noexcept { - return m_data == other.m_data && m_bit == other.m_bit; + return m_data == other.m_data && + m_bit == other.m_bit && + m_current == other.m_current; } auto operator*() const noexcept { return m_current; @@ -299,8 +306,12 @@ public: private: void get_next() noexcept { - if (*this == end(m_data)) + if (auto e = end(m_table - compressed_size_info().first); + m_data == e.m_data && m_bit == e.m_bit) + { + m_current = -1; return; + } if constexpr (bytes_saved() > 0) { auto *node = m_table; int data = *m_data; @@ -376,4 +387,7 @@ constexpr auto operator ""_huffman() return huffman_compressor(); } +template +constexpr auto huffman_compress = huffman_compressor(); + #endif // TCSULLIVAN_CONSTEVAL_HUFFMAN_HPP_