Mercurial > code
changeset 91:b3ba5f5df3b9
New style for array.c and array.h, no pointer to these object thus
no need to check if array_new succeeded. array_set() added to use own
allocation functions and other settings at any time
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 03 Jan 2012 16:05:06 +0100 |
parents | 145493469aa0 |
children | 4d723e81b685 |
files | array.c array.h |
diffstat | 2 files changed, 59 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/array.c Wed Nov 30 11:11:51 2011 +0100 +++ b/array.c Tue Jan 03 16:05:06 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_new(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 default 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 Wed Nov 30 11:11:51 2011 +0100 +++ b/array.h Tue Jan 03 16:05:06 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 { @@ -38,12 +42,17 @@ size_t unit; /* unit size (sizeof the object) */ int bsize; /* block size (used when growing array) */ int i; /* only for ARRAY_FOREACH(_R) */ + + /* Own alloc function */ + 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_new(struct array *, size_t); +void array_set(struct array *arr, const char *fmt, ...); int array_push(struct array *, const void *); int array_insert(struct array *, const void *, int); int array_append(struct array *, const void *); @@ -66,10 +75,6 @@ ((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); \ (a)->i < (a)->length; \