Mercurial > hg > th-libs
changeset 74:8ff993207415
Branch merge.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 18 Nov 2012 23:12:47 +0200 |
parents | e37d7c1f8a03 (current diff) 43df05a632cb (diff) |
children | cfb475e11b9f |
files | |
diffstat | 6 files changed, 285 insertions(+), 150 deletions(-) [+] |
line wrap: on
line diff
--- a/th_config.c Sun Nov 18 23:12:33 2012 +0200 +++ b/th_config.c Sun Nov 18 23:12:47 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); }
--- a/th_config.h Sun Nov 18 23:12:33 2012 +0200 +++ b/th_config.h Sun Nov 18 23:12:47 2012 +0200 @@ -12,13 +12,13 @@ extern "C" { #endif -#include "th_util.h" -#include <stdio.h> +#include "th_ioctx.h" /* Definitions */ -enum ITEM_TYPE { +enum ITEM_TYPE +{ ITEM_SECTION = 1, ITEM_COMMENT, ITEM_STRING, @@ -33,7 +33,8 @@ }; -typedef struct _cfgitem_t { +typedef struct _th_cfgitem_t +{ int type; char *name; union { @@ -44,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 }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/th_ioctx.c Sun Nov 18 23:12:47 2012 +0200 @@ -0,0 +1,98 @@ +/* + * Standard I/O context helpers + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2012 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#include "th_ioctx.h" +#include "th_string.h" + +/* Simple STD I/O contexts + */ +BOOL th_ioctx_init(th_ioctx_t *ctx, const char *filename, + void (*error)(struct _th_ioctx_t *, const int, const char *msg), + void (*msg)(struct _th_ioctx_t *, const char *msg)) + +{ + if (ctx == NULL || filename == NULL) + return FALSE; + + th_memset(ctx, 0, sizeof(ctx)); + ctx->error = error; + ctx->msg = msg; + + if ((ctx->filename = th_strdup(filename)) == NULL) + return FALSE; + + return TRUE; +} + + +BOOL th_ioctx_open(th_ioctx_t *ctx, const char *filename, const char *mode, + void (*error)(struct _th_ioctx_t *, const int, const char *msg), + void (*msg)(struct _th_ioctx_t *, const char *msg)) +{ + if (!th_ioctx_init(ctx, filename, error, msg) || mode == NULL) + return FALSE; + + if ((ctx->fp = fopen(filename, mode)) == NULL) + return FALSE; + + return TRUE; +} + + +void th_ioctx_close(th_ioctx_t *ctx) +{ + if (ctx != NULL) + { + th_free(ctx->filename); + ctx->filename = NULL; + + if (ctx->fp != NULL) + fclose(ctx->fp); + ctx->fp = NULL; + } +} + + +void th_ioctx_error(th_ioctx_t *ctx, const int err, const char *fmt, ...) +{ + char *msg; + va_list ap; + + va_start(ap, fmt); + msg = th_strdup_vprintf(fmt, ap); + va_end(ap); + + if (ctx->error != NULL) + ctx->error(ctx, err, msg); + else + THERR("'%s' #%d: %s\n", ctx->filename, (unsigned int) ctx->line, msg); + + th_free(msg); +} + + +th_ioctx_t *th_ioctx_new(const char *filename, + void (*error)(struct _th_ioctx_t *, const int, const char *msg), + void (*msg)(struct _th_ioctx_t *, const char *msg)) +{ + th_ioctx_t *ctx = th_malloc0(sizeof(th_ioctx_t)); + if (ctx == NULL) + return NULL; + + th_ioctx_init(ctx, filename, error, msg); + ctx->allocated = TRUE; + return ctx; +} + + +void th_ioctx_free(th_ioctx_t *ctx) +{ + th_ioctx_close(ctx); + + if (ctx->allocated) + th_free(ctx); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/th_ioctx.h Sun Nov 18 23:12:47 2012 +0200 @@ -0,0 +1,53 @@ +/* + * Standard I/O context helpers + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2012 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#ifndef TH_IOCTX_H +#define TH_IOCTX_H + +#include "th_util.h" +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Simple STD I/O contexts + */ +typedef struct _th_ioctx_t +{ + BOOL allocated; + char *filename; + FILE *fp; + size_t line; + + void (*error)(struct _th_ioctx_t *, const int, const char *msg); + void (*msg)(struct _th_ioctx_t *, const char *msg); +} th_ioctx_t; + + +BOOL th_ioctx_init(th_ioctx_t *ctx, const char *filename, + void (*error)(struct _th_ioctx_t *, const int, const char *msg), + void (*msg)(struct _th_ioctx_t *, const char *msg)); + +BOOL th_ioctx_open(th_ioctx_t *ctx, const char *filename, const char *mode, + void (*error)(struct _th_ioctx_t *, const int, const char *msg), + void (*msg)(struct _th_ioctx_t *, const char *msg)); + +void th_ioctx_close(th_ioctx_t *ctx); +void th_ioctx_error(th_ioctx_t *ctx, const int err, const char *fmt, ...); + +th_ioctx_t * th_ioctx_new(const char *filename, + void (*error)(struct _th_ioctx_t *, const int, const char *msg), + void (*msg)(struct _th_ioctx_t *, const char *msg)); +void th_ioctx_free(th_ioctx_t *ctx); + + +#ifdef __cplusplus +} +#endif +#endif /* TH_IOCTX_H */
--- a/th_util.c Sun Nov 18 23:12:33 2012 +0200 +++ b/th_util.c Sun Nov 18 23:12:47 2012 +0200 @@ -130,6 +130,12 @@ } +void *th_malloc0(size_t l) +{ + return calloc(1, l); +} + + void *th_calloc(size_t n, size_t l) { return calloc(n, l);
--- a/th_util.h Sun Nov 18 23:12:33 2012 +0200 +++ b/th_util.h Sun Nov 18 23:12:47 2012 +0200 @@ -80,6 +80,7 @@ void THPRINT_V(int, const char *, va_list); void *th_malloc(size_t); +void *th_malloc0(size_t); void *th_calloc(size_t, size_t); void *th_realloc(void *, size_t); void th_free(void *); @@ -93,7 +94,8 @@ /* Doubly linked list handling */ -typedef struct _qlist_t { +typedef struct _qlist_t +{ void *data; size_t num; struct _qlist_t *prev, *next; @@ -124,7 +126,8 @@ /* Ringbuffer implementation */ -typedef struct { +typedef struct +{ char **data; int n, size; void (*deallocator)(void *);