util: move percent/permille/permyriad parser into percent-util.[ch]
A good chunk of parse-util.[ch] has been about parsing parts per hundred/thousand/ten-thousand. Let's split that out into its own file. No code changes, just some shuffling around.
This commit is contained in:
@@ -176,6 +176,8 @@ basic_sources = files('''
|
||||
path-lookup.h
|
||||
path-util.c
|
||||
path-util.h
|
||||
percent-util.c
|
||||
percent-util.h
|
||||
prioq.c
|
||||
prioq.h
|
||||
proc-cmdline.c
|
||||
|
||||
@@ -627,146 +627,6 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_parts_value_whole(const char *p, const char *symbol) {
|
||||
const char *pc, *n;
|
||||
int r, v;
|
||||
|
||||
pc = endswith(p, symbol);
|
||||
if (!pc)
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(p, pc - p);
|
||||
r = safe_atoi(n, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (v < 0)
|
||||
return -ERANGE;
|
||||
|
||||
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;
|
||||
|
||||
v = parse_percent_unbounded(p);
|
||||
if (v > 100)
|
||||
return -ERANGE;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int parse_permille_unbounded(const char *p) {
|
||||
const char *pm;
|
||||
|
||||
pm = endswith(p, "‰");
|
||||
if (pm)
|
||||
return parse_parts_value_whole(p, "‰");
|
||||
|
||||
return parse_parts_value_with_tenths_place(p, "%");
|
||||
}
|
||||
|
||||
int parse_permille(const char *p) {
|
||||
int v;
|
||||
|
||||
v = parse_permille_unbounded(p);
|
||||
if (v > 1000)
|
||||
return -ERANGE;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -127,15 +127,6 @@ int safe_atod(const char *s, double *ret_d);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "percent-util.h"
|
||||
#include "string-util.h"
|
||||
#include "parse-util.h"
|
||||
|
||||
static int parse_parts_value_whole(const char *p, const char *symbol) {
|
||||
const char *pc, *n;
|
||||
int r, v;
|
||||
|
||||
pc = endswith(p, symbol);
|
||||
if (!pc)
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(p, pc - p);
|
||||
r = safe_atoi(n, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (v < 0)
|
||||
return -ERANGE;
|
||||
|
||||
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;
|
||||
|
||||
v = parse_percent_unbounded(p);
|
||||
if (v > 100)
|
||||
return -ERANGE;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int parse_permille_unbounded(const char *p) {
|
||||
const char *pm;
|
||||
|
||||
pm = endswith(p, "‰");
|
||||
if (pm)
|
||||
return parse_parts_value_whole(p, "‰");
|
||||
|
||||
return parse_parts_value_with_tenths_place(p, "%");
|
||||
}
|
||||
|
||||
int parse_permille(const char *p) {
|
||||
int v;
|
||||
|
||||
v = parse_permille_unbounded(p);
|
||||
if (v > 1000)
|
||||
return -ERANGE;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
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);
|
||||
|
||||
int parse_permyriad_unbounded(const char *p);
|
||||
int parse_permyriad(const char *p);
|
||||
Reference in New Issue
Block a user