#include #include #include #include namespace hex { const char digits[] = "0123456789abcdef"; const uint8_t map[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // }; bool isValid(const char *str, size_t str_size) noexcept { return baseN::isValid(str, str_size, map); } bool isValid(std::string_view str) noexcept { return baseN::isValid(str, map); } size_t sizeEncoded(std::span data) { if (data.size() > std::numeric_limits::max() / 2) { throw basen::Exception(basen::Exception::Code::OVERFLOW); } return data.size() * 2; } size_t sizeDecoded(std::string_view str) noexcept { return str.size() / 2; } void encode(const uint8_t *data, size_t data_size, char *str, size_t str_size) { if (str_size < hex::sizeEncoded(std::span(data, data_size))) { throw basen::Exception(basen::Exception::Code::LENGTH); } for (size_t i = 0; i < data_size; i++) { str[i * 2] = digits[data[i] >> 4]; str[i * 2 + 1] = digits[data[i] & 0x0F]; } } std::string encode(std::span data) { std::string str(hex::sizeEncoded(data), ' '); hex::encode(data.data(), data.size(), str.data(), str.size()); return str; } void decode(const char *str, size_t str_size, uint8_t *data, size_t data_size) { if (str_size % 2 != 0) { throw basen::Exception(basen::Exception::Code::PADDING); } if (data_size < hex::sizeDecoded(std::string_view(str, str_size))) { throw basen::Exception(basen::Exception::Code::LENGTH); } if (!hex::isValid(str, str_size)) { throw basen::Exception(basen::Exception::Code::OUT_OF_ALPH); } for (size_t i = 0; i * 2 < str_size; i++) { data[i] = map[(uint8_t)str[i * 2]] << 4 | map[(uint8_t)str[i * 2 + 1]]; } } std::vector decode(std::string_view str) { std::vector data(hex::sizeDecoded(str)); hex::decode(str.data(), str.size(), data.data(), data.size()); return data; } }