#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
uint8_t *encode_table = (uint8_t *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uint8_t decode_table[256] = {};
void base64_init() {
for(size_t i = 0; i < 64; ++i) {
uint8_t v = encode_table[i];
decode_table[v] = i;
}
// default init to zero anyway
//decode_table['='] = 0;
}
void base64_encode(char *in, uint8_t *out, size_t in_len, size_t out_len, size_t *written_len) {
*written_len = 0;
if(in_len == 0)
return;
size_t len_remainder = in_len % 3;
size_t len_trunck = in_len - len_remainder;
size_t out_i = 0;
for(size_t i = 0; i < len_trunck; i += 3) {
uint32_t v = (in[i + 0] << 16) | (in[i + 1] << 8) | (in[i + 2] << 0);
out[out_i + 3] = encode_table[(v >> 0) & 0x3f];
out[out_i + 2] = encode_table[(v >> 6) & 0x3f];
out[out_i + 1] = encode_table[(v >> 12) & 0x3f];
out[out_i + 0] = encode_table[(v >> 18) & 0x3f];
out_i += 4;
}
if(len_remainder == 1) {
uint32_t v = in[len_trunck] << 16;
out[out_i + 3] = '=';
out[out_i + 2] = '=';
out[out_i + 1] = encode_table[(v >> 12) & 0x3f];
out[out_i + 0] = encode_table[(v >> 18) & 0x3f];
out_i += 4;
} else if(len_remainder == 2) {
uint32_t v = (in[len_trunck + 0] << 16) | (in[len_trunck + 1] << 8);
out[out_i + 3] = '=';
out[out_i + 2] = encode_table[(v >> 6) & 0x3f];
out[out_i + 1] = encode_table[(v >> 12) & 0x3f];
out[out_i + 0] = encode_table[(v >> 18) & 0x3f];
out_i += 4;
}
*written_len = out_i;
}
void base64_decode(uint8_t *in, char *out, size_t in_len, size_t out_len, size_t *written_len) {
*written_len = 0;
if(in_len == 0)
return;
size_t len_trunck = in_len & ~3ULL;
// Fix: implement slowpath for incorrect base64
assert((in_len & 3) == 0 && "Input must be padded to 4 bytes");
size_t out_i = 0;
for(size_t i = 0; i < len_trunck; i += 4) {
uint32_t d0 = decode_table[in[i + 0]] << 18;
uint32_t d1 = decode_table[in[i + 1]] << 12;
uint32_t d2 = decode_table[in[i + 2]] << 6;
uint32_t d3 = decode_table[in[i + 3]] << 0;
uint32_t v = d0 | d1 | d2 | d3;
out[out_i + 0] = v >> 16;
out[out_i + 1] = v >> 8;
out[out_i + 2] = v >> 0;
out_i += 3;
}
*written_len = out_i;
}
int main(void) {
base64_init();
char *text = "epletest";
uint8_t encoded[1000];
size_t written_len_encoded = 0;
base64_encode(text, encoded, strlen(text), sizeof(encoded), &written_len_encoded);
printf("%.*s\n", (int)written_len_encoded, encoded);
char decoded[1000];
size_t written_len_decoded = 0;
base64_decode(encoded, decoded, written_len_encoded, sizeof(decoded), &written_len_decoded);
printf("%.*s\n", (int)written_len_decoded, decoded);
return 0;
}