2.56
xs_hex.h
1/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */
2
3#ifndef _XS_HEX_H
4
5#define _XS_HEX_H
6
7 int xs_is_hex_digit(char str);
8 void xs_hex_enc_1(char **dst, const char **src);
9 int xs_hex_dec_1(char **dst, const char **src);
10 char *_xs_hex_enc(char *dst, const char *src, int src_size);
11 char *_xs_hex_dec(char *dst, const char *src, int src_size);
12
13#ifdef _XS_H
14 xs_str *xs_hex_enc(const xs_val *data, int size);
15 xs_val *xs_hex_dec(const xs_str *hex, int *size);
16 int xs_is_hex(const char *str);
17#endif /* _XS_H */
18
19
20#ifdef XS_IMPLEMENTATION
21
22#include <string.h>
23
24/** hex **/
25
26static char rev_hex_digits[] = "fedcba9876543210FEDCBA";
27
28int xs_is_hex_digit(char str)
29/* checks if the char is an hex digit */
30{
31 return strchr(rev_hex_digits, str) != NULL;
32}
33
34
35void xs_hex_enc_1(char **dst, const char **src)
36/* decodes one character into two hex digits */
37{
38 const char *i = *src;
39 char *o = *dst;
40
41 *o++ = rev_hex_digits[0xf - (*i >> 4 & 0xf)];
42 *o++ = rev_hex_digits[0xf - (*i & 0xf)];
43
44 *src = i + 1;
45 *dst = o;
46}
47
48
49int xs_hex_dec_1(char **dst, const char **src)
50/* decodes two hex digits (returns 0 on error) */
51{
52 const char *i = *src;
53 char *o = *dst;
54
55 char *d1 = strchr(rev_hex_digits, *i++);
56 char *d2 = strchr(rev_hex_digits, *i++);
57
58 if (!d1 || !d2) {
59 /* decoding error */
60 return 0;
61 }
62
63 *o++ = (0xf - ((d1 - rev_hex_digits) & 0xf)) << 4 |
64 (0xf - ((d2 - rev_hex_digits) & 0xf));
65
66 *src = i;
67 *dst = o;
68 return 1;
69}
70
71
72char *_xs_hex_enc(char *dst, const char *src, int src_size)
73/* hex-encodes the src buffer into dst, which has enough size */
74{
75 const char *e = src + src_size;
76
77 while (src < e)
78 xs_hex_enc_1(&dst, &src);
79
80 return dst;
81}
82
83
84char *_xs_hex_dec(char *dst, const char *src, int src_size)
85/* hex-decodes the src string int dst, which has enough size.
86 return NULL on decoding errors or the final position of dst */
87{
88 if (src_size % 2)
89 return NULL;
90
91 const char *e = src + src_size;
92
93 while (src < e) {
94 if (!xs_hex_dec_1(&dst, &src))
95 return NULL;
96 }
97
98 return dst;
99}
100
101
102#ifdef _XS_H
103
104xs_str *xs_hex_enc(const xs_val *data, int size)
105/* returns an hexdump of data */
106{
107 xs_str *s = xs_realloc(NULL, _xs_blk_size(size * 2 + 1));
108
109 char *q = _xs_hex_enc(s, data, size);
110
111 *q = '\0';
112
113 return s;
114}
115
116
117xs_val *xs_hex_dec(const xs_str *hex, int *size)
118/* decodes an hexdump into data */
119{
120 int sz = strlen(hex);
121 xs_val *s = NULL;
122
123 *size = sz / 2;
124 s = xs_realloc(NULL, _xs_blk_size(*size + 1));
125
126 if (!_xs_hex_dec(s, hex, sz))
127 return xs_free(s);
128
129 s[*size] = '\0';
130
131 return s;
132}
133
134
135int xs_is_hex(const char *str)
136/* returns 1 if str is an hex string */
137{
138 if (strlen(str) % 2)
139 return 0;
140
141 while (*str) {
142 if (!xs_is_hex_digit(*str++))
143 return 0;
144 }
145
146 return 1;
147}
148
149#endif /* _XS_H */
150
151#endif /* XS_IMPLEMENTATION */
152
153#endif /* _XS_HEX_H */