summaryrefslogtreecommitdiff
path: root/xs_hex.h
diff options
context:
space:
mode:
Diffstat (limited to 'xs_hex.h')
-rw-r--r--xs_hex.h85
1 files changed, 85 insertions, 0 deletions
diff --git a/xs_hex.h b/xs_hex.h
new file mode 100644
index 0000000..2d87a65
--- /dev/null
+++ b/xs_hex.h
@@ -0,0 +1,85 @@
1/* copyright (c) 2022 - 2023 grunfink et al. / MIT license */
2
3#ifndef _XS_HEX_H
4
5#define _XS_HEX_H
6
7xs_str *xs_hex_enc(const xs_val *data, int size);
8xs_val *xs_hex_dec(const xs_str *hex, int *size);
9int xs_is_hex(const char *str);
10
11#ifdef XS_IMPLEMENTATION
12
13/** hex **/
14
15static char rev_hex_digits[] = "fedcba9876543210FEDCBA";
16
17xs_str *xs_hex_enc(const xs_val *data, int size)
18/* returns an hexdump of data */
19{
20 xs_str *s;
21 char *p;
22 int n;
23
24 p = s = xs_realloc(NULL, _xs_blk_size(size * 2 + 1));
25
26 for (n = 0; n < size; n++) {
27 *p++ = rev_hex_digits[0xf - (*data >> 4 & 0xf)];
28 *p++ = rev_hex_digits[0xf - (*data & 0xf)];
29 data++;
30 }
31
32 *p = '\0';
33
34 return s;
35}
36
37
38xs_val *xs_hex_dec(const xs_str *hex, int *size)
39/* decodes an hexdump into data */
40{
41 int sz = strlen(hex);
42 xs_val *s = NULL;
43 char *p;
44 int n;
45
46 if (sz % 2)
47 return NULL;
48
49 p = s = xs_realloc(NULL, _xs_blk_size(sz / 2 + 1));
50
51 for (n = 0; n < sz; n += 2) {
52 char *d1 = strchr(rev_hex_digits, *hex++);
53 char *d2 = strchr(rev_hex_digits, *hex++);
54
55 if (!d1 || !d2) {
56 /* decoding error */
57 return xs_free(s);
58 }
59
60 *p++ = (0xf - ((d1 - rev_hex_digits) & 0xf)) << 4 |
61 (0xf - ((d2 - rev_hex_digits) & 0xf));
62 }
63
64 *p = '\0';
65 *size = sz / 2;
66
67 return s;
68}
69
70
71int xs_is_hex(const char *str)
72/* returns 1 if str is an hex string */
73{
74 while (*str) {
75 if (strchr(rev_hex_digits, *str++) == NULL)
76 return 0;
77 }
78
79 return 1;
80}
81
82
83#endif /* XS_IMPLEMENTATION */
84
85#endif /* _XS_HEX_H */