From 38d0c270063c9d7379b45b80b20b179a713edc6e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Feb 2021 15:33:05 +0100 Subject: [PATCH] percent-util: when parsing permyriads, permit percents too with 1 place after the dot MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Previously, when parsing myriads, we'd support: x% → percent, no places after the dot x.yz% → percent, two places after the dot x‰ → permille, no places after the dot x.y‰ → permille, one place after the dot x‱ → permyriad, no places after the dot What's missing is: x.y% → percent, one place after the dot Let's add it in. --- src/basic/percent-util.c | 20 ++++++++++++++++---- src/test/test-percent-util.c | 9 +++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/basic/percent-util.c b/src/basic/percent-util.c index f58a51dcf9..06f20fd61e 100644 --- a/src/basic/percent-util.c +++ b/src/basic/percent-util.c @@ -64,11 +64,23 @@ static int parse_parts_value_with_hundredths_place(const char *p, const char *sy dot = memchr(p, '.', pc - p); if (dot) { - if (dot + 3 != pc) - return -EINVAL; - if (dot[1] < '0' || dot[1] > '9' || dot[2] < '0' || dot[2] > '9') + if (dot + 3 == pc) { + /* Support two places after the dot */ + + if (dot[1] < '0' || dot[1] > '9' || dot[2] < '0' || dot[2] > '9') + return -EINVAL; + q = (dot[1] - '0') * 10 + (dot[2] - '0'); + + } else if (dot + 2 == pc) { + /* Support one place after the dot */ + + if (dot[1] < '0' || dot[1] > '9') + return -EINVAL; + q = (dot[1] - '0') * 10; + } else + /* We do not support zero or more than two places */ return -EINVAL; - q = (dot[1] - '0') * 10 + (dot[2] - '0'); + n = strndupa(p, dot - p); } else { q = 0; diff --git a/src/test/test-percent-util.c b/src/test/test-percent-util.c index 9d0ad90de1..75f8a6c83d 100644 --- a/src/test/test-percent-util.c +++ b/src/test/test-percent-util.c @@ -7,6 +7,7 @@ static void test_parse_percent(void) { assert_se(parse_percent("") == -EINVAL); assert_se(parse_percent("foo") == -EINVAL); assert_se(parse_percent("0") == -EINVAL); + assert_se(parse_percent("0.1") == -EINVAL); assert_se(parse_percent("50") == -EINVAL); assert_se(parse_percent("100") == -EINVAL); assert_se(parse_percent("-1") == -EINVAL); @@ -34,6 +35,10 @@ static void test_parse_permille(void) { assert_se(parse_permille("50") == -EINVAL); assert_se(parse_permille("100") == -EINVAL); assert_se(parse_permille("-1") == -EINVAL); + assert_se(parse_permille("0.1") == -EINVAL); + assert_se(parse_permille("5%") == 50); + assert_se(parse_permille("5.5%") == 55); + assert_se(parse_permille("5.12%") == -EINVAL); assert_se(parse_permille("0‰") == 0); assert_se(parse_permille("555‰") == 555); @@ -45,6 +50,7 @@ static void test_parse_permille(void) { assert_se(parse_permille("‰1") == -EINVAL); assert_se(parse_permille("1‰‰") == -EINVAL); assert_se(parse_permille("3.2‰") == -EINVAL); + assert_se(parse_permille("0.1‰") == -EINVAL); assert_se(parse_permille("0%") == 0); assert_se(parse_permille("55%") == 550); @@ -57,6 +63,7 @@ static void test_parse_permille(void) { assert_se(parse_permille("%1") == -EINVAL); assert_se(parse_permille("1%%") == -EINVAL); assert_se(parse_permille("3.21%") == -EINVAL); + assert_se(parse_permille("0.1%") == 1); } static void test_parse_permille_unbounded(void) { @@ -107,6 +114,8 @@ static void test_parse_permyriad(void) { assert_se(parse_permyriad("0%") == 0); assert_se(parse_permyriad("55%") == 5500); + assert_se(parse_permyriad("55.5%") == 5550); + assert_se(parse_permyriad("55.50%") == 5550); assert_se(parse_permyriad("55.53%") == 5553); assert_se(parse_permyriad("100%") == 10000); assert_se(parse_permyriad("-7%") == -ERANGE); -- 2.25.1