Mercurial > hg > th-libs
diff th_config.c @ 16:0cea9c0cfce7
Sync.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 02 Nov 2010 23:22:44 +0200 |
parents | 4adf7093060c |
children | 05a44cbd1150 |
line wrap: on
line diff
--- a/th_config.c Sat Oct 30 17:48:40 2010 +0300 +++ b/th_config.c Tue Nov 02 23:22:44 2010 +0200 @@ -1,7 +1,7 @@ /* * Very simple configuration handling functions * Programmed and designed by Matti 'ccr' Hamalainen - * (C) Copyright 2004-2008 Tecnic Software productions (TNSP) + * (C) Copyright 2004-2010 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ @@ -19,15 +19,15 @@ /* Free a given configuration (the values are not free'd) */ -void th_config_free(cfgitem_t *cfg) +void th_cfg_free(cfgitem_t *cfg) { cfgitem_t *curr = cfg; while (curr != NULL) { cfgitem_t *next = curr->next; - if (curr->type == ITEM_BLOCK) - th_config_free((cfgitem_t *) curr->data); + if (curr->type == ITEM_SECTION) + th_cfg_free((cfgitem_t *) curr->data); th_free(curr->name); th_free(curr); @@ -38,8 +38,7 @@ /* Allocate and add new item to configuration */ -static cfgitem_t *th_config_add(cfgitem_t **cfg, char *name, int type, - BOOL (*validate)(cfgitem_t *), void *data) +static cfgitem_t *th_cfg_add(cfgitem_t **cfg, const char *name, const int type, void *data) { cfgitem_t *node; @@ -54,7 +53,6 @@ /* Set values */ node->type = type; node->data = data; - node->validate = validate; node->name = th_strdup(name); /* Insert into linked list */ @@ -74,12 +72,12 @@ /* Add integer type setting into give configuration */ -int th_config_add_int(cfgitem_t ** cfg, char * name, BOOL(*itemValidate) (cfgitem_t *), +int th_cfg_add_int(cfgitem_t ** cfg, char * name, int *itemData, int itemDef) { cfgitem_t *node; - node = th_config_add(cfg, name, ITEM_INT, itemValidate, (void *) itemData); + node = th_cfg_add(cfg, name, ITEM_INT, (void *) itemData); if (node == NULL) return -1; @@ -89,12 +87,12 @@ } -int th_config_add_hexvalue(cfgitem_t ** cfg, char * name, BOOL(*itemValidate) (cfgitem_t *), +int th_cfg_add_hexvalue(cfgitem_t ** cfg, char * name, int *itemData, int itemDef) { cfgitem_t *node; - node = th_config_add(cfg, name, ITEM_HEX_TRIPLET, itemValidate, (void *) itemData); + node = th_cfg_add(cfg, name, ITEM_HEX_TRIPLET, (void *) itemData); if (node == NULL) return -1; @@ -106,12 +104,12 @@ /* Add unsigned integer type setting into give configuration */ -int th_config_add_uint(cfgitem_t ** cfg, char * name, BOOL(*itemValidate) (cfgitem_t *), +int th_cfg_add_uint(cfgitem_t ** cfg, char * name, unsigned int * itemData, unsigned int itemDef) { cfgitem_t *node; - node = th_config_add(cfg, name, ITEM_UINT, itemValidate, (void *) itemData); + node = th_cfg_add(cfg, name, ITEM_UINT, (void *) itemData); if (node == NULL) return -1; @@ -123,12 +121,12 @@ /* Add strint type setting into given configuration */ -int th_config_add_string(cfgitem_t ** cfg, char * name, BOOL(*itemValidate) (cfgitem_t *), +int th_cfg_add_string(cfgitem_t ** cfg, char * name, char ** itemData, char * itemDef) { cfgitem_t *node; - node = th_config_add(cfg, name, ITEM_STRING, itemValidate, (void *) itemData); + node = th_cfg_add(cfg, name, ITEM_STRING, (void *) itemData); if (node == NULL) return -1; @@ -140,12 +138,12 @@ /* Add boolean type setting into given configuration */ -int th_config_add_bool(cfgitem_t ** cfg, char * name, BOOL(*itemValidate) (cfgitem_t *), +int th_cfg_add_bool(cfgitem_t ** cfg, char * name, BOOL * itemData, BOOL itemDef) { cfgitem_t *node; - node = th_config_add(cfg, name, ITEM_BOOL, itemValidate, (void *) itemData); + node = th_cfg_add(cfg, name, ITEM_BOOL, (void *) itemData); if (node == NULL) return -1; @@ -157,11 +155,11 @@ /* Add implicit comment */ -int th_config_add_comment(cfgitem_t ** cfg, char * comment) +int th_cfg_add_comment(cfgitem_t ** cfg, char * comment) { cfgitem_t *node; - node = th_config_add(cfg, comment, ITEM_COMMENT, NULL, NULL); + node = th_cfg_add(cfg, comment, ITEM_COMMENT, NULL); if (node == NULL) return -1; @@ -169,13 +167,28 @@ } -/* Add new block +/* Add new section */ -int th_config_add_section(cfgitem_t ** cfg, char * name, cfgitem_t *data) +int th_cfg_add_section(cfgitem_t ** cfg, char * name, cfgitem_t *data) { cfgitem_t *node; - node = th_config_add(cfg, name, ITEM_BLOCK, NULL, (void *) data); + node = th_cfg_add(cfg, name, ITEM_SECTION, (void *) data); + if (node == NULL) + return -1; + + return 0; +} + + +int th_cfg_add_string_list(cfgitem_t ** cfg, char * name, qlist_t **data) +{ + cfgitem_t *node; + + if (data == NULL) + return -5; + + node = th_cfg_add(cfg, name, ITEM_STRING_LIST, (void *) data); if (node == NULL) return -1; @@ -196,7 +209,8 @@ PM_STRING, PM_INT, PM_BOOL, - PM_BLOCK + PM_SECTION, + PM_ARRAY }; #define VADDCH(ch) if (strPos < SET_MAX_BUF) { tmpStr[strPos++] = ch; } @@ -209,7 +223,7 @@ } conffile_t; -static void th_config_error(conffile_t *f, const char *fmt, ...) +static void th_cfg_error(conffile_t *f, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -219,7 +233,7 @@ } -static int th_config_read_sect(conffile_t *f, cfgitem_t * cfg, int nesting) +static int th_cfg_read_sect(conffile_t *f, cfgitem_t * cfg, int nesting) { cfgitem_t *item = NULL; char tmpStr[SET_MAX_BUF + 1]; @@ -241,7 +255,7 @@ switch (c = fgetc(f->file)) { case EOF: if (parseMode != PM_NORMAL) { - th_config_error(f, + th_cfg_error(f, "Unexpected end of file.\n"); parseMode = PM_ERROR; } else @@ -277,8 +291,7 @@ /* Check for validation errors */ return (validError) ? 1 : 0; } else { - th_config_error(f, - "HMMM!\n"); + th_cfg_error(f, "Invalid nesting sequence encountered.\n"); parseMode = PM_ERROR; } } else if (th_isalpha(c)) { @@ -288,7 +301,7 @@ strPos = 0; } else { /* Error! Invalid character found */ - th_config_error(f, + th_cfg_error(f, "Unexpected character '%c'.\n", c); parseMode = PM_ERROR; } @@ -312,7 +325,7 @@ else { /* Error! Key name string too long! */ - th_config_error(f, + th_cfg_error(f, "Config key name too long!"); parseMode = PM_ERROR; } @@ -320,7 +333,7 @@ } else { /* Error! Invalid character found */ tmpStr[strPos] = 0; - th_config_error(f, + th_cfg_error(f, "Unexpected character '%c' in key name '%s'.\n", c, tmpStr); parseMode = PM_ERROR; } @@ -348,6 +361,10 @@ nextMode = PM_STRING; break; + case ITEM_STRING_LIST: + nextMode = PM_ARRAY; + break; + case ITEM_INT: case ITEM_UINT: nextMode = PM_INT; @@ -357,8 +374,8 @@ nextMode = PM_BOOL; break; - case ITEM_BLOCK: - nextMode = PM_BLOCK; + case ITEM_SECTION: + nextMode = PM_SECTION; break; } @@ -368,7 +385,7 @@ strPos = 0; } else { /* Error! No configuration key by this name found */ - th_config_error(f, + th_cfg_error(f, "No such configuration setting ('%s')\n", tmpStr); parseMode = PM_ERROR; } @@ -376,7 +393,7 @@ c = -1; } else { /* Error! '=' expected! */ - th_config_error(f, + th_cfg_error(f, "Unexpected character '%c', assignation '=' was expected.\n", c); parseMode = PM_ERROR; } @@ -398,15 +415,39 @@ } break; - case PM_BLOCK: - /* Block parsing mode */ + case PM_ARRAY: + if (isStart) { + switch (item->type) { + case ITEM_STRING_LIST: + prevMode = parseMode; + parseMode = PM_STRING; + break; + } + } else if (c == ',') { + switch (item->type) { + case ITEM_STRING_LIST: + c = -1; + isStart = TRUE; + prevMode = parseMode; + parseMode = PM_NEXT; + nextMode = PM_STRING; + break; + } + } else { + prevMode = parseMode; + parseMode = PM_NORMAL; + } + break; + + case PM_SECTION: + /* Section parsing mode */ if (c != '{') { - /* Error! Block start '{' expected! */ - th_config_error(f, - "Unexpected character '%c', block start '{' was expected.\n", c); + /* Error! Section start '{' expected! */ + th_cfg_error(f, + "Unexpected character '%c', section start '{' was expected.\n", c); parseMode = PM_ERROR; } else { - int res = th_config_read_sect(f, (cfgitem_t *) item->data, nesting + 1); + int res = th_cfg_read_sect(f, (cfgitem_t *) item->data, nesting + 1); c = -1; if (res > 0) validError = TRUE; @@ -430,23 +471,32 @@ /* End of string, set the value */ tmpStr[strPos] = 0; - if (item->type == ITEM_HEX_TRIPLET) { - } else if (item->type == ITEM_STRING) { - th_pstrcpy((char **) item->data, tmpStr); + switch (item->type) { + case ITEM_HEX_TRIPLET: + *(int *) item->data = th_get_hex_triplet(tmpStr); + prevMode = parseMode; + parseMode = PM_NORMAL; + break; + case ITEM_STRING: + th_pstrcpy((char **) item->data, tmpStr); + prevMode = parseMode; + parseMode = PM_NORMAL; + break; + case ITEM_STRING_LIST: + th_llist_append(item->list, th_strdup(tmpStr)); + prevMode = parseMode; + parseMode = PM_NEXT; + nextMode = PM_ARRAY; + break; } - if (item->validate != NULL && !item->validate(item)) - validError = TRUE; - - prevMode = parseMode; - parseMode = PM_NORMAL; } else { /* Add character to string */ VADDCH(c) else { /* Error! String too long! */ - th_config_error(f, + th_cfg_error(f, "String too long! Maximum is %d characters.", SET_MAX_BUF); parseMode = PM_ERROR; @@ -460,7 +510,7 @@ /* Integer parsing mode */ if (isStart && item->type == ITEM_UINT && c == '-') { /* Error! Negative values not allowed for unsigned ints */ - th_config_error(f, + th_cfg_error(f, "Negative value specified for %s, unsigned value expected.", item->name); parseMode = PM_ERROR; @@ -484,14 +534,12 @@ *((unsigned int *) item->data) = atol(tmpStr); break; } - if (item->validate != NULL && !item->validate(item)) - validError = TRUE; prevMode = parseMode; parseMode = PM_NORMAL; } else { /* Error! Unexpected character. */ - th_config_error(f, + th_cfg_error(f, "Unexpected character '%c' for integer setting '%s'.", c, item->name); parseMode = PM_ERROR; @@ -499,7 +547,7 @@ if (isError) { /* Error! String too long! */ - th_config_error(f, "String too long! Maximum is %d characters.", + th_cfg_error(f, "String too long! Maximum is %d characters.", SET_MAX_BUF); parseMode = PM_ERROR; } @@ -535,14 +583,11 @@ } if (isError) { - th_config_error(f, "Invalid boolean value for '%s'.\n", item->name); + th_cfg_error(f, "Invalid boolean value for '%s'.\n", item->name); parseMode = PM_ERROR; } else { *((BOOL *) item->data) = tmpBool; - if (item->validate != NULL && !item->validate(item)) - validError = TRUE; - prevMode = parseMode; parseMode = PM_NORMAL; } @@ -564,7 +609,7 @@ } -int th_config_read(FILE *inFile, char *filename, cfgitem_t * cfg) +int th_cfg_read(FILE *inFile, char *filename, cfgitem_t * cfg) { conffile_t f; @@ -572,7 +617,7 @@ f.filename = filename; f.line = 1; - return th_config_read_sect(&f, cfg, 0); + return th_cfg_read_sect(&f, cfg, 0); } @@ -586,7 +631,7 @@ } -static int th_config_write_sect(conffile_t *f, cfgitem_t *item, int nesting) +static int th_cfg_write_sect(conffile_t *f, cfgitem_t *item, int nesting) { while (item != NULL) { if (item->type == ITEM_COMMENT) { @@ -599,42 +644,67 @@ switch (item->type) { case ITEM_STRING: - if (*((char **) item->data) == NULL) { + if (*(item->val_str) == NULL) { if (fprintf(f->file, "#%s = \"\"\n", item->name) < 0) return -3; } else { if (fprintf(f->file, "%s = \"%s\"\n", - item->name, *((char **) item->data)) < 0) + item->name, *(item->val_str)) < 0) + return -3; + } + break; + + case ITEM_STRING_LIST: + if (*(item->list) == NULL) { + if (fprintf(f->file, "#%s = \"\", \"\"\n", item->name) < 0) + return -3; + } else { + qlist_t *node = *(item->list); + size_t n = th_llist_length(node); + if (fprintf(f->file, "%s = ", item->name) < 0) + return -3; + + while (node != NULL) { + if (node->data != NULL) + fprintf(f->file, "\"%s\"", (char *) node->data); + + if (--n > 0) + fprintf(f->file, ", "); + + node = node->next; + } + + if (fprintf(f->file, "\n") < 0) return -3; } break; case ITEM_INT: if (fprintf(f->file, "%s = %i\n", - item->name, *((int *) item->data)) < 0) + item->name, *(item->val_int)) < 0) return -4; break; case ITEM_UINT: if (fprintf(f->file, "%s = %d\n", - item->name, *((unsigned int *) item->data)) < 0) + item->name, *(item->val_uint)) < 0) return -5; break; case ITEM_BOOL: if (fprintf(f->file, "%s = %s\n", - item->name, *((BOOL *) item->data) ? "yes" : "no") < 0) + item->name, *(item->val_bool) ? "yes" : "no") < 0) return -6; break; - case ITEM_BLOCK: + case ITEM_SECTION: { int res; - if (fprintf(f->file, "\n%s = {\n", item->name) < 0) + if (fprintf(f->file, "%s = {\n", item->name) < 0) return -7; - res = th_config_write_sect(f, (cfgitem_t *) item->data, nesting + 1); + res = th_cfg_write_sect(f, (cfgitem_t *) item->data, nesting + 1); if (res != 0) return res; - if (fprintf(f->file, "} # End of '%s'\n\n", item->name) < 0) + if (fprintf(f->file, "}\n\n") < 0) return -8; } break; @@ -653,7 +723,7 @@ } -int th_config_write(FILE *outFile, char *filename, cfgitem_t *cfg) +int th_cfg_write(FILE *outFile, char *filename, cfgitem_t *cfg) { conffile_t f; @@ -667,7 +737,7 @@ fprintf(outFile, "# Configuration written by %s %s\n\n", th_prog_fullname, th_prog_version); - return th_config_write_sect(&f, cfg, 0); + return th_cfg_write_sect(&f, cfg, 0); }