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