diff options
Diffstat (limited to 'xs_encdec.h')
| -rw-r--r-- | xs_encdec.h | 221 |
1 files changed, 211 insertions, 10 deletions
diff --git a/xs_encdec.h b/xs_encdec.h index 12f40ef..2502520 100644 --- a/xs_encdec.h +++ b/xs_encdec.h | |||
| @@ -7,13 +7,20 @@ | |||
| 7 | xs_str *xs_hex_enc(const xs_val *data, int size); | 7 | xs_str *xs_hex_enc(const xs_val *data, int size); |
| 8 | xs_val *xs_hex_dec(const xs_str *hex, int *size); | 8 | xs_val *xs_hex_dec(const xs_str *hex, int *size); |
| 9 | int xs_is_hex(const char *str); | 9 | int xs_is_hex(const char *str); |
| 10 | xs_str *xs_base32_enc(const xs_val *data, int sz); | ||
| 11 | xs_str *xs_base32hex_enc(const xs_val *data, int sz); | ||
| 12 | xs_val *xs_base32_dec(const xs_str *data, int *size); | ||
| 13 | xs_val *xs_base32hex_dec(const xs_str *data, int *size); | ||
| 10 | xs_str *xs_base64_enc(const xs_val *data, int sz); | 14 | xs_str *xs_base64_enc(const xs_val *data, int sz); |
| 11 | xs_val *xs_base64_dec(const xs_str *data, int *size); | 15 | xs_val *xs_base64_dec(const xs_str *data, int *size); |
| 16 | int xs_is_base64(const char *str); | ||
| 12 | xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint); | 17 | xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint); |
| 13 | 18 | ||
| 14 | 19 | ||
| 15 | #ifdef XS_IMPLEMENTATION | 20 | #ifdef XS_IMPLEMENTATION |
| 16 | 21 | ||
| 22 | /** hex **/ | ||
| 23 | |||
| 17 | xs_str *xs_hex_enc(const xs_val *data, int size) | 24 | xs_str *xs_hex_enc(const xs_val *data, int size) |
| 18 | /* returns an hexdump of data */ | 25 | /* returns an hexdump of data */ |
| 19 | { | 26 | { |
| @@ -78,16 +85,178 @@ int xs_is_hex(const char *str) | |||
| 78 | } | 85 | } |
| 79 | 86 | ||
| 80 | 87 | ||
| 81 | xs_str *xs_base64_enc(const xs_val *data, int sz) | 88 | /** base32 */ |
| 82 | /* encodes data to base64 */ | 89 | |
| 90 | static char *xs_b32_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
| 91 | "234567="; | ||
| 92 | |||
| 93 | static char *xs_b32hex_tbl = "0123456789" | ||
| 94 | "ABCDEFGHIJKLMNOPQRSTUV="; | ||
| 95 | |||
| 96 | /* | ||
| 97 | 00000|00011|11111|12222|22223|33333|33444|44444 | ||
| 98 | */ | ||
| 99 | |||
| 100 | xs_str *xs_base32_enc_tbl(const xs_val *data, int sz, const char *b32_tbl) | ||
| 101 | /* encodes data to base32 using a table */ | ||
| 102 | { | ||
| 103 | xs_str *s = xs_str_new(NULL); | ||
| 104 | unsigned char *p; | ||
| 105 | int n; | ||
| 106 | |||
| 107 | p = (unsigned char *)data; | ||
| 108 | |||
| 109 | for (n = 0; n < sz; n += 5) { | ||
| 110 | int l = sz - n; | ||
| 111 | char enc[9] = "========"; | ||
| 112 | |||
| 113 | enc[0] = b32_tbl[(p[n] >> 3) & 0x1f]; | ||
| 114 | |||
| 115 | if (l > 1) { | ||
| 116 | enc[1] = b32_tbl[(p[n] << 2 | p[n + 1] >> 6) & 0x1f]; | ||
| 117 | enc[2] = b32_tbl[(p[n + 1] >> 1) & 0x1f]; | ||
| 118 | |||
| 119 | if (l > 2) { | ||
| 120 | enc[3] = b32_tbl[(p[n + 1] << 4 | p[n + 2] >> 4) & 0x1f]; | ||
| 121 | |||
| 122 | if (l > 3) { | ||
| 123 | enc[4] = b32_tbl[(p[n + 2] << 1 | p[n + 3] >> 7) & 0x1f]; | ||
| 124 | enc[5] = b32_tbl[(p[n + 3] >> 2) & 0x1f]; | ||
| 125 | |||
| 126 | if (l > 4) { | ||
| 127 | enc[6] = b32_tbl[(p[n + 3] << 3 | p[n + 4] >> 5) & 0x1f]; | ||
| 128 | enc[7] = b32_tbl[(p[n + 4]) & 0x1f]; | ||
| 129 | } | ||
| 130 | else | ||
| 131 | enc[6] = b32_tbl[(p[n + 3] << 3) & 0x1f]; | ||
| 132 | } | ||
| 133 | else | ||
| 134 | enc[4] = b32_tbl[(p[n + 2] << 1) & 0x1f]; | ||
| 135 | } | ||
| 136 | else | ||
| 137 | enc[3] = b32_tbl[(p[n + 1] << 4) & 0x1f]; | ||
| 138 | } | ||
| 139 | else | ||
| 140 | enc[1] = b32_tbl[(p[n] << 2) & 0x1f]; | ||
| 141 | |||
| 142 | s = xs_str_cat(s, enc); | ||
| 143 | } | ||
| 144 | |||
| 145 | return s; | ||
| 146 | } | ||
| 147 | |||
| 148 | |||
| 149 | xs_str *xs_base32_enc(const xs_val *data, int sz) | ||
| 150 | /* encodes data to base32 */ | ||
| 151 | { | ||
| 152 | return xs_base32_enc_tbl(data, sz, xs_b32_tbl); | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | xs_str *xs_base32hex_enc(const xs_val *data, int sz) | ||
| 157 | /* encodes data to base32 with HEX alphabet (RFC4648) */ | ||
| 158 | { | ||
| 159 | return xs_base32_enc_tbl(data, sz, xs_b32hex_tbl); | ||
| 160 | } | ||
| 161 | |||
| 162 | |||
| 163 | xs_val *xs_base32_dec_tbl(const xs_str *data, int *size, const char *b32_tbl) | ||
| 164 | /* decodes data from base32 using a table */ | ||
| 165 | { | ||
| 166 | xs_val *s = NULL; | ||
| 167 | int sz = 0; | ||
| 168 | char *p; | ||
| 169 | |||
| 170 | p = (char *)data; | ||
| 171 | |||
| 172 | /* size of data must be a multiple of 8 */ | ||
| 173 | if (strlen(p) % 8) | ||
| 174 | return NULL; | ||
| 175 | |||
| 176 | for (p = (char *)data; *p; p += 8) { | ||
| 177 | int cs[8]; | ||
| 178 | int n; | ||
| 179 | unsigned char tmp[5]; | ||
| 180 | |||
| 181 | for (n = 0; n < 8; n++) { | ||
| 182 | char *ss = strchr(b32_tbl, p[n]); | ||
| 183 | |||
| 184 | if (ss == NULL) { | ||
| 185 | /* not a base32 char */ | ||
| 186 | return xs_free(s); | ||
| 187 | } | ||
| 188 | |||
| 189 | cs[n] = ss - b32_tbl; | ||
| 190 | } | ||
| 191 | |||
| 192 | n = 0; | ||
| 193 | |||
| 194 | /* #0 byte */ | ||
| 195 | tmp[n++] = cs[0] << 3 | cs[1] >> 2; | ||
| 196 | |||
| 197 | if (cs[2] != 32) { | ||
| 198 | /* #1 byte */ | ||
| 199 | tmp[n++] = (cs[1] & 0x3) << 6 | cs[2] << 1 | (cs[3] & 0x10) >> 4; | ||
| 200 | |||
| 201 | if (cs[4] != 32) { | ||
| 202 | /* #2 byte */ | ||
| 203 | tmp[n++] = (cs[3] & 0xf) << 4 | cs[4] >> 1; | ||
| 204 | |||
| 205 | if (cs[5] != 32) { | ||
| 206 | /* #3 byte */ | ||
| 207 | tmp[n++] = (cs[4] & 0x1) << 7 | cs[5] << 2 | cs[6] >> 3; | ||
| 208 | |||
| 209 | if (cs[7] != 32) { | ||
| 210 | /* #4 byte */ | ||
| 211 | tmp[n++] = (cs[6] & 0x7) << 5 | cs[7]; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | /* must be done manually because data can be pure binary */ | ||
| 218 | s = xs_realloc(s, _xs_blk_size(sz + n)); | ||
| 219 | memcpy(s + sz, tmp, n); | ||
| 220 | sz += n; | ||
| 221 | } | ||
| 222 | |||
| 223 | /* asciiz it to use it as a string */ | ||
| 224 | s = xs_realloc(s, _xs_blk_size(sz + 1)); | ||
| 225 | s[sz] = '\0'; | ||
| 226 | |||
| 227 | *size = sz; | ||
| 228 | |||
| 229 | return s; | ||
| 230 | } | ||
| 231 | |||
| 232 | |||
| 233 | xs_val *xs_base32_dec(const xs_str *data, int *size) | ||
| 234 | /* decodes data from base32 */ | ||
| 235 | { | ||
| 236 | return xs_base32_dec_tbl(data, size, xs_b32_tbl); | ||
| 237 | } | ||
| 238 | |||
| 239 | |||
| 240 | xs_val *xs_base32hex_dec(const xs_str *data, int *size) | ||
| 241 | /* decodes data from base32 with HEX alphabet (RFC4648) */ | ||
| 242 | { | ||
| 243 | return xs_base32_dec_tbl(data, size, xs_b32hex_tbl); | ||
| 244 | } | ||
| 245 | |||
| 246 | |||
| 247 | /** base64 */ | ||
| 248 | |||
| 249 | static char *xs_b64_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
| 250 | "abcdefghijklmnopqrstuvwxyz" | ||
| 251 | "0123456789+/="; | ||
| 252 | |||
| 253 | xs_str *xs_base64_enc_tbl(const xs_val *data, int sz, const char *b64_tbl) | ||
| 254 | /* encodes data to base64 using a table */ | ||
| 83 | { | 255 | { |
| 84 | xs_str *s; | 256 | xs_str *s; |
| 85 | unsigned char *p; | 257 | unsigned char *p; |
| 86 | char *i; | 258 | char *i; |
| 87 | int bsz, n; | 259 | int bsz, n; |
| 88 | static char *b64_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
| 89 | "abcdefghijklmnopqrstuvwxyz" | ||
| 90 | "0123456789+/"; | ||
| 91 | 260 | ||
| 92 | bsz = ((sz + 3 - 1) / 3) * 4; | 261 | bsz = ((sz + 3 - 1) / 3) * 4; |
| 93 | i = s = xs_realloc(NULL, _xs_blk_size(bsz + 1)); | 262 | i = s = xs_realloc(NULL, _xs_blk_size(bsz + 1)); |
| @@ -123,15 +292,19 @@ xs_str *xs_base64_enc(const xs_val *data, int sz) | |||
| 123 | } | 292 | } |
| 124 | 293 | ||
| 125 | 294 | ||
| 126 | xs_val *xs_base64_dec(const xs_str *data, int *size) | 295 | xs_str *xs_base64_enc(const xs_val *data, int sz) |
| 127 | /* decodes data from base64 */ | 296 | /* encodes data to base64 */ |
| 297 | { | ||
| 298 | return xs_base64_enc_tbl(data, sz, xs_b64_tbl); | ||
| 299 | } | ||
| 300 | |||
| 301 | |||
| 302 | xs_val *xs_base64_dec_tbl(const xs_str *data, int *size, const char *b64_tbl) | ||
| 303 | /* decodes data from base64 using a table */ | ||
| 128 | { | 304 | { |
| 129 | xs_val *s = NULL; | 305 | xs_val *s = NULL; |
| 130 | int sz = 0; | 306 | int sz = 0; |
| 131 | char *p; | 307 | char *p; |
| 132 | static char *b64_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
| 133 | "abcdefghijklmnopqrstuvwxyz" | ||
| 134 | "0123456789+/="; | ||
| 135 | 308 | ||
| 136 | p = (char *)data; | 309 | p = (char *)data; |
| 137 | 310 | ||
| @@ -184,6 +357,34 @@ xs_val *xs_base64_dec(const xs_str *data, int *size) | |||
| 184 | } | 357 | } |
| 185 | 358 | ||
| 186 | 359 | ||
| 360 | xs_val *xs_base64_dec(const xs_str *data, int *size) | ||
| 361 | /* decodes data from base64 */ | ||
| 362 | { | ||
| 363 | return xs_base64_dec_tbl(data, size, xs_b64_tbl); | ||
| 364 | } | ||
| 365 | |||
| 366 | |||
| 367 | int xs_is_base64_tbl(const char *str, const char *b64_tbl) | ||
| 368 | /* returns 1 if str is a base64 string, with table */ | ||
| 369 | { | ||
| 370 | while (*str) { | ||
| 371 | if (strchr(b64_tbl, *str++) == NULL) | ||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | return 1; | ||
| 376 | } | ||
| 377 | |||
| 378 | |||
| 379 | int xs_is_base64(const char *str) | ||
| 380 | /* returns 1 if str is a base64 string */ | ||
| 381 | { | ||
| 382 | return xs_is_base64_tbl(str, xs_b64_tbl); | ||
| 383 | } | ||
| 384 | |||
| 385 | |||
| 386 | /** utf-8 **/ | ||
| 387 | |||
| 187 | xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint) | 388 | xs_str *xs_utf8_enc(xs_str *str, unsigned int cpoint) |
| 188 | /* encodes an Unicode codepoint to utf8 */ | 389 | /* encodes an Unicode codepoint to utf8 */ |
| 189 | { | 390 | { |