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"
27 #include "libconfig.h"
32 #include "wincompat.h"
44 #define PATH_TOKENS ":./"
46 #define FLOAT_PRECISION 10
48 #define _new(T) (T *)calloc(sizeof(T), 1) /* zeroed */
49 #define _delete(P) free((void *)(P))
51 /* ------------------------------------------------------------------------- */
53 #ifndef LIBCONFIG_STATIC
54 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
56 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
62 #endif /* LIBCONFIG_STATIC */
64 /* ------------------------------------------------------------------------- */
66 static const char *__io_error = "file I/O error";
68 static void __config_list_destroy(config_list_t *list);
69 static void __config_write_setting(const config_setting_t *setting,
70 FILE *stream, int depth,
71 unsigned short tab_width);
73 extern int libconfig_yyparse(void *scanner, struct parse_context *ctx,
74 struct scan_context *scan_ctx);
75 extern int libconfig_yylex_init_extra(struct scan_context *scan_ctx,
78 /* ------------------------------------------------------------------------- */
80 static void __config_locale_override(void)
82 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
83 && ! defined(__MINGW32__)
85 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
86 setlocale(LC_NUMERIC, "C");
88 #elif defined(__APPLE__)
90 locale_t loc = newlocale(LC_NUMERIC_MASK, "C", NULL);
93 #elif ((defined HAVE_NEWLOCALE) && (defined HAVE_USELOCALE))
95 locale_t loc = newlocale(LC_NUMERIC, "C", NULL);
100 /* locale overriding is pretty pointless (rathena doesn't make use of the area that uses locale functionality), but I'm actually removing it because it floods the buildbot with warnings */
101 //#warning "No way to modify calling thread's locale!"
106 /* ------------------------------------------------------------------------- */
108 static void __config_locale_restore(void)
110 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
111 && ! defined(__MINGW32__)
113 _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
115 #elif ((defined HAVE_USELOCALE) && (defined HAVE_FREELOCALE))
117 locale_t loc = uselocale(LC_GLOBAL_LOCALE);
122 /* locale overriding is pretty pointless (rathena doesn't make use of the area that uses locale functionality), but I'm actually removing it because it floods the buildbot with warnings */
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;
559 // YY_BUFFER_STATE buffer = NULL;
562 /* Reinitialize the config */
563 void (*destructor)(void *) = config->destructor;
564 const char *include_dir = config->include_dir;
565 unsigned short tab_width = config->tab_width;
566 unsigned short flags = config->flags;
568 config->include_dir = NULL;
569 config_destroy(config);
572 config->destructor = destructor;
573 config->include_dir = include_dir;
574 config->tab_width = tab_width;
575 config->flags = flags;
577 parsectx_init(&parse_ctx);
578 parse_ctx.config = config;
579 parse_ctx.parent = config->root;
580 parse_ctx.setting = config->root;
582 __config_locale_override();
584 scanctx_init(&scan_ctx, filename);
585 scan_ctx.config = config;
586 libconfig_yylex_init_extra(&scan_ctx, &scanner);
589 libconfig_yyrestart(stream, scanner);
590 else /* read from string */
592 libconfig_yy_scan_string(str, scanner);
594 libconfig_yyset_lineno(1, scanner);
595 r = libconfig_yyparse(scanner, &parse_ctx, &scan_ctx);
601 config->error_file = scanctx_current_filename(&scan_ctx);
602 config->error_type = CONFIG_ERR_PARSE;
604 /* Unwind the include stack, freeing the buffers and closing the files. */
605 while((buf = (YY_BUFFER_STATE)scanctx_pop_include(&scan_ctx)) != NULL)
606 libconfig_yy_delete_buffer(buf, scanner);
609 libconfig_yylex_destroy(scanner);
610 config->filenames = scanctx_cleanup(&scan_ctx, &(config->num_filenames));
611 parsectx_cleanup(&parse_ctx);
613 __config_locale_restore();
615 return(r == 0 ? CONFIG_TRUE : CONFIG_FALSE);
618 /* ------------------------------------------------------------------------- */
620 int config_read(config_t *config, FILE *stream)
622 return(__config_read(config, stream, NULL, NULL));
625 /* ------------------------------------------------------------------------- */
627 int config_read_string(config_t *config, const char *str)
629 return(__config_read(config, NULL, NULL, str));
632 /* ------------------------------------------------------------------------- */
634 static void __config_write_setting(const config_setting_t *setting,
635 FILE *stream, int depth,
636 unsigned short tab_width)
639 __config_indent(stream, depth, tab_width);
643 fputs(setting->name, stream);
644 fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '='));
647 __config_write_value(&(setting->value), setting->type,
648 config_setting_get_format(setting),
649 depth, tab_width, stream);
658 /* ------------------------------------------------------------------------- */
660 void config_write(const config_t *config, FILE *stream)
662 __config_locale_override();
664 __config_write_setting(config->root, stream, 0, config->tab_width);
666 __config_locale_restore();
669 /* ------------------------------------------------------------------------- */
671 int config_read_file(config_t *config, const char *filename)
674 FILE *stream = fopen(filename, "rt");
677 config->error_text = __io_error;
678 config->error_type = CONFIG_ERR_FILE_IO;
679 return(CONFIG_FALSE);
682 ret = __config_read(config, stream, filename, NULL);
688 /* ------------------------------------------------------------------------- */
690 int config_write_file(config_t *config, const char *filename)
692 FILE *f = fopen(filename, "wt");
695 config->error_text = __io_error;
696 config->error_type = CONFIG_ERR_FILE_IO;
697 return(CONFIG_FALSE);
700 config_write(config, f);
702 config->error_type = CONFIG_ERR_NONE;
706 /* ------------------------------------------------------------------------- */
708 void config_destroy(config_t *config)
710 unsigned int count = config->num_filenames;
713 __config_setting_destroy(config->root);
715 for(f = config->filenames; count > 0; ++f, --count)
718 _delete(config->filenames);
719 _delete(config->include_dir);
721 memset((void *)config, 0, sizeof(config_t));
724 /* ------------------------------------------------------------------------- */
726 void config_init(config_t *config)
728 memset((void *)config, 0, sizeof(config_t));
730 config->root = _new(config_setting_t);
731 config->root->type = CONFIG_TYPE_GROUP;
732 config->root->config = config;
733 config->tab_width = 2;
736 /* ------------------------------------------------------------------------- */
738 void config_set_auto_convert(config_t *config, int flag)
741 config->flags |= CONFIG_OPTION_AUTOCONVERT;
743 config->flags &= ~CONFIG_OPTION_AUTOCONVERT;
746 /* ------------------------------------------------------------------------- */
748 int config_get_auto_convert(const config_t *config)
750 return((config->flags & CONFIG_OPTION_AUTOCONVERT) != 0);
753 /* ------------------------------------------------------------------------- */
755 static config_setting_t *config_setting_create(config_setting_t *parent,
756 const char *name, int type)
758 config_setting_t *setting;
761 if((parent->type != CONFIG_TYPE_GROUP)
762 && (parent->type != CONFIG_TYPE_ARRAY)
763 && (parent->type != CONFIG_TYPE_LIST))
766 setting = _new(config_setting_t);
767 setting->parent = parent;
768 setting->name = (name == NULL) ? NULL : strdup(name);
769 setting->type = type;
770 setting->config = parent->config;
771 setting->hook = NULL;
774 list = parent->value.list;
777 list = parent->value.list = _new(config_list_t);
779 __config_list_add(list, setting);
784 /* ------------------------------------------------------------------------- */
786 static int __config_setting_get_int(const config_setting_t *setting,
789 switch(setting->type)
791 case CONFIG_TYPE_INT:
792 *value = setting->value.ival;
795 case CONFIG_TYPE_INT64:
796 if((setting->value.llval > INT32_MAX)
797 || (setting->value.llval < INT32_MIN))
800 *value = (int)(setting->value.llval);
803 case CONFIG_TYPE_FLOAT:
804 if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
806 *value = (int)(setting->value.fval);
810 { /* fall through */ }
813 return(CONFIG_FALSE);
817 /* ------------------------------------------------------------------------- */
819 int config_setting_get_int(const config_setting_t *setting)
822 __config_setting_get_int(setting, &value);
826 /* ------------------------------------------------------------------------- */
828 static int __config_setting_get_int64(const config_setting_t *setting,
831 switch(setting->type)
833 case CONFIG_TYPE_INT64:
834 *value = setting->value.llval;
837 case CONFIG_TYPE_INT:
838 *value = (long long)(setting->value.ival);
841 case CONFIG_TYPE_FLOAT:
842 if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
844 *value = (long long)(setting->value.fval);
848 { /* fall through */ }
851 return(CONFIG_FALSE);
855 /* ------------------------------------------------------------------------- */
857 long long config_setting_get_int64(const config_setting_t *setting)
860 __config_setting_get_int64(setting, &value);
864 /* ------------------------------------------------------------------------- */
866 int config_setting_lookup_int(const config_setting_t *setting,
867 const char *name, int *value)
869 config_setting_t *member = config_setting_get_member(setting, name);
871 return(CONFIG_FALSE);
873 return(__config_setting_get_int(member, value));
876 /* ------------------------------------------------------------------------- */
878 int config_setting_lookup_int64(const config_setting_t *setting,
879 const char *name, long long *value)
881 config_setting_t *member = config_setting_get_member(setting, name);
883 return(CONFIG_FALSE);
885 return(__config_setting_get_int64(member, value));
888 /* ------------------------------------------------------------------------- */
890 static int __config_setting_get_float(const config_setting_t *setting,
893 switch(setting->type)
895 case CONFIG_TYPE_FLOAT:
896 *value = setting->value.fval;
899 case CONFIG_TYPE_INT:
900 if(config_get_auto_convert(setting->config))
902 *value = (double)(setting->value.ival);
906 return(CONFIG_FALSE);
908 case CONFIG_TYPE_INT64:
909 if(config_get_auto_convert(setting->config))
911 *value = (double)(setting->value.llval);
915 { /* fall through */ }
918 return(CONFIG_FALSE);
922 /* ------------------------------------------------------------------------- */
924 double config_setting_get_float(const config_setting_t *setting)
927 __config_setting_get_float(setting, &value);
931 /* ------------------------------------------------------------------------- */
933 int config_setting_lookup_float(const config_setting_t *setting,
934 const char *name, double *value)
936 config_setting_t *member = config_setting_get_member(setting, name);
938 return(CONFIG_FALSE);
940 return(__config_setting_get_float(member, value));
943 /* ------------------------------------------------------------------------- */
945 int config_setting_lookup_string(const config_setting_t *setting,
946 const char *name, const char **value)
948 config_setting_t *member = config_setting_get_member(setting, name);
950 return(CONFIG_FALSE);
952 if(config_setting_type(member) != CONFIG_TYPE_STRING)
953 return(CONFIG_FALSE);
955 *value = config_setting_get_string(member);
959 /* ------------------------------------------------------------------------- */
961 int config_setting_lookup_bool(const config_setting_t *setting,
962 const char *name, int *value)
964 config_setting_t *member = config_setting_get_member(setting, name);
966 return(CONFIG_FALSE);
968 if(config_setting_type(member) != CONFIG_TYPE_BOOL)
969 return(CONFIG_FALSE);
971 *value = config_setting_get_bool(member);
975 /* ------------------------------------------------------------------------- */
977 int config_setting_set_int(config_setting_t *setting, int value)
979 switch(setting->type)
981 case CONFIG_TYPE_NONE:
982 setting->type = CONFIG_TYPE_INT;
985 case CONFIG_TYPE_INT:
986 setting->value.ival = value;
989 case CONFIG_TYPE_FLOAT:
990 if(config_get_auto_convert(setting->config))
992 setting->value.fval = (float)value;
996 return(CONFIG_FALSE);
999 return(CONFIG_FALSE);
1003 /* ------------------------------------------------------------------------- */
1005 int config_setting_set_int64(config_setting_t *setting, long long value)
1007 switch(setting->type)
1009 case CONFIG_TYPE_NONE:
1010 setting->type = CONFIG_TYPE_INT64;
1013 case CONFIG_TYPE_INT64:
1014 setting->value.llval = value;
1015 return(CONFIG_TRUE);
1017 case CONFIG_TYPE_INT:
1018 if((value > INT32_MAX) || (value < INT32_MIN))
1019 setting->value.ival = 0;
1021 setting->value.ival = (int)value;
1022 return(CONFIG_TRUE);
1024 case CONFIG_TYPE_FLOAT:
1025 if(config_get_auto_convert(setting->config))
1027 setting->value.fval = (float)value;
1028 return(CONFIG_TRUE);
1031 return(CONFIG_FALSE);
1034 return(CONFIG_FALSE);
1038 /* ------------------------------------------------------------------------- */
1040 int config_setting_set_float(config_setting_t *setting, double value)
1042 switch(setting->type)
1044 case CONFIG_TYPE_NONE:
1045 setting->type = CONFIG_TYPE_FLOAT;
1048 case CONFIG_TYPE_FLOAT:
1049 setting->value.fval = value;
1050 return(CONFIG_TRUE);
1052 case CONFIG_TYPE_INT:
1053 if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
1055 setting->value.ival = (int)value;
1056 return(CONFIG_TRUE);
1059 return(CONFIG_FALSE);
1061 case CONFIG_TYPE_INT64:
1062 if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
1064 setting->value.llval = (long long)value;
1065 return(CONFIG_TRUE);
1068 return(CONFIG_FALSE);
1071 return(CONFIG_FALSE);
1075 /* ------------------------------------------------------------------------- */
1077 int config_setting_get_bool(const config_setting_t *setting)
1079 return((setting->type == CONFIG_TYPE_BOOL) ? setting->value.ival : 0);
1082 /* ------------------------------------------------------------------------- */
1084 int config_setting_set_bool(config_setting_t *setting, int value)
1086 if(setting->type == CONFIG_TYPE_NONE)
1087 setting->type = CONFIG_TYPE_BOOL;
1088 else if(setting->type != CONFIG_TYPE_BOOL)
1089 return(CONFIG_FALSE);
1091 setting->value.ival = value;
1092 return(CONFIG_TRUE);
1095 /* ------------------------------------------------------------------------- */
1097 const char *config_setting_get_string(const config_setting_t *setting)
1099 return((setting->type == CONFIG_TYPE_STRING) ? setting->value.sval : NULL);
1102 /* ------------------------------------------------------------------------- */
1104 int config_setting_set_string(config_setting_t *setting, const char *value)
1106 if(setting->type == CONFIG_TYPE_NONE)
1107 setting->type = CONFIG_TYPE_STRING;
1108 else if(setting->type != CONFIG_TYPE_STRING)
1109 return(CONFIG_FALSE);
1111 if(setting->value.sval)
1112 _delete(setting->value.sval);
1114 setting->value.sval = (value == NULL) ? NULL : strdup(value);
1115 return(CONFIG_TRUE);
1118 /* ------------------------------------------------------------------------- */
1120 int config_setting_set_format(config_setting_t *setting, short format)
1122 if(((setting->type != CONFIG_TYPE_INT)
1123 && (setting->type != CONFIG_TYPE_INT64))
1124 || ((format != CONFIG_FORMAT_DEFAULT) && (format != CONFIG_FORMAT_HEX)))
1125 return(CONFIG_FALSE);
1127 setting->format = format;
1129 return(CONFIG_TRUE);
1132 /* ------------------------------------------------------------------------- */
1134 short config_setting_get_format(const config_setting_t *setting)
1136 return(setting->format != 0 ? setting->format
1137 : setting->config->default_format);
1140 /* ------------------------------------------------------------------------- */
1142 config_setting_t *config_lookup_from(config_setting_t *setting,
1145 const char *p = path;
1146 config_setting_t *found;
1150 while(*p && strchr(PATH_TOKENS, *p))
1157 found = config_setting_get_elem(setting, atoi(++p));
1159 found = config_setting_get_member(setting, p);
1166 while(! strchr(PATH_TOKENS, *p))
1170 return(*p ? NULL : setting);
1173 /* ------------------------------------------------------------------------- */
1175 config_setting_t *config_lookup(const config_t *config, const char *path)
1177 return(config_lookup_from(config->root, path));
1180 /* ------------------------------------------------------------------------- */
1182 int config_lookup_string(const config_t *config, const char *path,
1185 const config_setting_t *s = config_lookup(config, path);
1187 return(CONFIG_FALSE);
1189 if(config_setting_type(s) != CONFIG_TYPE_STRING)
1190 return(CONFIG_FALSE);
1192 *value = config_setting_get_string(s);
1194 return(CONFIG_TRUE);
1197 /* ------------------------------------------------------------------------- */
1199 int config_lookup_int(const config_t *config, const char *path,
1202 const config_setting_t *s = config_lookup(config, path);
1204 return(CONFIG_FALSE);
1206 return(__config_setting_get_int(s, value));
1209 /* ------------------------------------------------------------------------- */
1211 int config_lookup_int64(const config_t *config, const char *path,
1214 const config_setting_t *s = config_lookup(config, path);
1216 return(CONFIG_FALSE);
1218 return(__config_setting_get_int64(s, value));
1221 /* ------------------------------------------------------------------------- */
1223 int config_lookup_float(const config_t *config, const char *path,
1226 const config_setting_t *s = config_lookup(config, path);
1228 return(CONFIG_FALSE);
1230 return(__config_setting_get_float(s, value));
1233 /* ------------------------------------------------------------------------- */
1235 int config_lookup_bool(const config_t *config, const char *path, int *value)
1237 const config_setting_t *s = config_lookup(config, path);
1239 return(CONFIG_FALSE);
1241 if(config_setting_type(s) != CONFIG_TYPE_BOOL)
1242 return(CONFIG_FALSE);
1244 *value = config_setting_get_bool(s);
1245 return(CONFIG_TRUE);
1248 /* ------------------------------------------------------------------------- */
1250 int config_setting_get_int_elem(const config_setting_t *vector, int idx)
1252 const config_setting_t *element = config_setting_get_elem(vector, idx);
1254 return(element ? config_setting_get_int(element) : 0);
1257 /* ------------------------------------------------------------------------- */
1259 config_setting_t *config_setting_set_int_elem(config_setting_t *vector,
1262 config_setting_t *element = NULL;
1264 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1269 if(! __config_vector_checktype(vector, CONFIG_TYPE_INT))
1272 element = config_setting_create(vector, NULL, CONFIG_TYPE_INT);
1276 element = config_setting_get_elem(vector, idx);
1282 if(! config_setting_set_int(element, value))
1288 /* ------------------------------------------------------------------------- */
1290 long long config_setting_get_int64_elem(const config_setting_t *vector,
1293 const config_setting_t *element = config_setting_get_elem(vector, idx);
1295 return(element ? config_setting_get_int64(element) : 0);
1298 /* ------------------------------------------------------------------------- */
1300 config_setting_t *config_setting_set_int64_elem(config_setting_t *vector,
1301 int idx, long long value)
1303 config_setting_t *element = NULL;
1305 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1310 if(! __config_vector_checktype(vector, CONFIG_TYPE_INT64))
1313 element = config_setting_create(vector, NULL, CONFIG_TYPE_INT64);
1317 element = config_setting_get_elem(vector, idx);
1323 if(! config_setting_set_int64(element, value))
1329 /* ------------------------------------------------------------------------- */
1331 double config_setting_get_float_elem(const config_setting_t *vector, int idx)
1333 config_setting_t *element = config_setting_get_elem(vector, idx);
1335 return(element ? config_setting_get_float(element) : 0.0);
1338 /* ------------------------------------------------------------------------- */
1340 config_setting_t *config_setting_set_float_elem(config_setting_t *vector,
1341 int idx, double value)
1343 config_setting_t *element = NULL;
1345 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1350 if(! __config_vector_checktype(vector, CONFIG_TYPE_FLOAT))
1353 element = config_setting_create(vector, NULL, CONFIG_TYPE_FLOAT);
1356 element = config_setting_get_elem(vector, idx);
1361 if(! config_setting_set_float(element, value))
1367 /* ------------------------------------------------------------------------- */
1369 int config_setting_get_bool_elem(const config_setting_t *vector, int idx)
1371 config_setting_t *element = config_setting_get_elem(vector, idx);
1374 return(CONFIG_FALSE);
1376 if(element->type != CONFIG_TYPE_BOOL)
1377 return(CONFIG_FALSE);
1379 return(element->value.ival);
1382 /* ------------------------------------------------------------------------- */
1384 config_setting_t *config_setting_set_bool_elem(config_setting_t *vector,
1387 config_setting_t *element = NULL;
1389 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1394 if(! __config_vector_checktype(vector, CONFIG_TYPE_BOOL))
1397 element = config_setting_create(vector, NULL, CONFIG_TYPE_BOOL);
1400 element = config_setting_get_elem(vector, idx);
1405 if(! config_setting_set_bool(element, value))
1411 /* ------------------------------------------------------------------------- */
1413 const char *config_setting_get_string_elem(const config_setting_t *vector,
1416 config_setting_t *element = config_setting_get_elem(vector, idx);
1421 if(element->type != CONFIG_TYPE_STRING)
1424 return(element->value.sval);
1427 /* ------------------------------------------------------------------------- */
1429 config_setting_t *config_setting_set_string_elem(config_setting_t *vector,
1430 int idx, const char *value)
1432 config_setting_t *element = NULL;
1434 if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1439 if(! __config_vector_checktype(vector, CONFIG_TYPE_STRING))
1442 element = config_setting_create(vector, NULL, CONFIG_TYPE_STRING);
1445 element = config_setting_get_elem(vector, idx);
1450 if(! config_setting_set_string(element, value))
1456 /* ------------------------------------------------------------------------- */
1458 config_setting_t *config_setting_get_elem(const config_setting_t *vector,
1461 config_list_t *list = vector->value.list;
1463 if(((vector->type != CONFIG_TYPE_ARRAY)
1464 && (vector->type != CONFIG_TYPE_LIST)
1465 && (vector->type != CONFIG_TYPE_GROUP)) || ! list)
1468 if(idx >= list->length)
1471 return(list->elements[idx]);
1474 /* ------------------------------------------------------------------------- */
1476 config_setting_t *config_setting_get_member(const config_setting_t *setting,
1479 if(setting->type != CONFIG_TYPE_GROUP)
1482 return(__config_list_search(setting->value.list, name, NULL));
1485 /* ------------------------------------------------------------------------- */
1487 void config_set_destructor(config_t *config, void (*destructor)(void *))
1489 config->destructor = destructor;
1492 /* ------------------------------------------------------------------------- */
1494 void config_set_include_dir(config_t *config, const char *include_dir)
1496 _delete(config->include_dir);
1497 config->include_dir = strdup(include_dir);
1500 /* ------------------------------------------------------------------------- */
1502 int config_setting_length(const config_setting_t *setting)
1504 if((setting->type != CONFIG_TYPE_GROUP)
1505 && (setting->type != CONFIG_TYPE_ARRAY)
1506 && (setting->type != CONFIG_TYPE_LIST))
1509 if(! setting->value.list)
1512 return(setting->value.list->length);
1515 /* ------------------------------------------------------------------------- */
1517 void config_setting_set_hook(config_setting_t *setting, void *hook)
1519 setting->hook = hook;
1522 /* ------------------------------------------------------------------------- */
1524 config_setting_t *config_setting_add(config_setting_t *parent,
1525 const char *name, int type)
1527 if((type < CONFIG_TYPE_NONE) || (type > CONFIG_TYPE_LIST))
1533 if((parent->type == CONFIG_TYPE_ARRAY) || (parent->type == CONFIG_TYPE_LIST))
1538 if(! __config_validate_name(name))
1542 if(config_setting_get_member(parent, name) != NULL)
1543 return(NULL); /* already exists */
1545 return(config_setting_create(parent, name, type));
1548 /* ------------------------------------------------------------------------- */
1550 int config_setting_remove(config_setting_t *parent, const char *name)
1553 config_setting_t *setting;
1556 return(CONFIG_FALSE);
1558 if(parent->type != CONFIG_TYPE_GROUP)
1559 return(CONFIG_FALSE);
1561 if(! (setting = __config_list_search(parent->value.list, name, &idx)))
1562 return(CONFIG_FALSE);
1564 __config_list_remove(parent->value.list, idx);
1565 __config_setting_destroy(setting);
1567 return(CONFIG_TRUE);
1570 /* ------------------------------------------------------------------------- */
1572 int config_setting_remove_elem(config_setting_t *parent, unsigned int idx)
1574 config_list_t *list;
1575 config_setting_t *removed = NULL;
1578 return(CONFIG_FALSE);
1580 list = parent->value.list;
1582 if(((parent->type != CONFIG_TYPE_ARRAY)
1583 && (parent->type != CONFIG_TYPE_LIST)
1584 && (parent->type != CONFIG_TYPE_GROUP)) || ! list)
1585 return(CONFIG_FALSE);
1587 if(idx >= list->length)
1588 return(CONFIG_FALSE);
1590 removed = __config_list_remove(list, idx);
1591 __config_setting_destroy(removed);
1593 return(CONFIG_TRUE);
1596 /* ------------------------------------------------------------------------- */
1598 int config_setting_index(const config_setting_t *setting)
1600 config_setting_t **found = NULL;
1601 config_list_t *list;
1604 if(! setting->parent)
1607 list = setting->parent->value.list;
1609 for(i = 0, found = list->elements; i < (int)list->length; ++i, ++found)
1611 if(*found == setting)
1618 /* ------------------------------------------------------------------------- */