#ifndef BASE_64_HPP #define BASE_64_HPP #include #include namespace base64 { inline std::string get_base64_chars() { static std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; return base64_chars; } inline std::string to_base64(const char* data, size_t size) { int counter = 0; uint32_t bit_stream = 0; const std::string base64_chars = get_base64_chars(); std::string encoded; encoded.reserve(static_cast(ceil(4.0 / 3.0 * size))); int offset = 0; for (unsigned int idx = 0; idx < size; idx++) { unsigned char c = data[idx]; auto num_val = static_cast(c); offset = 16 - counter % 3 * 8; bit_stream += num_val << offset; if (offset == 16) { encoded += base64_chars.at(bit_stream >> 18 & 0x3f); } if (offset == 8) { encoded += base64_chars.at(bit_stream >> 12 & 0x3f); } if (offset == 0 && counter != 3) { encoded += base64_chars.at(bit_stream >> 6 & 0x3f); encoded += base64_chars.at(bit_stream & 0x3f); bit_stream = 0; } counter++; } if (offset == 16) { encoded += base64_chars.at(bit_stream >> 12 & 0x3f); encoded += "=="; } if (offset == 8) { encoded += base64_chars.at(bit_stream >> 6 & 0x3f); encoded += '='; } return encoded; } inline std::string to_base64(std::string const& data) { return to_base64(data.c_str(), data.length()); } inline std::string from_base64(std::string const& data) { int counter = 0; uint32_t bit_stream = 0; std::string decoded; int offset = 0; const std::string base64_chars = get_base64_chars(); for (unsigned char c : data) { auto num_val = base64_chars.find(c); if (num_val != std::string::npos) { offset = 18 - counter % 4 * 6; bit_stream += static_cast(num_val << offset); if (offset == 12) { decoded += static_cast(bit_stream >> 16 & 0xff); } if (offset == 6) { decoded += static_cast(bit_stream >> 8 & 0xff); } if (offset == 0 && counter != 4) { decoded += static_cast(bit_stream & 0xff); bit_stream = 0; } } else if (c != '=') { return std::string(); } counter++; } return decoded; } } #endif // BASE_64_HPP