From: Pravin B Shelar Date: Mon, 10 Nov 2014 20:46:11 +0000 (-0800) Subject: util: Introduce ovs_scan_len() X-Git-Tag: v2.4.0~956 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=f071cbbaadc271b6f6b1d3c38c943f1ee2c17b67 util: Introduce ovs_scan_len() 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 Acked-by: Thomas Graf Acked-by: Ben Pfaff --- diff --git a/lib/util.c b/lib/util.c index 1b9eea6ce..f4d0f8de5 100644 --- a/lib/util.c +++ b/lib/util.c @@ -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) { diff --git a/lib/util.h b/lib/util.h index e0e9e07e5..2258315c6 100644 --- a/lib/util.h +++ b/lib/util.h @@ -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 *);