diff options
author | Jonathan McCrohan <jmccrohan@gmail.com> | 2011-12-01 22:56:23 +0000 |
---|---|---|
committer | Jonathan McCrohan <jmccrohan@gmail.com> | 2011-12-01 22:56:23 +0000 |
commit | 429e46051dba814e7d6c74368eb1bba550222cbe (patch) | |
tree | ed1dd43cd23c69f156aae2165006a16a66262cef /lib/libconfig.c | |
parent | 58bf1382be0cbcf3f9649286fd2719b789a1595f (diff) | |
download | libconfig-upstream/1.4.8.tar.gz |
Imported Upstream version 1.4.8upstream/1.4.8
Diffstat (limited to '')
-rw-r--r-- | lib/libconfig.c (renamed from libconfig.c) | 389 |
1 files changed, 258 insertions, 131 deletions
diff --git a/libconfig.c b/lib/libconfig.c index c09921d..f301c8c 100644 --- a/libconfig.c +++ b/lib/libconfig.c @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- libconfig - A library for processing structured configuration files - Copyright (C) 2005-2009 Mark A Lindner + Copyright (C) 2005-2010 Mark A Lindner This file is part of libconfig. @@ -27,7 +27,8 @@ #include "libconfig.h" #include "grammar.h" #include "scanner.h" -#include "private.h" +#include "scanctx.h" +#include "parsectx.h" #include "wincompat.h" #include <locale.h> @@ -37,10 +38,11 @@ #endif #include <stdlib.h> +#include <string.h> #include <ctype.h> #define PATH_TOKENS ":./" -#define CHUNK_SIZE 10 +#define CHUNK_SIZE 16 #define FLOAT_PRECISION 10 #define _new(T) (T *)calloc(sizeof(T), 1) /* zeroed */ @@ -48,6 +50,7 @@ /* ------------------------------------------------------------------------- */ +#ifndef LIBCONFIG_STATIC #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) @@ -55,7 +58,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return(TRUE); } -#endif +#endif /* WIN32 */ +#endif /* LIBCONFIG_STATIC */ /* ------------------------------------------------------------------------- */ @@ -63,13 +67,17 @@ static const char *__io_error = "file I/O error"; static void __config_list_destroy(config_list_t *list); static void __config_write_setting(const config_setting_t *setting, - FILE *stream, int depth); + FILE *stream, int depth, + unsigned short tab_width); -extern int libconfig_yyparse(void *scanner, struct parse_context *ctx); +extern int libconfig_yyparse(void *scanner, struct parse_context *ctx, + struct scan_context *scan_ctx); +extern int libconfig_yylex_init_extra(struct scan_context *scan_ctx, + yyscan_t *scanner); /* ------------------------------------------------------------------------- */ -static void __config_locale_override() +static void __config_locale_override(void) { #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ && ! defined(__MINGW32__) @@ -96,7 +104,7 @@ static void __config_locale_override() /* ------------------------------------------------------------------------- */ -static void __config_locale_restore() +static void __config_locale_restore(void) { #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ && ! defined(__MINGW32__) @@ -143,8 +151,23 @@ static int __config_name_compare(const char *a, const char *b) /* ------------------------------------------------------------------------- */ +static void __config_indent(FILE *stream, int depth, unsigned short w) +{ + if(w) + fprintf(stream, "%*s", (depth - 1) * w, " "); + else + { + int i; + for(i = 0; i < (depth - 1); ++i) + fputc('\t', stream); + } +} + +/* ------------------------------------------------------------------------- */ + static void __config_write_value(const config_value_t *value, int type, - int format, int depth, FILE *stream) + int format, int depth, + unsigned short tab_width, FILE *stream) { char fbuf[64]; @@ -160,12 +183,12 @@ static void __config_write_value(const config_value_t *value, int type, switch(format) { case CONFIG_FORMAT_HEX: - fprintf(stream, "0x%lX", value->ival); + fprintf(stream, "0x%X", value->ival); break; case CONFIG_FORMAT_DEFAULT: default: - fprintf(stream, "%ld", value->ival); + fprintf(stream, "%d", value->ival); break; } break; @@ -193,18 +216,15 @@ static void __config_write_value(const config_value_t *value, int type, snprintf(fbuf, sizeof(fbuf) - 3, "%.*g", FLOAT_PRECISION, value->fval); /* check for exponent */ - q = strchr(fbuf, 'e'); if(! q) { /* no exponent */ - if(! strchr(fbuf, '.')) /* no decimal point */ strcat(fbuf, ".0"); else { /* has decimal point */ - char *p; for(p = fbuf + strlen(fbuf) - 1; p > fbuf; --p) @@ -233,12 +253,13 @@ static void __config_write_value(const config_value_t *value, int type, { for(p = value->sval; *p; p++) { - switch(*p) + int c = (int)*p & 0xFF; + switch(c) { case '\"': case '\\': fputc('\\', stream); - fputc(*p, stream); + fputc(c, stream); break; case '\n': @@ -258,7 +279,10 @@ static void __config_write_value(const config_value_t *value, int type, break; default: - fputc(*p, stream); + if(c >= ' ') + fputc(c, stream); + else + fprintf(stream, "\\x%02X", c); } } } @@ -280,8 +304,9 @@ static void __config_write_value(const config_value_t *value, int type, for(s = list->elements; len--; s++) { - __config_write_value(&((*s)->value), (*s)->type, (*s)->format, - depth + 1, stream); + __config_write_value(&((*s)->value), (*s)->type, + config_setting_get_format(*s), + depth + 1, tab_width, stream); if(len) fputc(',', stream); @@ -308,8 +333,9 @@ static void __config_write_value(const config_value_t *value, int type, for(s = list->elements; len--; s++) { - __config_write_value(&((*s)->value), (*s)->type, (*s)->format, - depth + 1, stream); + __config_write_value(&((*s)->value), (*s)->type, + config_setting_get_format(*s), + depth + 1, tab_width, stream); if(len) fputc(',', stream); @@ -335,7 +361,7 @@ static void __config_write_value(const config_value_t *value, int type, fputc('\n', stream); if(depth > 1) - fprintf(stream, "%*s", (depth - 1) * 2, " "); + __config_indent(stream, depth, tab_width); #endif fprintf(stream, "{\n"); } @@ -346,11 +372,11 @@ static void __config_write_value(const config_value_t *value, int type, config_setting_t **s; for(s = list->elements; len--; s++) - __config_write_setting(*s, stream, depth + 1); + __config_write_setting(*s, stream, depth + 1, tab_width); } if(depth > 1) - fprintf(stream, "%*s", (depth - 1) * 2, " "); + __config_indent(stream, depth, tab_width); if(depth > 0) fputc('}', stream); @@ -369,11 +395,11 @@ static void __config_write_value(const config_value_t *value, int type, static void __config_list_add(config_list_t *list, config_setting_t *setting) { - if(list->length == list->capacity) + if((list->length % CHUNK_SIZE) == 0) { - list->capacity += CHUNK_SIZE; list->elements = (config_setting_t **)realloc( - list->elements, list->capacity * sizeof(config_setting_t *)); + list->elements, + (list->length + CHUNK_SIZE) * sizeof(config_setting_t *)); } list->elements[list->length] = setting; @@ -423,10 +449,7 @@ static config_setting_t *__config_list_remove(config_list_t *list, int idx) list->length--; - if((list->capacity - list->length) >= CHUNK_SIZE) - { - /* realloc smaller? */ - } + /* possibly realloc smaller? */ return(removed); } @@ -525,28 +548,64 @@ static int __config_validate_name(const char *name) /* ------------------------------------------------------------------------- */ -int config_read(config_t *config, FILE *stream) +static int __config_read(config_t *config, FILE *stream, const char *filename, + const char *str) { yyscan_t scanner; - struct parse_context ctx; + struct scan_context scan_ctx; + struct parse_context parse_ctx; + YY_BUFFER_STATE buffer = NULL; int r; - /* Reinitialize the config (keep the destructor) */ + /* Reinitialize the config */ void (*destructor)(void *) = config->destructor; + const char *include_dir = config->include_dir; + unsigned short tab_width = config->tab_width; + unsigned short flags = config->flags; + + config->include_dir = NULL; config_destroy(config); config_init(config); + config->destructor = destructor; + config->include_dir = include_dir; + config->tab_width = tab_width; + config->flags = flags; - ctx.config = config; - ctx.parent = config->root; - ctx.setting = config->root; + parsectx_init(&parse_ctx); + parse_ctx.config = config; + parse_ctx.parent = config->root; + parse_ctx.setting = config->root; __config_locale_override(); - libconfig_yylex_init(&scanner); - libconfig_yyrestart(stream, scanner); - r = libconfig_yyparse(scanner, &ctx); + scanctx_init(&scan_ctx, filename); + scan_ctx.config = config; + libconfig_yylex_init_extra(&scan_ctx, &scanner); + + if(stream) + libconfig_yyrestart(stream, scanner); + else /* read from string */ + buffer = libconfig_yy_scan_string(str, scanner); + + libconfig_yyset_lineno(1, scanner); + r = libconfig_yyparse(scanner, &parse_ctx, &scan_ctx); + + if(r != 0) + { + YY_BUFFER_STATE buf; + + config->error_file = scanctx_current_filename(&scan_ctx); + config->error_type = CONFIG_ERR_PARSE; + + /* Unwind the include stack, freeing the buffers and closing the files. */ + while((buf = (YY_BUFFER_STATE)scanctx_pop_include(&scan_ctx)) != NULL) + libconfig_yy_delete_buffer(buf, scanner); + } + libconfig_yylex_destroy(scanner); + config->filenames = scanctx_cleanup(&scan_ctx, &(config->num_filenames)); + parsectx_cleanup(&parse_ctx); __config_locale_restore(); @@ -555,11 +614,26 @@ int config_read(config_t *config, FILE *stream) /* ------------------------------------------------------------------------- */ +int config_read(config_t *config, FILE *stream) +{ + return(__config_read(config, stream, NULL, NULL)); +} + +/* ------------------------------------------------------------------------- */ + +int config_read_string(config_t *config, const char *str) +{ + return(__config_read(config, NULL, NULL, str)); +} + +/* ------------------------------------------------------------------------- */ + static void __config_write_setting(const config_setting_t *setting, - FILE *stream, int depth) + FILE *stream, int depth, + unsigned short tab_width) { if(depth > 1) - fprintf(stream, "%*s", (depth - 1) * 2, " "); + __config_indent(stream, depth, tab_width); if(setting->name) { @@ -567,8 +641,9 @@ static void __config_write_setting(const config_setting_t *setting, fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '=')); } - __config_write_value(&(setting->value), setting->type, setting->format, - depth, stream); + __config_write_value(&(setting->value), setting->type, + config_setting_get_format(setting), + depth, tab_width, stream); if(depth > 0) { @@ -583,7 +658,7 @@ void config_write(const config_t *config, FILE *stream) { __config_locale_override(); - __config_write_setting(config->root, stream, 0); + __config_write_setting(config->root, stream, 0, config->tab_width); __config_locale_restore(); } @@ -593,15 +668,17 @@ void config_write(const config_t *config, FILE *stream) int config_read_file(config_t *config, const char *filename) { int ret; - FILE *f = fopen(filename, "rt"); - if(! f) + FILE *stream = fopen(filename, "rt"); + if(! stream) { config->error_text = __io_error; + config->error_type = CONFIG_ERR_FILE_IO; return(CONFIG_FALSE); } - ret = config_read(config, f); - fclose(f); + ret = __config_read(config, stream, filename, NULL); + fclose(stream); + return(ret); } @@ -613,11 +690,13 @@ int config_write_file(config_t *config, const char *filename) if(! f) { config->error_text = __io_error; + config->error_type = CONFIG_ERR_FILE_IO; return(CONFIG_FALSE); } config_write(config, f); fclose(f); + config->error_type = CONFIG_ERR_NONE; return(CONFIG_TRUE); } @@ -625,8 +704,17 @@ int config_write_file(config_t *config, const char *filename) void config_destroy(config_t *config) { + unsigned int count = config->num_filenames; + const char **f; + __config_setting_destroy(config->root); + for(f = config->filenames; count > 0; ++f, --count) + _delete(*f); + + _delete(config->filenames); + _delete(config->include_dir); + memset((void *)config, 0, sizeof(config_t)); } @@ -639,6 +727,7 @@ void config_init(config_t *config) config->root = _new(config_setting_t); config->root->type = CONFIG_TYPE_GROUP; config->root->config = config; + config->tab_width = 2; } /* ------------------------------------------------------------------------- */ @@ -691,68 +780,94 @@ static config_setting_t *config_setting_create(config_setting_t *parent, /* ------------------------------------------------------------------------- */ -long config_setting_get_int(const config_setting_t *setting) +static int __config_setting_get_int(const config_setting_t *setting, + int *value) { switch(setting->type) { case CONFIG_TYPE_INT: - return(setting->value.ival); + *value = setting->value.ival; + return(CONFIG_TRUE); case CONFIG_TYPE_INT64: if((setting->value.llval > INT32_MAX) || (setting->value.llval < INT32_MIN)) - return(0); + *value = 0; else - return((long)setting->value.llval); + *value = (int)(setting->value.llval); + return(CONFIG_TRUE); case CONFIG_TYPE_FLOAT: if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) - return((long)(setting->value.fval)); + { + *value = (int)(setting->value.fval); + return(CONFIG_TRUE); + } else - /* fall through */; + { /* fall through */ } default: - return(0); + return(CONFIG_FALSE); } } /* ------------------------------------------------------------------------- */ -long long config_setting_get_int64(const config_setting_t *setting) +int config_setting_get_int(const config_setting_t *setting) +{ + int value = 0; + __config_setting_get_int(setting, &value); + return(value); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_setting_get_int64(const config_setting_t *setting, + long long *value) { switch(setting->type) { case CONFIG_TYPE_INT64: - return(setting->value.llval); + *value = setting->value.llval; + return(CONFIG_TRUE); case CONFIG_TYPE_INT: - return((long long)setting->value.ival); + *value = (long long)(setting->value.ival); + return(CONFIG_TRUE); case CONFIG_TYPE_FLOAT: if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) - return((long long)(setting->value.fval)); + { + *value = (long long)(setting->value.fval); + return(CONFIG_TRUE); + } else - /* fall through */; + { /* fall through */ } default: - return(0); + return(CONFIG_FALSE); } } /* ------------------------------------------------------------------------- */ +long long config_setting_get_int64(const config_setting_t *setting) +{ + long long value = 0; + __config_setting_get_int64(setting, &value); + return(value); +} + +/* ------------------------------------------------------------------------- */ + int config_setting_lookup_int(const config_setting_t *setting, - const char *name, long *value) + const char *name, int *value) { config_setting_t *member = config_setting_get_member(setting, name); if(! member) return(CONFIG_FALSE); - if(config_setting_type(member) != CONFIG_TYPE_INT) - return(CONFIG_FALSE); - - *value = config_setting_get_int(member); - return(CONFIG_TRUE); + return(__config_setting_get_int(member, value)); } /* ------------------------------------------------------------------------- */ @@ -764,11 +879,50 @@ int config_setting_lookup_int64(const config_setting_t *setting, if(! member) return(CONFIG_FALSE); - if(config_setting_type(member) != CONFIG_TYPE_INT64) - return(CONFIG_FALSE); + return(__config_setting_get_int64(member, value)); +} - *value = config_setting_get_int64(member); - return(CONFIG_TRUE); +/* ------------------------------------------------------------------------- */ + +static int __config_setting_get_float(const config_setting_t *setting, + double *value) +{ + switch(setting->type) + { + case CONFIG_TYPE_FLOAT: + *value = setting->value.fval; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + if(config_get_auto_convert(setting->config)) + { + *value = (double)(setting->value.ival); + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + case CONFIG_TYPE_INT64: + if(config_get_auto_convert(setting->config)) + { + *value = (double)(setting->value.llval); + return(CONFIG_TRUE); + } + else + { /* fall through */ } + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +double config_setting_get_float(const config_setting_t *setting) +{ + double value = 0.0; + __config_setting_get_float(setting, &value); + return(value); } /* ------------------------------------------------------------------------- */ @@ -780,11 +934,7 @@ int config_setting_lookup_float(const config_setting_t *setting, if(! member) return(CONFIG_FALSE); - if(config_setting_type(member) != CONFIG_TYPE_FLOAT) - return(CONFIG_FALSE); - - *value = config_setting_get_float(member); - return(CONFIG_TRUE); + return(__config_setting_get_float(member, value)); } /* ------------------------------------------------------------------------- */ @@ -821,7 +971,7 @@ int config_setting_lookup_bool(const config_setting_t *setting, /* ------------------------------------------------------------------------- */ -int config_setting_set_int(config_setting_t *setting, long value) +int config_setting_set_int(config_setting_t *setting, int value) { switch(setting->type) { @@ -865,7 +1015,7 @@ int config_setting_set_int64(config_setting_t *setting, long long value) if((value > INT32_MAX) || (value < INT32_MIN)) setting->value.ival = 0; else - setting->value.ival = (long)value; + setting->value.ival = (int)value; return(CONFIG_TRUE); case CONFIG_TYPE_FLOAT: @@ -884,32 +1034,6 @@ int config_setting_set_int64(config_setting_t *setting, long long value) /* ------------------------------------------------------------------------- */ -double config_setting_get_float(const config_setting_t *setting) -{ - switch(setting->type) - { - case CONFIG_TYPE_FLOAT: - return(setting->value.fval); - - case CONFIG_TYPE_INT: - if(config_get_auto_convert(setting->config)) - return((double)(setting->value.ival)); - else - return(0.0); - - case CONFIG_TYPE_INT64: - if(config_get_auto_convert(setting->config)) - return((double)(setting->value.llval)); - else - return(0.0); - - default: - return(0.0); - } -} - -/* ------------------------------------------------------------------------- */ - int config_setting_set_float(config_setting_t *setting, double value) { switch(setting->type) @@ -925,7 +1049,7 @@ int config_setting_set_float(config_setting_t *setting, double value) case CONFIG_TYPE_INT: if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) { - setting->value.ival = (long)value; + setting->value.ival = (int)value; return(CONFIG_TRUE); } else @@ -1004,17 +1128,19 @@ int config_setting_set_format(config_setting_t *setting, short format) /* ------------------------------------------------------------------------- */ -short config_setting_get_format(config_setting_t *setting) +short config_setting_get_format(const config_setting_t *setting) { - return(setting->format); + return(setting->format != 0 ? setting->format + : setting->config->default_format); } /* ------------------------------------------------------------------------- */ -config_setting_t *config_lookup(const config_t *config, const char *path) +config_setting_t *config_lookup_from(config_setting_t *setting, + const char *path) { const char *p = path; - config_setting_t *setting = config->root, *found; + config_setting_t *found; for(;;) { @@ -1043,6 +1169,13 @@ config_setting_t *config_lookup(const config_t *config, const char *path) /* ------------------------------------------------------------------------- */ +config_setting_t *config_lookup(const config_t *config, const char *path) +{ + return(config_lookup_from(config->root, path)); +} + +/* ------------------------------------------------------------------------- */ + int config_lookup_string(const config_t *config, const char *path, const char **value) { @@ -1061,18 +1194,13 @@ int config_lookup_string(const config_t *config, const char *path, /* ------------------------------------------------------------------------- */ int config_lookup_int(const config_t *config, const char *path, - long *value) + int *value) { const config_setting_t *s = config_lookup(config, path); if(! s) return(CONFIG_FALSE); - if(config_setting_type(s) != CONFIG_TYPE_INT) - return(CONFIG_FALSE); - - *value = config_setting_get_int(s); - - return(CONFIG_TRUE); + return(__config_setting_get_int(s, value)); } /* ------------------------------------------------------------------------- */ @@ -1084,12 +1212,7 @@ int config_lookup_int64(const config_t *config, const char *path, if(! s) return(CONFIG_FALSE); - if(config_setting_type(s) != CONFIG_TYPE_INT64) - return(CONFIG_FALSE); - - *value = config_setting_get_int64(s); - - return(CONFIG_TRUE); + return(__config_setting_get_int64(s, value)); } /* ------------------------------------------------------------------------- */ @@ -1101,11 +1224,7 @@ int config_lookup_float(const config_t *config, const char *path, if(! s) return(CONFIG_FALSE); - if(config_setting_type(s) != CONFIG_TYPE_FLOAT) - return(CONFIG_FALSE); - - *value = config_setting_get_float(s); - return(CONFIG_TRUE); + return(__config_setting_get_float(s, value)); } /* ------------------------------------------------------------------------- */ @@ -1125,7 +1244,7 @@ int config_lookup_bool(const config_t *config, const char *path, int *value) /* ------------------------------------------------------------------------- */ -long config_setting_get_int_elem(const config_setting_t *vector, int idx) +int config_setting_get_int_elem(const config_setting_t *vector, int idx) { const config_setting_t *element = config_setting_get_elem(vector, idx); @@ -1135,7 +1254,7 @@ long config_setting_get_int_elem(const config_setting_t *vector, int idx) /* ------------------------------------------------------------------------- */ config_setting_t *config_setting_set_int_elem(config_setting_t *vector, - int idx, long value) + int idx, int value) { config_setting_t *element = NULL; @@ -1369,6 +1488,14 @@ void config_set_destructor(config_t *config, void (*destructor)(void *)) /* ------------------------------------------------------------------------- */ +void config_set_include_dir(config_t *config, const char *include_dir) +{ + _delete(config->include_dir); + config->include_dir = strdup(include_dir); +} + +/* ------------------------------------------------------------------------- */ + int config_setting_length(const config_setting_t *setting) { if((setting->type != CONFIG_TYPE_GROUP) @@ -1476,7 +1603,7 @@ int config_setting_index(const config_setting_t *setting) list = setting->parent->value.list; - for(i = 0, found = list->elements; i < list->length; ++i, ++found) + for(i = 0, found = list->elements; i < (int)list->length; ++i, ++found) { if(*found == setting) return(i); |