23 constexpr std::string_view base64_itoa_map =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
24 constexpr std::string_view crypt64_itoa_map =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
26 constexpr
auto fill_atoi_map(std::string_view itoa)
28 std::array<int, 256> atoi{};
29 #if __cpp_lib_array_constexpr >= 201811L
32 for(
int& elem : atoi) { elem = -1; }
35 for(std::size_t
i = 0;
i < itoa.size(); ++
i) {
36 atoi[itoa[
i]] =
static_cast<int>(
i);
42 constexpr std::array<int, 256> base64_atoi_map = fill_atoi_map(base64_itoa_map);
43 constexpr std::array<int, 256> crypt64_atoi_map = fill_atoi_map(crypt64_itoa_map);
45 char itoa(
unsigned value, std::string_view map)
47 return map[value & 0x3f];
52 const std::size_t last_char =
in.find_last_not_of(
"=");
53 if(last_char == std::string::npos) {
56 const std::size_t num_chars = last_char + 1;
57 const std::size_t length = num_chars * 6 / 8;
59 std::vector<uint8_t> out;
62 int val = 0, bits = -8;
63 for(
unsigned char c:
in) {
64 if(atoi_map[
c] == -1) {
72 val = (val<<6) + atoi_map[
c];
75 out.push_back(
static_cast<char>((val >> bits) & 0xFF));
80 if(out.size() != length) {
89 const std::size_t last_char =
in.find_last_not_of(
"=");
90 if(last_char == std::string::npos) {
93 const std::size_t length = last_char * 6 / 8;
95 std::vector<uint8_t> out;
98 for(std::size_t
i = 0;
i <= last_char;
i += 4) {
100 unsigned value = atoi_map[
in[
i]];
102 const bool second_char =
i + 1 <= last_char;
107 value |= atoi_map[
in[
i+1]] << 6;
110 out.push_back(value & 0xFF);
112 const bool third_char =
i + 2 <= last_char;
117 value |= atoi_map[
in[
i+2]] << 12;
120 out.push_back((value >> 8) & 0xFF);
122 const bool fourth_char =
i + 3 <= last_char;
127 value |= atoi_map[
in[
i+3]] << 18;
130 out.push_back((value >> 16) & 0xFF);
136 std::string generic_encode_be(
utils::byte_view in, std::string_view itoa_map,
bool pad)
138 const int in_len =
in.size();
139 const int groups = (in_len + 2) / 3;
140 const int out_len = groups * 4;
145 out.reserve(out_len);
154 out.push_back(itoa(value >> bits, itoa_map));
158 out.push_back(itoa(value << (6 - bits), itoa_map));
163 out.resize(out_len,
'=');
169 std::string generic_encode_le(
utils::byte_view in, std::string_view itoa_map,
bool pad)
171 const int in_len =
in.size();
172 const int groups = (in_len + 2) / 3;
173 const int out_len = groups * 4;
178 out.reserve(out_len);
181 unsigned value =
in[
i];
183 out.push_back(itoa(value, itoa_map));
185 const bool second_byte = ++
i < in_len;
187 value |=
static_cast<int>(
in[
i]) << 8;
190 out.push_back(itoa(value >> 6, itoa_map));
195 const bool third_byte = ++
i < in_len;
197 value |=
static_cast<int>(
in[
i]) << 16;
200 out.push_back(itoa(value >> 12, itoa_map));
203 out.push_back(itoa(value >> 18, itoa_map));
210 out.resize(out_len,
'=');
221 return generic_decode_be(
in, base64_atoi_map);
225 return generic_encode_be(bytes, base64_itoa_map,
true);
231 return generic_decode_le(
in, crypt64_atoi_map);
235 return generic_encode_le(bytes, crypt64_itoa_map,
false);
239 std::size_t pos = crypt64_itoa_map.find(encoded_char);
240 return pos == std::string::npos ? -1 : pos;
244 return itoa(value, crypt64_itoa_map);
unsigned in
If equal to search_counter, the node is off the list.
std::string encode(utils::byte_view bytes)
std::vector< uint8_t > decode(std::string_view in)
std::string encode(utils::byte_view bytes)
std::vector< uint8_t > decode(std::string_view in)