luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

base64.c (3181B)


      1 /*
      2  * base64.c - Base64 encoding/decoding functions
      3  */
      4 
      5 #include <stdint.h>
      6 #include <stdlib.h>
      7 #include <stddef.h>
      8 
      9 /* Base64 encoding table */
     10 static const char base64_chars[] =
     11     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     12 
     13 /* Base64 encode */
     14 char* base64_encode(const uint8_t *data, size_t len, size_t *out_len) {
     15     size_t encoded_len = 4 * ((len + 2) / 3);
     16     char *encoded = malloc(encoded_len + 1);
     17     if (!encoded) return NULL;
     18 
     19     size_t i, j;
     20     for (i = 0, j = 0; i < len; ) {
     21         uint32_t octet_a = i < len ? data[i++] : 0;
     22         uint32_t octet_b = i < len ? data[i++] : 0;
     23         uint32_t octet_c = i < len ? data[i++] : 0;
     24 
     25         uint32_t triple = (octet_a << 16) + (octet_b << 8) + octet_c;
     26 
     27         encoded[j++] = base64_chars[(triple >> 18) & 0x3F];
     28         encoded[j++] = base64_chars[(triple >> 12) & 0x3F];
     29         encoded[j++] = base64_chars[(triple >> 6) & 0x3F];
     30         encoded[j++] = base64_chars[triple & 0x3F];
     31     }
     32 
     33     /* Add padding */
     34     for (i = 0; i < (3 - len % 3) % 3; i++) {
     35         encoded[encoded_len - 1 - i] = '=';
     36     }
     37 
     38     encoded[encoded_len] = '\0';
     39     if (out_len) *out_len = encoded_len;
     40     return encoded;
     41 }
     42 
     43 /* Base64 decoding table */
     44 static const unsigned char base64_decode_table[256] = {
     45     ['A'] = 0,  ['B'] = 1,  ['C'] = 2,  ['D'] = 3,  ['E'] = 4,  ['F'] = 5,
     46     ['G'] = 6,  ['H'] = 7,  ['I'] = 8,  ['J'] = 9,  ['K'] = 10, ['L'] = 11,
     47     ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15, ['Q'] = 16, ['R'] = 17,
     48     ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23,
     49     ['Y'] = 24, ['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29,
     50     ['e'] = 30, ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35,
     51     ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39, ['o'] = 40, ['p'] = 41,
     52     ['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47,
     53     ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53,
     54     ['2'] = 54, ['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59,
     55     ['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63
     56 };
     57 
     58 /* Base64 decode */
     59 uint8_t* base64_decode(const char *data, size_t len, size_t *out_len) {
     60     if (len == 0 || len % 4 != 0) return NULL;
     61 
     62     size_t decoded_len = len / 4 * 3;
     63     if (data[len - 1] == '=') decoded_len--;
     64     if (data[len - 2] == '=') decoded_len--;
     65 
     66     uint8_t *decoded = malloc(decoded_len);
     67     if (!decoded) return NULL;
     68 
     69     size_t i, j;
     70     for (i = 0, j = 0; i < len;) {
     71         uint32_t sextet_a = base64_decode_table[(unsigned char)data[i++]];
     72         uint32_t sextet_b = base64_decode_table[(unsigned char)data[i++]];
     73         uint32_t sextet_c = base64_decode_table[(unsigned char)data[i++]];
     74         uint32_t sextet_d = base64_decode_table[(unsigned char)data[i++]];
     75 
     76         uint32_t triple = (sextet_a << 18) + (sextet_b << 12) +
     77                           (sextet_c << 6) + sextet_d;
     78 
     79         if (j < decoded_len) decoded[j++] = (triple >> 16) & 0xFF;
     80         if (j < decoded_len) decoded[j++] = (triple >> 8) & 0xFF;
     81         if (j < decoded_len) decoded[j++] = triple & 0xFF;
     82     }
     83 
     84     if (out_len) *out_len = decoded_len;
     85     return decoded;
     86 }