From 891e438a7af2c4e5f6c274262ea47134e2343cce Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 29 Aug 2012 11:40:50 +0200 Subject: [PATCH] Adding dynamic array datastructure. --- array.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ array.h | 80 ++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 array.c create mode 100644 array.h diff --git a/array.c b/array.c new file mode 100644 index 0000000..2eba991 --- /dev/null +++ b/array.c @@ -0,0 +1,148 @@ +/* array.c + * + * Copyright (C) 2010, 2012 Henrik Hautakoski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include "xalloc.h" +#include "array.h" + +struct __array { + void *items; + unsigned nr; +}; + +static void resize(struct __array *arr, unsigned n) { + + if (!arr->nr) { + xfree(arr->items); + arr->items = NULL; + return; + } + arr->items = xrealloc(arr->items, n * arr->nr); +} + +void* array_create(void) { + + struct __array *arr = xmalloc(sizeof(struct __array)); + arr->items = NULL; + arr->nr = 0; + return arr; +} + +void* __array_copy(void *__arr, unsigned n) { + + struct __array *arr = __arr, *copy; + + if (arr && arr->nr && n) { + copy = xmalloc(sizeof(*arr)); + copy->items = xmemdup(arr->items, n * arr->nr); + copy->nr = arr->nr; + return copy; + } + return NULL; +} + +int array_destroy(void *arr) { + + array_clear(arr); + xfree(arr); + return 0; +} + +void __array_clear_fn(void *__arr, array_clear_fn_t *fn, + unsigned n) { + + struct __array *arr = __arr; + + if (arr->items) { + if (fn) { + int i; + for(i=0; i < arr->nr; i++) + fn(arr->items + (i * n)); + } + xfree(arr->items); + } + arr->items = NULL; + arr->nr = 0; +} + +int __array_insert(void *__arr, const void *item, unsigned n) { + + struct __array *arr = __arr; + if (arr) { + arr->items = xrealloc(arr->items, n * (++arr->nr)); + memcpy(arr->items + ((arr->nr - 1) * n), item, n); + return arr->nr; + } + return -1; +} + +void* __array_remove(void *__arr, unsigned i, unsigned n) { + + struct __array *arr = __arr; + void *item = NULL; + + if (i < arr->nr) { + /* I bet this will come back and bite me in the ass. */ + item = arr->items + (i * n); + if (i < --arr->nr) { + memmove(arr->items + (i * n), + arr->items + ((i + 1) * n), + (arr->nr - i) * n); + } + resize(arr, n); + } + return item; +} + +void* __array_reduce(void *__arr, unsigned n) { + + struct __array *arr = __arr; + void *item = NULL; + + if (arr->nr) { + item = arr->items + ((--arr->nr) * n); + resize(arr, n); + } + return item; +} + +int __array_indexof(void *__arr, const void *item, unsigned n) { + + int i; + struct __array *arr = __arr; + + for(i=0; i < arr->nr; i++) { + + if (!memcmp(arr->items + (i * n), item, n)) + return i; + } + return -1; +} + +void* __array_lookup(void *__arr, const void *item, + array_cmp_fn_t fn, unsigned n) { + + int i; + struct __array *arr = __arr; + + if (fn) { + for(i=0; i < arr->nr; i++) { + void *cmp = arr->items + (i * n); + if (fn(cmp, item) == 0) + return cmp; + } + } else { + i = __array_indexof(arr, item, n); + if (i >= 0) + return arr->items + (i * n); + } + return NULL; +} diff --git a/array.h b/array.h new file mode 100644 index 0000000..8b3ab76 --- /dev/null +++ b/array.h @@ -0,0 +1,80 @@ +/* array.h + * + * Copyright (C) 2010, 2012 Henrik Hautakoski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __ARRAY_H +#define __ARRAY_H + +#include + +/* + * This macro should be used to define the array struct: + * struct myarray ARRAY(struct element); + */ +#define ARRAY(type) \ + type *__items; \ + unsigned __nr; + +#define ARRAY_INIT { NULL, 0 } + +typedef void (array_clear_fn_t)(void*); +typedef int (array_cmp_fn_t)(const void *, const void *b); + +/* public API */ +void* array_create(void); + +#define array_copy(a) __array_copy(a, array_ele_size(a)) + +int array_destroy(void *arr); + +#define array_clear(a) __array_clear_fn(a, NULL, -1); + +#define array_clear_fn(a, fn) __array_clear_fn(a, fn, array_ele_size(a)); + +#define array_insert(a, i) __array_insert(a, i, array_ele_size(a)); + +#define array_remove(a, i) __array_remove(a, i, array_ele_size(a)); + +#define array_reduce(a) __array_reduce(a, array_ele_size(a)); + +#define array_has(a, i, fn) \ + (__array_lookup(a, i, fn, array_ele_size(a)) != NULL) + +#define array_size(a) ((a) ? (a)->nr : 0) + +#define array_ele_size(a) sizeof(*((a)->__items)) + +#define array_isempty(a) (!(a) || (a)->nr == 0) + +#define array_foreach(a, i) \ + for(i = (a)->__items; \ + i < ((a)->__items + (a)->__nr); \ + i++) + +/* internal */ + +void* __array_copy(void *__arr, unsigned n); + +void __array_clear_fn(void *__arr, + array_clear_fn_t *fn, unsigned n); + +int __array_insert(void *__arr, + const void *item, unsigned n); + +void* __array_remove(void *__arr, unsigned i, unsigned n); + +void* __array_reduce(void *__arr, unsigned n); + +void* __array_lookup(void *__arr, const void *item, + array_cmp_fn_t *fn, unsigned n); + +int __array_indexof(void *__arr, + const void *item, unsigned n); + +#endif /* __ARRAY_H */