Mercurial > code
changeset 95:cb5d3d66ea04
Merge
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 12 Jan 2012 20:12:48 +0100 |
parents | 820426789f17 (current diff) f5339bdc5cb1 (diff) |
children | dcaf2c61c902 |
files | module.c module.h |
diffstat | 9 files changed, 327 insertions(+), 237 deletions(-) [+] |
line wrap: on
line diff
--- a/array.c Thu Jan 12 15:42:08 2012 +0100 +++ b/array.c Thu Jan 12 20:12:48 2012 +0100 @@ -26,26 +26,57 @@ static int array_grow(struct array *); -struct array * -array_new(enum array_type type, size_t unit, int length) +int +array_init(struct array *arr, size_t unit) { - struct array *arr; + if (unit == 0) + return -1; - if (unit == 0 || (arr = malloc(sizeof (struct array))) == NULL) - return NULL; - - memset(arr, 0, sizeof (struct array)); - arr->type = type; - arr->bsize = (length == 0) ? ARRAY_DEFAULT_BSIZE : length; arr->unit = unit; arr->size = OFFSET(arr->bsize); - if ((arr->data = malloc(arr->size)) == NULL) { - free(arr); - return NULL; - } + /* Set defaults if needed */ + arr->bsize = (arr->bsize <= 0) ? ARRAY_DEFAULT_BSIZE : arr->bsize; + arr->malloc = (arr->malloc == NULL) ? &malloc : arr->malloc; + arr->realloc = (arr->realloc == NULL) ? &realloc : arr->realloc; + + if ((arr->data = arr->malloc(arr->size)) == NULL) + return -1; + + return 0; +} + +/* + * Valid options that can be set for an array : + * l -> optional array block size of type int + * m -> malloc function that must matches void * (*malloc)(size_t) + * r -> realloc function that must matches void * (*realloc)(void *, size_t) + * t -> type of array of type enum array_type + */ - return arr; +void +array_set(struct array *arr, const char *fmt, ...) +{ + va_list ap; + const char *p; + + va_start(ap, fmt); + for (p = fmt; *p != '\0'; ++p) + switch (*p) { + case 'l': + arr->bsize = va_arg(ap, int); + break; + case 'm': + arr->malloc = va_arg(ap, void *(*)(size_t)); + break; + case 'r': + arr->realloc = va_arg(ap, void *(*)(void *, size_t)); + break; + case 't': + arr->type = va_arg(ap, enum array_type); + default: + break; + } } /* @@ -178,7 +209,7 @@ * function. */ - if ((tmp = malloc(arr->unit)) == NULL) + if ((tmp = arr->malloc(arr->unit)) == NULL) return -1; memcpy((char *)tmp, (char *)arr->data + OFFSET(i1), arr->unit); @@ -282,8 +313,6 @@ if (arr->data) free(arr->data); - - free(arr); } /* @@ -299,7 +328,7 @@ return 0; if (arr->type == ARRAY_AUTO) { - if ((arr->data = realloc(arr->data, arr->size + + if ((arr->data = arr->realloc(arr->data, arr->size + OFFSET(arr->bsize))) == NULL) return -1;
--- a/array.h Thu Jan 12 15:42:08 2012 +0100 +++ b/array.h Thu Jan 12 20:12:48 2012 +0100 @@ -23,11 +23,15 @@ extern "C" { #endif +#include <stdarg.h> + +#ifndef ARRAY_DEFAULT_BSIZE #define ARRAY_DEFAULT_BSIZE 128 +#endif enum array_type { - ARRAY_FIXED = 0, - ARRAY_AUTO = 1 + ARRAY_AUTO = 0, + ARRAY_FIXED = 1 }; struct array { @@ -37,26 +41,31 @@ size_t size; /* current buffer size (allocated memory) */ size_t unit; /* unit size (sizeof the object) */ int bsize; /* block size (used when growing array) */ - int i; /* only for ARRAY_FOREACH(_R) */ + int i; /* only for ARRAY_FOREACH */ + + /* Own allocation functions */ + void * (*malloc)(size_t); + void * (*realloc)(void *, size_t); }; typedef void (*array_map_fn)(void *, void *); typedef int (*array_cmp_fn)(void *, void *); -struct array *array_new(enum array_type, size_t, int); -int array_push(struct array *, const void *); -int array_insert(struct array *, const void *, int); -int array_append(struct array *, const void *); -void array_pop(struct array *); -void array_unqueue(struct array *); -void array_remove(struct array *, int); -void array_unref(struct array *, const void *); -int array_iswap(struct array *, int, int); -int array_pswap(struct array *, const void *, const void *); -void array_map(const struct array *, array_map_fn, void *); -int array_find(const struct array *, array_cmp_fn, void *, void *); -void array_clear(struct array *); -void array_free(struct array *); +int array_init(struct array *, size_t); +void array_set(struct array *, const char *, ...); +int array_push(struct array *, const void *); +int array_insert(struct array *, const void *, int); +int array_append(struct array *, const void *); +void array_pop(struct array *); +void array_unqueue(struct array *); +void array_remove(struct array *, int); +void array_unref(struct array *, const void *); +int array_iswap(struct array *, int, int); +int array_pswap(struct array *, const void *, const void *); +void array_map(const struct array *, array_map_fn, void *); +int array_find(const struct array *, array_cmp_fn, void *, void *); +void array_clear(struct array *); +void array_free(struct array *); #define ARRAY_HEAD(a, type) \ (((type *)a->data)[0]) @@ -66,14 +75,10 @@ ((type *)(a)->data)[((i) < 0) \ ? 0 : ((i) >= (a)->length) ? (a)->length - 1 : (i)] -#define ARRAY_FOREACH_R(a, var) \ - for ((a)->i = 0, var = ARRAY_TAIL((a)); \ - (a)->i < (a)->length; ++(a)->i, --var) - -#define ARRAY_FOREACH(a, var, type) \ - for ((a)->i = 0, var = ARRAY_HEAD((a), type); \ +#define ARRAY_FOREACH(a, var) \ + for ((a)->i = 0, (var) = (a)->data; \ (a)->i < (a)->length; \ - ++(a)->i, var = ARRAY_INDEX((a), (a)->i, type)) + ++(a)->i, ++(var)) /* Only for ARRAY_FIXED */ #define ARRAY_FULL(a) \
--- a/err.h Thu Jan 12 15:42:08 2012 +0100 +++ b/err.h Thu Jan 12 20:12:48 2012 +0100 @@ -37,8 +37,10 @@ * a warning like `a may be used uninitialized'. */ -#ifdef __GNUC__ +#if defined(__GNUC__) # define __at_noreturn __attribute__ ((noreturn)) +#elif defined(_MSC_VER) +# define __at_noreturn __declspec(noreturn) #endif /*
--- a/ini.c Thu Jan 12 15:42:08 2012 +0100 +++ b/ini.c Thu Jan 12 20:12:48 2012 +0100 @@ -26,9 +26,9 @@ #include "ini.h" -/* -------------------------------------------------------- - * structure definitions - * -------------------------------------------------------- */ +/* -------------------------------------------------------- */ +/* structure definitions */ +/* -------------------------------------------------------- */ struct ini_option { char *key; /* option name */ @@ -59,11 +59,11 @@ STAILQ_HEAD(, ini_section) sections; }; -static char iniError[1024 + 1]; +static char ini_error[1024 + 1]; -/* -------------------------------------------------------- - * prototypes - * -------------------------------------------------------- */ +/* -------------------------------------------------------- */ +/* prototypes */ +/* -------------------------------------------------------- */ static void *ini_read(struct ini_config *, FILE *); static int ini_getline(struct ini_config *, FILE *); @@ -119,7 +119,7 @@ */ char ** -ini_get_sections_names(struct ini_config *conf, int *number) +ini_get_sections_names(const struct ini_config *conf, int *number) { struct ini_section *s; char **list; @@ -129,6 +129,10 @@ STAILQ_FOREACH(s, &conf->sections, next) ++ i; + /* For safety */ + if (number != NULL) + *number = 0; + if ((list = calloc(i + 1, sizeof (char *))) == NULL) return NULL; @@ -188,7 +192,7 @@ */ struct ini_section * -ini_select_section(struct ini_config *conf, const char *section) +ini_select_section(const struct ini_config *conf, const char *section) { struct ini_section *s; @@ -207,7 +211,7 @@ */ char * -ini_option_once(struct ini_config *conf, const char *sect, const char *key) +ini_get_option_once(const struct ini_config *conf, const char *sect, const char *key) { struct ini_option *o; struct ini_section *s; @@ -228,7 +232,7 @@ */ char ** -ini_get_option_names(struct ini_section *section, int *nb) +ini_get_option_names(const struct ini_section *section, int *nb) { char **list; struct ini_option *o; @@ -238,6 +242,9 @@ STAILQ_FOREACH(o, §ion->options, next) ++ i; + if (nb != NULL) + *nb = i; + if ((list = calloc(i + 1, sizeof (char *))) == NULL) return NULL; @@ -258,7 +265,7 @@ */ char * -ini_get_option(struct ini_section *section, const char *key) +ini_get_option(const struct ini_section *section, const char *key) { struct ini_option *o; @@ -270,16 +277,101 @@ } /* + * These section provide very small API to convert value + * and store them to the dst pointer. Because you can also + * use your own handlers, the user data here can't be used. + */ + +void +ini_value_dispatch(struct ini_config *config, struct ini_handler *hdrs, int length) +{ + const char *sectionName; + int i; + char *value; + struct ini_section *section; + + sectionName = NULL; + for (i = 0; i < length; ++i) { + /* Do not select the same section for performance. */ + if (sectionName == NULL || strcmp(hdrs[i].section, sectionName) != 0) { + sectionName = hdrs[i].section; + section = ini_select_section(config, hdrs[i].section); + } + + /* Skip the section if does not exists in the config */ + if (section == NULL) + continue; + + value = ini_get_option(section, hdrs[i].option); + hdrs[i].handler(hdrs[i].dst, value, hdrs[i].userdata); + } +} + +void +ini_convert_bool(void *dst, const char *value, void *dummy) +{ + char *p = dst; + + if (value == NULL) + return ; + + if (strcmp(value, "yes") == 0 || + strcmp(value, "true") == 0 || + strcmp(value, "1") == 0) + *p = 1; + else + *p = 0; + (void)dummy; +} + +void +ini_convert_int(void *dst, const char *value, void *dummy) +{ + int *p = dst; + + if (value == NULL) + return ; + + *p = (int) strtol(value, NULL, 10); + (void)dummy; +} + +void +ini_convert_short(void *dst, const char *value, void *dummy) +{ + short *p = dst; + + if (value == NULL) + return ; + + *p = (short) strtol(value, NULL, 10); + (void)dummy; +} + +void +ini_convert_string(void *dst, const char *value, void *dummy) +{ + char **p = dst; + + if (value == NULL) + *p = NULL; + else + *p = strdup(value); + + (void)dummy; +} + +/* * Return the last error or "No error" if there is not error at all. */ char * -ini_error(void) +ini_get_error(void) { - if (iniError[0] == '\0') + if (ini_error[0] == '\0') return "No error"; - return iniError; + return ini_error; } void @@ -410,8 +502,10 @@ handler = &ini_switch; else if (!conf->ignore) handler = &ini_register; - else + else { handler = NULL; + ++ lp; + } /* Success or not? */ if (handler != NULL && handler(conf, &lp) < 0) @@ -522,7 +616,8 @@ /* Find end of option value */ token = *endValue; if (token == '\'' || token == '"') { - for (*lp = ++endValue; *endValue != token && *endValue != '\0'; ++endValue) + for (*lp = ++endValue; *endValue != token && + *endValue != '\0'; ++endValue) continue; length = endValue - *lp; @@ -533,7 +628,8 @@ else WARN(conf, "line %d: missing '%c'\n", conf->lineno, token); } else { - for (*lp = endValue; !isspace(*endValue) && *endValue != '\0'; ++endValue) + for (*lp = endValue; !isspace(*endValue) && *endValue != '\0' && + *endValue != '#' && *endValue != ';'; ++endValue) continue; length = endValue - *lp; @@ -588,11 +684,11 @@ fclose(fp); va_start(ap, fmt); - vsnprintf(iniError, 1024, fmt, ap); + vsnprintf(ini_error, 1024, fmt, ap); va_end(ap); /* Directly print error if VERBOSE is enabled */ - WARN(conf, "%s\n", iniError); + WARN(conf, "%s\n", ini_error); free(conf);
--- a/ini.h Thu Jan 12 15:42:08 2012 +0100 +++ b/ini.h Thu Jan 12 20:12:48 2012 +0100 @@ -26,6 +26,16 @@ struct ini_config; struct ini_section; +struct ini_handler { + const char *section; /* section to query */ + const char *option; /* option to check */ + void *dst; /* where to store */ + + /* Conversion function */ + void (*handler)(void *, const char *, void *); + void *userdata; /* optional user data */ +}; + /* -------------------------------------------------------- * struct ini_config functions. * -------------------------------------------------------- */ @@ -34,31 +44,75 @@ ini_load(const char *, int); char ** -ini_get_sections_names(struct ini_config *, int *); +ini_get_sections_names(const struct ini_config *, int *); struct ini_section ** ini_get_sections(const struct ini_config *, const char *, int *); struct ini_section * -ini_select_section(struct ini_config *, const char *); +ini_select_section(const struct ini_config *, const char *); char * -ini_get_option_once(struct ini_config *, const char *, const char *); +ini_get_option_once(const struct ini_config *, const char *, const char *); void ini_free(struct ini_config *, int, int); -char * -ini_error(void); - /* -------------------------------------------------------- * struct ini_section functions. * -------------------------------------------------------- */ char ** -ini_get_option_names(struct ini_section *, int *); +ini_get_option_names(const struct ini_section *, int *); + +char * +ini_get_option(const struct ini_section *, const char *key); + +/* -------------------------------------------------------- + * convenient api to query and convert data + * -------------------------------------------------------- */ char * -ini_get_option(struct ini_section *, const char *key); +ini_get_error(void); + +/* + * For the config, read all available value and store them in + * the array ini_handler. + */ + +void +ini_value_dispatch(struct ini_config *, struct ini_handler *, int); + +/* + * Convert to bool. dst must be (char *). + * It converts "yes" "true" "1" or opposites. Only lower + * case is supported right now. + */ + +void +ini_convert_bool(void *, const char *, void *); + +/* + * Convert to a int. dst must be (int *). + */ + +void +ini_convert_int(void *, const char *, void *); + +/* + * Convert to a short. dst must be (short *). + */ + +void +ini_convert_short(void *, const char *, void *); + +/* + * Convert to a char *. dst must be (char **). This + * function use strdup() you need to free the dst + * pointer. + */ + +void +ini_convert_string(void *, const char *, void *); #endif /* _INI_H_ */
--- a/module.c Thu Jan 12 15:42:08 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * module.c -- portable functions to manipulate dynamic libraries - * - * Copyright (c) 2011, David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <stdio.h> -#include <stdlib.h> - -#include "module.h" - -struct module * -module_load(const char *path, int flags) -{ - struct module *mod; - - if ((mod = malloc(sizeof (struct module))) == NULL) - return NULL; - - /* Flags are not supported on Windows */ -#if defined(_WIN32) || defined(__WIN32__) - (void) flags; - mod->handler = LoadLibrary(path); -#else - mod->handler = dlopen(path, flags); -#endif - - if (!(mod->handler)) { - module_free(mod); - return NULL; - } - - return mod; -} - -int -module_find(struct module *mod, const char *sym) -{ -#if defined(_WIN32) || defined(__WIN32__) - mod->sym = GetProcAddress(mod->handler, sym); -#else - mod->sym = dlsym(mod->handler, sym); -#endif - - if (!(mod->sym)) - return -1; - - return 0; -} - -void -module_free(struct module *mod) -{ -#if defined(_WIN32) || defined(__WIN32__) - FreeLibrary(mod->handler); -#else - dlclose(mod->handler); -#endif - - free(mod); -}
--- a/module.h Thu Jan 12 15:42:08 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * module.h -- portable functions to manipulate dynamic libraries - * - * Copyright (c) 2011, David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _MODULE_H_ -#define _MODULE_H_ - -#if defined(_WIN32) || defined(__WIN32__) -#include <windows.h> -#else -#include <dlfcn.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Unsupported on windows */ -#if defined(_WIN32) || defined(__WIN32__) -#define MOD_LAZY 1 -#define MOD_NOW 1 -#else -#define MOD_LAZY RTLD_LAZY -#define MOD_NOW RTLD_NOW -#endif - -struct module { -#if defined(_WIN32) || defined(__WIN32__) - HMODULE handler; - FARPROC sym; -#else - void *handler; - void *sym; -#endif -}; - -struct module *module_load(const char *, int); -int module_find(struct module *, const char *); -void module_free(struct module *); - -#ifdef __cplusplus -} -#endif - -#endif /* _MODULE_H_ */
--- a/parray.c Thu Jan 12 15:42:08 2012 +0100 +++ b/parray.c Thu Jan 12 20:12:48 2012 +0100 @@ -26,26 +26,55 @@ static int parray_grow(struct parray *); -struct parray * -parray_new(enum parray_type type, int length) +int +parray_init(struct parray *arr) { - struct parray *arr; + /* Set defaults if needed */ + arr->bsize = (arr->bsize <= 0) ? PARRAY_DEFAULT_BSIZE : arr->bsize; + arr->malloc = (arr->malloc == NULL) ? &malloc : arr->malloc; + arr->realloc = (arr->realloc == NULL) ? &realloc : arr->realloc; - if ((arr = malloc(sizeof (struct parray))) == NULL) - return NULL; - - memset(arr, 0, sizeof (struct parray)); - - arr->type = type; - arr->bsize = (length == 0) ? PARRAY_DEFAULT_BSIZE : length; arr->size = LENGTH(arr->bsize); - if ((arr->datas = calloc(arr->bsize, sizeof (void *))) == NULL) { - free(arr); - return NULL; - } + if ((arr->datas = arr->malloc(arr->size)) == NULL) + return -1; + + memset(arr->datas, 0, arr->bsize); + + return 0; +} + +/* + * Valid options that can be set for an array : + * l -> optional array block size of type int + * m -> malloc function that must matches void * (*malloc)(size_t) + * r -> realloc function that must matches void * (*realloc)(void *, size_t) + * t -> type of array of type enum array_type + */ - return arr; +void +parray_set(struct parray *arr, const char *fmt, ...) +{ + va_list ap; + const char *p; + + va_start(ap, fmt); + for (p = fmt; *p != '\0'; ++p) + switch (*p) { + case 'l': + arr->bsize = va_arg(ap, int); + break; + case 'm': + arr->malloc = va_arg(ap, void * (*)(size_t)); + break; + case 'r': + arr->realloc = va_arg(ap, void *(*)(void *, size_t)); + break; + case 't': + arr->type = va_arg(ap, enum parray_type); + default: + break; + } } /* @@ -263,8 +292,6 @@ if (arr->datas) free(arr->datas); - - free(arr); } /* @@ -280,7 +307,7 @@ return 0; if (arr->type == PARRAY_AUTO) { - if ((arr->datas = realloc(arr->datas, arr->size + + if ((arr->datas = arr->realloc(arr->datas, arr->size + LENGTH(arr->bsize))) == NULL) return -1;
--- a/parray.h Thu Jan 12 15:42:08 2012 +0100 +++ b/parray.h Thu Jan 12 20:12:48 2012 +0100 @@ -23,11 +23,15 @@ extern "C" { #endif +#include <stdarg.h> + +#ifndef PARRAY_DEFAULT_BSIZE #define PARRAY_DEFAULT_BSIZE 128 +#endif enum parray_type { - PARRAY_FIXED = 0, - PARRAY_AUTO = 1 + PARRAY_AUTO = 0, + PARRAY_FIXED = 1 }; struct parray { @@ -37,25 +41,30 @@ size_t size; /* current buffer size (allocated memory) */ int bsize; /* block size (used when growing array) */ int i; /* only for PARRAY_FOREACH(_R) */ + + /* Own allocation functions */ + void * (*malloc)(size_t); + void * (*realloc)(void *, size_t); }; typedef void (*parray_map_fn)(void *, void *); typedef int (*parray_cmp_fn)(void *, void *); -struct parray *parray_new(enum parray_type, int); -int parray_push(struct parray *, void *); -int parray_insert(struct parray *, void *, int); -int parray_append(struct parray *, void *); -void parray_pop(struct parray *); -void parray_unqueue(struct parray *); -void parray_remove(struct parray *, int); -void parray_unref(struct parray *, const void *); -int parray_iswap(struct parray *, int, int); -int parray_pswap(struct parray *, const void *, const void *); -void parray_map(const struct parray *, parray_map_fn, void *); -int parray_find(const struct parray *, parray_cmp_fn, void **, void *); -void parray_clear(struct parray *); -void parray_free(struct parray *); +int parray_init(struct parray *); +void parray_set(struct parray *, const char *, ...); +int parray_push(struct parray *, void *); +int parray_insert(struct parray *, void *, int); +int parray_append(struct parray *, void *); +void parray_pop(struct parray *); +void parray_unqueue(struct parray *); +void parray_remove(struct parray *, int); +void parray_unref(struct parray *, const void *); +int parray_iswap(struct parray *, int, int); +int parray_pswap(struct parray *, const void *, const void *); +void parray_map(const struct parray *, parray_map_fn, void *); +int parray_find(const struct parray *, parray_cmp_fn, void **, void *); +void parray_clear(struct parray *); +void parray_free(struct parray *); #define PARRAY_HEAD(a) \ (a->datas[0])