encoder.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Module encoders
  2. #include "module.h"
  3. #include "lauxlib.h"
  4. #include "lmem.h"
  5. #include <stdint.h>
  6. #include <string.h>
  7. #define BASE64_INVALID '\xff'
  8. #define BASE64_PADDING '='
  9. #define ISBASE64(c) (unbytes64[c] != BASE64_INVALID)
  10. static const uint8_t b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  11. static uint8_t *toBase64 ( lua_State* L, const uint8_t *msg, size_t *len){
  12. size_t i, n = *len;
  13. if (!n) // handle empty string case
  14. return NULL;
  15. uint8_t * q, *out = (uint8_t *)luaM_malloc(L, (n + 2) / 3 * 4);
  16. uint8_t bytes64[sizeof(b64)];
  17. memcpy(bytes64, b64, sizeof(b64)); //Avoid lots of flash unaligned fetches
  18. for (i = 0, q = out; i < n; i += 3) {
  19. int a = msg[i];
  20. int b = (i + 1 < n) ? msg[i + 1] : 0;
  21. int c = (i + 2 < n) ? msg[i + 2] : 0;
  22. *q++ = bytes64[a >> 2];
  23. *q++ = bytes64[((a & 3) << 4) | (b >> 4)];
  24. *q++ = (i + 1 < n) ? bytes64[((b & 15) << 2) | (c >> 6)] : BASE64_PADDING;
  25. *q++ = (i + 2 < n) ? bytes64[(c & 63)] : BASE64_PADDING;
  26. }
  27. *len = q - out;
  28. return out;
  29. }
  30. static uint8_t *fromBase64 ( lua_State* L, const uint8_t *enc_msg, size_t *len){
  31. int i, n = *len, blocks = (n>>2), pad = 0;
  32. const uint8_t *p;
  33. uint8_t unbytes64[UCHAR_MAX+1], *msg, *q;
  34. if (!n) // handle empty string case
  35. return NULL;
  36. if (n & 3)
  37. luaL_error (L, "Invalid base64 string");
  38. memset(unbytes64, BASE64_INVALID, sizeof(unbytes64));
  39. for (i = 0; i < sizeof(b64)-1; i++) unbytes64[b64[i]] = i; // sequential so no exceptions
  40. if (enc_msg[n-1] == BASE64_PADDING) {
  41. pad = (enc_msg[n-2] != BASE64_PADDING) ? 1 : 2;
  42. blocks--; //exclude padding block
  43. }
  44. for (i = 0; i < n - pad; i++) if (!ISBASE64(enc_msg[i])) luaL_error (L, "Invalid base64 string");
  45. unbytes64[BASE64_PADDING] = 0;
  46. msg = q = (uint8_t *) luaM_malloc(L, 1+ (3 * n / 4));
  47. for (i = 0, p = enc_msg; i<blocks; i++) {
  48. uint8_t a = unbytes64[*p++];
  49. uint8_t b = unbytes64[*p++];
  50. uint8_t c = unbytes64[*p++];
  51. uint8_t d = unbytes64[*p++];
  52. *q++ = (a << 2) | (b >> 4);
  53. *q++ = (b << 4) | (c >> 2);
  54. *q++ = (c << 6) | d;
  55. }
  56. if (pad) { //now process padding block bytes
  57. uint8_t a = unbytes64[*p++];
  58. uint8_t b = unbytes64[*p++];
  59. *q++ = (a << 2) | (b >> 4);
  60. if (pad == 1) *q++ = (b << 4) | (unbytes64[*p] >> 2);
  61. }
  62. *len = q - msg;
  63. return msg;
  64. }
  65. static inline uint8_t to_hex_nibble(uint8_t b) {
  66. return b + ( b < 10 ? '0' : 'a' - 10 );
  67. }
  68. static uint8_t *toHex ( lua_State* L, const uint8_t *msg, size_t *len){
  69. int i, n = *len;
  70. uint8_t *q, *out = (uint8_t *)luaM_malloc(L, n * 2);
  71. for (i = 0, q = out; i < n; i++) {
  72. *q++ = to_hex_nibble(msg[i] >> 4);
  73. *q++ = to_hex_nibble(msg[i] & 0xf);
  74. }
  75. *len = 2*n;
  76. return out;
  77. }
  78. static uint8_t *fromHex ( lua_State* L, const uint8_t *msg, size_t *len){
  79. int i, n = *len;
  80. const uint8_t *p;
  81. uint8_t b, *q, *out = (uint8_t *)luaM_malloc(L, n * 2);
  82. uint8_t c = 0;
  83. if (n &1)
  84. luaL_error (L, "Invalid hex string");
  85. for (i = 0, p = msg, q = out; i < n; i++) {
  86. if (*p >= '0' && *p <= '9') {
  87. b = *p++ - '0';
  88. } else if (*p >= 'a' && *p <= 'f') {
  89. b = *p++ - ('a' - 10);
  90. } else if (*p >= 'A' && *p <= 'F') {
  91. b = *p++ - ('A' - 10);
  92. } else {
  93. luaL_error (L, "Invalid hex string");
  94. __builtin_unreachable ();
  95. }
  96. if ((i&1) == 0) {
  97. c = b<<4;
  98. } else {
  99. *q++ = c+ b;
  100. }
  101. }
  102. *len = n>>1;
  103. return out;
  104. }
  105. // All encoder functions are of the form:
  106. // Lua: output_string = encoder.function(input_string)
  107. // Where input string maybe empty, but not nil
  108. // Hence these all call the do_func wrapper
  109. static int do_func (lua_State *L, uint8_t * (*conv_func)(lua_State *, const uint8_t *, size_t *)) {
  110. size_t l;
  111. const uint8_t *input = (const uint8_t *)luaL_checklstring(L, 1, &l);
  112. // luaL_argcheck(L, l>0, 1, "input string empty");
  113. uint8_t *output = conv_func(L, input, &l);
  114. if (output) {
  115. lua_pushlstring(L, (char *)output, l);
  116. luaM_free(L, output);
  117. } else {
  118. lua_pushstring(L, "");
  119. }
  120. return 1;
  121. }
  122. #define DECLARE_FUNCTION(f) static int encoder_ ## f (lua_State *L) \
  123. { return do_func(L, f); }
  124. DECLARE_FUNCTION(fromBase64);
  125. DECLARE_FUNCTION(toBase64);
  126. DECLARE_FUNCTION(fromHex);
  127. DECLARE_FUNCTION(toHex);
  128. // Module function map
  129. static const LUA_REG_TYPE encoder_map[] = {
  130. { LSTRKEY("fromBase64"), LFUNCVAL(encoder_fromBase64) },
  131. { LSTRKEY("toBase64"), LFUNCVAL(encoder_toBase64) },
  132. { LSTRKEY("fromHex"), LFUNCVAL(encoder_fromHex) },
  133. { LSTRKEY("toHex"), LFUNCVAL(encoder_toHex) },
  134. { LNILKEY, LNILVAL }
  135. };
  136. NODEMCU_MODULE(ENCODER, "encoder", encoder_map, NULL);