str/hex: to-from hexstring conversion routines.
[ccan] / ccan / str / hex / hex.c
1 /* CC0 license (public domain) - see LICENSE file for details */
2 #include <ccan/str/hex/hex.h>
3 #include <assert.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 static bool char_to_hex(unsigned char *val, char c)
8 {
9         if (c >= '0' && c <= '9') {
10                 *val = c - '0';
11                 return true;
12         }
13         if (c >= 'a' && c <= 'f') {
14                 *val = c - 'a' + 10;
15                 return true;
16         }
17         if (c >= 'A' && c <= 'F') {
18                 *val = c - 'A' + 10;
19                 return true;
20         }
21         return false;
22 }
23
24 bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize)
25 {
26         unsigned char v1, v2;
27         unsigned char *p = buf;
28
29         while (slen > 1) {
30                 if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1]))
31                         return false;
32                 if (!bufsize)
33                         return false;
34                 *(p++) = (v1 << 4) | v2;
35                 str += 2;
36                 slen -= 2;
37                 bufsize--;
38         }
39         return slen == 0 && bufsize == 0;
40 }
41
42 static char hexchar(unsigned int val)
43 {
44         if (val < 10)
45                 return '0' + val;
46         if (val < 16)
47                 return 'a' + val - 10;
48         abort();
49 }
50
51 bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize)
52 {
53         size_t used = 0;
54
55         if (destsize < 1)
56                 return false;
57
58         while (used < bufsize) {
59                 unsigned int c = ((const unsigned char *)buf)[used];
60                 if (destsize < 3)
61                         return false;
62                 *(dest++) = hexchar(c >> 4);
63                 *(dest++) = hexchar(c & 0xF);
64                 used++;
65                 destsize -= 2;
66         }
67         *dest = '\0';
68
69         return used + 1;
70 }