mbyte.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #include <stddef.h>
  2. #include <inttypes.h>
  3. #include <assert.h>
  4. #include <stdbool.h>
  5. #include "nvim/types.h"
  6. #include "nvim/mbyte.h"
  7. #include "nvim/ascii.h"
  8. const uint8_t utf8len_tab_zero[] = {
  9. //1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
  10. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0
  11. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 2
  12. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 4
  13. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 6
  14. 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, // 8
  15. 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, // A
  16. 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,2,2, // C
  17. 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0, // E
  18. };
  19. const uint8_t utf8len_tab[] = {
  20. // ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?A ?B ?C ?D ?E ?F
  21. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0?
  22. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1?
  23. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2?
  24. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3?
  25. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4?
  26. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5?
  27. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6?
  28. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7?
  29. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8?
  30. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9?
  31. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A?
  32. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B?
  33. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C?
  34. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D?
  35. 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E?
  36. 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1, // F?
  37. };
  38. int utf_ptr2char(const char_u *const p)
  39. {
  40. if (p[0] < 0x80) { // Be quick for ASCII.
  41. return p[0];
  42. }
  43. const uint8_t len = utf8len_tab_zero[p[0]];
  44. if (len > 1 && (p[1] & 0xc0) == 0x80) {
  45. if (len == 2) {
  46. return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f);
  47. }
  48. if ((p[2] & 0xc0) == 0x80) {
  49. if (len == 3) {
  50. return (((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6)
  51. + (p[2] & 0x3f));
  52. }
  53. if ((p[3] & 0xc0) == 0x80) {
  54. if (len == 4) {
  55. return (((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12)
  56. + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f));
  57. }
  58. if ((p[4] & 0xc0) == 0x80) {
  59. if (len == 5) {
  60. return (((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18)
  61. + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6)
  62. + (p[4] & 0x3f));
  63. }
  64. if ((p[5] & 0xc0) == 0x80 && len == 6) {
  65. return (((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24)
  66. + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12)
  67. + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f));
  68. }
  69. }
  70. }
  71. }
  72. }
  73. // Illegal value: just return the first byte.
  74. return p[0];
  75. }
  76. bool utf_composinglike(const char_u *p1, const char_u *p2)
  77. {
  78. return false;
  79. }
  80. char_u *string_convert(const vimconv_T *conv, char_u *data, size_t *size)
  81. {
  82. return NULL;
  83. }
  84. int utf_ptr2len_len(const char_u *p, int size)
  85. {
  86. int len;
  87. int i;
  88. int m;
  89. len = utf8len_tab[*p];
  90. if (len == 1)
  91. return 1; /* NUL, ascii or illegal lead byte */
  92. if (len > size)
  93. m = size; /* incomplete byte sequence. */
  94. else
  95. m = len;
  96. for (i = 1; i < m; ++i)
  97. if ((p[i] & 0xc0) != 0x80)
  98. return 1;
  99. return len;
  100. }
  101. int utfc_ptr2len_len(const char_u *p, int size)
  102. {
  103. int len;
  104. int prevlen;
  105. if (size < 1 || *p == NUL)
  106. return 0;
  107. if (p[0] < 0x80 && (size == 1 || p[1] < 0x80)) /* be quick for ASCII */
  108. return 1;
  109. /* Skip over first UTF-8 char, stopping at a NUL byte. */
  110. len = utf_ptr2len_len(p, size);
  111. /* Check for illegal byte and incomplete byte sequence. */
  112. if ((len == 1 && p[0] >= 0x80) || len > size)
  113. return 1;
  114. /*
  115. * Check for composing characters. We can handle only the first six, but
  116. * skip all of them (otherwise the cursor would get stuck).
  117. */
  118. prevlen = 0;
  119. while (len < size) {
  120. int len_next_char;
  121. if (p[len] < 0x80)
  122. break;
  123. /*
  124. * Next character length should not go beyond size to ensure that
  125. * UTF_COMPOSINGLIKE(...) does not read beyond size.
  126. */
  127. len_next_char = utf_ptr2len_len(p + len, size - len);
  128. if (len_next_char > size - len)
  129. break;
  130. if (!UTF_COMPOSINGLIKE(p + prevlen, p + len))
  131. break;
  132. /* Skip over composing char */
  133. prevlen = len;
  134. len += len_next_char;
  135. }
  136. return len;
  137. }
  138. int utf_char2len(const int c)
  139. {
  140. if (c < 0x80) {
  141. return 1;
  142. } else if (c < 0x800) {
  143. return 2;
  144. } else if (c < 0x10000) {
  145. return 3;
  146. } else if (c < 0x200000) {
  147. return 4;
  148. } else if (c < 0x4000000) {
  149. return 5;
  150. } else {
  151. return 6;
  152. }
  153. }
  154. int utf_char2bytes(const int c, char_u *const buf)
  155. {
  156. if (c < 0x80) { // 7 bits
  157. buf[0] = c;
  158. return 1;
  159. } else if (c < 0x800) { // 11 bits
  160. buf[0] = 0xc0 + ((unsigned)c >> 6);
  161. buf[1] = 0x80 + (c & 0x3f);
  162. return 2;
  163. } else if (c < 0x10000) { // 16 bits
  164. buf[0] = 0xe0 + ((unsigned)c >> 12);
  165. buf[1] = 0x80 + (((unsigned)c >> 6) & 0x3f);
  166. buf[2] = 0x80 + (c & 0x3f);
  167. return 3;
  168. } else if (c < 0x200000) { // 21 bits
  169. buf[0] = 0xf0 + ((unsigned)c >> 18);
  170. buf[1] = 0x80 + (((unsigned)c >> 12) & 0x3f);
  171. buf[2] = 0x80 + (((unsigned)c >> 6) & 0x3f);
  172. buf[3] = 0x80 + (c & 0x3f);
  173. return 4;
  174. } else if (c < 0x4000000) { // 26 bits
  175. buf[0] = 0xf8 + ((unsigned)c >> 24);
  176. buf[1] = 0x80 + (((unsigned)c >> 18) & 0x3f);
  177. buf[2] = 0x80 + (((unsigned)c >> 12) & 0x3f);
  178. buf[3] = 0x80 + (((unsigned)c >> 6) & 0x3f);
  179. buf[4] = 0x80 + (c & 0x3f);
  180. return 5;
  181. } else { // 31 bits
  182. buf[0] = 0xfc + ((unsigned)c >> 30);
  183. buf[1] = 0x80 + (((unsigned)c >> 24) & 0x3f);
  184. buf[2] = 0x80 + (((unsigned)c >> 18) & 0x3f);
  185. buf[3] = 0x80 + (((unsigned)c >> 12) & 0x3f);
  186. buf[4] = 0x80 + (((unsigned)c >> 6) & 0x3f);
  187. buf[5] = 0x80 + (c & 0x3f);
  188. return 6;
  189. }
  190. }
  191. int utf_ptr2len(const char_u *const p)
  192. {
  193. if (*p == NUL) {
  194. return 0;
  195. }
  196. const int len = utf8len_tab[*p];
  197. for (int i = 1; i < len; i++) {
  198. if ((p[i] & 0xc0) != 0x80) {
  199. return 1;
  200. }
  201. }
  202. return len;
  203. }
  204. int utfc_ptr2len(const char_u *const p)
  205. {
  206. uint8_t b0 = (uint8_t)(*p);
  207. if (b0 == NUL) {
  208. return 0;
  209. }
  210. if (b0 < 0x80 && p[1] < 0x80) { // be quick for ASCII
  211. return 1;
  212. }
  213. // Skip over first UTF-8 char, stopping at a NUL byte.
  214. int len = utf_ptr2len(p);
  215. // Check for illegal byte.
  216. if (len == 1 && b0 >= 0x80) {
  217. return 1;
  218. }
  219. // Check for composing characters. We can handle only the first six, but
  220. // skip all of them (otherwise the cursor would get stuck).
  221. int prevlen = 0;
  222. for (;;) {
  223. if (p[len] < 0x80 || !UTF_COMPOSINGLIKE(p + prevlen, p + len)) {
  224. return len;
  225. }
  226. // Skip over composing char.
  227. prevlen = len;
  228. len += utf_ptr2len(p + len);
  229. }
  230. }
  231. void mb_copy_char(const char_u **fp, char_u **tp)
  232. {
  233. const size_t l = utfc_ptr2len(*fp);
  234. memmove(*tp, *fp, (size_t)l);
  235. *tp += l;
  236. *fp += l;
  237. }