83 lines
2.1 KiB
C++
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));
|
||
|
}
|