// Copyright 2020 Google LLC. All Rights Reserved. #include "base/base64.h" #include #include namespace base { namespace { static const char kBase64Codes[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; // Calculates a/b using round-up division (only works for numbers // greater than 0). constexpr size_t CeilDivide(size_t a, size_t b) { return ((a - 1) / b) + 1; } } // namespace void Base64Encode(const std::string& input, std::string* output) { if (input.empty()) { output->clear(); return; } // |temp| stores a 24-bit block that is treated as an array where insertions // occur from high to low. uint32_t temp = 0; size_t out_index = 0; const size_t out_size = CeilDivide(input.size(), 3) * 4; std::string result(out_size, '\0'); for (size_t i = 0; i < input.size(); i++) { // "insert" 8-bits of data temp = (temp << 8) | (input[i] & 0x0FF); if (i % 3 == 2) { result[out_index++] = kBase64Codes[(temp >> 18) & 0x3f]; result[out_index++] = kBase64Codes[(temp >> 12) & 0x3f]; result[out_index++] = kBase64Codes[(temp >> 6) & 0x3f]; result[out_index++] = kBase64Codes[temp & 0x3f]; temp = 0; } } if (input.size() % 3 == 1) { result[out_index++] = kBase64Codes[(temp >> 18) & 0x3f]; result[out_index++] = kBase64Codes[(temp >> 12) & 0x3f]; result[out_index++] = '='; result[out_index++] = '='; } else if (input.size() % 3 == 2) { result[out_index++] = kBase64Codes[(temp >> 18) & 0x3f]; result[out_index++] = kBase64Codes[(temp >> 12) & 0x3f]; result[out_index++] = kBase64Codes[(temp >> 6) & 0x3f]; result[out_index++] = '='; } output->swap(result); } } // namespace base