Base64 (C)
Topics: bit manipulation, encoding, RFC 4648
Problem
Implement standard Base64 (RFC 4648) over caller-provided buffers — no
allocation. The standard alphabet is A-Za-z0-9+/ with = padding.
size_t b64_encode(const unsigned char *in, size_t inlen, char *out, size_t outcap);
long b64_decode(const char *in, size_t inlen, unsigned char *out, size_t outcap);
b64_encode: take 3 input bytes (24 bits) at a time and emit 4 characters
(6 bits each). For a trailing 1 or 2 bytes, pad the final quartet with =
(Zg==, Zm8=). NUL-terminate out; return the length (excluding the NUL),
or 0 if out is too small.
b64_decode: reverse it. Input length must be a multiple of 4. Map each
character back to 6 bits, reassemble bytes, and account for 0/1/2 = at the
very end. Return the decoded byte count, or -1 on malformed input.
What "malformed" means for decode
- length not a multiple of 4,
- any character outside the alphabet (other than trailing
=),
- padding anywhere but the final group, or a lone
= (x=y).
The classic vectors: "", f→Zg==, fo→Zm8=, foo→Zm9v,
foob→Zm9vYg==, fooba→Zm9vYmE=, foobar→Zm9vYmFy.
Key concepts
- 6-bit packing: the work is bit-shuffling — pack 3 bytes into a 24-bit value,
then slice it into four 6-bit indices (
(n >> 18) & 63, etc.).
- A reverse table: decoding is just the inverse map plus validation; reject
out-of-alphabet bytes instead of silently treating them as zero.
- Padding is structure, not decoration: the count of
= tells you whether the
last group carries 1 or 2 real bytes.
Run
cc -std=c11 -O2 -Wall tests.c -o /tmp/base64 && /tmp/base64
Sign in to submit your solution.