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 */