lib.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include <stdint.h>
  2. #include <stddef.h>
  3. #include "libbase64.h"
  4. #include "codecs.h"
  5. #include "tables.h"
  6. // These static function pointers are initialized once when the library is
  7. // first used, and remain in use for the remaining lifetime of the program.
  8. // The idea being that CPU features don't change at runtime.
  9. static struct codec codec = { NULL, NULL };
  10. const uint8_t
  11. base64_table_enc[] =
  12. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  13. "abcdefghijklmnopqrstuvwxyz"
  14. "0123456789+/";
  15. // In the lookup table below, note that the value for '=' (character 61) is
  16. // 254, not 255. This character is used for in-band signaling of the end of
  17. // the datastream, and we will use that later. The characters A-Z, a-z, 0-9
  18. // and + / are mapped to their "decoded" values. The other bytes all map to
  19. // the value 255, which flags them as "invalid input".
  20. const uint8_t
  21. base64_table_dec[] =
  22. {
  23. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0..15
  24. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 16..31
  25. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, // 32..47
  26. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, // 48..63
  27. 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64..79
  28. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // 80..95
  29. 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96..111
  30. 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, // 112..127
  31. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 128..143
  32. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  33. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  34. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  35. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  36. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  37. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  38. 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  39. };
  40. void
  41. base64_stream_encode_init (struct base64_state *state, int flags)
  42. {
  43. // If any of the codec flags are set, redo choice:
  44. if (codec.enc == NULL || flags & 0xFF) {
  45. codec_choose(&codec, flags);
  46. }
  47. state->eof = 0;
  48. state->bytes = 0;
  49. state->carry = 0;
  50. state->flags = flags;
  51. }
  52. void
  53. base64_stream_encode
  54. ( struct base64_state *state
  55. , const char *src
  56. , size_t srclen
  57. , char *out
  58. , size_t *outlen
  59. )
  60. {
  61. codec.enc(state, src, srclen, out, outlen);
  62. }
  63. void
  64. base64_stream_encode_final
  65. ( struct base64_state *state
  66. , char *out
  67. , size_t *outlen
  68. )
  69. {
  70. uint8_t *o = (uint8_t *)out;
  71. if (state->bytes == 1) {
  72. *o++ = base64_table_enc[state->carry];
  73. *o++ = '=';
  74. *o++ = '=';
  75. *outlen = 3;
  76. return;
  77. }
  78. if (state->bytes == 2) {
  79. *o++ = base64_table_enc[state->carry];
  80. *o++ = '=';
  81. *outlen = 2;
  82. return;
  83. }
  84. *outlen = 0;
  85. }
  86. void
  87. base64_stream_decode_init (struct base64_state *state, int flags)
  88. {
  89. // If any of the codec flags are set, redo choice:
  90. if (codec.dec == NULL || flags & 0xFF) {
  91. codec_choose(&codec, flags);
  92. }
  93. state->eof = 0;
  94. state->bytes = 0;
  95. state->carry = 0;
  96. state->flags = flags;
  97. }
  98. int
  99. base64_stream_decode
  100. ( struct base64_state *state
  101. , const char *src
  102. , size_t srclen
  103. , char *out
  104. , size_t *outlen
  105. )
  106. {
  107. return codec.dec(state, src, srclen, out, outlen);
  108. }
  109. void
  110. base64_encode
  111. ( const char *src
  112. , size_t srclen
  113. , char *out
  114. , size_t *outlen
  115. , int flags
  116. )
  117. {
  118. size_t s;
  119. size_t t;
  120. struct base64_state state;
  121. // Init the stream reader:
  122. base64_stream_encode_init(&state, flags);
  123. // Feed the whole string to the stream reader:
  124. base64_stream_encode(&state, src, srclen, out, &s);
  125. // Finalize the stream by writing trailer if any:
  126. base64_stream_encode_final(&state, out + s, &t);
  127. // Final output length is stream length plus tail:
  128. *outlen = s + t;
  129. }
  130. int
  131. base64_decode
  132. ( const char *src
  133. , size_t srclen
  134. , char *out
  135. , size_t *outlen
  136. , int flags
  137. )
  138. {
  139. int ret;
  140. struct base64_state state;
  141. // Init the stream reader:
  142. base64_stream_decode_init(&state, flags);
  143. // Feed the whole string to the stream reader:
  144. ret = base64_stream_decode(&state, src, srclen, out, outlen);
  145. // If when decoding a whole block, we're still waiting for input then fail:
  146. if (ret && (state.bytes == 0)) {
  147. return ret;
  148. }
  149. return 0;
  150. }