11 constexpr
const char ALPHABET[] =
12 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
15 result.reserve((input.size() + (3 - 1 )) / 3 * 4);
18 const unsigned char* data =
reinterpret_cast<const unsigned char*
>(input.data());
21 for (; i + 2 < input.size(); i += 3) {
22 result.push_back(ALPHABET[data[i] >> 2]);
23 result.push_back(ALPHABET[((data[i] & 0b11) << 4) | (data[i + 1] >> 4)]);
24 result.push_back(ALPHABET[((data[i + 1] & 0b1111) << 2) | (data[i + 2] >> 6)]);
25 result.push_back(ALPHABET[data[i + 2] & 0b111111]);
27 switch (input.size() - i) {
29 result.push_back(ALPHABET[data[i] >> 2]);
30 result.push_back(ALPHABET[((data[i] & 0b11) << 4) | (data[i + 1] >> 4)]);
31 result.push_back(ALPHABET[(data[i + 1] & 0b1111) << 2]);
32 result.push_back(
'=');
35 result.push_back(ALPHABET[data[i] >> 2]);
36 result.push_back(ALPHABET[(data[i] & 0b11) << 4]);
37 result.push_back(
'=');
38 result.push_back(
'=');
47 std::vector<unsigned char>
base64Decode(
const std::string& input) {
48 if (input.length() % 4) {
49 throw std::runtime_error(
"Invalid base64 length!");
52 constexpr
char kPadCharacter =
'=';
54 std::size_t padding{};
57 if (input[input.length() - 1] == kPadCharacter) padding++;
58 if (input[input.length() - 2] == kPadCharacter) padding++;
61 std::vector<unsigned char> decoded;
62 decoded.reserve(((input.length() / 4) * 3) - padding);
65 auto it = input.begin();
67 while (it < input.end()) {
68 for (std::size_t i = 0; i < 4; ++i) {
70 if (*it >= 0x41 && *it <= 0x5A)
72 else if (*it >= 0x61 && *it <= 0x7A)
74 else if (*it >= 0x30 && *it <= 0x39)
80 else if (*it == kPadCharacter) {
81 switch (input.end() - it) {
83 decoded.push_back((temp >> 16) & 0x000000FF);
84 decoded.push_back((temp >> 8) & 0x000000FF);
87 decoded.push_back((temp >> 10) & 0x000000FF);
90 throw std::runtime_error(
"Invalid padding in base64!");
93 throw std::runtime_error(
"Invalid character in base64!");
98 decoded.push_back((temp >> 16) & 0x000000FF);
99 decoded.push_back((temp >> 8) & 0x000000FF);
100 decoded.push_back((temp)&0x000000FF);