1 /* ----------------------------------------------------------------------------
2 libconfig - A library for processing structured configuration files
3 Copyright (C) 2005-2010 Mark A Lindner
5 This file is part of libconfig.
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with this library; if not, see
19 <http://www.gnu.org/licenses/>.
20 ----------------------------------------------------------------------------
24 #include "ac_config.h"
38 #include "libconfig.h"
42 #include "wincompat.h"
46 #define PATH_TOKENS ":./"
48 #define FLOAT_PRECISION DBL_DIG
50 #define _new(T) (T *)calloc(sizeof(T), 1) /* zeroed */
51 #define _delete(P) free((void *)(P))
53 /* ------------------------------------------------------------------------- */
55 #ifndef LIBCONFIG_STATIC
56 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
58 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
64 #endif /* LIBCONFIG_STATIC */
66 /* ------------------------------------------------------------------------- */
68 static const char *__io_error = "file I/O error";
70 static void __config_list_destroy(config_list_t *list);
71 static void __config_write_setting(const config_setting_t *setting,
72 FILE *stream, int depth,
73 unsigned short tab_width);
75 extern int libconfig_yyparse(void *scanner, struct parse_context *ctx,
76 struct scan_context *scan_ctx);
77 extern int libconfig_yylex_init_extra(struct scan_context *scan_ctx,
80 /* ------------------------------------------------------------------------- */
82 static void __config_locale_override(void)
84 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
85 && ! defined(__MINGW32__)
87 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
88 setlocale(LC_NUMERIC, "C");
90 #elif defined(__APPLE__)
92 locale_t loc = newlocale(LC_NUMERIC_MASK, "C", NULL);
95 #elif ((defined HAVE_NEWLOCALE) && (defined HAVE_USELOCALE))
97 locale_t loc = newlocale(LC_NUMERIC, "C", NULL);
102 #warning "No way to modify calling thread's locale!"
107 /* ------------------------------------------------------------------------- */
109 static void __config_locale_restore(void)
111 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
112 && ! defined(__MINGW32__)
114 _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
116 #elif ((defined HAVE_USELOCALE) && (defined HAVE_FREELOCALE))
118 locale_t loc = uselocale(LC_GLOBAL_LOCALE);
123 #warning "No way to modify calling thread's locale!"
128 /* ------------------------------------------------------------------------- */
130 static int __config_name_compare(const char *a, const char *b)
134 for(p = a, q = b; ; p++, q++)
136 int pd = ((! *p) || strchr(PATH_TOKENS, *p));
137 int qd = ((! *q) || strchr(PATH_TOKENS, *q));
154 /* ------------------------------------------------------------------------- */
156 static void __config_indent(FILE *stream, int depth, unsigned short w)
159 fprintf(stream, "%*s", (depth - 1) * w, " ");
163 for(i = 0; i < (depth - 1); ++i)
168 /* ------------------------------------------------------------------------- */
170 static void __config_write_value(const config_value_t *value, int type,
171 int format, int depth,
172 unsigned short tab_width, FILE *stream)
179 case CONFIG_TYPE_BOOL:
180 fputs(value->ival ? "true" : "false", stream);
184 case CONFIG_TYPE_INT:
187 case CONFIG_FORMAT_HEX:
188 fprintf(stream, "0x%X", value->ival);
191 case CONFIG_FORMAT_DEFAULT:
193 fprintf(stream, "%d", value->ival);
199 case CONFIG_TYPE_INT64:
202 case CONFIG_FORMAT_HEX:
203 fprintf(stream, "0x" INT64_HEX_FMT "L", value->llval);
206 case CONFIG_FORMAT_DEFAULT:
208 fprintf(stream, INT64_FMT "L", value->llval);
214 case CONFIG_TYPE_FLOAT:
218 snprintf(fbuf, sizeof(fbuf) - 3, "%.*g", FLOAT_PRECISION, value->fval);
220 /* check for exponent */
221 q = strchr(fbuf, 'e');
225 if(! strchr(fbuf, '.')) /* no decimal point */
229 /* has decimal point */
232 for(p = fbuf + strlen(fbuf) - 1; p > fbuf; --p)
248 case CONFIG_TYPE_STRING:
256 for(p = value->sval; *p; p++)
258 int c = (int)*p & 0xFF;
268 fputs("\\n", stream);
272 fputs("\\r", stream);
276 fputs("\\f", stream);
280 fputs("\\t", stream);
287 fprintf(stream, "\\x%02X", c);
296 case CONFIG_TYPE_LIST:
298 config_list_t *list = value->list;
300 fprintf(stream, "( ");
304 int len = list->length;
305 config_setting_t **s;
307 for(s = list->elements; len--; s++)
309 __config_write_value(&((*s)->value), (*s)->type,
310 config_setting_get_format(*s),
311 depth + 1, tab_width, stream);
325 case CONFIG_TYPE_ARRAY:
327 config_list_t *list = value->list;
329 fprintf(stream, "[ ");
333 int len = list->length;
334 config_setting_t **s;
336 for(s = list->elements; len--; s++)
338 __config_write_value(&((*s)->value), (*s)->type,
339 config_setting_get_format(*s),
340 depth + 1, tab_width, stream);
354 case CONFIG_TYPE_GROUP:
356 config_list_t *list = value->list;
360 #ifdef K_AND_R_STYLE /* Horrendous, but many people like it. */
366 __config_indent(stream, depth, tab_width);
368 fprintf(stream, "{\n");
373 int len = list->length;
374 config_setting_t **s;
376 for(s = list->elements; len--; s++)
377 __config_write_setting(*s, stream, depth + 1, tab_width);
381 __config_indent(stream, depth, tab_width);
390 /* this shouldn't happen, but handle it gracefully... */
391 fputs("???", stream);
396 /* ------------------------------------------------------------------------- */
398 static void __config_list_add(config_list_t *list, config_setting_t *setting)
400 if((list->length % CHUNK_SIZE) == 0)
402 list->elements = (config_setting_t **)realloc(
404 (list->length + CHUNK_SIZE) * sizeof(config_setting_t *));
407 list->elements[list->length] = setting;
411 /* ------------------------------------------------------------------------- */
413 static config_setting_t *__config_list_search(config_list_t *list,
417 config_setting_t **found = NULL;
423 for(i = 0, found = list->elements; i < list->length; i++, found++)
428 if(! __config_name_compare(name, (*found)->name))
440 /* ------------------------------------------------------------------------- */
442 static config_setting_t *__config_list_remove(config_list_t *list, int idx)
444 config_setting_t *removed = *(list->elements + idx);
445 int offset = (idx * sizeof(config_setting_t *));
446 int len = list->length - 1 - idx;
447 char *base = (char *)list->elements + offset;
449 memmove(base, base + sizeof(config_setting_t *),
450 len * sizeof(config_setting_t *));
454 /* possibly realloc smaller? */
459 /* ------------------------------------------------------------------------- */
461 static void __config_setting_destroy(config_setting_t *setting)
466 _delete(setting->name);
468 if(setting->type == CONFIG_TYPE_STRING)
469 _delete(setting->value.sval);
471 else if((setting->type == CONFIG_TYPE_GROUP)
472 || (setting->type == CONFIG_TYPE_ARRAY)
473 || (setting->type == CONFIG_TYPE_LIST))
475 if(setting->value.list)
476 __config_list_destroy(setting->value.list);
479 if(setting->hook && setting->config->destructor)
480 setting->config->destructor(setting->hook);
486 /* ------------------------------------------------------------------------- */
488 static void __config_list_destroy(config_list_t *list)
490 config_setting_t **p;
498 for(p = list->elements, i = 0; i < list->length; p++, i++)
499 __config_setting_destroy(*p);
501 _delete(list->elements);
507 /* ------------------------------------------------------------------------- */
509 static int __config_vector_checktype(const config_setting_t *vector, int type)
511 /* if the array is empty, then it has no type yet */
513 if(! vector->value.list)
516 if(vector->value.list->length == 0)
519 /* if it's a list, any type is allowed */
521 if(vector->type == CONFIG_TYPE_LIST)
524 /* otherwise the first element added determines the type of the array */
526 return((vector->value.list->elements[0]->type == type)
527 ? CONFIG_TRUE : CONFIG_FALSE);
530 /* ------------------------------------------------------------------------- */
532 static int __config_validate_name(const char *name)
534 const char *p = name;
537 return(CONFIG_FALSE);
539 if(! isalpha((int)*p) && (*p != '*'))
540 return(CONFIG_FALSE);
544 if(! (isalpha((int)*p) || isdigit((int)*p) || strchr("*_-", (int)*p)))
545 return(CONFIG_FALSE);
551 /* ------------------------------------------------------------------------- */
553 static int __config_read(config_t *config, FILE *stream, const char *filename,
557 struct scan_context scan_ctx;
558 struct parse_context parse_ctx;
561 /* Reinitialize the config */
562 void (*destructor)(void *) = config->destructor;
563 const char *include_dir = config->include_dir;
564 unsigned short tab_width = config->tab_width;
565 unsigned short flags = config->flags;
567 config->include_dir = NULL;
568 config_destroy(config);
571 config->destructor = destructor;
572 config->include_dir = include_dir;
573 config->tab_width = tab_width;
574 config->flags = flags;
576 parsectx_init(&parse_ctx);
577 parse_ctx.config = config;
578 parse_ctx.parent = config->root;
579 parse_ctx.setting = config->root;
581 __config_locale_override();
583 scanctx_init(&scan_ctx, filename);
584 config->root->file = scanctx_current_filename(&scan_ctx);
585 scan_ctx.config = config;
586 libconfig_yylex_init_extra(&scan_ctx, &scanner);
589 libconfig_yyrestart(stream, scanner);
590 else /* read from string */
591 (void)libconfig_yy_scan_string(str, scanner);
593 libconfig_yyset_lineno(1, scanner);
594 r = libconfig_yyparse(scanner, &parse_ctx, &scan_ctx);
600 config->error_file = scanctx_current_filename(&scan_ctx);
601 config->error_type = CONFIG_ERR_PARSE;
603 /* Unwind the include stack, freeing the buffers and closing the files. */
604 while((buf = (YY_BUFFER_STATE)scanctx_pop_include(&scan_ctx)) != NULL)
605 libconfig_yy_delete_buffer(buf, scanner);
608 libconfig_yylex_destroy(scanner);
609 config->filenames = scanctx_cleanup(&scan_ctx, &(config->num_filenames));
610 parsectx_cleanup(&parse_ctx);
612 __config_locale_restore();
614 return(r == 0 ? CONFIG_TRUE : CONFIG_FALSE);
617 /* ------------------------------------------------------------------------- */
619 int config_read(config_t *config, FILE *stream)
621 return(__config_read(config, stream, NULL, NULL));
624 /* ------------------------------------------------------------------------- */
626 int config_read_string(config_t *config, const char *str)
628 return(__config_read(config, NULL, NULL, str));
631 /* ------------------------------------------------------------------------- */
633 static void __config_write_setting(const config_setting_t *setting,
634 FILE *stream, int depth,
635 unsigned short tab_width)
638 __config_indent(stream, depth, tab_width);
642 fputs(setting->name, stream);
643 fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '='));
646 __config_write_value(&(setting->value), setting->type,
647 config_setting_get_format(setting),
648 depth, tab_width, stream);
657 /* ------------------------------------------------------------------------- */
659 void config_write(const config_t *config, FILE *stream)
661 __config_locale_override();
663 __config_write_setting(config->root, stream, 0, config->tab_width);
665 __config_locale_restore();
668 /* ------------------------------------------------------------------------- */
670 int config_read_file(config_t *config, const char *filename)
673 FILE *stream = fopen(filename, "rt");
676 config->error_text = __io_error;
677 config->error_type = CONFIG_ERR_FILE_IO;
678 return(CONFIG_FALSE);
681 ret = __config_read(config, stream, filename, NULL);
687 /* ------------------------------------------------------------------------- */
689 int config_write_file(config_t *config, const char *filename)
691 FILE *f = fopen(filename, "wt");
694 config->error_text = __io_error;
695 config->error_type = CONFIG_ERR_FILE_IO;
696 return(CONFIG_FALSE);
699 config_write(config, f);
701 config->error_type = CONFIG_ERR_NONE;
705 /* ------------------------------------------------------------------------- */
707 void config_destroy(config_t *config)
709 unsigned int count = config->num_filenames;
712 __config_setting_destroy(config->root);
714 for(f = config->filenames; count > 0; ++f, --count)
717 _delete(config->filenames);
718 _delete(config->include_dir);
720 memset((void *)config, 0, sizeof(config_t));
723 /* ------------------------------------------------------------------------- */
725 void config_init(config_t *config)
727 memset((void *)config, 0, sizeof(config_t));
729 config->root = _new(config_setting_t);
730 config->root->type = CONFIG_TYPE_GROUP;
731 config->root->config = config;
732 config->tab_width = 2;
735 /* ------------------------------------------------------------------------- */
737 void config_set_auto_convert(config_t *config, int flag)
740 config->flags |= CONFIG_OPTION_AUTOCONVERT;
742 config->flags &= ~CONFIG_OPTION_AUTOCONVERT;
745 /* ------------------------------------------------------------------------- */
747 int config_get_auto_convert(const config_t *config)
749 return((config->flags & CONFIG_OPTION_AUTOCONVERT) != 0);
752 /* ------------------------------------------------------------------------- */
754 static config_setting_t *config_setting_create(config_setting_t *parent,
755 const char *name, int type)
757 config_setting_t *setting;
760 if((parent->type != CONFIG_TYPE_GROUP)
761 && (parent->type != CONFIG_TYPE_ARRAY)
762 && (parent->type != CONFIG_TYPE_LIST))
765 setting = _new(config_setting_t);
766 setting->parent = parent;
767 setting->name = (name == NULL) ? NULL : strdup(name);
768 setting->type = type;
769 setting->config = parent->config;
770 setting->hook = NULL;
773 list = parent->value.list;
776 list = parent->value.list = _new(config_list_t);
778 __config_list_add(list, setting);
783 /* ------------------------------------------------------------------------- */
785 static int __config_setting_get_int(const config_setting_t *setting,
788 switch(setting->type)
790 case CONFIG_TYPE_INT:
791 *value = setting->value.ival;
794 case CONFIG_TYPE_INT64:
795 if((setting->value.llval > INT32_MAX)
796 || (setting->value.llval < INT32_MIN))
799 *value = (int)(setting->value.llval);
802 case CONFIG_TYPE_FLOAT:
803 if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
805 *value = (int)(setting->value.fval);
809 { /* fall through */ }
812 return(CONFIG_FALSE);
816 /* ------------------------------------------------------------------------- */
818 int config_setting_get_int(const config_setting_t *setting)
821 __config_setting_get_int(setting, &value);
825 /* ------------------------------------------------------------------------- */
827 static int __config_setting_get_int64(const config_setting_t *setting,
830 switch(setting->type)
832 case CONFIG_TYPE_INT64:
833 *value = setting->value.llval;
836 case CONFIG_TYPE_INT:
837 *value = (long long)(setting->value.ival);
840 case CONFIG_TYPE_FLOAT:
841 if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
843 *value = (long long)(setting->value.fval);
847 { /* fall through */ }
850 return(CONFIG_FALSE);
854 /* ------------------------------------------------------------------------- */
856 long long config_setting_get_int64(const config_setting_t *setting)
859 __config_setting_get_int64(setting, &value);
863 /* ------------------------------------------------------------------------- */
865 int config_setting_lookup_int(const config_setting_t *setting,
866 const char *name, int *value)
868 config_setting_t *member = config_setting_get_member(setting, name);
870 return(CONFIG_FALSE);
872 return(__config_setting_get_int(member, value));
875 /* ------------------------------------------------------------------------- */
877 int config_setting_lookup_int64(const config_setting_t *setting,
878 const char *name, long long *value)
880 config_setting_t *member = config_setting_get_member(setting, name);
882 return(CONFIG_FALSE);
884 return(__config_setting_get_int64(member, value));
887 /* ------------------------------------------------------------------------- */
889 static int __config_setting_get_float(const config_setting_t *setting,
892 switch(setting->type)
894 case CONFIG_TYPE_FLOAT:
895 *value = setting->value.fval;
898 case CONFIG_TYPE_INT:
899 if(config_get_auto_convert(setting->config))
901 *value = (double)(setting->value.ival);
905 return(CONFIG_FALSE);
907 case CONFIG_TYPE_INT64:
908 if(config_get_auto_convert(setting->config))
910 *value = (double)(setting->value.llval);
914 { /* fall through */ }
917 return(CONFIG_FALSE);
921 /* ------------------------------------------------------------------------- */
923 double config_setting_get_float(const config_setting_t *setting)
926 __config_setting_get_float(setting, &value);
930 /* ------------------------------------------------------------------------- */
932 int config_setting_lookup_float(const config_setting_t *setting,
933 const char *name, double *value)
935 config_setting_t *member = config_setting_get_member(setting, name);
937 return(CONFIG_FALSE);
939 return(__config_setting_get_float(member, value));
942 /* ------------------------------------------------------------------------- */
944 int config_setting_lookup_string(const config_setting_t *setting,
945 const char *name, const char **value)
947 config_setting_t *member = config_setting_get_member(setting, name);
949 return(CONFIG_FALSE);
951 if(config_setting_type(member) != CONFIG_TYPE_STRING)
952 return(CONFIG_FALSE);
954 *value = config_setting_get_string(member);
958 /* ------------------------------------------------------------------------- */
960 int config_setting_lookup_bool(const config_setting_t *setting,
961 const char *name, int *value)
963 config_setting_t *member = config_setting_get_member(setting, name);
965 return(CONFIG_FALSE);
967 if(config_setting_type(member) != CONFIG_TYPE_BOOL)
968 return(CONFIG_FALSE);
970 *value = config_setting_get_bool(member);
974 /* ------------------------------------------------------------------------- */
976 int config_setting_set_int(config_setting_t *setting, int value)
978 switch(setting->type)
980 case CONFIG_TYPE_NONE:
981 setting->type = CONFIG_TYPE_INT;
984 case CONFIG_TYPE_INT:
985 setting->value.ival = value;
988 case CONFIG_TYPE_FLOAT:
989 if(config_get_auto_convert(setting->config))
991 setting->value.fval = (float)value;
995 return(CONFIG_FALSE);
998 return(CONFIG_FALSE);
1002 /* ------------------------------------------------------------------------- */
1004 int config_setting_set_int64(config_setting_t *setting, long long value)
1006 switch(setting->type)
1008 case CONFIG_TYPE_NONE:
1009 setting->type = CONFIG_TYPE_INT64;
1012 case CONFIG_TYPE_INT64:
1013 setting->value.llval = value;
1014 return(CONFIG_TRUE);
1016 case CONFIG_TYPE_INT:
1017 if((value > INT32_MAX) || (value < INT32_MIN))
1018 setting->value.ival = 0;
1020 setting->value.ival = (int)value;
1021 return(CONFIG_TRUE);
1023 case CONFIG_TYPE_FLOAT:
1024 if(config_get_auto_convert(setting->config))
1026 setting->value.fval = (float)value;
1027 return(CONFIG_TRUE);
1030 return(CONFIG_FALSE);
1033 return(CONFIG_FALSE);
1037 /* ------------------------------------------------------------------------- */
1039 int config_setting_set_float(config_setting_t *setting, double value)
1041 switch(setting->type)
1043 case CONFIG_TYPE_NONE:
1044 setting->type = CONFIG_TYPE_FLOAT;
1047 case CONFIG_TYPE_FLOAT:
1048 setting->value.fval = value;
1049 return(CONFIG_TRUE);
1051 case CONFIG_TYPE_INT:
1052 if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
1054 setting->value.ival = (int)value;
1055 return(CONFIG_TRUE);
1058 return(CONFIG_FALSE);
1060 case CONFIG_TYPE_INT64:
1061 if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
1063 setting->value.llval = (long long)value;
1064 return(CONFIG_TRUE);
1067 return(CONFIG_FALSE);
1070 return(CONFIG_FALSE);
1074 /* ------------------------------------------------------------------------- */
1076 int config_setting_get_bool(const config_setting_t *setting)
1078 return((setting->type == CONFIG_TYPE_BOOL) ? setting->value.ival : 0);
1081 /* ------------------------------------------------------------------------- */
1083 int config_setting_set_bool(config_setting_t *setting, int value)
1085 if(setting->type == CONFIG_TYPE_NONE)
1086 setting->type = CONFIG_TYPE_BOOL;
1087 else if(setting->type != CONFIG_TYPE_BOOL)
1088 return(CONFIG_FALSE);
1090 setting->value.ival = value;
1091 return(CONFIG_TRUE);
1094 /* ------------------------------------------------------------------------- */
1096 const char *config_setting_get_string(const config_setting_t *setting)
1098 return((setting->type == CONFIG_TYPE_STRING) ? setting->value.sval : NULL);
1101 /* ------------------------------------------------------------------------- */
1103 int config_setting_set_string(config_setting_t *setting, const char *value)
1105 if(setting->type == CONFIG_TYPE_NONE)
1106 setting->type = CONFIG_TYPE_STRING;
1107 else if(setting->type != CONFIG_TYPE_STRING)
1108 return(CONFIG_FALSE);
1110 if(setting->value.sval)
1111 _delete(setting->value.sval);
1113 setting->value.sval = (value == NULL) ? NULL : strdup(value);
1114 return(CONFIG_TRUE);
1117 /* ------------------------------------------------------------------------- */
1119 int config_setting_set_format(config_setting_t *setting, short format)
1121 if(((setting->type != CONFIG_TYPE_INT)
1122 && (setting->type != CONFIG_TYPE_INT64))
1123 || ((format != CONFIG_FORMAT_DEFAULT) && (format != CONFIG_FORMAT_HEX)))
1124 return(CONFIG_FALSE);
1126 setting->format = format;
1128 return(CONFIG_TRUE);
1131 /* ------------------------------------------------------------------------- */
1133 short config_setting_get_format(const config_setting_t *setting)
1135 return(setting->format != 0 ? setting->format
1136 : setting->config->default_format);
1139 /* ------------------------------------------------------------------------- */
1141 config_setting_t *config_setting_lookup(config_setting_t *setting,
1144 const char *p = path;
1145 config_setting_t *found;
1149 while(*p && strchr(PATH_TOKENS, *p))
1156 found = config_setting_get_elem(setting, atoi(++p));
1158 found = config_setting_get_member(setting, p);
1165 while(! strchr(PATH_TOKENS, *p))
1169 return(*p ? NULL : setting);
1172 /* ------------------------------------------------------------------------- */
1174 config_setting_t *config_lookup(const config_t *config, const char *path)
1176 return(config_setting_lookup(config->root, path));
1179 /* ------------------------------------------------------------------------- */
1181 int config_lookup_string(const config_t *config, const char *path,
1184 const config_setting_t *s = config_lookup(config, path);
1186 return(CONFIG_FALSE);
1188 if(config_setting_type(s) != CONFIG_TYPE_STRING)
1189 return(CONFIG_FALSE);
1191 *value = config_setting_get_string(s);
1193 return(CONFIG_TRUE);
1196 /* ------------------------------------------------------------------------- */
1198 int config_lookup_int(const config_t *config, const char *path,
1201 const config_setting_t *s = config_lookup(config, path);
1203 return(CONFIG_FALSE);
1205 return(__config_setting_get_int(s, value));
1208 /* ------------------------------------------------------------------------- */
1210 int config_lookup_int64(const config_t *config, const char *path,
1213 const config_setting_t *s = config_lookup(config, path);
1215 return(CONFIG_FALSE);
1217 return(__config_setting_get_int64(s, value));
1220 /* ------------------------------------------------------------------------- */
1222 int config_lookup_float(const config_t *config, const char *path,
1225 const config_setting_t *s = config_lookup(config, path);
1227 return(CONFIG_FALSE);
1229 return(__config_setting_get_float(s, value));
1232 /* ------------------------------------------------------------------------- */
1234 int config_lookup_bool(const config_t *config, const char *path, int *value)
1236 const config_setting_t *s = config_lookup(config, path);
1238 return(CONFIG_FALSE);
1240 if(config_setting_type(s) != CONFIG_TYPE_BOOL)
1241 return(CONFIG_FALSE);
1243 *value = config_setting_get_bool(s);
1244 return(CONFIG_TRUE);
1247 /* ------------------------------------------------------------------------- */
1249 int config_setting_get_int_elem(const config_setting_t *vector, int idx)
1251 const config_setting_t *element = config_setting_get_elem(vector, idx);
1253 return(element ? config_setting_get_int(element) : 0);
1256 /* ------------------------------------------------------------------------- */
1258 config_setting_t *config_setting_set_int_elem(config_setting_t *vector,
1261 config_setting_t *element = NULL;
1263 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1268 if(! __config_vector_checktype(vector, CONFIG_TYPE_INT))
1271 element = config_setting_create(vector, NULL, CONFIG_TYPE_INT);
1275 element = config_setting_get_elem(vector, idx);
1281 if(! config_setting_set_int(element, value))
1287 /* ------------------------------------------------------------------------- */
1289 long long config_setting_get_int64_elem(const config_setting_t *vector,
1292 const config_setting_t *element = config_setting_get_elem(vector, idx);
1294 return(element ? config_setting_get_int64(element) : 0);
1297 /* ------------------------------------------------------------------------- */
1299 config_setting_t *config_setting_set_int64_elem(config_setting_t *vector,
1300 int idx, long long value)
1302 config_setting_t *element = NULL;
1304 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1309 if(! __config_vector_checktype(vector, CONFIG_TYPE_INT64))
1312 element = config_setting_create(vector, NULL, CONFIG_TYPE_INT64);
1316 element = config_setting_get_elem(vector, idx);
1322 if(! config_setting_set_int64(element, value))
1328 /* ------------------------------------------------------------------------- */
1330 double config_setting_get_float_elem(const config_setting_t *vector, int idx)
1332 config_setting_t *element = config_setting_get_elem(vector, idx);
1334 return(element ? config_setting_get_float(element) : 0.0);
1337 /* ------------------------------------------------------------------------- */
1339 config_setting_t *config_setting_set_float_elem(config_setting_t *vector,
1340 int idx, double value)
1342 config_setting_t *element = NULL;
1344 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1349 if(! __config_vector_checktype(vector, CONFIG_TYPE_FLOAT))
1352 element = config_setting_create(vector, NULL, CONFIG_TYPE_FLOAT);
1355 element = config_setting_get_elem(vector, idx);
1360 if(! config_setting_set_float(element, value))
1366 /* ------------------------------------------------------------------------- */
1368 int config_setting_get_bool_elem(const config_setting_t *vector, int idx)
1370 config_setting_t *element = config_setting_get_elem(vector, idx);
1373 return(CONFIG_FALSE);
1375 if(element->type != CONFIG_TYPE_BOOL)
1376 return(CONFIG_FALSE);
1378 return(element->value.ival);
1381 /* ------------------------------------------------------------------------- */
1383 config_setting_t *config_setting_set_bool_elem(config_setting_t *vector,
1386 config_setting_t *element = NULL;
1388 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1393 if(! __config_vector_checktype(vector, CONFIG_TYPE_BOOL))
1396 element = config_setting_create(vector, NULL, CONFIG_TYPE_BOOL);
1399 element = config_setting_get_elem(vector, idx);
1404 if(! config_setting_set_bool(element, value))
1410 /* ------------------------------------------------------------------------- */
1412 const char *config_setting_get_string_elem(const config_setting_t *vector,
1415 config_setting_t *element = config_setting_get_elem(vector, idx);
1420 if(element->type != CONFIG_TYPE_STRING)
1423 return(element->value.sval);
1426 /* ------------------------------------------------------------------------- */
1428 config_setting_t *config_setting_set_string_elem(config_setting_t *vector,
1429 int idx, const char *value)
1431 config_setting_t *element = NULL;
1433 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1438 if(! __config_vector_checktype(vector, CONFIG_TYPE_STRING))
1441 element = config_setting_create(vector, NULL, CONFIG_TYPE_STRING);
1444 element = config_setting_get_elem(vector, idx);
1449 if(! config_setting_set_string(element, value))
1455 /* ------------------------------------------------------------------------- */
1457 config_setting_t *config_setting_get_elem(const config_setting_t *vector,
1460 config_list_t *list = vector->value.list;
1462 if(((vector->type != CONFIG_TYPE_ARRAY)
1463 && (vector->type != CONFIG_TYPE_LIST)
1464 && (vector->type != CONFIG_TYPE_GROUP)) || ! list)
1467 if(idx >= list->length)
1470 return(list->elements[idx]);
1473 /* ------------------------------------------------------------------------- */
1475 config_setting_t *config_setting_get_member(const config_setting_t *setting,
1478 if(setting->type != CONFIG_TYPE_GROUP)
1481 return(__config_list_search(setting->value.list, name, NULL));
1484 /* ------------------------------------------------------------------------- */
1486 void config_set_destructor(config_t *config, void (*destructor)(void *))
1488 config->destructor = destructor;
1491 /* ------------------------------------------------------------------------- */
1493 void config_set_include_dir(config_t *config, const char *include_dir)
1495 _delete(config->include_dir);
1496 config->include_dir = strdup(include_dir);
1499 /* ------------------------------------------------------------------------- */
1501 int config_setting_length(const config_setting_t *setting)
1503 if((setting->type != CONFIG_TYPE_GROUP)
1504 && (setting->type != CONFIG_TYPE_ARRAY)
1505 && (setting->type != CONFIG_TYPE_LIST))
1508 if(! setting->value.list)
1511 return(setting->value.list->length);
1514 /* ------------------------------------------------------------------------- */
1516 void config_setting_set_hook(config_setting_t *setting, void *hook)
1518 setting->hook = hook;
1521 /* ------------------------------------------------------------------------- */
1523 config_setting_t *config_setting_add(config_setting_t *parent,
1524 const char *name, int type)
1526 if((type < CONFIG_TYPE_NONE) || (type > CONFIG_TYPE_LIST))
1532 if((parent->type == CONFIG_TYPE_ARRAY) || (parent->type == CONFIG_TYPE_LIST))
1537 if(! __config_validate_name(name))
1541 if(config_setting_get_member(parent, name) != NULL)
1542 return(NULL); /* already exists */
1544 return(config_setting_create(parent, name, type));
1547 /* ------------------------------------------------------------------------- */
1549 int config_setting_remove(config_setting_t *parent, const char *name)
1552 config_setting_t *setting;
1555 return(CONFIG_FALSE);
1557 if(parent->type != CONFIG_TYPE_GROUP)
1558 return(CONFIG_FALSE);
1560 if(! (setting = __config_list_search(parent->value.list, name, &idx)))
1561 return(CONFIG_FALSE);
1563 __config_list_remove(parent->value.list, idx);
1564 __config_setting_destroy(setting);
1566 return(CONFIG_TRUE);
1569 /* ------------------------------------------------------------------------- */
1571 int config_setting_remove_elem(config_setting_t *parent, unsigned int idx)
1573 config_list_t *list;
1574 config_setting_t *removed = NULL;
1577 return(CONFIG_FALSE);
1579 list = parent->value.list;
1581 if(((parent->type != CONFIG_TYPE_ARRAY)
1582 && (parent->type != CONFIG_TYPE_LIST)
1583 && (parent->type != CONFIG_TYPE_GROUP)) || ! list)
1584 return(CONFIG_FALSE);
1586 if(idx >= list->length)
1587 return(CONFIG_FALSE);
1589 removed = __config_list_remove(list, idx);
1590 __config_setting_destroy(removed);
1592 return(CONFIG_TRUE);
1595 /* ------------------------------------------------------------------------- */
1597 int config_setting_index(const config_setting_t *setting)
1599 config_setting_t **found = NULL;
1600 config_list_t *list;
1603 if(! setting->parent)
1606 list = setting->parent->value.list;
1608 for(i = 0, found = list->elements; i < (int)list->length; ++i, ++found)
1610 if(*found == setting)
1617 /* ------------------------------------------------------------------------- */