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>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
13 #include "lib/chartype.h"
20 uns name; // one-letter name of the unit
21 uns num, den; // fraction
24 static const struct unit units[] = {
29 { 'g', 1000000000, 1 },
32 { 'G', 1073741824, 1 },
37 static const struct unit *
38 lookup_unit(const char *value, const char *end, char **msg)
41 if (end == value || end[1] || *end >= '0' && *end <= '9')
42 *msg = "Invalid number";
44 for (const struct unit *u=units; u->name; u++)
45 if ((char)u->name == *end)
47 *msg = "Invalid unit";
53 static char cf_rngerr[] = "Number out of range";
56 cf_parse_int(const char *str, int *ptr)
60 msg = "Missing number";
65 uns x = strtoul(str, &end, 0);
68 else if (u = lookup_unit(str, end, &msg)) {
69 u64 y = (u64)x * u->num;
71 msg = "Number is not an integer";
85 cf_parse_u64(const char *str, u64 *ptr)
89 msg = "Missing number";
94 u64 x = strtoull(str, &end, 0);
97 else if (u = lookup_unit(str, end, &msg)) {
98 if (x > ~(u64)0 / u->num)
99 msg = "Number out of range";
103 msg = "Number is not an integer";
114 cf_parse_double(const char *str, double *ptr)
118 msg = "Missing number";
120 const struct unit *u;
123 if (sscanf(str, "%lf%n", &x, &read_chars) != 1)
124 msg = "Invalid number";
125 else if (u = lookup_unit(str, str + read_chars, &msg))
126 *ptr = x * u->num / u->den;
134 cf_parse_ip(const char *p, u32 *varp)
137 return "Missing IP address";
140 if (*p == '0' && (p[1] | 32) == 'x' && Cxdigit(p[2])) {
142 x = strtoul(p, &p2, 16);
143 if (errno == ERANGE || x > 0xffffffff)
148 for (uns i = 0; i < 4; i++) {
156 uns y = strtoul(p, &p2, 10);
157 if (errno == ERANGE || p2 == (char*) p || y > 255)
163 return *p ? "Trailing characters" : NULL;
165 return "Invalid IP address";