Skip to content

Instantly share code, notes, and snippets.

@eklitzke
Created January 6, 2021 03:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eklitzke/3b70e2ebefb81c5fee234347a18856ba to your computer and use it in GitHub Desktop.
Save eklitzke/3b70e2ebefb81c5fee234347a18856ba to your computer and use it in GitHub Desktop.
std::string DecodeBase64(std::string_view input) {
static const uint8_t b64_decode[] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62,
64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
size_t in_len = input.size();
ASSERT_DEBUG(in_len % 4 == 0);
size_t out_len = in_len / 4 * 3;
if (input[in_len - 1] == '=') out_len--;
if (input[in_len - 2] == '=') out_len--;
std::string out(out_len, 0);
for (size_t i = 0, j = 0; i < in_len;) {
uint32_t a = input[i] == '=' ? 0 & i++ : b64_decode[static_cast<int>(input[i++])];
uint32_t b = input[i] == '=' ? 0 & i++ : b64_decode[static_cast<int>(input[i++])];
uint32_t c = input[i] == '=' ? 0 & i++ : b64_decode[static_cast<int>(input[i++])];
uint32_t d = input[i] == '=' ? 0 & i++ : b64_decode[static_cast<int>(input[i++])];
uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
if (j < out_len) out[j++] = (triple >> 2 * 8) & 0xFF;
if (j < out_len) out[j++] = (triple >> 1 * 8) & 0xFF;
if (j < out_len) out[j++] = (triple >> 0 * 8) & 0xFF;
}
return out;
}
std::string EncodeBase64(std::string_view v) {
size_t sz = v.size();
size_t padding = sz % 3;
if (padding) {
padding = 3 - padding;
}
sz += padding;
ASSERT_DEBUG(sz % 3 == 0);
std::string out(sz * 4 / 3, 0);
// base64 lookup table
static const char b64_encode[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
size_t p = 0;
for (size_t i = 0; i < sz; i += 3) {
uint8_t b = v[i] >> 2;
ASSERT_DEBUG(b < 64);
out[p++] = b64_encode[b];
b = ((v[i] & 0x3) << 4) + (v[i + 1] >> 4);
ASSERT_DEBUG(b < 64);
out[p++] = b64_encode[b];
b = ((v[i + 1] & 0xf) << 2) + (v[i + 2] >> 6);
ASSERT_DEBUG(b < 64);
out[p++] = b64_encode[b];
b = v[i + 2] & 0x3f;
ASSERT_DEBUG(b < 64);
out[p++] = b64_encode[b];
}
// add padding bytes
for (size_t i = 0; i < padding; i++) {
out[p++] = '=';
}
ASSERT_DEBUG(p == out.size());
return out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment