mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
parse-util: add permyriad parsing
This commit is contained in:
parent
77591e9732
commit
94a8e2d6db
@ -627,11 +627,11 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_percent_unbounded(const char *p) {
|
||||
static int parse_parts_value_whole(const char *p, const char *symbol) {
|
||||
const char *pc, *n;
|
||||
int r, v;
|
||||
|
||||
pc = endswith(p, "%");
|
||||
pc = endswith(p, symbol);
|
||||
if (!pc)
|
||||
return -EINVAL;
|
||||
|
||||
@ -645,6 +645,74 @@ int parse_percent_unbounded(const char *p) {
|
||||
return v;
|
||||
}
|
||||
|
||||
static int parse_parts_value_with_tenths_place(const char *p, const char *symbol) {
|
||||
const char *pc, *dot, *n;
|
||||
int r, q, v;
|
||||
|
||||
pc = endswith(p, symbol);
|
||||
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 < 0)
|
||||
return -ERANGE;
|
||||
if (v > (INT_MAX - q) / 10)
|
||||
return -ERANGE;
|
||||
|
||||
v = v * 10 + q;
|
||||
return v;
|
||||
}
|
||||
|
||||
static int parse_parts_value_with_hundredths_place(const char *p, const char *symbol) {
|
||||
const char *pc, *dot, *n;
|
||||
int r, q, v;
|
||||
|
||||
pc = endswith(p, symbol);
|
||||
if (!pc)
|
||||
return -EINVAL;
|
||||
|
||||
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')
|
||||
return -EINVAL;
|
||||
q = (dot[1] - '0') * 10 + (dot[2] - '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 < 0)
|
||||
return -ERANGE;
|
||||
if (v > (INT_MAX - q) / 100)
|
||||
return -ERANGE;
|
||||
|
||||
v = v * 100 + q;
|
||||
return v;
|
||||
}
|
||||
|
||||
int parse_percent_unbounded(const char *p) {
|
||||
return parse_parts_value_whole(p, "%");
|
||||
}
|
||||
|
||||
int parse_percent(const char *p) {
|
||||
int v;
|
||||
|
||||
@ -656,46 +724,13 @@ int parse_percent(const char *p) {
|
||||
}
|
||||
|
||||
int parse_permille_unbounded(const char *p) {
|
||||
const char *pc, *pm, *dot, *n;
|
||||
int r, q, v;
|
||||
const char *pm;
|
||||
|
||||
pm = endswith(p, "‰");
|
||||
if (pm) {
|
||||
n = strndupa(p, pm - p);
|
||||
r = safe_atoi(n, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (v < 0)
|
||||
return -ERANGE;
|
||||
} else {
|
||||
pc = endswith(p, "%");
|
||||
if (!pc)
|
||||
return -EINVAL;
|
||||
if (pm)
|
||||
return parse_parts_value_whole(p, "‰");
|
||||
|
||||
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 < 0)
|
||||
return -ERANGE;
|
||||
if (v > (INT_MAX - q) / 10)
|
||||
return -ERANGE;
|
||||
|
||||
v = v * 10 + q;
|
||||
}
|
||||
|
||||
return v;
|
||||
return parse_parts_value_with_tenths_place(p, "%");
|
||||
}
|
||||
|
||||
int parse_permille(const char *p) {
|
||||
@ -708,6 +743,30 @@ int parse_permille(const char *p) {
|
||||
return v;
|
||||
}
|
||||
|
||||
int parse_permyriad_unbounded(const char *p) {
|
||||
const char *pm;
|
||||
|
||||
pm = endswith(p, "‱");
|
||||
if (pm)
|
||||
return parse_parts_value_whole(p, "‱");
|
||||
|
||||
pm = endswith(p, "‰");
|
||||
if (pm)
|
||||
return parse_parts_value_with_tenths_place(p, "‰");
|
||||
|
||||
return parse_parts_value_with_hundredths_place(p, "%");
|
||||
}
|
||||
|
||||
int parse_permyriad(const char *p) {
|
||||
int v;
|
||||
|
||||
v = parse_permyriad_unbounded(p);
|
||||
if (v > 10000)
|
||||
return -ERANGE;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int parse_nice(const char *p, int *ret) {
|
||||
int n, r;
|
||||
|
||||
|
@ -133,6 +133,9 @@ int parse_percent(const char *p);
|
||||
int parse_permille_unbounded(const char *p);
|
||||
int parse_permille(const char *p);
|
||||
|
||||
int parse_permyriad_unbounded(const char *p);
|
||||
int parse_permyriad(const char *p);
|
||||
|
||||
int parse_nice(const char *p, int *ret);
|
||||
|
||||
int parse_ip_port(const char *s, uint16_t *ret);
|
||||
|
@ -790,6 +790,72 @@ static void test_parse_permille_unbounded(void) {
|
||||
assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE);
|
||||
}
|
||||
|
||||
static void test_parse_permyriad(void) {
|
||||
assert_se(parse_permyriad("") == -EINVAL);
|
||||
assert_se(parse_permyriad("foo") == -EINVAL);
|
||||
assert_se(parse_permyriad("0") == -EINVAL);
|
||||
assert_se(parse_permyriad("50") == -EINVAL);
|
||||
assert_se(parse_permyriad("100") == -EINVAL);
|
||||
assert_se(parse_permyriad("-1") == -EINVAL);
|
||||
|
||||
assert_se(parse_permyriad("0‱") == 0);
|
||||
assert_se(parse_permyriad("555‱") == 555);
|
||||
assert_se(parse_permyriad("1000‱") == 1000);
|
||||
assert_se(parse_permyriad("-7‱") == -ERANGE);
|
||||
assert_se(parse_permyriad("10007‱") == -ERANGE);
|
||||
assert_se(parse_permyriad("‱") == -EINVAL);
|
||||
assert_se(parse_permyriad("‱‱") == -EINVAL);
|
||||
assert_se(parse_permyriad("‱1") == -EINVAL);
|
||||
assert_se(parse_permyriad("1‱‱") == -EINVAL);
|
||||
assert_se(parse_permyriad("3.2‱") == -EINVAL);
|
||||
|
||||
assert_se(parse_permyriad("0‰") == 0);
|
||||
assert_se(parse_permyriad("555.5‰") == 5555);
|
||||
assert_se(parse_permyriad("1000.0‰") == 10000);
|
||||
assert_se(parse_permyriad("-7‰") == -ERANGE);
|
||||
assert_se(parse_permyriad("1007‰") == -ERANGE);
|
||||
assert_se(parse_permyriad("‰") == -EINVAL);
|
||||
assert_se(parse_permyriad("‰‰") == -EINVAL);
|
||||
assert_se(parse_permyriad("‰1") == -EINVAL);
|
||||
assert_se(parse_permyriad("1‰‰") == -EINVAL);
|
||||
assert_se(parse_permyriad("3.22‰") == -EINVAL);
|
||||
|
||||
assert_se(parse_permyriad("0%") == 0);
|
||||
assert_se(parse_permyriad("55%") == 5500);
|
||||
assert_se(parse_permyriad("55.53%") == 5553);
|
||||
assert_se(parse_permyriad("100%") == 10000);
|
||||
assert_se(parse_permyriad("-7%") == -ERANGE);
|
||||
assert_se(parse_permyriad("107%") == -ERANGE);
|
||||
assert_se(parse_permyriad("%") == -EINVAL);
|
||||
assert_se(parse_permyriad("%%") == -EINVAL);
|
||||
assert_se(parse_permyriad("%1") == -EINVAL);
|
||||
assert_se(parse_permyriad("1%%") == -EINVAL);
|
||||
assert_se(parse_permyriad("3.212%") == -EINVAL);
|
||||
}
|
||||
|
||||
static void test_parse_permyriad_unbounded(void) {
|
||||
assert_se(parse_permyriad_unbounded("1001‱") == 1001);
|
||||
assert_se(parse_permyriad_unbounded("4000‱") == 4000);
|
||||
assert_se(parse_permyriad_unbounded("2147483647‱") == 2147483647);
|
||||
assert_se(parse_permyriad_unbounded("2147483648‱") == -ERANGE);
|
||||
assert_se(parse_permyriad_unbounded("4294967295‱") == -ERANGE);
|
||||
assert_se(parse_permyriad_unbounded("4294967296‱") == -ERANGE);
|
||||
|
||||
assert_se(parse_permyriad_unbounded("101‰") == 1010);
|
||||
assert_se(parse_permyriad_unbounded("400‰") == 4000);
|
||||
assert_se(parse_permyriad_unbounded("214748364.7‰") == 2147483647);
|
||||
assert_se(parse_permyriad_unbounded("214748364.8‰") == -ERANGE);
|
||||
assert_se(parse_permyriad_unbounded("429496729.5‰") == -ERANGE);
|
||||
assert_se(parse_permyriad_unbounded("429496729.6‰") == -ERANGE);
|
||||
|
||||
assert_se(parse_permyriad_unbounded("99%") == 9900);
|
||||
assert_se(parse_permyriad_unbounded("40%") == 4000);
|
||||
assert_se(parse_permyriad_unbounded("21474836.47%") == 2147483647);
|
||||
assert_se(parse_permyriad_unbounded("21474836.48%") == -ERANGE);
|
||||
assert_se(parse_permyriad_unbounded("42949672.95%") == -ERANGE);
|
||||
assert_se(parse_permyriad_unbounded("42949672.96%") == -ERANGE);
|
||||
}
|
||||
|
||||
static void test_parse_nice(void) {
|
||||
int n;
|
||||
|
||||
@ -987,6 +1053,8 @@ int main(int argc, char *argv[]) {
|
||||
test_parse_percent_unbounded();
|
||||
test_parse_permille();
|
||||
test_parse_permille_unbounded();
|
||||
test_parse_permyriad();
|
||||
test_parse_permyriad_unbounded();
|
||||
test_parse_nice();
|
||||
test_parse_dev();
|
||||
test_parse_errno();
|
||||
|
Loading…
Reference in New Issue
Block a user