Here is the interface of my generic dynamic array;
/* dynamic array interface */ #ifndef DA_HEADER #define DA_HEADER #include <stdlib.h> /* size_t */ /* creates a new dynamic array, with each element of "size" bytes */ void *danew(size_t unitsize); /* returns pointer to element after the last element */ void *daend(void *arr); /* appends new element after last element return pointer to array head */ void *daappend(void *arr, const void *elem); /* removes the last element and returns a pointer to it or null if empty */ void *dapop(void *arr); /* frees the array */ void dafree(void *arr); #endif /* DA_HEADER */
and this is the implementation of my generic dynamic array:
/* dynamic array implementation */ #include <string.h> /* memcpy */ #include <stdlib.h> /* free */ #include "xalloc.h" /* xmalloc, xrealloc */ struct dynamic_array { size_t cap; size_t len; size_t unitsize; char data[1]; }; #define DATAOFFSET ((unsigned long)(((struct dynamic_array*)0)->data)) #define DA_STRUCT(DATAPTR) (struct dynamic_array *)((char *)DATAPTR-DATAOFFSET) void *danew(size_t unitsize) { /* -1 because we already have one byte in struct */ struct dynamic_array *da = xmalloc(sizeof(struct dynamic_array) + unitsize - 1); da->cap = 1; da->len = 0; da->unitsize = unitsize; return &(da->data); } static __inline struct dynamic_array *__dagrow(struct dynamic_array *da, size_t size) { while(size > da->cap) da->cap = 2*da->cap; /* -1 because we already have one byte in sizeof(struct) */ return xrealloc(da, sizeof(struct dynamic_array) + da->unitsize*da->cap - 1); } void *daappend(void *arr, const void *elem) { struct dynamic_array *da = DA_STRUCT(arr); da = __dagrow(da, da->len + 1); memcpy(&da->data[da->unitsize * da->len++], elem, da->unitsize); return &da->data; } void *dapop(void *arr) { struct dynamic_array *da = DA_STRUCT(arr); if(!da->len) return NULL; return &da->data[da->unitsize * --da->len]; } void *daend(void *arr) { struct dynamic_array *da = DA_STRUCT(arr); return &da->data[da->unitsize * da->len]; } void dafree(void *arr) { struct dynamic_array *da = DA_STRUCT(arr); free(da); }
And this is the example usage:
#include <stdio.h> #include "dynamic_array.h" struct foo { int number; char *text; }; int main() { struct foo *myfoos = danew(sizeof(struct foo)); struct foo *tmp_ptr; struct foo tmp; int i; int numbers[] = {1,2,3,4,5}; char *texts[] = {"ali", "veli","osman","zekiye","mahmut"}; for (i=0; i < 5; i++) { tmp.number = numbers[i]; tmp.text = texts[i]; myfoos = daappend(myfoos, &tmp); } /* Random access */ printf("3rd element is number: %d, text: %s", myfoos[2].number, myfoos[2].text); printf("Accessing sequentially\n"); /* Sequential access */ for (tmp_ptr = myfoos; tmp_ptr != daend(myfoos); tmp_ptr++) { printf("current element: number: %d, text: %s\n", tmp_ptr->number, tmp_ptr->text); } printf("Accessing LIFO\n"); /* LIFO access */ while((tmp_ptr = dapop(myfoos))) printf("current element number: %d, text: %s\n", tmp_ptr->number, tmp_ptr->text); return 0; }