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