Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / isc / hex.c
blob2b46d548c79f87a6b6012eec01cc13f8eb2da67b
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: hex.c,v 1.20 2008/09/25 04:02:39 tbox Exp */
22 /*! \file */
24 #include <config.h>
26 #include <ctype.h>
28 #include <isc/buffer.h>
29 #include <isc/hex.h>
30 #include <isc/lex.h>
31 #include <isc/string.h>
32 #include <isc/util.h>
34 #define RETERR(x) do { \
35 isc_result_t _r = (x); \
36 if (_r != ISC_R_SUCCESS) \
37 return (_r); \
38 } while (0)
42 * BEW: These static functions are copied from lib/dns/rdata.c.
44 static isc_result_t
45 str_totext(const char *source, isc_buffer_t *target);
47 static isc_result_t
48 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
50 static const char hex[] = "0123456789ABCDEF";
52 isc_result_t
53 isc_hex_totext(isc_region_t *source, int wordlength,
54 const char *wordbreak, isc_buffer_t *target)
56 char buf[3];
57 unsigned int loops = 0;
59 if (wordlength < 2)
60 wordlength = 2;
62 memset(buf, 0, sizeof(buf));
63 while (source->length > 0) {
64 buf[0] = hex[(source->base[0] >> 4) & 0xf];
65 buf[1] = hex[(source->base[0]) & 0xf];
66 RETERR(str_totext(buf, target));
67 isc_region_consume(source, 1);
69 loops++;
70 if (source->length != 0 &&
71 (int)((loops + 1) * 2) >= wordlength)
73 loops = 0;
74 RETERR(str_totext(wordbreak, target));
77 return (ISC_R_SUCCESS);
80 /*%
81 * State of a hex decoding process in progress.
83 typedef struct {
84 int length; /*%< Desired length of binary data or -1 */
85 isc_buffer_t *target; /*%< Buffer for resulting binary data */
86 int digits; /*%< Number of buffered hex digits */
87 int val[2];
88 } hex_decode_ctx_t;
90 static inline void
91 hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target)
93 ctx->digits = 0;
94 ctx->length = length;
95 ctx->target = target;
98 static inline isc_result_t
99 hex_decode_char(hex_decode_ctx_t *ctx, int c) {
100 char *s;
102 if ((s = strchr(hex, toupper(c))) == NULL)
103 return (ISC_R_BADHEX);
104 ctx->val[ctx->digits++] = s - hex;
105 if (ctx->digits == 2) {
106 unsigned char num;
108 num = (ctx->val[0] << 4) + (ctx->val[1]);
109 RETERR(mem_tobuffer(ctx->target, &num, 1));
110 if (ctx->length >= 0) {
111 if (ctx->length == 0)
112 return (ISC_R_BADHEX);
113 else
114 ctx->length -= 1;
116 ctx->digits = 0;
118 return (ISC_R_SUCCESS);
121 static inline isc_result_t
122 hex_decode_finish(hex_decode_ctx_t *ctx) {
123 if (ctx->length > 0)
124 return (ISC_R_UNEXPECTEDEND);
125 if (ctx->digits != 0)
126 return (ISC_R_BADHEX);
127 return (ISC_R_SUCCESS);
130 isc_result_t
131 isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
132 hex_decode_ctx_t ctx;
133 isc_textregion_t *tr;
134 isc_token_t token;
135 isc_boolean_t eol;
137 hex_decode_init(&ctx, length, target);
139 while (ctx.length != 0) {
140 unsigned int i;
142 if (length > 0)
143 eol = ISC_FALSE;
144 else
145 eol = ISC_TRUE;
146 RETERR(isc_lex_getmastertoken(lexer, &token,
147 isc_tokentype_string, eol));
148 if (token.type != isc_tokentype_string)
149 break;
150 tr = &token.value.as_textregion;
151 for (i = 0; i < tr->length; i++)
152 RETERR(hex_decode_char(&ctx, tr->base[i]));
154 if (ctx.length < 0)
155 isc_lex_ungettoken(lexer, &token);
156 RETERR(hex_decode_finish(&ctx));
157 return (ISC_R_SUCCESS);
160 isc_result_t
161 isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
162 hex_decode_ctx_t ctx;
164 hex_decode_init(&ctx, -1, target);
165 for (;;) {
166 int c = *cstr++;
167 if (c == '\0')
168 break;
169 if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
170 continue;
171 RETERR(hex_decode_char(&ctx, c));
173 RETERR(hex_decode_finish(&ctx));
174 return (ISC_R_SUCCESS);
177 static isc_result_t
178 str_totext(const char *source, isc_buffer_t *target) {
179 unsigned int l;
180 isc_region_t region;
182 isc_buffer_availableregion(target, &region);
183 l = strlen(source);
185 if (l > region.length)
186 return (ISC_R_NOSPACE);
188 memcpy(region.base, source, l);
189 isc_buffer_add(target, l);
190 return (ISC_R_SUCCESS);
193 static isc_result_t
194 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
195 isc_region_t tr;
197 isc_buffer_availableregion(target, &tr);
198 if (length > tr.length)
199 return (ISC_R_NOSPACE);
200 memcpy(tr.base, base, length);
201 isc_buffer_add(target, length);
202 return (ISC_R_SUCCESS);