commit bf435af

default  ·  2023-12-27 11:54:38 +0000 UTC
parent 94a6274
Backport from xs.
4 files changed,  +247, -128
+103, -35
  1@@ -4,65 +4,129 @@
  2 
  3 #define _XS_HEX_H
  4 
  5-xs_str *xs_hex_enc(const xs_val *data, int size);
  6-xs_val *xs_hex_dec(const xs_str *hex, int *size);
  7-int xs_is_hex(const char *str);
  8+ int xs_is_hex_digit(char str);
  9+ void xs_hex_enc_1(char **dst, const char **src);
 10+ int xs_hex_dec_1(char **dst, const char **src);
 11+ char *_xs_hex_enc(char *dst, const char *src, int src_size);
 12+ char *_xs_hex_dec(char *dst, const char *src, int src_size);
 13+
 14+#ifdef _XS_H
 15+ xs_str *xs_hex_enc(const xs_val *data, int size);
 16+ xs_val *xs_hex_dec(const xs_str *hex, int *size);
 17+ int xs_is_hex(const char *str);
 18+#endif /* _XS_H */
 19+
 20 
 21 #ifdef XS_IMPLEMENTATION
 22 
 23+#include <string.h>
 24+
 25 /** hex **/
 26 
 27 static char rev_hex_digits[] = "fedcba9876543210FEDCBA";
 28 
 29-xs_str *xs_hex_enc(const xs_val *data, int size)
 30-/* returns an hexdump of data */
 31+int xs_is_hex_digit(char str)
 32+/* checks if the char is an hex digit */
 33 {
 34-    xs_str *s;
 35-    char *p;
 36-    int n;
 37+    return strchr(rev_hex_digits, str) != NULL;
 38+}
 39 
 40-    p = s = xs_realloc(NULL, _xs_blk_size(size * 2 + 1));
 41 
 42-    for (n = 0; n < size; n++) {
 43-        *p++ = rev_hex_digits[0xf - (*data >> 4 & 0xf)];
 44-        *p++ = rev_hex_digits[0xf - (*data      & 0xf)];
 45-        data++;
 46+void xs_hex_enc_1(char **dst, const char **src)
 47+/* decodes one character into two hex digits */
 48+{
 49+    const char *i = *src;
 50+    char *o = *dst;
 51+
 52+    *o++ = rev_hex_digits[0xf - (*i >> 4 & 0xf)];
 53+    *o++ = rev_hex_digits[0xf - (*i      & 0xf)];
 54+
 55+    *src = i + 1;
 56+    *dst = o;
 57+}
 58+
 59+
 60+int xs_hex_dec_1(char **dst, const char **src)
 61+/* decodes two hex digits (returns 0 on error) */
 62+{
 63+    const char *i = *src;
 64+    char *o = *dst;
 65+
 66+    char *d1 = strchr(rev_hex_digits, *i++);
 67+    char *d2 = strchr(rev_hex_digits, *i++);
 68+
 69+    if (!d1 || !d2) {
 70+        /* decoding error */
 71+        return 0;
 72     }
 73 
 74-    *p = '\0';
 75+    *o++ = (0xf - ((d1 - rev_hex_digits) & 0xf)) << 4 |
 76+           (0xf - ((d2 - rev_hex_digits) & 0xf));
 77 
 78-    return s;
 79+    *src = i;
 80+    *dst = o;
 81+    return 1;
 82 }
 83 
 84 
 85-xs_val *xs_hex_dec(const xs_str *hex, int *size)
 86-/* decodes an hexdump into data */
 87+char *_xs_hex_enc(char *dst, const char *src, int src_size)
 88+/* hex-encodes the src buffer into dst, which has enough size */
 89 {
 90-    int sz = strlen(hex);
 91-    xs_val *s = NULL;
 92-    char *p;
 93-    int n;
 94+    const char *e = src + src_size;
 95 
 96-    if (sz % 2)
 97-        return NULL;
 98+    while (src < e)
 99+        xs_hex_enc_1(&dst, &src);
100 
101-    p = s = xs_realloc(NULL, _xs_blk_size(sz / 2 + 1));
102+    return dst;
103+}
104 
105-    for (n = 0; n < sz; n += 2) {
106-        char *d1 = strchr(rev_hex_digits, *hex++);
107-        char *d2 = strchr(rev_hex_digits, *hex++);
108 
109-        if (!d1 || !d2) {
110-            /* decoding error */
111-            return xs_free(s);
112-        }
113+char *_xs_hex_dec(char *dst, const char *src, int src_size)
114+/* hex-decodes the src string int dst, which has enough size.
115+   return NULL on decoding errors or the final position of dst */
116+{
117+    if (src_size % 2)
118+        return NULL;
119 
120-        *p++ = (0xf - ((d1 - rev_hex_digits) & 0xf)) << 4 |
121-               (0xf - ((d2 - rev_hex_digits) & 0xf));
122+    const char *e = src + src_size;
123+
124+    while (src < e) {
125+        if (!xs_hex_dec_1(&dst, &src))
126+            return NULL;
127     }
128 
129-    *p = '\0';
130+    return dst;
131+}
132+
133+
134+#ifdef _XS_H
135+
136+xs_str *xs_hex_enc(const xs_val *data, int size)
137+/* returns an hexdump of data */
138+{
139+    xs_str *s = xs_realloc(NULL, _xs_blk_size(size * 2 + 1));
140+
141+    char *q = _xs_hex_enc(s, data, size);
142+
143+    *q = '\0';
144+
145+    return s;
146+}
147+
148+
149+xs_val *xs_hex_dec(const xs_str *hex, int *size)
150+/* decodes an hexdump into data */
151+{
152+    int sz = strlen(hex);
153+    xs_val *s = NULL;
154+
155     *size = sz / 2;
156+    s = xs_realloc(NULL, _xs_blk_size(*size + 1));
157+
158+    if (!_xs_hex_dec(s, hex, sz))
159+        return xs_free(s);
160+
161+    s[*size] = '\0';
162 
163     return s;
164 }
165@@ -71,14 +135,18 @@ xs_val *xs_hex_dec(const xs_str *hex, int *size)
166 int xs_is_hex(const char *str)
167 /* returns 1 if str is an hex string */
168 {
169+    if (strlen(str) % 2)
170+        return 0;
171+
172     while (*str) {
173-        if (strchr(rev_hex_digits, *str++) == NULL)
174+        if (!xs_is_hex_digit(*str++))
175             return 0;
176     }
177 
178     return 1;
179 }
180 
181+#endif /* _XS_H */
182 
183 #endif /* XS_IMPLEMENTATION */
184 
+30, -13
 1@@ -7,9 +7,13 @@
 2 int xs_socket_timeout(int s, double rto, double sto);
 3 int xs_socket_server(const char *addr, const char *serv);
 4 FILE *xs_socket_accept(int rs);
 5-xs_str *xs_socket_peername(int s);
 6+int _xs_socket_peername(int s, char *buf, int buf_size);
 7 int xs_socket_connect(const char *addr, const char *serv);
 8 
 9+#ifdef _XS_H
10+xs_str *xs_socket_peername(int s);
11+#endif
12+
13 
14 #ifdef XS_IMPLEMENTATION
15 
16@@ -17,6 +21,9 @@ int xs_socket_connect(const char *addr, const char *serv);
17 #include <netdb.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20+#include <string.h>
21+#include <stdlib.h>
22+#include <unistd.h>
23 
24 
25 int xs_socket_timeout(int s, double rto, double sto)
26@@ -100,34 +107,28 @@ FILE *xs_socket_accept(int rs)
27 }
28 
29 
30-xs_str *xs_socket_peername(int s)
31-/* returns the remote address as a string */
32+int _xs_socket_peername(int s, char *buf, int buf_size)
33+/* fill the buffer with the socket peername */
34 {
35-    xs_str *ip = NULL;
36     struct sockaddr_storage addr;
37     socklen_t slen = sizeof(addr);
38+    const char *p = NULL;
39 
40     if (getpeername(s, (struct sockaddr *)&addr, &slen) != -1) {
41-        char buf[1024];
42-        const char *p = NULL;
43-
44         if (addr.ss_family == AF_INET) {
45             struct sockaddr_in *sa = (struct sockaddr_in *)&addr;
46 
47-            p = inet_ntop(AF_INET, &sa->sin_addr, buf, sizeof(buf));
48+            p = inet_ntop(AF_INET, &sa->sin_addr, buf, buf_size);
49         }
50         else
51         if (addr.ss_family == AF_INET6) {
52             struct sockaddr_in6 *sa = (struct sockaddr_in6 *)&addr;
53 
54-            p = inet_ntop(AF_INET6, &sa->sin6_addr, buf, sizeof(buf));
55+            p = inet_ntop(AF_INET6, &sa->sin6_addr, buf, buf_size);
56         }
57-
58-        if (p != NULL)
59-            ip = xs_str_new(p);
60     }
61 
62-    return ip;
63+    return p != NULL;
64 }
65 
66 
67@@ -195,6 +196,22 @@ int xs_socket_connect(const char *addr, const char *serv)
68 }
69 
70 
71+#ifdef _XS_H
72+
73+xs_str *xs_socket_peername(int s)
74+/* returns the remote address as a string */
75+{
76+    char buf[2028];
77+    xs_str *p = NULL;
78+
79+    if (_xs_socket_peername(s, buf, sizeof(buf)))
80+        p = xs_str_new(buf);
81+
82+    return p;
83+}
84+
85+#endif /* _XS_H */
86+
87 #endif /* XS_IMPLEMENTATION */
88 
89 #endif /* _XS_SOCKET_H */
+113, -79
  1@@ -5,7 +5,6 @@
  2 #define _XS_UNICODE_H
  3 
  4  int _xs_utf8_enc(char buf[4], unsigned int cpoint);
  5- xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint);
  6  unsigned int xs_utf8_dec(char **str);
  7  int xs_unicode_width(unsigned int cpoint);
  8  int xs_is_surrogate(unsigned int cpoint);
  9@@ -21,13 +20,20 @@
 10  int xs_unicode_nfc(unsigned int base, unsigned int diac, unsigned int *cpoint);
 11  int xs_unicode_is_alpha(unsigned int cpoint);
 12 
 13+#ifdef _XS_H
 14+ xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint);
 15+#endif
 16+
 17 #ifdef XS_IMPLEMENTATION
 18 
 19+#ifndef countof
 20+#define countof(a) (sizeof((a)) / sizeof((*a)))
 21+#endif
 22 
 23 int _xs_utf8_enc(char buf[4], unsigned int cpoint)
 24 /* encodes an Unicode codepoint to utf-8 into buf and returns the size in bytes */
 25 {
 26-    unsigned char *p = (unsigned char *)buf;
 27+    char *p = buf;
 28 
 29     if (cpoint < 0x80) /* 1 byte char */
 30         *p++ = cpoint & 0xff;
 31@@ -48,27 +54,16 @@ int _xs_utf8_enc(char buf[4], unsigned int cpoint)
 32         *p++ = 0x80 | (cpoint & 0x3f);
 33     }
 34 
 35-    return p - (unsigned char *)buf;
 36-}
 37-
 38-
 39-xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint)
 40-/* encodes an Unicode codepoint to utf-8 into str */
 41-{
 42-    char tmp[4];
 43-
 44-    int c = _xs_utf8_enc(tmp, cpoint);
 45-
 46-    return xs_append_m(str, tmp, c);
 47+    return p - buf;
 48 }
 49 
 50 
 51 unsigned int xs_utf8_dec(char **str)
 52 /* decodes an utf-8 char inside str and updates the pointer */
 53 {
 54-    unsigned char *p = (unsigned char *)*str;
 55+    char *p = *str;
 56     unsigned int cpoint = 0;
 57-    int c = *p++;
 58+    unsigned char c = *p++;
 59     int cb = 0;
 60 
 61     if ((c & 0x80) == 0) { /* 1 byte char */
 62@@ -91,30 +86,19 @@ unsigned int xs_utf8_dec(char **str)
 63     }
 64 
 65     /* process the continuation bytes */
 66-    while (cb--) {
 67-        if ((*p & 0xc0) == 0x80)
 68-            cpoint |= (*p++ & 0x3f) << (cb * 6);
 69-        else {
 70-            cpoint = 0xfffd;
 71-            break;
 72-        }
 73-    }
 74+    while (cb > 0 && *p && (*p & 0xc0) == 0x80)
 75+        cpoint |= (*p++ & 0x3f) << (--cb * 6);
 76 
 77-    *str = (char *)p;
 78-    return cpoint;
 79-}
 80-
 81-
 82-static int int_range_cmp(const void *p1, const void *p2)
 83-{
 84-    const unsigned int *a = p1;
 85-    const unsigned int *b = p2;
 86+    /* incomplete or broken? */
 87+    if (cb)
 88+        cpoint = 0xfffd;
 89 
 90-    return *a < b[0] ? -1 : *a > b[1] ? 1 : 0;
 91+    *str = p;
 92+    return cpoint;
 93 }
 94 
 95 
 96-/* intentionally dead simple */
 97+/** Unicode character width: intentionally dead simple **/
 98 
 99 static unsigned int xs_unicode_width_table[] = {
100     0x300,      0x36f,      0,      /* diacritics */
101@@ -132,12 +116,23 @@ static unsigned int xs_unicode_width_table[] = {
102 int xs_unicode_width(unsigned int cpoint)
103 /* returns the width in columns of a Unicode codepoint (somewhat simplified) */
104 {
105-    unsigned int *r = bsearch(&cpoint, xs_unicode_width_table,
106-                        sizeof(xs_unicode_width_table) / (sizeof(unsigned int) * 3),
107-                        sizeof(unsigned int) * 3,
108-                        int_range_cmp);
109+    int b = 0;
110+    int t = countof(xs_unicode_width_table) / 3 - 1;
111+
112+    while (t >= b) {
113+        int n = (b + t) / 2;
114+        unsigned int *p = &xs_unicode_width_table[n * 3];
115+
116+        if (cpoint < p[0])
117+            t = n - 1;
118+        else
119+        if (cpoint > p[1])
120+            b = n + 1;
121+        else
122+            return p[2];
123+    }
124 
125-    return r ? r[2] : 1;
126+    return 1;
127 }
128 
129 
130@@ -167,38 +162,56 @@ unsigned int xs_surrogate_enc(unsigned int cpoint)
131 }
132 
133 
134-#ifdef _XS_UNICODE_TBL_H
135-
136-/* include xs_unicode_tbl.h before this one to use these functions */
137+#ifdef _XS_H
138 
139-static int int_cmp(const void *p1, const void *p2)
140+xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint)
141+/* encodes an Unicode codepoint to utf-8 into str */
142 {
143-    const unsigned int *a = p1;
144-    const unsigned int *b = p2;
145+    char tmp[4];
146+
147+    int c = _xs_utf8_enc(tmp, cpoint);
148 
149-    return *a < *b ? -1 : *a > *b ? 1 : 0;
150+    return xs_append_m(str, tmp, c);
151 }
152 
153+#endif /* _XS_H */
154+
155+
156+#ifdef _XS_UNICODE_TBL_H
157+
158+/* include xs_unicode_tbl.h before this one to use these functions */
159 
160 unsigned int *_xs_unicode_upper_search(unsigned int cpoint)
161 /* searches for an uppercase codepoint in the case fold table */
162 {
163-    return bsearch(&cpoint, xs_unicode_case_fold_table,
164-        sizeof(xs_unicode_case_fold_table) / (sizeof(unsigned int) * 2),
165-        sizeof(unsigned int) * 2,
166-        int_cmp);
167+    int b = 0;
168+    int t = countof(xs_unicode_case_fold_table) / 2 + 1;
169+
170+    while (t >= b) {
171+        int n = (b + t) / 2;
172+        unsigned int *p = &xs_unicode_case_fold_table[n * 2];
173+
174+        if (cpoint < p[0])
175+            t = n - 1;
176+        else
177+        if (cpoint > p[0])
178+            b = n + 1;
179+        else
180+            return p;
181+    }
182+
183+    return NULL;
184 }
185 
186 
187 unsigned int *_xs_unicode_lower_search(unsigned int cpoint)
188 /* searches for a lowercase codepoint in the case fold table */
189 {
190-    unsigned int *p = xs_unicode_case_fold_table + 1;
191-    unsigned int *e = xs_unicode_case_fold_table +
192-            sizeof(xs_unicode_case_fold_table) / sizeof(unsigned int);
193+    unsigned int *p = xs_unicode_case_fold_table;
194+    unsigned int *e = p + countof(xs_unicode_case_fold_table);
195 
196     while (p < e) {
197-        if (cpoint == *p)
198+        if (cpoint == p[1])
199             return p;
200 
201         p += 2;
202@@ -208,38 +221,49 @@ unsigned int *_xs_unicode_lower_search(unsigned int cpoint)
203 }
204 
205 
206-unsigned int xs_unicode_to_upper(unsigned int cpoint)
207-/* returns the cpoint to uppercase */
208+unsigned int xs_unicode_to_lower(unsigned int cpoint)
209+/* returns the cpoint to lowercase */
210 {
211-    unsigned int *p = _xs_unicode_lower_search(cpoint);
212+    unsigned int *p = _xs_unicode_upper_search(cpoint);
213 
214-    return p == NULL ? cpoint : p[-1];
215+    return p == NULL ? cpoint : p[1];
216 }
217 
218 
219-unsigned int xs_unicode_to_lower(unsigned int cpoint)
220-/* returns the cpoint to lowercase */
221+unsigned int xs_unicode_to_upper(unsigned int cpoint)
222+/* returns the cpoint to uppercase */
223 {
224-    unsigned int *p = _xs_unicode_upper_search(cpoint);
225+    unsigned int *p = _xs_unicode_lower_search(cpoint);
226 
227-    return p == NULL ? cpoint : p[1];
228+    return p == NULL ? cpoint : p[0];
229 }
230 
231 
232 int xs_unicode_nfd(unsigned int cpoint, unsigned int *base, unsigned int *diac)
233 /* applies unicode Normalization Form D */
234 {
235-    unsigned int *r = bsearch(&cpoint, xs_unicode_nfd_table,
236-                        sizeof(xs_unicode_nfd_table) / (sizeof(unsigned int) * 3),
237-                        sizeof(unsigned int) * 3,
238-                        int_cmp);
239-
240-    if (r != NULL) {
241-        *base = r[1];
242-        *diac = r[2];
243+    int b = 0;
244+    int t = countof(xs_unicode_nfd_table) / 3 - 1;
245+
246+    while (t >= b) {
247+        int n = (b + t) / 2;
248+        unsigned int *p = &xs_unicode_nfd_table[n * 3];
249+
250+        int c = cpoint - p[0];
251+
252+        if (c < 0)
253+            t = n - 1;
254+        else
255+        if (c > 0)
256+            b = n + 1;
257+        else {
258+            *base = p[1];
259+            *diac = p[2];
260+            return 1;
261+        }
262     }
263 
264-    return !!r;
265+    return 0;
266 }
267 
268 
269@@ -247,8 +271,7 @@ int xs_unicode_nfc(unsigned int base, unsigned int diac, unsigned int *cpoint)
270 /* applies unicode Normalization Form C */
271 {
272     unsigned int *p = xs_unicode_nfd_table;
273-    unsigned int *e = xs_unicode_nfd_table +
274-        sizeof(xs_unicode_nfd_table) / sizeof(unsigned int);
275+    unsigned int *e = p + countof(xs_unicode_nfd_table);
276 
277     while (p < e) {
278         if (p[1] == base && p[2] == diac) {
279@@ -266,12 +289,23 @@ int xs_unicode_nfc(unsigned int base, unsigned int diac, unsigned int *cpoint)
280 int xs_unicode_is_alpha(unsigned int cpoint)
281 /* checks if a codepoint is an alpha (i.e. a letter) */
282 {
283-    unsigned int *r = bsearch(&cpoint, xs_unicode_alpha_table,
284-                        sizeof(xs_unicode_alpha_table) / (sizeof(unsigned int) * 2),
285-                        sizeof(unsigned int) * 2,
286-                        int_range_cmp);
287+    int b = 0;
288+    int t = countof(xs_unicode_alpha_table) / 2 - 1;
289+
290+    while (t >= b) {
291+        int n = (b + t) / 2;
292+        unsigned int *p = &xs_unicode_alpha_table[n * 2];
293+
294+        if (cpoint < p[0])
295+            t = n - 1;
296+        else
297+        if (cpoint > p[1])
298+            b = n + 1;
299+        else
300+            return 1;
301+    }
302 
303-    return !!r;
304+    return 0;
305 }
306 
307 
+1, -1
1@@ -1 +1 @@
2-/* 3582ff265e19407df1d532eb1d90c372fe22ca62 2023-12-08T06:10:40+01:00 */
3+/* fd50c72456b717bb235eec8fe5f712da5f695f2b 2023-12-27T12:51:14+01:00 */