Mercurial > code
comparison ini.c @ 95:cb5d3d66ea04
Merge
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 12 Jan 2012 20:12:48 +0100 |
parents | 145493469aa0 |
children | dcaf2c61c902 |
comparison
equal
deleted
inserted
replaced
80:820426789f17 | 95:cb5d3d66ea04 |
---|---|
24 #include <ctype.h> | 24 #include <ctype.h> |
25 #include <errno.h> | 25 #include <errno.h> |
26 | 26 |
27 #include "ini.h" | 27 #include "ini.h" |
28 | 28 |
29 /* -------------------------------------------------------- | 29 /* -------------------------------------------------------- */ |
30 * structure definitions | 30 /* structure definitions */ |
31 * -------------------------------------------------------- */ | 31 /* -------------------------------------------------------- */ |
32 | 32 |
33 struct ini_option { | 33 struct ini_option { |
34 char *key; /* option name */ | 34 char *key; /* option name */ |
35 char *value; /* option value */ | 35 char *value; /* option value */ |
36 STAILQ_ENTRY(ini_option) next; | 36 STAILQ_ENTRY(ini_option) next; |
57 | 57 |
58 /* For querying functions */ | 58 /* For querying functions */ |
59 STAILQ_HEAD(, ini_section) sections; | 59 STAILQ_HEAD(, ini_section) sections; |
60 }; | 60 }; |
61 | 61 |
62 static char iniError[1024 + 1]; | 62 static char ini_error[1024 + 1]; |
63 | 63 |
64 /* -------------------------------------------------------- | 64 /* -------------------------------------------------------- */ |
65 * prototypes | 65 /* prototypes */ |
66 * -------------------------------------------------------- */ | 66 /* -------------------------------------------------------- */ |
67 | 67 |
68 static void *ini_read(struct ini_config *, FILE *); | 68 static void *ini_read(struct ini_config *, FILE *); |
69 static int ini_getline(struct ini_config *, FILE *); | 69 static int ini_getline(struct ini_config *, FILE *); |
70 static void *ini_readline(struct ini_config *); | 70 static void *ini_readline(struct ini_config *); |
71 static int ini_switch(struct ini_config *, char **); | 71 static int ini_switch(struct ini_config *, char **); |
117 * number is not NULL, number is set to the total number of | 117 * number is not NULL, number is set to the total number of |
118 * section correctly parsed. | 118 * section correctly parsed. |
119 */ | 119 */ |
120 | 120 |
121 char ** | 121 char ** |
122 ini_get_sections_names(struct ini_config *conf, int *number) | 122 ini_get_sections_names(const struct ini_config *conf, int *number) |
123 { | 123 { |
124 struct ini_section *s; | 124 struct ini_section *s; |
125 char **list; | 125 char **list; |
126 int i; | 126 int i; |
127 | 127 |
128 i = 0; | 128 i = 0; |
129 STAILQ_FOREACH(s, &conf->sections, next) | 129 STAILQ_FOREACH(s, &conf->sections, next) |
130 ++ i; | 130 ++ i; |
131 | |
132 /* For safety */ | |
133 if (number != NULL) | |
134 *number = 0; | |
131 | 135 |
132 if ((list = calloc(i + 1, sizeof (char *))) == NULL) | 136 if ((list = calloc(i + 1, sizeof (char *))) == NULL) |
133 return NULL; | 137 return NULL; |
134 | 138 |
135 if (number != NULL) | 139 if (number != NULL) |
186 * definition is enabled because it seek from the beginning, you should use | 190 * definition is enabled because it seek from the beginning, you should use |
187 * ini_get_sections() and then ini_get_option() for each section. | 191 * ini_get_sections() and then ini_get_option() for each section. |
188 */ | 192 */ |
189 | 193 |
190 struct ini_section * | 194 struct ini_section * |
191 ini_select_section(struct ini_config *conf, const char *section) | 195 ini_select_section(const struct ini_config *conf, const char *section) |
192 { | 196 { |
193 struct ini_section *s; | 197 struct ini_section *s; |
194 | 198 |
195 STAILQ_FOREACH(s, &conf->sections, next) | 199 STAILQ_FOREACH(s, &conf->sections, next) |
196 if (strcmp(s->key, section) == 0) | 200 if (strcmp(s->key, section) == 0) |
205 * call to ini_option independantly. Warning, this function returns the | 209 * call to ini_option independantly. Warning, this function returns the |
206 * first occurence of the option so it is not advised to use it | 210 * first occurence of the option so it is not advised to use it |
207 */ | 211 */ |
208 | 212 |
209 char * | 213 char * |
210 ini_option_once(struct ini_config *conf, const char *sect, const char *key) | 214 ini_get_option_once(const struct ini_config *conf, const char *sect, const char *key) |
211 { | 215 { |
212 struct ini_option *o; | 216 struct ini_option *o; |
213 struct ini_section *s; | 217 struct ini_section *s; |
214 | 218 |
215 STAILQ_FOREACH(s, &conf->sections, next) | 219 STAILQ_FOREACH(s, &conf->sections, next) |
226 /* | 230 /* |
227 * Return a NULL list of all available options in the section. | 231 * Return a NULL list of all available options in the section. |
228 */ | 232 */ |
229 | 233 |
230 char ** | 234 char ** |
231 ini_get_option_names(struct ini_section *section, int *nb) | 235 ini_get_option_names(const struct ini_section *section, int *nb) |
232 { | 236 { |
233 char **list; | 237 char **list; |
234 struct ini_option *o; | 238 struct ini_option *o; |
235 int i; | 239 int i; |
236 | 240 |
237 i = 0; | 241 i = 0; |
238 STAILQ_FOREACH(o, §ion->options, next) | 242 STAILQ_FOREACH(o, §ion->options, next) |
239 ++ i; | 243 ++ i; |
240 | 244 |
245 if (nb != NULL) | |
246 *nb = i; | |
247 | |
241 if ((list = calloc(i + 1, sizeof (char *))) == NULL) | 248 if ((list = calloc(i + 1, sizeof (char *))) == NULL) |
242 return NULL; | 249 return NULL; |
243 | 250 |
244 if (nb != NULL) | 251 if (nb != NULL) |
245 *nb = i; | 252 *nb = i; |
256 * ini_select() before using this function. Returns the value of | 263 * ini_select() before using this function. Returns the value of |
257 * key or NULL if the option does not exists. | 264 * key or NULL if the option does not exists. |
258 */ | 265 */ |
259 | 266 |
260 char * | 267 char * |
261 ini_get_option(struct ini_section *section, const char *key) | 268 ini_get_option(const struct ini_section *section, const char *key) |
262 { | 269 { |
263 struct ini_option *o; | 270 struct ini_option *o; |
264 | 271 |
265 STAILQ_FOREACH(o, §ion->options, next) | 272 STAILQ_FOREACH(o, §ion->options, next) |
266 if (strcmp(o->key, key) == 0) | 273 if (strcmp(o->key, key) == 0) |
268 | 275 |
269 return NULL; | 276 return NULL; |
270 } | 277 } |
271 | 278 |
272 /* | 279 /* |
280 * These section provide very small API to convert value | |
281 * and store them to the dst pointer. Because you can also | |
282 * use your own handlers, the user data here can't be used. | |
283 */ | |
284 | |
285 void | |
286 ini_value_dispatch(struct ini_config *config, struct ini_handler *hdrs, int length) | |
287 { | |
288 const char *sectionName; | |
289 int i; | |
290 char *value; | |
291 struct ini_section *section; | |
292 | |
293 sectionName = NULL; | |
294 for (i = 0; i < length; ++i) { | |
295 /* Do not select the same section for performance. */ | |
296 if (sectionName == NULL || strcmp(hdrs[i].section, sectionName) != 0) { | |
297 sectionName = hdrs[i].section; | |
298 section = ini_select_section(config, hdrs[i].section); | |
299 } | |
300 | |
301 /* Skip the section if does not exists in the config */ | |
302 if (section == NULL) | |
303 continue; | |
304 | |
305 value = ini_get_option(section, hdrs[i].option); | |
306 hdrs[i].handler(hdrs[i].dst, value, hdrs[i].userdata); | |
307 } | |
308 } | |
309 | |
310 void | |
311 ini_convert_bool(void *dst, const char *value, void *dummy) | |
312 { | |
313 char *p = dst; | |
314 | |
315 if (value == NULL) | |
316 return ; | |
317 | |
318 if (strcmp(value, "yes") == 0 || | |
319 strcmp(value, "true") == 0 || | |
320 strcmp(value, "1") == 0) | |
321 *p = 1; | |
322 else | |
323 *p = 0; | |
324 (void)dummy; | |
325 } | |
326 | |
327 void | |
328 ini_convert_int(void *dst, const char *value, void *dummy) | |
329 { | |
330 int *p = dst; | |
331 | |
332 if (value == NULL) | |
333 return ; | |
334 | |
335 *p = (int) strtol(value, NULL, 10); | |
336 (void)dummy; | |
337 } | |
338 | |
339 void | |
340 ini_convert_short(void *dst, const char *value, void *dummy) | |
341 { | |
342 short *p = dst; | |
343 | |
344 if (value == NULL) | |
345 return ; | |
346 | |
347 *p = (short) strtol(value, NULL, 10); | |
348 (void)dummy; | |
349 } | |
350 | |
351 void | |
352 ini_convert_string(void *dst, const char *value, void *dummy) | |
353 { | |
354 char **p = dst; | |
355 | |
356 if (value == NULL) | |
357 *p = NULL; | |
358 else | |
359 *p = strdup(value); | |
360 | |
361 (void)dummy; | |
362 } | |
363 | |
364 /* | |
273 * Return the last error or "No error" if there is not error at all. | 365 * Return the last error or "No error" if there is not error at all. |
274 */ | 366 */ |
275 | 367 |
276 char * | 368 char * |
277 ini_error(void) | 369 ini_get_error(void) |
278 { | 370 { |
279 if (iniError[0] == '\0') | 371 if (ini_error[0] == '\0') |
280 return "No error"; | 372 return "No error"; |
281 | 373 |
282 return iniError; | 374 return ini_error; |
283 } | 375 } |
284 | 376 |
285 void | 377 void |
286 ini_free(struct ini_config *conf, int freeSections, int freeOptions) | 378 ini_free(struct ini_config *conf, int freeSections, int freeOptions) |
287 { | 379 { |
408 | 500 |
409 if (*lp == '[') | 501 if (*lp == '[') |
410 handler = &ini_switch; | 502 handler = &ini_switch; |
411 else if (!conf->ignore) | 503 else if (!conf->ignore) |
412 handler = &ini_register; | 504 handler = &ini_register; |
413 else | 505 else { |
414 handler = NULL; | 506 handler = NULL; |
507 ++ lp; | |
508 } | |
415 | 509 |
416 /* Success or not? */ | 510 /* Success or not? */ |
417 if (handler != NULL && handler(conf, &lp) < 0) | 511 if (handler != NULL && handler(conf, &lp) < 0) |
418 return (I_FAILERROR(conf)) ? NULL : conf; | 512 return (I_FAILERROR(conf)) ? NULL : conf; |
419 | 513 |
520 SKIP_SPACES(endValue); | 614 SKIP_SPACES(endValue); |
521 | 615 |
522 /* Find end of option value */ | 616 /* Find end of option value */ |
523 token = *endValue; | 617 token = *endValue; |
524 if (token == '\'' || token == '"') { | 618 if (token == '\'' || token == '"') { |
525 for (*lp = ++endValue; *endValue != token && *endValue != '\0'; ++endValue) | 619 for (*lp = ++endValue; *endValue != token && |
620 *endValue != '\0'; ++endValue) | |
526 continue; | 621 continue; |
527 | 622 |
528 length = endValue - *lp; | 623 length = endValue - *lp; |
529 | 624 |
530 /* Correctly closed */ | 625 /* Correctly closed */ |
531 if (token != '\0' && *endValue == token) | 626 if (token != '\0' && *endValue == token) |
532 ++ endValue; | 627 ++ endValue; |
533 else | 628 else |
534 WARN(conf, "line %d: missing '%c'\n", conf->lineno, token); | 629 WARN(conf, "line %d: missing '%c'\n", conf->lineno, token); |
535 } else { | 630 } else { |
536 for (*lp = endValue; !isspace(*endValue) && *endValue != '\0'; ++endValue) | 631 for (*lp = endValue; !isspace(*endValue) && *endValue != '\0' && |
632 *endValue != '#' && *endValue != ';'; ++endValue) | |
537 continue; | 633 continue; |
538 | 634 |
539 length = endValue - *lp; | 635 length = endValue - *lp; |
540 } | 636 } |
541 | 637 |
586 | 682 |
587 if (fp != NULL) | 683 if (fp != NULL) |
588 fclose(fp); | 684 fclose(fp); |
589 | 685 |
590 va_start(ap, fmt); | 686 va_start(ap, fmt); |
591 vsnprintf(iniError, 1024, fmt, ap); | 687 vsnprintf(ini_error, 1024, fmt, ap); |
592 va_end(ap); | 688 va_end(ap); |
593 | 689 |
594 /* Directly print error if VERBOSE is enabled */ | 690 /* Directly print error if VERBOSE is enabled */ |
595 WARN(conf, "%s\n", iniError); | 691 WARN(conf, "%s\n", ini_error); |
596 | 692 |
597 free(conf); | 693 free(conf); |
598 | 694 |
599 return NULL; | 695 return NULL; |
600 } | 696 } |