22 #ifndef GEARS_UTILITY_BASE64_HPP
23 #define GEARS_UTILITY_BASE64_HPP
26 #include <unordered_map>
41 const char* what()
const noexcept
override {
42 return "base64 string provided is invalid";
48 const signed char npos = -1;
62 inline std::string
encode(
const std::string& str) {
64 static auto read = [&index](
const std::string& s) ->
signed char {
65 if(index >= s.length() || s.empty()) {
68 signed char result = s[index++] & 0xFF;
72 static const char lookup[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
75 signed char buffer[3];
78 buffer[0] = read(str);
79 if(buffer[0] == detail::npos) {
83 buffer[1] = read(str);
84 buffer[2] = read(str);
86 result += lookup[buffer[0] >> 2];
87 if(buffer[1] != detail::npos) {
88 result += lookup[((buffer[0] << 4) & 0x30) | (buffer[1] >> 4)];
90 if(buffer[2] != detail::npos) {
91 result += lookup[((buffer[1] << 2) & 0x3C) | (buffer[2] >> 6)];
92 result += lookup[buffer[2] & 0x3F];
95 result += lookup[(buffer[1] << 2) & 0x3C];
101 result += lookup[(buffer[0] << 4) & 0x30];
121 inline std::string
decode(
const std::string& str) {
124 static std::unordered_map<char,int> lookup = {
125 {
'A', 0}, {
'B', 1}, {
'C', 2}, {
'D', 3}, {
'E', 4}, {
'F', 5}, {
'G', 6}, {
'H', 7}, {
'I', 8},
126 {
'J', 9}, {
'K', 10}, {
'L', 11}, {
'M', 12}, {
'N', 13}, {
'O', 14}, {
'P', 15}, {
'Q', 16},
127 {
'R', 17}, {
'S', 18}, {
'T', 19}, {
'U', 20}, {
'V', 21}, {
'W', 22}, {
'X', 23}, {
'Y', 24},
128 {
'Z', 25}, {
'a', 26}, {
'b', 27}, {
'c', 28}, {
'd', 29}, {
'e', 30}, {
'f', 31}, {
'g', 32},
129 {
'h', 33}, {
'i', 34}, {
'j', 35}, {
'k', 36}, {
'l', 37}, {
'm', 38}, {
'n', 39}, {
'o', 40},
130 {
'p', 41}, {
'q', 42}, {
'r', 43}, {
's', 44}, {
't', 45}, {
'u', 46}, {
'v', 47}, {
'w', 48},
131 {
'x', 49}, {
'y', 50}, {
'z', 51}, {
'0', 52}, {
'1', 53}, {
'2', 54}, {
'3', 55}, {
'4', 56},
132 {
'5', 57}, {
'6', 58}, {
'7', 59}, {
'8', 60}, {
'9', 61}, {
'+', 62}, {
'/', 63}
135 static auto read = [&](
const std::string& st) ->
signed char {
141 if(index > st.length()) {
145 auto next = st[index];
147 auto it = lookup.find(next);
148 if(it != lookup.end()) {
157 buffer[0] = read(str);
158 if(buffer[0] == detail::npos) {
162 buffer[1] = read(str);
163 if(buffer[1] == detail::npos) {
168 buffer[2] = read(str);
169 buffer[3] = read(str);
170 result += ((buffer[0] << 2) & 0xFF) | (buffer[1] >> 4);
172 if(buffer[2] == detail::npos) {
176 result += ((buffer[1] << 4) & 0xFF) | (buffer[2] >> 2);
178 if(buffer[3] == detail::npos) {
182 result += ((buffer[2] << 6) & 0xFF) | buffer[3];
191 #endif // GEARS_UTILITY_BASE64_HPP