snac2

Fork of https://codeberg.org/grunfink/snac2
git clone https://git.inz.fi/snac2
Log | Files | Refs | README | LICENSE

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 */