2 * UCW Library -- Reading of configuration files
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.
12 #include "lib/conf2.h"
13 #include "lib/mempool.h"
18 /* Memory allocation */
20 static struct mempool *cf_pool;
25 return mp_alloc(cf_pool, size);
29 cf_malloc_zero(uns size)
31 return mp_alloc_zero(cf_pool, size);
37 return mp_strdup(cf_pool, s);
41 cf_printf(char *fmt, ...)
45 byte *res = mp_vprintf(cf_pool, fmt, args);
53 cf_journal_block(void *ptr UNUSED, uns len UNUSED)
57 /* Parsers for standard types */
60 uns name; // one-letter name of the unit
61 uns num, den; // fraction
64 static const struct unit units[] = {
69 { 'g', 1000000000, 1 },
72 { 'G', 1073741824, 1 },
77 static const struct unit *
78 lookup_unit(byte *value, byte *end, byte **msg)
81 if (end == value || end[1] || *end >= '0' && *end <= '9')
82 *msg = "Invalid number";
84 for (const struct unit *u=units; u->name; u++)
87 *msg = "Invalid unit";
93 static char cf_rngerr[] = "Number out of range";
96 cf_parse_int(uns number, byte **pars, int *ptr)
98 for (uns i=0; i<number; i++)
102 msg = "Missing number";
104 const struct unit *u;
107 uns x = strtoul(pars[i], &end, 0);
110 else if (u = lookup_unit(pars[i], end, &msg)) {
111 u64 y = (u64)x * u->num;
113 msg = "Number is not an integer";
124 return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
130 cf_parse_u64(uns number, byte **pars, u64 *ptr)
132 for (uns i=0; i<number; i++)
136 msg = "Missing number";
138 const struct unit *u;
141 u64 x = strtoull(pars[i], &end, 0);
144 else if (u = lookup_unit(pars[i], end, &msg)) {
145 if (x > ~(u64)0 / u->num)
146 msg = "Number out of range";
150 msg = "Number is not an integer";
158 return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
164 cf_parse_double(uns number, byte **pars, double *ptr)
166 for (uns i=0; i<number; i++)
170 msg = "Missing number";
172 const struct unit *u;
175 double x = strtoul(pars[i], &end, 0);
178 else if (u = lookup_unit(pars[i], end, &msg))
179 ptr[i] = x * u->num / u->den;
184 return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
190 cf_parse_string(uns number, byte **pars, byte **ptr)
192 for (uns i=0; i<number; i++)
193 ptr[i] = cf_strdup(pars[i]);
197 /* Register size of and parser for each basic type */
202 { sizeof(int), cf_parse_int },
203 { sizeof(u64), cf_parse_u64 },
204 { sizeof(double), cf_parse_double },
205 { sizeof(byte*), cf_parse_string }
209 cf_parse_dyn(uns number, byte **pars, void **ptr, enum cf_type type)
211 cf_journal_block(ptr, sizeof(void*));
212 *ptr = cf_malloc((number+1) * parsers[type].size) + parsers[type].size;
213 * (uns*) (ptr - parsers[type].size) = number;
214 return ((cf_parser*) parsers[type].parser) (number, pars, *ptr);