2 * UCW Library -- Configuration files: parsers for basic types
4 * (c) 2001--2006 Robert Spalek <robert@ucw.cz>
5 * (c) 2003--2006 Martin Mares <mj@ucw.cz>
6 * (c) 2019 Pavel Charvat <pchar@ucw.cz>
8 * This software may be freely distributed and used according to the terms
9 * of the GNU Lesser General Public License.
14 #include <ucw/chartype.h>
21 uint name; // one-letter name of the unit
26 static const struct unit units[] = {
31 { 'g', 1, 1000000000 },
32 { 't', 1, 1000000000000LLU },
41 static const struct unit *
42 lookup_unit(const char *value, const char *end, char **msg)
45 if (end == value || end[1] || *end >= '0' && *end <= '9')
46 *msg = "Invalid number";
48 for (const struct unit *u=units; u->name; u++)
49 if ((char)u->name == *end)
51 *msg = "Invalid unit";
57 static char cf_rngerr[] = "Number out of range";
60 cf_parse_int(const char *str, int *ptr)
64 msg = "Missing number";
69 uint x = strtoul(str, &end, 0);
72 else if (u = lookup_unit(str, end, &msg)) {
73 u64 y = (u64)x * u->num;
75 msg = "Number is not an integer";
89 cf_parse_u64(const char *str, u64 *ptr)
93 msg = "Missing number";
98 u64 x = strtoull(str, &end, 0);
101 else if (u = lookup_unit(str, end, &msg)) {
102 if (x > ~(u64)0 / u->num)
103 msg = "Number out of range";
107 msg = "Number is not an integer";
118 cf_parse_double(const char *str, double *ptr)
122 msg = "Missing number";
124 const struct unit *u;
127 if (sscanf(str, "%lf%n", &x, &read_chars) != 1)
128 msg = "Invalid number";
129 else if (u = lookup_unit(str, str + read_chars, &msg))
130 *ptr = x * u->num / u->den;
138 cf_parse_ip(const char *p, u32 *varp)
141 return "Missing IP address";
144 if (*p == '0' && (p[1] | 32) == 'x' && Cxdigit(p[2])) {
146 x = strtoul(p, &p2, 16);
147 if (errno == ERANGE || x > 0xffffffff)
152 for (uint i = 0; i < 4; i++) {
160 uint y = strtoul(p, &p2, 10);
161 if (errno == ERANGE || p2 == (char*) p || y > 255)
167 return *p ? "Trailing characters" : NULL;
169 return "Invalid IP address";