#include #include "hex.h" static void hex_encode(char c, char out[2]); static inline char hex_decode(char nibble1, char nibble2); std::string hex_encode(const char* in, size_t in_size) { std::string out; out.reserve(in_size * 2); for (size_t i = 0; i < in_size; i++) { char encoded[2]; hex_encode(in[i], encoded); out.append(encoded, 2); } return out; } std::string percent_encode(std::string_view in) { std::string out; char encoded[2]; size_t pos = 0; size_t last_pos = 0; out.reserve(in.size()); while ((pos = in.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", pos)) != std::string::npos) { out.append(in, last_pos, pos - last_pos); hex_encode(in[pos], encoded); out += '%'; out.append(encoded, 2); pos++; last_pos = pos; } if (in.size() > last_pos) { out.append(in, last_pos); } return out; } std::vector hex_decode(std::string_view in) { if (in.size() % 2 != 0) { throw std::invalid_argument("hex_decode(): hex string with an odd size passed"); } std::vector out; out.reserve(in.size() / 2); for (size_t i = 0; i < in.size(); i += 2) { out.push_back(hex_decode(in[i], in[i + 1])); } return out; } static void hex_encode(char c, char out[2]) { char nibble1 = (c >> 4) & 0xF; char nibble2 = c & 0xF; auto hex_encode = [](char nibble) { return static_cast(nibble < 10 ? '0' + nibble : 'A' + nibble - 10); }; out[0] = hex_encode(nibble1); out[1] = hex_encode(nibble2); } static inline char hex_decode(char nibble1, char nibble2) { auto hex_decode = [](char nibble) { if (nibble >= '0' && nibble <= '9') return nibble - '0'; if (nibble >= 'a' && nibble <= 'f') return nibble - 'a' + 10; if (nibble >= 'A' && nibble <= 'F') return nibble - 'A' + 10; throw std::invalid_argument("hex_decode(): invalid nibble"); }; return static_cast((hex_decode(nibble1) << 4) | hex_decode(nibble2)); }