Archived
1
0
Fork 0

Adding dynamic array datastructure.

This commit is contained in:
Henrik Hautakoski 2012-08-29 11:40:50 +02:00
parent ff54ec830d
commit 891e438a7a
2 changed files with 228 additions and 0 deletions

148
array.c Normal file
View file

@ -0,0 +1,148 @@
/* array.c
*
* Copyright (C) 2010, 2012 Henrik Hautakoski <henrik@fiktivkod.org>
*
* 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 <stdlib.h>
#include <string.h>
#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;
}

80
array.h Normal file
View file

@ -0,0 +1,80 @@
/* array.h
*
* Copyright (C) 2010, 2012 Henrik Hautakoski <henrik@fiktivkod.org>
*
* 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 <stddef.h>
/*
* 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 */