da394ccfb041d4fe7c2452d701b57ad9e677644e
[libjh.git] / hex.c
1 HEADER #include <sys/types.h>
2 #include <assert.h>
3 #include <string.h>
4
5 static inline char hexchar(unsigned char c) {
6   if (c >= 10) return c+'a'-10;
7   return c+'0';
8 }
9
10 // If `in_len` is -1, it means that `in` is a null-terminated string.
11 // `out` must have space for `in_len*2+1` bytes.
12 PUBLIC_FN void hex_encode(char *in, ssize_t in_len, char *out) {
13   if (in_len == -1) in_len = strlen(in);
14   assert(in_len >= 0);
15   char *in_end = in+in_len;
16   while (in < in_end) {
17     unsigned char c = *(unsigned char *)(in++);
18     *(out++) = hexchar(c>>4);
19     *(out++) = hexchar(c&0xf);
20   }
21   *(out++) = '\0';
22 }
23
24 static inline unsigned char unhexchar(char c) {
25   if (c >= '0' && c <= '9') return c-'0';
26   if (c >= 'a' && c <= 'f') return c-'a'+10;
27   if (c >= 'A' && c <= 'F') return c-'A'+10;
28   return 255;
29 }
30
31 // Returns number of decoded bytes or -1(error).
32 // Does not null-terminate output.
33 PUBLIC_FN ssize_t hex_decode(char *in, ssize_t in_len, char *out) {
34   char *out_ = out;
35   if (in_len == -1) in_len = strlen(in);
36   assert(in_len >= 0);
37   if (in_len&1) return -1; /* n%2 must be 0 */
38   char *in_end = in + in_len;
39   while (in < in_end) {
40     unsigned char hi = unhexchar(*(in++));
41     unsigned char lo = unhexchar(*(in++));
42     if (hi == 255 || lo == 255) return -1;
43     *(out++) = (hi<<4) | lo;
44   }
45   return out_ - out;
46 }