commit bf435af
default
·
2023-12-27 11:54:38 +0000 UTC
parent 94a6274
Backport from xs.
4 files changed,
+247,
-128
M
xs_hex.h
+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 */