summaryrefslogtreecommitdiff
path: root/arr.c
diff options
context:
space:
mode:
Diffstat (limited to 'arr.c')
-rw-r--r--arr.c110
1 files changed, 42 insertions, 68 deletions
diff --git a/arr.c b/arr.c
index ff94377..6ec7db2 100644
--- a/arr.c
+++ b/arr.c
@@ -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)