60 lines
1.6 KiB
C
60 lines
1.6 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
|
|
#include "base64.h"
|
|
|
|
static const char encoding_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
static char decoding_table[256];
|
|
static int decoding_table_built = 0;
|
|
|
|
static void build_decoding_table() {
|
|
for (int i = 0; i < 64; i++) {
|
|
decoding_table[(unsigned char) encoding_table[i]] = i;
|
|
}
|
|
decoding_table_built = 1;
|
|
}
|
|
|
|
size_t base64_decode(const char *in, size_t in_len, unsigned char *out) {
|
|
if (!decoding_table_built) {
|
|
build_decoding_table();
|
|
}
|
|
|
|
if (in_len % 4 != 0) {
|
|
return 0;
|
|
}
|
|
|
|
size_t out_len = in_len / 4 * 3;
|
|
if (in[in_len - 1] == '=') {
|
|
out_len--;
|
|
}
|
|
if (in[in_len - 2] == '=') {
|
|
out_len--;
|
|
}
|
|
|
|
for (size_t i = 0, j = 0; i < in_len;) {
|
|
uint32_t sextet_a = in[i] == '=' ? 0 : decoding_table[(unsigned char)in[i]];
|
|
i++;
|
|
uint32_t sextet_b = in[i] == '=' ? 0 : decoding_table[(unsigned char)in[i]];
|
|
i++;
|
|
uint32_t sextet_c = in[i] == '=' ? 0 : decoding_table[(unsigned char)in[i]];
|
|
i++;
|
|
uint32_t sextet_d = in[i] == '=' ? 0 : decoding_table[(unsigned char)in[i]];
|
|
i++;
|
|
|
|
uint32_t triple = (sextet_a << 18) + (sextet_b << 12) + (sextet_c << 6) + sextet_d;
|
|
|
|
if (j < out_len) {
|
|
out[j++] = (triple >> 16) & 0xFF;
|
|
}
|
|
if (j < out_len) {
|
|
out[j++] = (triple >> 8) & 0xFF;
|
|
}
|
|
if (j < out_len) {
|
|
out[j++] = triple & 0xFF;
|
|
}
|
|
}
|
|
|
|
return out_len;
|
|
} |