Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / hex_code.c
blob3ab99d27e23c624c57a2f9aa8bdf8b28eb17019f
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* hex_code 3
6 /* SUMMARY
7 /* encode/decode data, hexadecimal style
8 /* SYNOPSIS
9 /* #include <hex_code.h>
11 /* VSTRING *hex_encode(result, in, len)
12 /* VSTRING *result;
13 /* const char *in;
14 /* ssize_t len;
16 /* VSTRING *hex_decode(result, in, len)
17 /* VSTRING *result;
18 /* const char *in;
19 /* ssize_t len;
20 /* DESCRIPTION
21 /* hex_encode() takes a block of len bytes and encodes it as one
22 /* upper-case null-terminated string. The result value is
23 /* the result argument.
25 /* hex_decode() performs the opposite transformation on
26 /* lower-case, upper-case or mixed-case input. The result
27 /* value is the result argument. The result is null terminated,
28 /* whether or not that makes sense.
29 /* DIAGNOSTICS
30 /* hex_decode() returns a null pointer when the input contains
31 /* characters not in the hexadecimal alphabet.
32 /* LICENSE
33 /* .ad
34 /* .fi
35 /* The Secure Mailer license must be distributed with this software.
36 /* AUTHOR(S)
37 /* Wietse Venema
38 /* IBM T.J. Watson Research
39 /* P.O. Box 704
40 /* Yorktown Heights, NY 10598, USA
41 /*--*/
43 /* System library. */
45 #include <sys_defs.h>
46 #include <ctype.h>
47 #include <string.h>
49 /* Utility library. */
51 #include <msg.h>
52 #include <mymalloc.h>
53 #include <vstring.h>
54 #include <hex_code.h>
56 /* Application-specific. */
58 static const unsigned char hex_chars[] = "0123456789ABCDEF";
60 #define UCHAR_PTR(x) ((const unsigned char *)(x))
62 /* hex_encode - raw data to encoded */
64 VSTRING *hex_encode(VSTRING *result, const char *in, ssize_t len)
66 const unsigned char *cp;
67 int ch;
68 ssize_t count;
70 VSTRING_RESET(result);
71 for (cp = UCHAR_PTR(in), count = len; count > 0; count--, cp++) {
72 ch = *cp;
73 VSTRING_ADDCH(result, hex_chars[(ch >> 4) & 0xf]);
74 VSTRING_ADDCH(result, hex_chars[ch & 0xf]);
76 VSTRING_TERMINATE(result);
77 return (result);
80 /* hex_decode - encoded data to raw */
82 VSTRING *hex_decode(VSTRING *result, const char *in, ssize_t len)
84 const unsigned char *cp;
85 ssize_t count;
86 unsigned int hex;
87 unsigned int bin;
89 VSTRING_RESET(result);
90 for (cp = UCHAR_PTR(in), count = len; count > 0; cp += 2, count -= 2) {
91 if (count < 2)
92 return (0);
93 hex = cp[0];
94 if (hex >= '0' && hex <= '9')
95 bin = (hex - '0') << 4;
96 else if (hex >= 'A' && hex <= 'F')
97 bin = (hex - 'A' + 10) << 4;
98 else if (hex >= 'a' && hex <= 'f')
99 bin = (hex - 'a' + 10) << 4;
100 else
101 return (0);
102 hex = cp[1];
103 if (hex >= '0' && hex <= '9')
104 bin |= (hex - '0');
105 else if (hex >= 'A' && hex <= 'F')
106 bin |= (hex - 'A' + 10);
107 else if (hex >= 'a' && hex <= 'f')
108 bin |= (hex - 'a' + 10);
109 else
110 return (0);
111 VSTRING_ADDCH(result, bin);
113 VSTRING_TERMINATE(result);
114 return (result);
117 #ifdef TEST
120 * Proof-of-concept test program: convert to hexadecimal and back.
123 #define STR(x) vstring_str(x)
124 #define LEN(x) VSTRING_LEN(x)
126 int main(int unused_argc, char **unused_argv)
128 VSTRING *b1 = vstring_alloc(1);
129 VSTRING *b2 = vstring_alloc(1);
130 char *test = "this is a test";
132 #define DECODE(b,x,l) { \
133 if (hex_decode((b),(x),(l)) == 0) \
134 msg_panic("bad hex: %s", (x)); \
136 #define VERIFY(b,t) { \
137 if (strcmp((b), (t)) != 0) \
138 msg_panic("bad test: %s", (b)); \
141 hex_encode(b1, test, strlen(test));
142 DECODE(b2, STR(b1), LEN(b1));
143 VERIFY(STR(b2), test);
145 hex_encode(b1, test, strlen(test));
146 hex_encode(b2, STR(b1), LEN(b1));
147 hex_encode(b1, STR(b2), LEN(b2));
148 DECODE(b2, STR(b1), LEN(b1));
149 DECODE(b1, STR(b2), LEN(b2));
150 DECODE(b2, STR(b1), LEN(b1));
151 VERIFY(STR(b2), test);
153 hex_encode(b1, test, strlen(test));
154 hex_encode(b2, STR(b1), LEN(b1));
155 hex_encode(b1, STR(b2), LEN(b2));
156 hex_encode(b2, STR(b1), LEN(b1));
157 hex_encode(b1, STR(b2), LEN(b2));
158 DECODE(b2, STR(b1), LEN(b1));
159 DECODE(b1, STR(b2), LEN(b2));
160 DECODE(b2, STR(b1), LEN(b1));
161 DECODE(b1, STR(b2), LEN(b2));
162 DECODE(b2, STR(b1), LEN(b1));
163 VERIFY(STR(b2), test);
165 vstring_free(b1);
166 vstring_free(b2);
167 return (0);
170 #endif