util: Add function hexits_value() for parsing multiple hex digits.
authorBen Pfaff <blp@nicira.com>
Mon, 15 Nov 2010 18:18:10 +0000 (10:18 -0800)
committerBen Pfaff <blp@nicira.com>
Mon, 15 Nov 2010 18:18:10 +0000 (10:18 -0800)
Suggested-by: Justin Pettit <jpettit@nicira.com>
lib/json.c
lib/nx-match.c
lib/ofp-parse.c
lib/sha1.c
lib/util.c
lib/util.h
lib/uuid.c
tests/test-aes128.c

index 5887f67..0a8bca2 100644 (file)
@@ -746,19 +746,15 @@ json_lex_number(struct json_parser *p)
 static const char *
 json_lex_4hex(const char *cp, const char *end, int *valuep)
 {
-    int value, i;
+    unsigned int value;
 
     if (cp + 4 > end) {
         return "quoted string ends within \\u escape";
     }
 
-    value = 0;
-    for (i = 0; i < 4; i++) {
-        unsigned char c = *cp++;
-        if (!isxdigit(c)) {
-            return "malformed \\u escape";
-        }
-        value = (value << 4) | hexit_value(c);
+    value = hexits_value(cp, 4, NULL);
+    if (value == UINT_MAX) {
+        return "malformed \\u escape";
     }
     if (!value) {
         return "null bytes not supported in quoted strings";
index 12ea4fb..9f869a7 100644 (file)
@@ -747,17 +747,15 @@ static const char *
 parse_hex_bytes(struct ofpbuf *b, const char *s, unsigned int n)
 {
     while (n--) {
-        int low, high;
         uint8_t byte;
+        bool ok;
 
         s += strspn(s, " ");
-        low = hexit_value(*s);
-        high = low < 0 ? low : hexit_value(s[1]);
-        if (low < 0 || high < 0) {
+        byte = hexits_value(s, 2, &ok);
+        if (!ok) {
             ovs_fatal(0, "%.2s: hex digits expected", s);
         }
 
-        byte = 16 * low + high;
         ofpbuf_put(b, &byte, 1);
         s += 2;
     }
index 6b53f26..2044032 100644 (file)
@@ -289,8 +289,8 @@ str_to_action(char *str, struct ofpbuf *b)
 
             b->size -= sizeof nan->note;
             while (arg && *arg != '\0') {
-                int high, low;
                 uint8_t byte;
+                bool ok;
 
                 if (*arg == '.') {
                     arg++;
@@ -299,16 +299,13 @@ str_to_action(char *str, struct ofpbuf *b)
                     break;
                 }
 
-                high = hexit_value(*arg++);
-                if (high >= 0) {
-                    low = hexit_value(*arg++);
-                }
-                if (high < 0 || low < 0) {
+                byte = hexits_value(arg, 2, &ok);
+                if (!ok) {
                     ovs_fatal(0, "bad hex digit in `note' argument");
                 }
-
-                byte = high * 16 + low;
                 ofpbuf_put(b, &byte, 1);
+
+                arg += 2;
             }
 
             len = b->size - start_ofs;
index 205b82f..3b16622 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is from the Apache Portable Runtime Library.
  * The full upstream copyright and license statement is included below.
- * Modifications copyright (c) 2009 Nicira Networks.
+ * Modifications copyright (c) 2009, 2010 Nicira Networks.
  */
 
 /* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -301,10 +301,12 @@ sha1_from_hex(uint8_t digest[SHA1_DIGEST_SIZE], const char *hex)
     int i;
 
     for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
-        if (!isxdigit(hex[0]) || !isxdigit(hex[1])) {
+        bool ok;
+
+        digest[i] = hexits_value(hex, 2, &ok);
+        if (!ok) {
             return false;
         }
-        digest[i] = (hexit_value(hex[0]) << 4) | hexit_value(hex[1]);
         hex += 2;
     }
     return true;
index 12403cb..4f1b9f7 100644 (file)
@@ -364,6 +364,33 @@ hexit_value(int c)
     }
 }
 
+/* Returns the integer value of the 'n' hexadecimal digits starting at 's', or
+ * UINT_MAX if one of those "digits" is not really a hex digit.  If 'ok' is
+ * nonnull, '*ok' is set to true if the conversion succeeds or to false if a
+ * non-hex digit is detected. */
+unsigned int
+hexits_value(const char *s, size_t n, bool *ok)
+{
+    unsigned int value;
+    size_t i;
+
+    value = 0;
+    for (i = 0; i < n; i++) {
+        int hexit = hexit_value(s[i]);
+        if (hexit < 0) {
+            if (ok) {
+                *ok = false;
+            }
+            return UINT_MAX;
+        }
+        value = (value << 4) + hexit;
+    }
+    if (ok) {
+        *ok = true;
+    }
+    return value;
+}
+
 /* Returns the current working directory as a malloc()'d string, or a null
  * pointer if the current working directory cannot be determined. */
 char *
index 6bc1740..703b93c 100644 (file)
@@ -132,6 +132,7 @@ bool str_to_ullong(const char *, int base, unsigned long long *);
 bool str_to_double(const char *, double *);
 
 int hexit_value(int c);
+unsigned int hexits_value(const char *s, size_t n, bool *ok);
 
 char *get_cwd(void);
 char *dir_name(const char *file_name);
index 2aac4c7..e259024 100644 (file)
@@ -156,23 +156,43 @@ uuid_from_string(struct uuid *uuid, const char *s)
 bool
 uuid_from_string_prefix(struct uuid *uuid, const char *s)
 {
-    static const char template[] = "00000000-1111-1111-2222-222233333333";
-    const char *t;
+    /* 0         1         2         3      */
+    /* 012345678901234567890123456789012345 */
+    /* ------------------------------------ */
+    /* 00000000-1111-1111-2222-222233333333 */
 
-    uuid_zero(uuid);
-    for (t = template; ; t++, s++) {
-        if (*t >= '0' && *t <= '3') {
-            uint32_t *part = &uuid->parts[*t - '0'];
-            if (!isxdigit(*s)) {
-                goto error;
-            }
-            *part = (*part << 4) + hexit_value(*s);
-        } else if (*t == 0) {
-            return true;
-        } else if (*t != *s) {
-            goto error;
-        }
+    bool ok;
+
+    uuid->parts[0] = hexits_value(s, 8, &ok);
+    if (!ok || s[8] != '-') {
+        goto error;
+    }
+
+    uuid->parts[1] = hexits_value(s + 9, 4, &ok) << 16;
+    if (!ok || s[13] != '-') {
+        goto error;
+    }
+
+    uuid->parts[1] += hexits_value(s + 14, 4, &ok);
+    if (!ok || s[18] != '-') {
+        goto error;
+    }
+
+    uuid->parts[2] = hexits_value(s + 19, 4, &ok) << 16;
+    if (!ok || s[23] != '-') {
+        goto error;
+    }
+
+    uuid->parts[2] += hexits_value(s + 24, 4, &ok);
+    if (!ok) {
+        goto error;
+    }
+
+    uuid->parts[3] = hexits_value(s + 28, 8, &ok);
+    if (!ok) {
+        goto error;
     }
+    return true;
 
 error:
     uuid_zero(uuid);
index 8a6c28c..e7e990c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,13 +28,12 @@ hex_to_uint8(const char *input, uint8_t *output, size_t n)
         goto error;
     }
     for (i = 0; i < n; i++) {
-        unsigned char hi = input[i * 2];
-        unsigned char lo = input[i * 2 + 1];
+        bool ok;
 
-        if (!isxdigit(hi) || !isxdigit(lo)) {
+        output[i] = hexits_value(&input[i * 2], 2, &ok);
+        if (!ok) {
             goto error;
         }
-        output[i] = (hexit_value(hi) << 4) + hexit_value(lo);
     }
     return;