From: Marc Kleine-Budde Date: Tue, 5 Jun 2018 13:15:33 +0000 (+0200) Subject: parse-util: add permille parser + tests X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=14db62d166679aa43ac4a6d050d79aa9c7b301d7;p=elogind.git parse-util: add permille parser + tests --- diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index e9bd8ade1..53e030efc 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -637,6 +637,58 @@ int parse_percent(const char *p) { return v; } +int parse_permille_unbounded(const char *p) { + const char *pc, *pm, *dot, *n; + int r, q, v; + + pm = endswith(p, "‰"); + if (pm) { + n = strndupa(p, pm - p); + r = safe_atoi(n, &v); + if (r < 0) + return r; + } else { + pc = endswith(p, "%"); + if (!pc) + return -EINVAL; + + dot = memchr(p, '.', pc - p); + if (dot) { + if (dot + 2 != pc) + return -EINVAL; + if (dot[1] < '0' || dot[1] > '9') + return -EINVAL; + q = dot[1] - '0'; + n = strndupa(p, dot - p); + } else { + q = 0; + n = strndupa(p, pc - p); + } + r = safe_atoi(n, &v); + if (r < 0) + return r; + if (v > ((INT_MAX - q) / 10)) + return -ERANGE; + + v = v * 10 + q; + } + + if (v < 0) + return -ERANGE; + + return v; +} + +int parse_permille(const char *p) { + int v; + + v = parse_permille_unbounded(p); + if (v > 1000) + return -ERANGE; + + return v; +} + #if 0 /// UNNEEDED by elogind int parse_nice(const char *p, int *ret) { int n, r; diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h index f0f785a88..fc52d1f22 100644 --- a/src/basic/parse-util.h +++ b/src/basic/parse-util.h @@ -117,6 +117,9 @@ int parse_fractional_part_u(const char **s, size_t digits, unsigned *res); int parse_percent_unbounded(const char *p); int parse_percent(const char *p); +int parse_permille_unbounded(const char *p); +int parse_permille(const char *p); + #if 0 /// UNNEEDED by elogind int parse_nice(const char *p, int *ret); diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c index 8f3cf671f..5a6af9ba8 100644 --- a/src/test/test-parse-util.c +++ b/src/test/test-parse-util.c @@ -653,6 +653,54 @@ static void test_parse_percent_unbounded(void) { assert_se(parse_percent_unbounded("400%") == 400); } +static void test_parse_permille(void) { + assert_se(parse_permille("") == -EINVAL); + assert_se(parse_permille("foo") == -EINVAL); + assert_se(parse_permille("0") == -EINVAL); + assert_se(parse_permille("50") == -EINVAL); + assert_se(parse_permille("100") == -EINVAL); + assert_se(parse_permille("-1") == -EINVAL); + + assert_se(parse_permille("0‰") == 0); + assert_se(parse_permille("555‰") == 555); + assert_se(parse_permille("1000‰") == 1000); + assert_se(parse_permille("-7‰") == -ERANGE); + assert_se(parse_permille("1007‰") == -ERANGE); + assert_se(parse_permille("‰") == -EINVAL); + assert_se(parse_permille("‰‰") == -EINVAL); + assert_se(parse_permille("‰1") == -EINVAL); + assert_se(parse_permille("1‰‰") == -EINVAL); + assert_se(parse_permille("3.2‰") == -EINVAL); + + assert_se(parse_permille("0%") == 0); + assert_se(parse_permille("55%") == 550); + assert_se(parse_permille("55.5%") == 555); + assert_se(parse_permille("100%") == 1000); + assert_se(parse_permille("-7%") == -ERANGE); + assert_se(parse_permille("107%") == -ERANGE); + assert_se(parse_permille("%") == -EINVAL); + assert_se(parse_permille("%%") == -EINVAL); + assert_se(parse_permille("%1") == -EINVAL); + assert_se(parse_permille("1%%") == -EINVAL); + assert_se(parse_permille("3.21%") == -EINVAL); +} + +static void test_parse_permille_unbounded(void) { + assert_se(parse_permille_unbounded("1001‰") == 1001); + assert_se(parse_permille_unbounded("4000‰") == 4000); + assert_se(parse_permille_unbounded("2147483647‰") == 2147483647); + assert_se(parse_permille_unbounded("2147483648‰") == -ERANGE); + assert_se(parse_permille_unbounded("4294967295‰") == -ERANGE); + assert_se(parse_permille_unbounded("4294967296‰") == -ERANGE); + + assert_se(parse_permille_unbounded("101%") == 1010); + assert_se(parse_permille_unbounded("400%") == 4000); + assert_se(parse_permille_unbounded("214748364.7%") == 2147483647); + assert_se(parse_permille_unbounded("214748364.8%") == -ERANGE); + assert_se(parse_permille_unbounded("429496729.5%") == -ERANGE); + assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE); +} + #if 0 /// UNNEEDED by elogind static void test_parse_nice(void) { int n; @@ -806,6 +854,8 @@ int main(int argc, char *argv[]) { test_safe_atod(); test_parse_percent(); test_parse_percent_unbounded(); + test_parse_permille(); + test_parse_permille_unbounded(); #if 0 /// UNNEEDED by elogind test_parse_nice(); #endif // 0