W32CE fix.
[gnupg.git] / common / convert.c
index d5301b8..aa3a3a8 100644 (file)
@@ -1,11 +1,11 @@
 /* convert.c - Hex conversion functions.
- *     Copyright (C) 2006 Free Software Foundation, Inc.
+ *     Copyright (C) 2006, 2008 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,9 +14,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -32,7 +30,7 @@
 
 /* Convert STRING consisting of hex characters into its binary
    representation and store that at BUFFER.  BUFFER needs to be of
-   LENGTH bytes.  The function check that the STRING will convert
+   LENGTH bytes.  The function checks that the STRING will convert
    exactly to LENGTH bytes. The string is delimited by either end of
    string or a white space character.  The function returns -1 on
    error or the length of the parsed string.  */
@@ -102,6 +100,7 @@ hexcolon2bin (const char *string, void *buffer, size_t length)
 }
 
 
+
 static char *
 do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
 {
@@ -116,7 +115,7 @@ do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
       size_t nbytes = n * length + 1; 
       if (length &&  (nbytes-1) / n != length) 
         {
-          errno = ENOMEM;
+          gpg_err_set_errno (ENOMEM);
           return NULL;
         }
       stringbuf = xtrymalloc (nbytes);
@@ -162,3 +161,89 @@ bin2hexcolon (const void *buffer, size_t length, char *stringbuf)
 }
 
 
+
+/* Convert HEXSTRING consisting of hex characters into string and
+   store that at BUFFER.  HEXSTRING is either delimited by end of
+   string or a white space character.  The function makes sure that
+   the resulting string in BUFFER is terminated by a Nul character.
+   BUFSIZE is the availabe length of BUFFER; if the converted result
+   plus a possible required Nul character does not fit into this
+   buffer, the function returns NULL and won't change the existing
+   conent of buffer.  In-place conversion is possible as long as
+   BUFFER points to HEXSTRING.
+   
+   If BUFFER is NULL and bufsize is 0 the function scans HEXSTRING but
+   does not store anything.  This may be used to find the end of
+   hexstring.
+
+   On sucess the function returns a pointer to the next character
+   after HEXSTRING (which is either end-of-string or a the next white
+   space).  If BUFLEN is not NULL the strlen of buffer is stored
+   there; this will even be done if BUFFER has been passed as NULL. */
+const char *
+hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen)
+{
+  const char *s = hexstring;
+  int idx, count;
+  int need_nul = 0;
+
+  if (buflen)
+    *buflen = 0;
+
+  for (s=hexstring, count=0; hexdigitp (s) && hexdigitp (s+1); s += 2, count++)
+    ;
+  if (*s && (!isascii (*s) || !isspace (*s)) )
+    return NULL;   /* Not followed by Nul or white space.  */
+  /* We need to append a nul character.  However we don't want that if
+     the hexstring already ends with "00".  */
+  need_nul = ((s == hexstring) || !(s[-2] == '0' && s[-1] == '0'));
+  if (need_nul)
+    count++;
+
+  if (buffer)
+    {
+      if (count > bufsize)
+        return NULL; /* Too long.  */
+      
+      for (s=hexstring, idx=0; hexdigitp (s) && hexdigitp (s+1); s += 2)
+        ((unsigned char*)buffer)[idx++] = xtoi_2 (s);
+      if (need_nul)
+        buffer[idx] = 0;
+    }
+
+  if (buflen)
+    *buflen = count - 1;
+  return s;
+}
+
+
+/* Same as hex2str but this function allocated a new string.  Returns
+   NULL on error.  If R_COUNT is not NULL, the number of scanned bytes
+   will be stored there.  ERRNO is set on error. */
+char *
+hex2str_alloc (const char *hexstring, size_t *r_count)
+{
+  const char *tail;
+  size_t nbytes;
+  char *result;
+
+  tail = hex2str (hexstring, NULL, 0, &nbytes);
+  if (!tail)
+    {
+      if (r_count)
+        *r_count = 0;
+      gpg_err_set_errno (EINVAL);
+      return NULL;
+    }
+  if (r_count)
+    *r_count = tail - hexstring;
+  result = xtrymalloc (nbytes+1);
+  if (!result)
+    return NULL;
+  if (!hex2str (hexstring, result, nbytes+1, NULL))
+    BUG ();
+  return result;
+}
+
+
+