diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2018-06-05 15:15:33 +0200 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2018-06-09 15:12:31 +0200 |
commit | 958acea18b8316c1ba9ec752b83f831c1a95c85f (patch) | |
tree | 3011e46d264ffdfa744abecdd5f5098d389c140a /src/basic/parse-util.c | |
parent | 194c03c839b23261d005d3b3a8ab197be53492a7 (diff) | |
download | systemd-958acea18b8316c1ba9ec752b83f831c1a95c85f.tar.gz |
parse-util: add permille parser + tests
Diffstat (limited to 'src/basic/parse-util.c')
-rw-r--r-- | src/basic/parse-util.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index 07f43b94e5..b25bc6e215 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -632,6 +632,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; +} + int parse_nice(const char *p, int *ret) { int n, r; |