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);
52 static uns journal_active;
55 cf_journal_active(uns flag)
57 uns f = journal_active;
58 journal_active = flag;
63 cf_journal_block(void *ptr UNUSED, uns len UNUSED)
67 /* Parsers for standard types */
70 uns name; // one-letter name of the unit
71 uns num, den; // fraction
74 static const struct unit units[] = {
79 { 'g', 1000000000, 1 },
82 { 'G', 1073741824, 1 },
87 static const struct unit *
88 lookup_unit(byte *value, byte *end, byte **msg)
91 if (end == value || end[1] || *end >= '0' && *end <= '9')
92 *msg = "Invalid number";
94 for (const struct unit *u=units; u->name; u++)
97 *msg = "Invalid unit";
103 static char cf_rngerr[] = "Number out of range";
106 cf_parse_int(uns number, byte **pars, int *ptr)
108 cf_journal_block(ptr, number * sizeof(int));
109 for (uns i=0; i<number; i++)
113 msg = "Missing number";
115 const struct unit *u;
118 uns x = strtoul(pars[i], &end, 0);
121 else if (u = lookup_unit(pars[i], end, &msg)) {
122 u64 y = (u64)x * u->num;
124 msg = "Number is not an integer";
135 return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
141 cf_parse_u64(uns number, byte **pars, u64 *ptr)
143 cf_journal_block(ptr, number * sizeof(u64));
144 for (uns i=0; i<number; i++)
148 msg = "Missing number";
150 const struct unit *u;
153 u64 x = strtoull(pars[i], &end, 0);
156 else if (u = lookup_unit(pars[i], end, &msg)) {
157 if (x > ~(u64)0 / u->num)
158 msg = "Number out of range";
162 msg = "Number is not an integer";
170 return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
176 cf_parse_double(uns number, byte **pars, double *ptr)
178 cf_journal_block(ptr, number * sizeof(double));
179 for (uns i=0; i<number; i++)
183 msg = "Missing number";
185 const struct unit *u;
188 double x = strtoul(pars[i], &end, 0);
191 else if (u = lookup_unit(pars[i], end, &msg))
192 ptr[i] = x * u->num / u->den;
197 return number==1 ? msg : cf_printf("Item #%d: %s", i+1, msg);
203 cf_parse_string(uns number, byte **pars, byte **ptr)
205 cf_journal_block(ptr, number * sizeof(byte*));
206 for (uns i=0; i<number; i++)
207 ptr[i] = cf_strdup(pars[i]);
212 cf_parse_int_ary(uns number, byte **pars, int **ptr)
214 cf_journal_block(ptr, sizeof(int**));
215 *ptr = (int*) cf_malloc((number+1) * sizeof(int*)) + 1;
216 ARRAY_LEN(*ptr) = number;
217 uns old_flag = cf_journal_active(0);
218 byte *msg = cf_parse_int(number, pars, *ptr);
219 cf_journal_active(old_flag);
224 cf_parse_u64_ary(uns number, byte **pars, u64 **ptr)
226 cf_journal_block(ptr, sizeof(u64**));
227 *ptr = (u64*) cf_malloc((number+1) * sizeof(u64*)) + 1;
228 ARRAY_LEN(*ptr) = number;
229 uns old_flag = cf_journal_active(0);
230 byte *msg = cf_parse_u64(number, pars, *ptr);
231 cf_journal_active(old_flag);
236 cf_parse_double_ary(uns number, byte **pars, double **ptr)
238 cf_journal_block(ptr, sizeof(double**));
239 *ptr = (double*) cf_malloc((number+1) * sizeof(double*)) + 1;
240 ARRAY_LEN(*ptr) = number;
241 uns old_flag = cf_journal_active(0);
242 byte *msg = cf_parse_double(number, pars, *ptr);
243 cf_journal_active(old_flag);
248 cf_parse_string_ary(uns number, byte **pars, byte ***ptr)
250 cf_journal_block(ptr, sizeof(byte***));
251 *ptr = (byte**) cf_malloc((number+1) * sizeof(byte**)) + 1;
252 ARRAY_LEN(*ptr) = number;
253 uns old_flag = cf_journal_active(0);
254 byte *msg = cf_parse_string(number, pars, *ptr);
255 cf_journal_active(old_flag);