diff options
Diffstat (limited to 'arr.c')
-rw-r--r-- | arr.c | 110 |
1 files changed, 42 insertions, 68 deletions
@@ -1,75 +1,49 @@ +/* OPTIM: is it faster to store void *end? */ typedef struct { - void *data; size_t len; size_t cap; - size_t item_sz; -} Array; - -static void arr_create(Array *arr, size_t item_sz) { - arr->len = arr->cap = 0; - arr->item_sz = item_sz; - arr->data = NULL; -} - -static inline void arr_reserve(Array *arr, size_t n) { - arr->cap = n; - arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); -} - -static inline void arr_reservea(Array *arr, size_t n, Allocator *a) { - arr->cap = n; - arr->data = allocr_realloc(a, arr->data, arr->item_sz * arr->cap); -} - -/* like arr_reserve, but sets the length of the array too */ -static inline void arr_set_len(Array *arr, size_t n) { - arr_reserve(arr, n); - arr->len = n; -} - -static inline void arr_set_lena(Array *arr, size_t n, Allocator *a) { - arr_reservea(arr, n, a); - arr->len = n; -} - -static inline void *arr_last(Array *arr) { - if (arr->data) - return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); - else - return NULL; -} - -static void *arr_add(Array *arr) { - if (arr->len >= arr->cap) { - arr_reserve(arr, (arr->cap + 1) * 2); + max_align_t data[]; +} ArrHeader; + +static inline ArrHeader *arr_hdr(void *arr) { + ArrHeader *hdr = (ArrHeader *)((char *)arr - offsetof(ArrHeader, data)); + return hdr; +} + +static inline size_t arr_len(void *arr) { + if (arr == NULL) return 0; + return arr_hdr(arr)->len; +} + +static void arr_resv_(void **arr, size_t n, size_t item_sz) { + if (*arr == NULL) { + ArrHeader *hdr = err_malloc(item_sz * n + sizeof(ArrHeader)); + hdr->len = 0; + hdr->cap = n; + *arr = hdr->data; + } else { + ArrHeader *hdr = arr_hdr(*arr); + hdr->cap = n; + hdr = realloc(hdr, item_sz * n + sizeof(ArrHeader)); + if (hdr->len > hdr->cap) hdr->len = hdr->cap; + *arr = hdr->data; } - arr->len++; - return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); -} - -static void *arr_adda(Array *arr, Allocator *a) { - if (arr->len >= arr->cap) { - arr_reservea(arr, (arr->cap + 1) * 2, a); + +} + +static void *arr_add_(void **arr, size_t item_sz) { + ArrHeader *hdr; + if (*arr == NULL) { + arr_resv_(*arr, 10, item_sz); + hdr = arr_hdr(*arr); + } else { + hdr = arr_hdr(*arr); + if (hdr->len >= hdr->cap) { + arr_resv_(*arr, hdr->len * 2, item_sz); + hdr = arr_hdr(*arr); + } } - arr->len++; - return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); -} - -static void arr_clear(Array *arr) { - free(arr->data); - arr->len = arr->cap = 0; - arr->data = NULL; -} - -static void arr_remove_last(Array *arr) { - /* OPTIM (memory): Shorten array. */ - arr->len--; -} - -static void arr_free(Array *arr) { - free(arr->data); + return &(((char *)hdr->data)[(hdr->len++) * item_sz]); } -/* NOTE: this will not work if type is a pointer! */ -#define arr_foreach(arr, type, var) for (type *var = (arr)->data, *var##_foreach_last = arr_last(arr); var; var == var##_foreach_last ? var = NULL : var++) -#define arr_foreach_reverse(arr, type, var) for (type *var = arr_last(arr); var; var == (arr)->data ? var = NULL : var--) +#define arr_add(arr) arr_add_((void **)arr, sizeof **arr) |