tools.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * (c) Philippe G. 20201, philippe_44@outlook.com
  3. * see other copyrights below
  4. *
  5. * This software is released under the MIT License.
  6. * https://opensource.org/licenses/MIT
  7. *
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <stdint.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include "tools.h"
  15. #include "esp_heap_caps.h"
  16. #include "esp_log.h"
  17. const static char TAG[] = "tools";
  18. /****************************************************************************************
  19. * UTF-8 tools
  20. */
  21. // Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
  22. // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
  23. // Copyright (c) 2017 ZephRay <zephray@outlook.com>
  24. //
  25. // utf8to1252 - almost equivalent to iconv -f utf-8 -t windows-1252, but better
  26. #define UTF8_ACCEPT 0
  27. #define UTF8_REJECT 1
  28. static const uint8_t utf8d[] = {
  29. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
  30. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
  31. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
  32. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
  33. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
  34. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
  35. 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
  36. 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
  37. 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
  38. 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
  39. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
  40. 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
  41. 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
  42. 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
  43. };
  44. static uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
  45. uint32_t type = utf8d[byte];
  46. *codep = (*state != UTF8_ACCEPT) ?
  47. (byte & 0x3fu) | (*codep << 6) :
  48. (0xff >> type) & (byte);
  49. *state = utf8d[256 + *state*16 + type];
  50. return *state;
  51. }
  52. static uint8_t UNICODEtoCP1252(uint16_t chr) {
  53. if (chr <= 0xff)
  54. return (chr&0xff);
  55. else {
  56. ESP_LOGI(TAG, "some multi-byte %hx", chr);
  57. switch(chr) {
  58. case 0x20ac: return 0x80; break;
  59. case 0x201a: return 0x82; break;
  60. case 0x0192: return 0x83; break;
  61. case 0x201e: return 0x84; break;
  62. case 0x2026: return 0x85; break;
  63. case 0x2020: return 0x86; break;
  64. case 0x2021: return 0x87; break;
  65. case 0x02c6: return 0x88; break;
  66. case 0x2030: return 0x89; break;
  67. case 0x0160: return 0x8a; break;
  68. case 0x2039: return 0x8b; break;
  69. case 0x0152: return 0x8c; break;
  70. case 0x017d: return 0x8e; break;
  71. case 0x2018: return 0x91; break;
  72. case 0x2019: return 0x92; break;
  73. case 0x201c: return 0x93; break;
  74. case 0x201d: return 0x94; break;
  75. case 0x2022: return 0x95; break;
  76. case 0x2013: return 0x96; break;
  77. case 0x2014: return 0x97; break;
  78. case 0x02dc: return 0x98; break;
  79. case 0x2122: return 0x99; break;
  80. case 0x0161: return 0x9a; break;
  81. case 0x203a: return 0x9b; break;
  82. case 0x0153: return 0x9c; break;
  83. case 0x017e: return 0x9e; break;
  84. case 0x0178: return 0x9f; break;
  85. default: return 0x00; break;
  86. }
  87. }
  88. }
  89. void utf8_decode(char *src) {
  90. uint32_t codep = 0, state = UTF8_ACCEPT;
  91. char *dst = src;
  92. while (src && *src) {
  93. if (!decode(&state, &codep, *src++)) *dst++ = UNICODEtoCP1252(codep);
  94. }
  95. *dst = '\0';
  96. }
  97. /****************************************************************************************
  98. * URL tools
  99. */
  100. static inline char from_hex(char ch) {
  101. return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
  102. }
  103. void url_decode(char *url) {
  104. char *p, *src = strdup(url);
  105. for (p = src; *src; url++) {
  106. *url = *src++;
  107. if (*url == '%') {
  108. *url = from_hex(*src++) << 4;
  109. *url |= from_hex(*src++);
  110. } else if (*url == '+') {
  111. *url = ' ';
  112. }
  113. }
  114. *url = '\0';
  115. free(p);
  116. }
  117. /****************************************************************************************
  118. * Memory tools
  119. */
  120. void * malloc_init_external(size_t sz){
  121. void * ptr=NULL;
  122. ptr = heap_caps_malloc(sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  123. if(ptr==NULL){
  124. ESP_LOGE(TAG,"malloc_init_external: unable to allocate %d bytes of PSRAM!",sz);
  125. }
  126. else {
  127. memset(ptr,0x00,sz);
  128. }
  129. return ptr;
  130. }
  131. void * clone_obj_psram(void * source, size_t source_sz){
  132. void * ptr=NULL;
  133. ptr = heap_caps_malloc(source_sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  134. if(ptr==NULL){
  135. ESP_LOGE(TAG,"clone_obj_psram: unable to allocate %d bytes of PSRAM!",source_sz);
  136. }
  137. else {
  138. memcpy(ptr,source,source_sz);
  139. }
  140. return ptr;
  141. }
  142. char * strdup_psram(const char * source){
  143. void * ptr=NULL;
  144. size_t source_sz = strlen(source)+1;
  145. ptr = heap_caps_malloc(source_sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  146. if(ptr==NULL){
  147. ESP_LOGE(TAG,"strdup_psram: unable to allocate %d bytes of PSRAM! Cannot clone string %s",source_sz,source);
  148. }
  149. else {
  150. memset(ptr,0x00,source_sz);
  151. strcpy(ptr,source);
  152. }
  153. return ptr;
  154. }