Subversion Repositories canSerial

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <stdint.h>
  2. #include <string.h>
  3.  
  4. static const char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  5.                                       'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  6.                                       'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  7.                                       'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  8.                                       'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  9.                                       'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  10.                                       'w', 'x', 'y', 'z', '0', '1', '2', '3',
  11.                                       '4', '5', '6', '7', '8', '9', '+', '/'};
  12.  
  13. static const char decoding_table[256] = {['A'] = 0, // using GCC initialiser style
  14.                                          ['B'] = 1,
  15.                                          ['C'] = 2,
  16.                                          ['D'] = 3,
  17.                                          ['E'] = 4,
  18.                                          ['F'] = 5,
  19.                                          ['G'] = 6,
  20.                                          ['H'] = 7,
  21.                                          ['I'] = 8,
  22.                                          ['J'] = 9,
  23.                                          ['K'] = 10,
  24.                                          ['L'] = 11,
  25.                                          ['M'] = 12,
  26.                                          ['N'] = 13,
  27.                                          ['O'] = 14,
  28.                                          ['P'] = 15,
  29.                                          ['Q'] = 16,
  30.                                          ['R'] = 17,
  31.                                          ['S'] = 18,
  32.                                          ['T'] = 19,
  33.                                          ['U'] = 20,
  34.                                          ['V'] = 21,
  35.                                          ['W'] = 22,
  36.                                          ['X'] = 23,
  37.                                          ['Y'] = 24,
  38.                                          ['Z'] = 25,
  39.                                          ['a'] = 26,
  40.                                          ['b'] = 27,
  41.                                          ['c'] = 28,
  42.                                          ['d'] = 29,
  43.                                          ['e'] = 30,
  44.                                          ['f'] = 31,
  45.                                          ['g'] = 32,
  46.                                          ['h'] = 33,
  47.                                          ['i'] = 34,
  48.                                          ['j'] = 35,
  49.                                          ['k'] = 36,
  50.                                          ['l'] = 37,
  51.                                          ['m'] = 38,
  52.                                          ['n'] = 39,
  53.                                          ['o'] = 40,
  54.                                          ['p'] = 41,
  55.                                          ['q'] = 42,
  56.                                          ['r'] = 43,
  57.                                          ['s'] = 44,
  58.                                          ['t'] = 45,
  59.                                          ['u'] = 46,
  60.                                          ['v'] = 47,
  61.                                          ['w'] = 48,
  62.                                          ['x'] = 49,
  63.                                          ['y'] = 50,
  64.                                          ['z'] = 51,
  65.                                          ['0'] = 52,
  66.                                          ['1'] = 53,
  67.                                          ['2'] = 54,
  68.                                          ['3'] = 55,
  69.                                          ['4'] = 56,
  70.                                          ['5'] = 57,
  71.                                          ['6'] = 58,
  72.                                          ['7'] = 59,
  73.                                          ['8'] = 60,
  74.                                          ['9'] = 61,
  75.                                          ['+'] = 62,
  76.                                          ['/'] = 63};
  77.  
  78. static const int mod_table[] = {0, 2, 1};
  79.  
  80. unsigned char *base64_encode(const unsigned char *data,
  81.                              size_t input_length,
  82.                              unsigned char *encoded_data,
  83.                              size_t *output_length)
  84. {
  85.  
  86.     *output_length = 4 * ((input_length + 2) / 3);
  87.  
  88.     for (int i = 0, j = 0; i < input_length;)
  89.     {
  90.  
  91.         uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
  92.         uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
  93.         uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
  94.  
  95.         uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
  96.  
  97.         encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
  98.         encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
  99.         encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
  100.         encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
  101.     }
  102.  
  103.     for (int i = 0; i < mod_table[input_length % 3]; i++)
  104.         encoded_data[*output_length - 1 - i] = '=';
  105.  
  106.     return encoded_data;
  107. }
  108.  
  109. unsigned char *base64_decode(const char *data,
  110.                              size_t input_length,
  111.                              unsigned char *decoded_data,
  112.                              size_t *output_length)
  113. {
  114.      if (input_length % 4 != 0)
  115.         return NULL;
  116.  
  117.     *output_length = input_length / 4 * 3;
  118.     if (data[input_length - 1] == '=')
  119.         (*output_length)--;
  120.     if (data[input_length - 2] == '=')
  121.         (*output_length)--;
  122.  
  123.     for (int i = 0, j = 0; i < input_length;)
  124.     {
  125.  
  126.         uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
  127.         uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
  128.         uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
  129.         uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[(int)data[i++]];
  130.  
  131.         uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
  132.  
  133.         if (j < *output_length)
  134.             decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
  135.         if (j < *output_length)
  136.             decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
  137.         if (j < *output_length)
  138.             decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
  139.     }
  140.  
  141.     return decoded_data;
  142. }