commit ca2e0fc
default
·
2023-05-30 17:49:30 +0000 UTC
parent 6c2ca0d
Backport from xs.
2 files changed,
+69,
-20
+68,
-19
1@@ -5,42 +5,91 @@
2 #define _XS_UNICODE_H
3
4 xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint);
5+ char *xs_utf8_dec(const char *str, unsigned int *cpoint);
6
7
8 #ifdef XS_IMPLEMENTATION
9
10-/** utf-8 **/
11+
12+char *_xs_utf8_enc(char buf[4], unsigned int cpoint)
13+/* encodes an Unicode codepoint to utf-8 into buf and returns the new position */
14+{
15+ unsigned char *p = (unsigned char *)buf;
16+
17+ if (cpoint < 0x80) /* 1 byte char */
18+ *p++ = cpoint & 0xff;
19+ else {
20+ if (cpoint < 0x800) /* 2 byte char */
21+ *p++ = 0xc0 | (cpoint >> 6);
22+ else {
23+ if (cpoint < 0x10000) /* 3 byte char */
24+ *p++ = 0xe0 | (cpoint >> 12);
25+ else { /* 4 byte char */
26+ *p++ = 0xf0 | (cpoint >> 18);
27+ *p++ = 0x80 | ((cpoint >> 12) & 0x3f);
28+ }
29+
30+ *p++ = 0x80 | ((cpoint >> 6) & 0x3f);
31+ }
32+
33+ *p++ = 0x80 | (cpoint & 0x3f);
34+ }
35+
36+ return (char *)p;
37+}
38+
39
40 xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint)
41-/* encodes an Unicode codepoint to utf8 */
42+/* encodes an Unicode codepoint to utf-8 into str */
43 {
44- unsigned char tmp[4];
45- int n = 0;
46+ char tmp[4], *p;
47+
48+ p = _xs_utf8_enc(tmp, cpoint);
49
50- if (cpoint < 0x80)
51- tmp[n++] = cpoint & 0xff;
52+ return xs_append_m(str, tmp, p - tmp);
53+}
54+
55+
56+char *xs_utf8_dec(const char *str, unsigned int *cpoint)
57+/* decodes an utf-8 char inside str into cpoint and returns the next position */
58+{
59+ unsigned char *p = (unsigned char *)str;
60+ int c = *p++;
61+ int cb = 0;
62+
63+ if ((c & 0x80) == 0) { /* 1 byte char */
64+ *cpoint = c;
65+ }
66 else
67- if (cpoint < 0x800) {
68- tmp[n++] = 0xc0 | (cpoint >> 6);
69- tmp[n++] = 0x80 | (cpoint & 0x3f);
70+ if ((c & 0xe0) == 0xc0) { /* 2 byte char */
71+ *cpoint = (c & 0x1f) << 6;
72+ cb = 1;
73 }
74 else
75- if (cpoint < 0x10000) {
76- tmp[n++] = 0xe0 | (cpoint >> 12);
77- tmp[n++] = 0x80 | ((cpoint >> 6) & 0x3f);
78- tmp[n++] = 0x80 | (cpoint & 0x3f);
79+ if ((c & 0xf0) == 0xe0) { /* 3 byte char */
80+ *cpoint = (c & 0x0f) << 12;
81+ cb = 2;
82 }
83 else
84- if (cpoint < 0x200000) {
85- tmp[n++] = 0xf0 | (cpoint >> 18);
86- tmp[n++] = 0x80 | ((cpoint >> 12) & 0x3f);
87- tmp[n++] = 0x80 | ((cpoint >> 6) & 0x3f);
88- tmp[n++] = 0x80 | (cpoint & 0x3f);
89+ if ((c & 0xf8) == 0xf0) { /* 4 byte char */
90+ *cpoint = (c & 0x07) << 18;
91+ cb = 3;
92+ }
93+
94+ /* process the continuation bytes */
95+ while (cb--) {
96+ if ((*p & 0xc0) == 0x80)
97+ *cpoint |= (*p++ & 0x3f) << (cb * 6);
98+ else {
99+ *cpoint = 0xfffd;
100+ break;
101+ }
102 }
103
104- return xs_append_m(str, (char *)tmp, n);
105+ return (char *)p;
106 }
107
108+
109 #endif /* XS_IMPLEMENTATION */
110
111 #endif /* _XS_UNICODE_H */
+1,
-1
1@@ -1 +1 @@
2-/* 1948fa3c5f0df994170cd38b9144b99734b071e6 */
3+/* 3588cbb7859917f1c5965254f8a53c3349c773ea */