diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2018-06-05 15:15:33 +0200 |
---|---|---|
committer | Sven Eden <yamakuzure@gmx.net> | 2018-08-24 16:47:08 +0200 |
commit | 14db62d166679aa43ac4a6d050d79aa9c7b301d7 (patch) | |
tree | 1113bb6f16ee4bb381e8717a6e325f332271f87c /src/basic/parse-util.c | |
parent | dad68a6342f86f817e07187ea06b44d2f0c90321 (diff) |
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 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; |