44static const char* base64_chars[2] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
45 "abcdefghijklmnopqrstuvwxyz"
49 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
50 "abcdefghijklmnopqrstuvwxyz"
54static unsigned int pos_of_char(
const unsigned char chr)
60 if (chr >=
'A' && chr <=
'Z')
62 else if (chr >=
'a' && chr <=
'z')
63 return chr -
'a' + (
'Z' -
'A') + 1;
64 else if (chr >=
'0' && chr <=
'9')
65 return chr -
'0' + (
'Z' -
'A') + (
'z' -
'a') + 2;
66 else if (chr ==
'+' || chr ==
'-')
68 else if (chr ==
'/' || chr ==
'_')
78static std::string insert_linebreaks(std::string str,
size_t distance)
87 size_t pos = distance;
89 while (pos < str.size()) {
90 str.insert(pos,
"\n");
97template <
typename String,
unsigned int line_length>
static std::string encode_with_line_breaks(String s)
99 return insert_linebreaks(
base64_encode(s,
false), line_length);
102template <
typename String>
static std::string encode_pem(String s)
104 return encode_with_line_breaks<String, 64>(s);
107template <
typename String>
static std::string encode_mime(String s)
109 return encode_with_line_breaks<String, 76>(s);
112template <
typename String>
static std::string encode(String s,
bool url)
114 return base64_encode(
reinterpret_cast<const unsigned char*
>(s.data()), s.length(), url);
117std::string
base64_encode(
unsigned char const* bytes_to_encode,
size_t in_len,
bool url)
120 size_t len_encoded = (in_len + 2) / 3 * 4;
122 unsigned char trailing_char = url ?
'.' :
'=';
133 const char* base64_chars_ = base64_chars[url];
136 ret.reserve(len_encoded);
138 unsigned int pos = 0;
140 while (pos < in_len) {
141 ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]);
143 if (pos + 1 < in_len) {
145 base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]);
147 if (pos + 2 < in_len) {
149 base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]);
150 ret.push_back(base64_chars_[bytes_to_encode[pos + 2] & 0x3f]);
152 ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]);
153 ret.push_back(
static_cast<char>(trailing_char));
157 ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]);
158 ret.push_back(
static_cast<char>(trailing_char));
159 ret.push_back(
static_cast<char>(trailing_char));
168template <
typename String>
static std::string decode(String encoded_string,
bool remove_linebreaks)
175 if (encoded_string.empty())
176 return std::string();
178 if (remove_linebreaks) {
180 std::string copy(encoded_string);
182 copy.erase(std::remove(copy.begin(), copy.end(),
'\n'), copy.end());
187 size_t length_of_string = encoded_string.length();
196 size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
198 ret.reserve(approx_length_of_decoded_string);
200 while (pos < length_of_string) {
214 size_t pos_of_char_1 = pos_of_char(
static_cast<unsigned char>(encoded_string[pos + 1]));
219 ret.push_back(
static_cast<std::string::value_type
>(
220 ((pos_of_char(
static_cast<unsigned char>(encoded_string[pos + 0])) << 2) + ((pos_of_char_1 & 0x30) >> 4))));
222 if ((pos + 2 < length_of_string) &&
224 encoded_string[pos + 2] !=
'=' &&
225 encoded_string[pos + 2] !=
'.'
230 unsigned int pos_of_char_2 = pos_of_char(
static_cast<unsigned char>(encoded_string[pos + 2]));
232 static_cast<std::string::value_type
>(((pos_of_char_1 & 0x0f) << 4) + ((pos_of_char_2 & 0x3c) >> 2)));
234 if ((pos + 3 < length_of_string) && encoded_string[pos + 3] !=
'=' && encoded_string[pos + 3] !=
'.') {
238 ret.push_back(
static_cast<std::string::value_type
>(
239 ((pos_of_char_2 & 0x03) << 6) + pos_of_char(
static_cast<unsigned char>(encoded_string[pos + 3]))));
251 return decode(s, remove_linebreaks);
256 return encode(s, url);
261 return encode_pem(s);
266 return encode_mime(s);
269#if __cplusplus >= 201703L
278 return encode(s, url);
283 return encode_pem(s);
288 return encode_mime(s);
291std::string
base64_decode(std::string_view s,
bool remove_linebreaks)
293 return decode(s, remove_linebreaks);
std::string base64_encode_mime(std::string const &s)
std::string base64_decode(std::string const &s, bool remove_linebreaks)
std::string base64_encode(unsigned char const *bytes_to_encode, size_t in_len, bool url)
std::string base64_encode_pem(std::string const &s)
void throw_or_abort(std::string const &err)