summaryrefslogtreecommitdiff
path: root/xs_encdec.h
diff options
context:
space:
mode:
Diffstat (limited to 'xs_encdec.h')
-rw-r--r--xs_encdec.h180
1 files changed, 180 insertions, 0 deletions
diff --git a/xs_encdec.h b/xs_encdec.h
new file mode 100644
index 0000000..e336218
--- /dev/null
+++ b/xs_encdec.h
@@ -0,0 +1,180 @@
1/* copyright (c) 2022 grunfink - MIT license */
2
3#ifndef _XS_ENCDEC_H
4
5#define _XS_ENCDEC_H
6
7d_char *xs_hex_enc(const char *data, int size);
8d_char *xs_hex_dec(const char *hex);
9d_char *xs_base64_enc(const char *data, int sz);
10d_char *xs_base64_dec(const char *data, int *size);
11d_char *xs_utf8_enc(d_char *str, unsigned int cpoint);
12
13
14#ifdef XS_IMPLEMENTATION
15
16d_char *xs_hex_enc(const char *data, int size)
17/* returns an hexdump of data */
18{
19 d_char *s;
20 char *p;
21 int n;
22
23 p = s = calloc(size * 2 + 1, 1);
24
25 for (n = 0; n < size; n++) {
26 sprintf(p, "%02x", (unsigned char)data[n]);
27 p += 2;
28 }
29
30 return s;
31}
32
33
34d_char *xs_hex_dec(const char *hex)
35/* decodes an hexdump into data */
36{
37 int sz = strlen(hex);
38 d_char *s;
39 char *p;
40 int n;
41
42 p = s = calloc(sz / 2, 1);
43
44 for (n = 0; n < sz; n += 2) {
45 int i;
46 if (sscanf(&hex[n], "%02x", &i) == 0) {
47 /* decoding error */
48 free(s);
49 s = NULL;
50 }
51 else
52 *p = i;
53
54 p++;
55 }
56
57 return s;
58}
59
60
61d_char *xs_base64_enc(const char *data, int sz)
62/* encodes data to base64 */
63{
64 d_char *s;
65 unsigned char *p;
66 int n;
67 static char *b64_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
68 "abcdefghijklmnopqrstuvwxyz"
69 "0123456789+/";
70
71 s = xs_str_new(NULL);
72 p = (unsigned char *)data;
73
74 for (n = 0; n < sz; n += 3) {
75 int l = sz - n;
76
77 if (l == 1) {
78 s = xs_append_m(s, &b64_tbl[(p[n] >> 2) & 0x3f], 1);
79 s = xs_append_m(s, &b64_tbl[(p[n] << 4) & 0x3f], 1);
80 s = xs_append_m(s, "==", 2);
81 }
82 else
83 if (l == 2) {
84 s = xs_append_m(s, &b64_tbl[(p[n] >> 2) & 0x3f], 1);
85 s = xs_append_m(s, &b64_tbl[(p[n] << 4 | p[n + 1] >> 4) & 0x3f], 1);
86 s = xs_append_m(s, &b64_tbl[(p[n + 1] << 2) & 0x3f], 1);
87 s = xs_append_m(s, "=", 1);
88 }
89 else {
90 s = xs_append_m(s, &b64_tbl[(p[n] >> 2) & 0x3f], 1);
91 s = xs_append_m(s, &b64_tbl[(p[n] << 4 | p[n + 1] >> 4) & 0x3f], 1);
92 s = xs_append_m(s, &b64_tbl[(p[n + 1] << 2 | p[n + 2] >> 6) & 0x3f], 1);
93 s = xs_append_m(s, &b64_tbl[(p[n + 2]) & 0x3f], 1);
94 }
95 }
96
97 return s;
98}
99
100
101d_char *xs_base64_dec(const char *data, int *size)
102/* decodes data from base64 */
103{
104 d_char *s = NULL;
105 int sz = 0;
106 char *p;
107 static char *b64_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
108 "abcdefghijklmnopqrstuvwxyz"
109 "0123456789+/=";
110
111 p = (char *)data;
112
113 for (p = (char *)data; *p; p += 4) {
114 int cs[4];
115 int n;
116 unsigned char tmp[3];
117
118 for (n = 0; n < 4; n++) {
119 char *ss = strchr(b64_tbl, p[n]);
120
121 if (ss == NULL) {
122 /* not a base64 char */
123 free(s);
124 return NULL;
125 }
126
127 cs[n] = ss - b64_tbl;
128 }
129
130 n = 0;
131
132 /* first byte */
133 tmp[n++] = cs[0] << 2 | ((cs[1] >> 4) & 0x0f);
134
135 /* second byte */
136 if (cs[2] != 64)
137 tmp[n++] = cs[1] << 4 | ((cs[2] >> 2) & 0x3f);
138
139 /* third byte */
140 if (cs[3] != 64)
141 tmp[n++] = cs[2] << 6 | (cs[3] & 0x3f);
142
143 /* must be done manually because data can be pure binary */
144 s = realloc(s, sz + n);
145 memcpy(s + sz, tmp, n);
146 sz += n;
147 }
148
149 *size = sz;
150
151 return s;
152}
153
154
155d_char *xs_utf8_enc(d_char *str, unsigned int cpoint)
156/* encodes an Unicode codepoint to utf8 */
157{
158 unsigned char tmp[4];
159 int n = 0;
160
161 if (cpoint < 0x80)
162 tmp[n++] = cpoint & 0xff;
163 else
164 if (cpoint < 0x800) {
165 tmp[n++] = 0xc0 | (cpoint >> 6);
166 tmp[n++] = 0x80 | (cpoint & 0x3f);
167 }
168 else
169 if (cpoint < 0x10000) {
170 tmp[n++] = 0xe0 | (cpoint >> 12);
171 tmp[n++] = 0x80 | ((cpoint >> 6) & 0x3f);
172 tmp[n++] = 0x80 | (cpoint & 0x3f);
173 }
174
175 return xs_append_m(str, (char *)tmp, n);
176}
177
178#endif /* XS_IMPLEMENTATION */
179
180#endif /* _XS_ENCDEC_H */