Pth tweaks and improved estream.c
[gnupg.git] / common / convert.c
1 /* convert.c - Hex conversion functions.
2  *      Copyright (C) 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <ctype.h>
26
27 #include "util.h"
28
29
30 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
31
32
33 /* Convert STRING consisting of hex characters into its binary representation
34    and store that at BUFFER.  BUFFER needs to be of LENGTH bytes.  The
35    function check that the STRING will convert exactly to LENGTH
36    bytes. Colons inbetween the hex digits are allowed, if one colon
37    has been given a colon is expected very 2 characters. The string
38    is delimited by either end of string or a white space character.
39    The function returns -1 on error or the length of the parsed
40    string.  */
41 int
42 hexcolon2bin (const char *string, void *buffer, size_t length)
43 {
44   int i;
45   const char *s = string;
46   int need_colon = 0;
47
48   for (i=0; i < length; )
49     {
50       if (i==1 && *s == ':')  /* Skip colons between hex digits.  */
51         {
52           need_colon = 1;
53           s++;
54         }
55       else if (need_colon && *s == ':')
56         s++;
57       else if (need_colon)
58         return -1;           /* Colon expected. */
59       if (!hexdigitp (s) || !hexdigitp (s+1))
60         return -1;           /* Invalid hex digits. */
61       ((unsigned char*)buffer)[i++] = xtoi_2 (s);
62       s += 2;
63     }
64   if (*s == ':')
65     return -1;             /* Trailing colons are not allowed.  */
66   if (*s && (!isascii (*s) || !isspace (*s)) )
67     return -1;             /* Not followed by Nul or white space.  */
68   if (i != length)
69     return -1;             /* Not of expected length.  */
70   if (*s)
71     s++; /* Skip the delimiter. */
72   return s - string;
73 }
74
75
76
77 static char *
78 do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
79 {
80   const unsigned char *s;
81   char *p;
82   
83   if (!stringbuf)
84     {
85       /* Not really correct for with_colon but we don't care about the
86          one wasted byte. */
87       size_t n = with_colon? 3:2; 
88       size_t nbytes = n * length + 1; 
89       if (length &&  (nbytes-1) / n != length) 
90         {
91           errno = ENOMEM;
92           return NULL;
93         }
94       stringbuf = xtrymalloc (nbytes);
95       if (!stringbuf)
96         return NULL;
97     }
98   
99   for (s = buffer, p = stringbuf; length; length--, s++)
100     {
101       if (with_colon && s != buffer)
102         *p++ = ':';
103       *p++ = tohex ((*s>>4)&15);
104       *p++ = tohex (*s&15);
105     }
106   *p = 0;
107
108   return stringbuf;
109 }
110
111
112 /* Convert LENGTH bytes of data in BUFFER into hex encoding and store
113    that at the provided STRINGBUF.  STRINGBUF must be allocated of at
114    least (2*LENGTH+1) bytes or be NULL so that the function mallocs an
115    appropriate buffer.  Returns STRINGBUF or NULL on error (which may
116    only occur if STRINGBUF has been NULL and the internal malloc
117    failed). */
118 char *
119 bin2hex (const void *buffer, size_t length, char *stringbuf)
120 {
121   return do_bin2hex (buffer, length, stringbuf, 0);
122 }
123
124 /* Convert LENGTH bytes of data in BUFFER into hex encoding and store
125    that at the provided STRINGBUF.  STRINGBUF must be allocated of at
126    least (3*LENGTH+1) bytes or be NULL so that the function mallocs an
127    appropriate buffer.  Returns STRINGBUF or NULL on error (which may
128    only occur if STRINGBUF has been NULL and the internal malloc
129    failed). */
130 char *
131 bin2hexcolon (const void *buffer, size_t length, char *stringbuf)
132 {
133   return do_bin2hex (buffer, length, stringbuf, 1);
134 }
135
136