#include "./utils.hpp" #include namespace detail { constexpr uint8_t nib_from_hex(char c) { assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); if (c >= '0' && c <= '9') { return static_cast(c) - '0'; } else if (c >= 'a' && c <= 'f') { return (static_cast(c) - 'a') + 10u; } else if (c >= 'A' && c <= 'F') { return (static_cast(c) - 'A') + 10u; } else { return 0u; } } constexpr char nib_to_hex(uint8_t c) { assert(c <= 0x0f); if (c <= 0x09) { return c + '0'; } else { return (c - 10u) + 'a'; } } } // detail std::vector hex2bin(const std::string& str) { return hex2bin(std::string_view{str}); } std::vector hex2bin(const std::string_view str) { assert(str.size() % 2 == 0); // TODO: should this be a hard assert?? std::vector bin{}; bin.resize(str.size()/2, 0); for (size_t i = 0; i < bin.size(); i++) { bin[i] = detail::nib_from_hex(str[i*2]) << 4 | detail::nib_from_hex(str[i*2+1]); } return bin; } std::string bin2hex(const ByteSpan bin) { std::string str; str.reserve(bin.size*2); for (size_t i = 0; i < bin.size; i++) { str.push_back(detail::nib_to_hex(bin[i] >> 4)); str.push_back(detail::nib_to_hex(bin[i] & 0x0f)); } return str; } std::string bin2hex(const std::vector& bin) { return bin2hex(ByteSpan{bin}); }