# HG changeset patch # User Matti Hamalainen # Date 1353000720 -7200 # Node ID a0e1b29be35d11b3b20a3dc45e0706db0f06ad44 # Parent 28156333ef4c22f95be96ecd74bd0b438364857a Refactor configuration file handling module rather thoroughly. The API is broken by these changes. diff -r 28156333ef4c -r a0e1b29be35d th_config.c --- a/th_config.c Thu Nov 15 19:22:42 2012 +0200 +++ b/th_config.c Thu Nov 15 19:32:00 2012 +0200 @@ -16,36 +16,36 @@ /* Free a given configuration (the values are not free'd) */ -void th_cfg_free(cfgitem_t *cfg) +void th_cfg_free(th_cfgitem_t *cfg) { - cfgitem_t *curr = cfg; + th_cfgitem_t *node = cfg; - while (curr != NULL) + while (node != NULL) { - cfgitem_t *next = curr->next; + th_cfgitem_t *next = node->next; - if (curr->type == ITEM_SECTION) - th_cfg_free((cfgitem_t *) curr->v.data); + if (node->type == ITEM_SECTION) + th_cfg_free((th_cfgitem_t *) node->v.data); - th_free(curr->name); - th_free(curr); - curr = next; + th_free(node->name); + th_free(node); + node = next; } } /* Allocate and add new item to configuration */ -static cfgitem_t *th_cfg_add(cfgitem_t **cfg, const char *name, +static th_cfgitem_t *th_cfg_add(th_cfgitem_t **cfg, const char *name, const int type, void *data) { - cfgitem_t *node; + th_cfgitem_t *node; if (cfg == NULL) return NULL; /* Allocate new item */ - node = (cfgitem_t *) th_calloc(1, sizeof(cfgitem_t)); + node = (th_cfgitem_t *) th_calloc(1, sizeof(th_cfgitem_t)); if (node == NULL) return NULL; @@ -74,9 +74,9 @@ /* Add integer type setting into give configuration */ -int th_cfg_add_int(cfgitem_t **cfg, char *name, int *itemData, int itemDef) +int th_cfg_add_int(th_cfgitem_t **cfg, const char *name, int *itemData, int itemDef) { - cfgitem_t *node; + th_cfgitem_t *node; node = th_cfg_add(cfg, name, ITEM_INT, (void *) itemData); if (node == NULL) @@ -88,10 +88,10 @@ } -int th_cfg_add_hexvalue(cfgitem_t **cfg, char *name, +int th_cfg_add_hexvalue(th_cfgitem_t **cfg, const char *name, int *itemData, int itemDef) { - cfgitem_t *node; + th_cfgitem_t *node; node = th_cfg_add(cfg, name, ITEM_HEX_TRIPLET, (void *) itemData); if (node == NULL) @@ -105,10 +105,10 @@ /* Add unsigned integer type setting into give configuration */ -int th_cfg_add_uint(cfgitem_t **cfg, char *name, +int th_cfg_add_uint(th_cfgitem_t **cfg, const char *name, unsigned int *itemData, unsigned int itemDef) { - cfgitem_t *node; + th_cfgitem_t *node; node = th_cfg_add(cfg, name, ITEM_UINT, (void *) itemData); if (node == NULL) @@ -122,10 +122,10 @@ /* Add strint type setting into given configuration */ -int th_cfg_add_string(cfgitem_t **cfg, char *name, +int th_cfg_add_string(th_cfgitem_t **cfg, const char *name, char **itemData, char *itemDef) { - cfgitem_t *node; + th_cfgitem_t *node; node = th_cfg_add(cfg, name, ITEM_STRING, (void *) itemData); if (node == NULL) @@ -139,10 +139,10 @@ /* Add boolean type setting into given configuration */ -int th_cfg_add_bool(cfgitem_t **cfg, char *name, +int th_cfg_add_bool(th_cfgitem_t **cfg, const char *name, BOOL *itemData, BOOL itemDef) { - cfgitem_t *node; + th_cfgitem_t *node; node = th_cfg_add(cfg, name, ITEM_BOOL, (void *) itemData); if (node == NULL) @@ -156,9 +156,9 @@ /* Add implicit comment */ -int th_cfg_add_comment(cfgitem_t **cfg, char *comment) +int th_cfg_add_comment(th_cfgitem_t **cfg, const char *comment) { - cfgitem_t *node; + th_cfgitem_t *node; node = th_cfg_add(cfg, comment, ITEM_COMMENT, NULL); if (node == NULL) @@ -170,9 +170,9 @@ /* Add new section */ -int th_cfg_add_section(cfgitem_t **cfg, char *name, cfgitem_t *data) +int th_cfg_add_section(th_cfgitem_t **cfg, const char *name, th_cfgitem_t *data) { - cfgitem_t *node; + th_cfgitem_t *node; node = th_cfg_add(cfg, name, ITEM_SECTION, (void *) data); if (node == NULL) @@ -182,9 +182,9 @@ } -int th_cfg_add_string_list(cfgitem_t **cfg, char *name, qlist_t **data) +int th_cfg_add_string_list(th_cfgitem_t **cfg, const char *name, qlist_t **data) { - cfgitem_t *node; + th_cfgitem_t *node; if (data == NULL) return -5; @@ -218,28 +218,9 @@ #define VADDCH(ch) if (strPos < SET_MAX_BUF) { tmpStr[strPos++] = ch; } #define VISEND(ch) (ch == '\r' || ch == '\n' || ch == ';' || th_isspace(c) || ch == '#') -typedef struct -{ - FILE *file; - char *filename; - size_t line; -} conffile_t; - - -static void th_cfg_error(conffile_t *f, const char *fmt, ...) +static int th_cfg_read_sect(th_ioctx_t *ctx, th_cfgitem_t *cfg, int nesting) { - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%s: '%s', line #%d: ", th_prog_name, f->filename, - (unsigned int) f->line); - vfprintf(stderr, fmt, ap); - va_end(ap); -} - - -static int th_cfg_read_sect(conffile_t *f, cfgitem_t *cfg, int nesting) -{ - cfgitem_t *item = NULL; + th_cfgitem_t *item = NULL; char tmpStr[SET_MAX_BUF + 1]; size_t strPos; int c, parseMode, prevMode, nextMode, tmpCh; @@ -258,12 +239,12 @@ if (c == -1) { /* Get next character */ - switch (c = fgetc(f->file)) + switch (c = fgetc(ctx->fp)) { case EOF: if (parseMode != PM_NORMAL) { - th_cfg_error(f, "Unexpected end of file.\n"); + th_ioctx_error(ctx, -1, "Unexpected end of file.\n"); parseMode = PM_ERROR; } else @@ -271,7 +252,7 @@ break; case '\n': - f->line++; + ctx->line++; } } @@ -309,8 +290,8 @@ } else { - th_cfg_error(f, - "Invalid nesting sequence encountered.\n"); + th_ioctx_error(ctx, -1, + "Invalid nesting sequence encountered.\n"); parseMode = PM_ERROR; } } @@ -324,7 +305,7 @@ else { /* Error! Invalid character found */ - th_cfg_error(f, "Unexpected character '%c'.\n", c); + th_ioctx_error(ctx, -1, "Unexpected character '%c'.\n", c); parseMode = PM_ERROR; } break; @@ -352,7 +333,7 @@ else { /* Error! Key name string too long! */ - th_cfg_error(f, "Config key name too long!"); + th_ioctx_error(ctx, -1, "Config key name too long!"); parseMode = PM_ERROR; } c = -1; @@ -361,9 +342,9 @@ { /* Error! Invalid character found */ tmpStr[strPos] = 0; - th_cfg_error(f, - "Unexpected character '%c' in key name '%s'.\n", - c, tmpStr); + th_ioctx_error(ctx, -1, + "Unexpected character '%c' in key name '%s'.\n", + c, tmpStr); parseMode = PM_ERROR; } break; @@ -420,9 +401,9 @@ else { /* Error! No configuration key by this name found */ - th_cfg_error(f, - "No such configuration setting ('%s')\n", - tmpStr); + th_ioctx_error(ctx, -1, + "No such configuration setting ('%s')\n", + tmpStr); parseMode = PM_ERROR; } @@ -431,9 +412,9 @@ else { /* Error! '=' expected! */ - th_cfg_error(f, - "Unexpected character '%c', assignation '=' was expected.\n", - c); + th_ioctx_error(ctx, -1, + "Unexpected character '%c', assignation '=' was expected.\n", + c); parseMode = PM_ERROR; } break; @@ -495,14 +476,14 @@ if (c != '{') { /* Error! Section start '{' expected! */ - th_cfg_error(f, - "Unexpected character '%c', section start '{' was expected.\n", - c); + th_ioctx_error(ctx, -1, + "Unexpected character '%c', section start '{' was expected.\n", + c); parseMode = PM_ERROR; } else { - int res = th_cfg_read_sect(f, item->v.section, nesting + 1); + int res = th_cfg_read_sect(ctx, item->v.section, nesting + 1); c = -1; if (res > 0) validError = TRUE; @@ -558,9 +539,9 @@ else { /* Error! String too long! */ - th_cfg_error(f, - "String too long! Maximum is %d characters.", - SET_MAX_BUF); + th_ioctx_error(ctx, -1, + "String too long! Maximum is %d characters.", + SET_MAX_BUF); parseMode = PM_ERROR; } } @@ -573,9 +554,9 @@ if (isStart && item->type == ITEM_UINT && c == '-') { /* Error! Negative values not allowed for unsigned ints */ - th_cfg_error(f, - "Negative value specified for %s, unsigned value expected.", - item->name); + th_ioctx_error(ctx, -1, + "Negative value specified for %s, unsigned value expected.", + item->name); parseMode = PM_ERROR; } else if (isStart && (c == '-' || c == '+')) @@ -611,17 +592,18 @@ else { /* Error! Unexpected character. */ - th_cfg_error(f, - "Unexpected character '%c' for integer setting '%s'.", - c, item->name); + th_ioctx_error(ctx, -1, + "Unexpected character '%c' for integer setting '%s'.", + c, item->name); parseMode = PM_ERROR; } if (isError) { /* Error! String too long! */ - th_cfg_error(f, "String too long! Maximum is %d characters.", - SET_MAX_BUF); + th_ioctx_error(ctx, -1, + "String too long! Maximum is %d characters.", + SET_MAX_BUF); parseMode = PM_ERROR; } @@ -665,8 +647,9 @@ if (isError) { - th_cfg_error(f, "Invalid boolean value for '%s'.\n", - item->name); + th_ioctx_error(ctx, -1, + "Invalid boolean value for '%s'.\n", + item->name); parseMode = PM_ERROR; } else @@ -694,56 +677,53 @@ } -int th_cfg_read(FILE *inFile, char *filename, cfgitem_t *cfg) +int th_cfg_read(th_ioctx_t *ctx, th_cfgitem_t *cfg) { - conffile_t f; + if (ctx == NULL || cfg == NULL) + return -1; - f.file = inFile; - f.filename = filename; - f.line = 1; - - return th_cfg_read_sect(&f, cfg, 0); + return th_cfg_read_sect(ctx, cfg, 0); } /* Write a configuration into file */ -static void th_print_indent(conffile_t *f, int nesting) +static void th_print_indent(th_ioctx_t *ctx, int nesting) { int i; for (i = 0; i < nesting * 2; i++) - fputc(' ', f->file); + fputc(' ', ctx->fp); } -static int th_cfg_write_sect(conffile_t *f, cfgitem_t *item, int nesting) +static int th_cfg_write_sect(th_ioctx_t *ctx, const th_cfgitem_t *item, int nesting) { while (item != NULL) { if (item->type == ITEM_COMMENT) { - th_print_indent(f, nesting); - if (fprintf - (f->file, "# %s\n", - (item->name != NULL) ? item->name : "") < 0) + th_print_indent(ctx, nesting); + if (fprintf(ctx->fp, "# %s\n", + (item->name != NULL) ? item->name : "") < 0) return -1; } else if (item->name != NULL) { - th_print_indent(f, nesting); + th_print_indent(ctx, nesting); switch (item->type) { case ITEM_STRING: if (*(item->v.val_str) == NULL) { - if (fprintf(f->file, "#%s = \"\"\n", item->name) < 0) + if (fprintf(ctx->fp, "#%s = \"\"\n", + item->name) < 0) return -3; } else { - if (fprintf(f->file, "%s = \"%s\"\n", - item->name, *(item->v.val_str)) < 0) + if (fprintf(ctx->fp, "%s = \"%s\"\n", + item->name, *(item->v.val_str)) < 0) return -3; } break; @@ -751,70 +731,69 @@ case ITEM_STRING_LIST: if (*(item->v.list) == NULL) { - if (fprintf(f->file, "#%s = \"\", \"\"\n", item->name) < - 0) + if (fprintf(ctx->fp, + "#%s = \"\", \"\"\n", item->name) < 0) return -3; } else { qlist_t *node = *(item->v.list); size_t n = th_llist_length(node); - if (fprintf(f->file, "%s = ", item->name) < 0) + if (fprintf(ctx->fp, "%s = ", item->name) < 0) return -3; while (node != NULL) { if (node->data != NULL) - fprintf(f->file, "\"%s\"", (char *) node->data); + fprintf(ctx->fp, "\"%s\"", (char *) node->data); if (--n > 0) { - fprintf(f->file, ",\n"); - th_print_indent(f, nesting); + fprintf(ctx->fp, ",\n"); + th_print_indent(ctx, nesting); } node = node->next; } - if (fprintf(f->file, "\n") < 0) + if (fprintf(ctx->fp, "\n") < 0) return -3; } break; case ITEM_INT: - if (fprintf(f->file, "%s = %i\n", - item->name, *(item->v.val_int)) < 0) + if (fprintf(ctx->fp, "%s = %i\n", + item->name, *(item->v.val_int)) < 0) return -4; break; case ITEM_UINT: - if (fprintf(f->file, "%s = %d\n", - item->name, *(item->v.val_uint)) < 0) + if (fprintf(ctx->fp, "%s = %d\n", + item->name, *(item->v.val_uint)) < 0) return -5; break; case ITEM_BOOL: - if (fprintf(f->file, "%s = %s\n", - item->name, - *(item->v.val_bool) ? "yes" : "no") < 0) + if (fprintf(ctx->fp, "%s = %s\n", item->name, + *(item->v.val_bool) ? "yes" : "no") < 0) return -6; break; case ITEM_SECTION: { int res; - if (fprintf(f->file, "%s = {\n", item->name) < 0) + if (fprintf(ctx->fp, "%s = {\n", item->name) < 0) return -7; - res = th_cfg_write_sect(f, item->v.section, nesting + 1); + res = th_cfg_write_sect(ctx, item->v.section, nesting + 1); if (res != 0) return res; - if (fprintf(f->file, "}\n\n") < 0) + if (fprintf(ctx->fp, "}\n\n") < 0) return -8; } break; case ITEM_HEX_TRIPLET: - if (fprintf(f->file, "%s = \"%06x\"\n", - item->name, *(item->v.val_int)) < 0) + if (fprintf(ctx->fp, "%s = \"%06x\"\n", + item->name, *(item->v.val_int)) < 0) return -6; break; } @@ -826,19 +805,13 @@ } -int th_cfg_write(FILE *outFile, char *filename, cfgitem_t *cfg) +int th_cfg_write(th_ioctx_t *ctx, const th_cfgitem_t *cfg) { - conffile_t f; - - if (cfg == NULL) + if (ctx == NULL || cfg == NULL) return -1; - f.file = outFile; - f.filename = filename; - f.line = 1; - - fprintf(outFile, "# Configuration written by %s %s\n\n", + fprintf(ctx->fp, "# Configuration written by %s %s\n\n", th_prog_desc, th_prog_version); - return th_cfg_write_sect(&f, cfg, 0); + return th_cfg_write_sect(ctx, cfg, 0); } diff -r 28156333ef4c -r a0e1b29be35d th_config.h --- a/th_config.h Thu Nov 15 19:22:42 2012 +0200 +++ b/th_config.h Thu Nov 15 19:32:00 2012 +0200 @@ -12,8 +12,7 @@ extern "C" { #endif -#include "th_util.h" -#include +#include "th_ioctx.h" /* Definitions @@ -34,7 +33,8 @@ }; -typedef struct _cfgitem_t { +typedef struct _th_cfgitem_t +{ int type; char *name; union { @@ -45,29 +45,30 @@ void *data; qlist_t **list; - struct _cfgitem_t *section; + struct _th_cfgitem_t *section; } v; - struct _cfgitem_t *next, *prev; -} cfgitem_t; + struct _th_cfgitem_t *next, *prev; +} th_cfgitem_t; /* Functions */ -int th_cfg_read(FILE *, char *, cfgitem_t *); -void th_cfg_free(cfgitem_t *); -int th_cfg_write(FILE *, char *, cfgitem_t *); +int th_cfg_read(th_ioctx_t *, th_cfgitem_t *); +void th_cfg_free(th_cfgitem_t *); +int th_cfg_write(th_ioctx_t *, const th_cfgitem_t *); + +int th_cfg_add_section(th_cfgitem_t **cfg, const char *name, th_cfgitem_t *data); +int th_cfg_add_comment(th_cfgitem_t **cfg, const char *comment); -int th_cfg_add_section(cfgitem_t **cfg, char *name, cfgitem_t *data); -int th_cfg_add_comment(cfgitem_t **cfg, char *comment); -int th_cfg_add_int(cfgitem_t **cfg, char *name, int *data, int itemDef); -int th_cfg_add_uint(cfgitem_t **cfg, char *name, unsigned int *data, unsigned int itemDef); -int th_cfg_add_string(cfgitem_t **cfg, char *name, char **data, char *itemDef); -int th_cfg_add_bool(cfgitem_t **cfg, char *name, BOOL *data, BOOL itemDef); -int th_cfg_add_float(cfgitem_t **cfg, char *name, float *data, float itemDef); -int th_cfg_add_hexvalue(cfgitem_t **cfg, char *name, int *data, int itemDef); +int th_cfg_add_int(th_cfgitem_t **cfg, const char *name, int *data, int itemDef); +int th_cfg_add_uint(th_cfgitem_t **cfg, const char *name, unsigned int *data, unsigned int itemDef); +int th_cfg_add_string(th_cfgitem_t **cfg, const char *name, char **data, char *itemDef); +int th_cfg_add_bool(th_cfgitem_t **cfg, const char *name, BOOL *data, BOOL itemDef); +int th_cfg_add_float(th_cfgitem_t **cfg, const char *name, float *data, float itemDef); +int th_cfg_add_hexvalue(th_cfgitem_t **cfg, const char *name, int *data, int itemDef); +int th_cfg_add_string_list(th_cfgitem_t **cfg, const char *name, qlist_t **list); -int th_cfg_add_string_list(cfgitem_t **cfg, char *name, qlist_t **list); #ifdef __cplusplus }