util: Introduce ovs_scan_len()
authorPravin B Shelar <pshelar@nicira.com>
Mon, 10 Nov 2014 20:46:11 +0000 (12:46 -0800)
committerPravin B Shelar <pshelar@nicira.com>
Wed, 12 Nov 2014 20:40:28 +0000 (12:40 -0800)
This is similar to ovs_scan but takes int pointer as extra
parameter, this pointer point to starting index of the string.
On successful scan this API stores number of characters
scanned.  This API is useful for parsing complex odp actions
e.g. tun_push action.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Thomas Graf <tgraf@noironetworks.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/util.c
lib/util.h

index 1b9eea6..f4d0f8d 100644 (file)
@@ -1613,34 +1613,13 @@ scan_chars(const char *s, const struct scan_spec *spec, va_list *args)
     return s + n;
 }
 
-/* This is an implementation of the standard sscanf() function, with the
- * following exceptions:
- *
- *   - It returns true if the entire format was successfully scanned and
- *     converted, false if any conversion failed.
- *
- *   - The standard doesn't define sscanf() behavior when an out-of-range value
- *     is scanned, e.g. if a "%"PRIi8 conversion scans "-1" or "0x1ff".  Some
- *     implementations consider this an error and stop scanning.  This
- *     implementation never considers an out-of-range value an error; instead,
- *     it stores the least-significant bits of the converted value in the
- *     destination, e.g. the value 255 for both examples earlier.
- *
- *   - Only single-byte characters are supported, that is, the 'l' modifier
- *     on %s, %[, and %c is not supported.  The GNU extension 'a' modifier is
- *     also not supported.
- *
- *   - %p is not supported.
- */
-bool
-ovs_scan(const char *s, const char *format, ...)
+static bool
+ovs_scan__(const char *s, int *n, const char *format, va_list *args)
 {
     const char *const start = s;
     bool ok = false;
     const char *p;
-    va_list args;
 
-    va_start(args, format);
     p = format;
     while (*p != '\0') {
         struct scan_spec spec;
@@ -1735,24 +1714,24 @@ ovs_scan(const char *s, const char *format, ...)
         }
         switch (c) {
         case 'd':
-            s = scan_int(s, &spec, 10, &args);
+            s = scan_int(s, &spec, 10, args);
             break;
 
         case 'i':
-            s = scan_int(s, &spec, 0, &args);
+            s = scan_int(s, &spec, 0, args);
             break;
 
         case 'o':
-            s = scan_int(s, &spec, 8, &args);
+            s = scan_int(s, &spec, 8, args);
             break;
 
         case 'u':
-            s = scan_int(s, &spec, 10, &args);
+            s = scan_int(s, &spec, 10, args);
             break;
 
         case 'x':
         case 'X':
-            s = scan_int(s, &spec, 16, &args);
+            s = scan_int(s, &spec, 16, args);
             break;
 
         case 'e':
@@ -1760,24 +1739,24 @@ ovs_scan(const char *s, const char *format, ...)
         case 'g':
         case 'E':
         case 'G':
-            s = scan_float(s, &spec, &args);
+            s = scan_float(s, &spec, args);
             break;
 
         case 's':
-            s = scan_string(s, &spec, &args);
+            s = scan_string(s, &spec, args);
             break;
 
         case '[':
-            s = scan_set(s, &spec, &p, &args);
+            s = scan_set(s, &spec, &p, args);
             break;
 
         case 'c':
-            s = scan_chars(s, &spec, &args);
+            s = scan_chars(s, &spec, args);
             break;
 
         case 'n':
             if (spec.type != SCAN_DISCARD) {
-                *va_arg(args, int *) = s - start;
+                *va_arg(*args, int *) = s - start;
             }
             break;
         }
@@ -1786,13 +1765,66 @@ ovs_scan(const char *s, const char *format, ...)
             goto exit;
         }
     }
-    ok = true;
+    if (n) {
+        *n = s - start;
+    }
 
+    ok = true;
 exit:
-    va_end(args);
     return ok;
 }
 
+/* This is an implementation of the standard sscanf() function, with the
+ * following exceptions:
+ *
+ *   - It returns true if the entire format was successfully scanned and
+ *     converted, false if any conversion failed.
+ *
+ *   - The standard doesn't define sscanf() behavior when an out-of-range value
+ *     is scanned, e.g. if a "%"PRIi8 conversion scans "-1" or "0x1ff".  Some
+ *     implementations consider this an error and stop scanning.  This
+ *     implementation never considers an out-of-range value an error; instead,
+ *     it stores the least-significant bits of the converted value in the
+ *     destination, e.g. the value 255 for both examples earlier.
+ *
+ *   - Only single-byte characters are supported, that is, the 'l' modifier
+ *     on %s, %[, and %c is not supported.  The GNU extension 'a' modifier is
+ *     also not supported.
+ *
+ *   - %p is not supported.
+ */
+bool
+ovs_scan(const char *s, const char *format, ...)
+{
+    va_list args;
+    bool res;
+
+    va_start(args, format);
+    res = ovs_scan__(s, NULL, format, &args);
+    va_end(args);
+    return res;
+}
+
+/*
+ * This function is similar to ocs_scan(), extra parameter `n` is added to
+ * return number of scanned characters.
+ */
+bool
+ovs_scan_len(const char *s, int *n, const char *format, ...)
+{
+    va_list args;
+    bool success;
+    int n1;
+
+    va_start(args, format);
+    success = ovs_scan__(s + *n, &n1, format, &args);
+    va_end(args);
+    if (success) {
+        *n = *n + n1;
+    }
+    return success;
+}
+
 void
 xsleep(unsigned int seconds)
 {
index e0e9e07..2258315 100644 (file)
@@ -317,6 +317,7 @@ bool str_to_llong(const char *, int base, long long *);
 bool str_to_uint(const char *, int base, unsigned int *);
 
 bool ovs_scan(const char *s, const char *format, ...) SCANF_FORMAT(2, 3);
+bool ovs_scan_len(const char *s, int *n, const char *format, ...);
 
 bool str_to_double(const char *, double *);