[Stefan Fuhrmann]
> --- subversion/libsvn_subr/checksum.c (revision 937673)
> +++ subversion/libsvn_subr/checksum.c (working copy)
> @@ -206,12 +206,39 @@
>  
>    for (i = 0; i < len; i++)
>      {
> -      if ((! isxdigit(hex[i * 2])) || (! isxdigit(hex[i * 2 + 1])))
> +      char c1 = hex[i * 2];
> +      char c2 = hex[i * 2 + 1];

Hmmmm.  On the one hand, your open-coding of isxdigit will be less
efficient than the original, which uses a table lookup.  On the other
hand, replacing isalpha is probably for the best, since isalpha is
locale-sensitive.

I'd rather see the whole thing become a single table lookup.  Untested
patch appended.

Peter
[[[
* subversion/libsvn_subr/checksum.c
  (svn_checksum_parse_hex): Use a single table lookup in place of
   isxdigit, isalpha, and (foo - 'a' + 10) gymnastics.  UNTESTED.
]]]
--- subversion/libsvn_subr/checksum.c
+++ subversion/libsvn_subr/checksum.c
@@ -192,6 +192,16 @@
   int len;
   int i;
   unsigned char is_zeros = '\0';
+  static const unsigned char xdigitval[256] =
+    {
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      1, 2, 3, 4, 5, 6, 7, 8, 9,10, 0, 0, 0, 0, 0, 0,   /* 0-9 */
+      0,11,12,13,14,15,16, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* A-F */
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      0,11,12,13,14,15,16,                              /* a-f */
+    };
 
   if (hex == NULL)
     {
@@ -206,13 +216,12 @@
 
   for (i = 0; i < len; i++)
     {
-      if ((! isxdigit(hex[i * 2])) || (! isxdigit(hex[i * 2 + 1])))
+      unsigned char x1 = xdigitval((unsigned char)hex[i * 2]);
+      unsigned char x2 = xdigitval((unsigned char)hex[i * 2 + 1]);
+      if (!x1-- || !x2--)
         return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL);
 
-      ((unsigned char *)(*checksum)->digest)[i] =
-        (( isalpha(hex[i*2]) ? hex[i*2] - 'a' + 10 : hex[i*2] - '0') << 4) |
-        ( isalpha(hex[i*2+1]) ? hex[i*2+1] - 'a' + 10 : hex[i*2+1] - '0');
-      is_zeros |= (*checksum)->digest[i];
+      is_zeros |= ((unsigned char *)(*checksum)->digest)[i] = x1 << 4 | x2;
     }
 
   if (is_zeros == '\0')

Reply via email to