diff --git a/compression/include/compression/hex.hpp b/compression/include/compression/hex.hpp new file mode 100644 index 0000000..331fc61 --- /dev/null +++ b/compression/include/compression/hex.hpp @@ -0,0 +1,60 @@ +// hex.hpp + +#pragma once + +#include + +struct hex { + hex(std::uint8_t x, bool w_char = false) : x_{x}, with_char_{w_char} {} + + std::uint8_t x_; + bool with_char_; +}; + +struct hex_view { + hex_view(std::uint8_t const * lo, std::uint8_t const * hi, bool as_text) : lo_{lo}, hi_{hi}, as_text_{as_text} {} + hex_view(char const * lo, char const * hi, bool as_text) + : lo_{reinterpret_cast(lo)}, + hi_{reinterpret_cast(hi)}, + as_text_{as_text} {} + + std::uint8_t const * lo_; + std::uint8_t const * hi_; + bool as_text_; +}; + +inline std::ostream & +operator<< (std::ostream & os, hex const & ins) { + std::uint8_t lo = ins.x_ & 0xf; + std::uint8_t hi = ins.x_ >> 4; + + char lo_ch = (lo < 10) ? '0' + lo : 'a' + lo - 10; + char hi_ch = (hi < 10) ? '0' + hi : 'a' + hi - 10; + + os << hi_ch << lo_ch; + + if (ins.with_char_) { + os << "("; + if (std::isprint(ins.x_)) + os << static_cast(ins.x_); + else + os << "?"; + os << ")"; + } + + return os; +} + +inline std::ostream & +operator<< (std::ostream & os, hex_view const & ins) { + os << "["; + std::size_t i = 0; + for (std::uint8_t const * p = ins.lo_; p < ins.hi_; ++p) { + if (i > 0) + os << " "; + os << hex(*p, ins.as_text_); + ++i; + } + os << "]"; + return os; +} diff --git a/compression/utest/hex.test.cpp b/compression/utest/hex.test.cpp new file mode 100644 index 0000000..3dc0234 --- /dev/null +++ b/compression/utest/hex.test.cpp @@ -0,0 +1,35 @@ +#define CATCH_CONFIG_ENABLE_BENCHMARKING + +#include "compression/hex.hpp" +#include +#include + +using namespace std; + +TEST_CASE("hex", "[hex]") { + stringstream ss; + + ss << ::hex(15, false); + + REQUIRE(ss.str() == "0f"); +} + +TEST_CASE("hex_view", "[hex]") { + stringstream ss; + + array v = {{ 10, 20, 30 }}; + + ss << ::hex_view(&v[0], &v[v.size()], false); + + REQUIRE(ss.str() == "[0a 14 1e]"); +} + +TEST_CASE("hex_view_2", "[hex]") { + stringstream ss; + + array v = {{ 'a', 'm', 'z' }}; + + ss << ::hex_view(&v[0], &v[v.size()], true); + + REQUIRE(ss.str() == "[61(a) 6d(m) 7a(z)]"); +}