coyote/hex.cpp

83 lines
2.1 KiB
C++

#include <stdexcept>
#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<char> 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<char> 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<char>(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<char>((hex_decode(nibble1) << 4) | hex_decode(nibble2));
}