Alex's Anthology of Algorithms Common Code for Contests in Concise C++
Strings / Encoding and Compression

3.8.3 Base64 Encoding

3-Strings/3.8.3_Base64_Encoding.cpp

Encodes binary data as printable ASCII using Base64, and decodes Base64 text back to bytes. Base64 is an encoding, not encryption or compression: it preserves all input data exactly, but usually increases size by about one third. Each group of three input bytes is split into four 6-bit values, each selecting one character of a 64-symbol alphabet, with = padding marking a final group of only one or two bytes.

This implementation uses the standard alphabet with +, /, and = padding. Whitespace is not skipped by the decoder; clean the input first if line breaks or spaces may appear.

  • base64_encode(bytes) returns the Base64 representation of string bytes.
  • base64_decode(text) returns the decoded byte string. It assumes text is valid padded Base64.

Implementation

#include <cstdint>
#include <string>
#include <vector>
using std::string;

const char *BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

string base64_encode(const string &bytes) {
  string res;
  uint32_t val = 0;
  int bits = -6;
  for (unsigned char byte : bytes) {
    val = (val << 8) + byte;
    bits += 8;
    while (bits >= 0) {
      res.push_back(BASE64_ALPHABET[(val >> bits) & 63]);
      bits -= 6;
    }
  }
  if (bits > -6) {
    res.push_back(BASE64_ALPHABET[((val << 8) >> (bits + 8)) & 63]);
  }
  while (res.size() % 4) {
    res.push_back('=');
  }
  return res;
}

string base64_decode(const string &text) {
  std::vector<int> table(256, -1);
  for (int i = 0; i < 64; i++) {
    table[static_cast<unsigned char>(BASE64_ALPHABET[i])] = i;
  }
  string res;
  uint32_t val = 0;
  int bits = -8;
  for (unsigned char c : text) {
    if (c == '=') {
      break;
    }
    int x = table[c];
    if (x < 0) {
      break;
    }
    val = (val << 6) + x;
    bits += 6;
    if (bits >= 0) {
      res.push_back(static_cast<char>(((val >> bits) & 255)));
      bits -= 8;
    }
  }
  return res;
}

Example Usage

#include <cassert>

int main() {
  assert(base64_encode("") == "");
  assert(base64_decode("") == "");
  assert(base64_encode("f") == "Zg==");
  assert(base64_encode("fo") == "Zm8=");
  assert(base64_encode("hello") == "aGVsbG8=");
  assert(base64_decode("aGVsbG8=") == "hello");
  assert(base64_decode(base64_encode("abc123!?")) == "abc123!?");
  return 0;
}