summaryrefslogtreecommitdiff
path: root/dynarr.h
diff options
context:
space:
mode:
Diffstat (limited to 'dynarr.h')
-rw-r--r--dynarr.h71
1 files changed, 71 insertions, 0 deletions
diff --git a/dynarr.h b/dynarr.h
new file mode 100644
index 0000000..fb577ef
--- /dev/null
+++ b/dynarr.h
@@ -0,0 +1,71 @@
+#ifndef DYNARR_H
+#define DYNARR_H
+
+#include "arena.h"
+
+#define DYNARR(t) struct { t *data; ptrdiff_t len, cap; }
+
+#define ZDA_FIT(da, c, zn) ((typeof((da)->data))\
+ zda_fit((void **)&(da)->data, sizeof((da)->data[0]),\
+ _Alignof(typeof((da)->data[0])), \
+ c, &(da)->cap, zn))
+
+#define ZDA_FIT_ALIGN(da, c, a, zn) ((typeof((da)->data))\
+ zda_fit((void **)&(da)->data, sizeof((da)->data[0]), a,\
+ c, &(da)->cap, zn))
+
+#define ZDA_GROW(da, n, zn) ZDA_FIT(da, (da)->len + n, zn)
+
+#define ZDA_PUSH(da, v, zn)\
+ (ZDA_GROW(da, 1, zn)[(da)->len++] = (v))
+
+#define ZDA_INIT_CAP 32
+
+#define DA_FIT(da, c) ((typeof((da)->data))\
+ da_fit((void **)&(da)->data, sizeof((da)->data[0]), c, &(da)->cap))
+
+#define DA_FIT_ALIGN(da, c, a) ((typeof((da)->data))\
+ da_fit((void **)&(da)->data, sizeof((da)->data[0]), a, c, &(da)->cap)
+
+#define DA_GROW(da, n) DA_FIT(da, (da)->len + n)
+#define DA_PUSH(da, ...) (DA_GROW(da, 1)[(da)->len++] = (__VA_ARGS__))
+#define DA_INIT_CAP 32
+
+void *da_fit(void **data, ptrdiff_t size, ptrdiff_t fit, ptrdiff_t *cap);
+void *zda_fit(void **data, ptrdiff_t size, ptrdiff_t align, ptrdiff_t fit, ptrdiff_t *cap, Arena *a);
+
+#ifdef DYNARR_IMPL
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void *da_fit(void **data, ptrdiff_t size, ptrdiff_t fit, ptrdiff_t *cap) {
+ ptrdiff_t c = *cap;
+ if (c >= fit) return *data;
+ if (!c) c = DA_INIT_CAP;
+ while (c < fit) c <<= 1;
+ size_t sz = c * size;
+ void *p = *data ? realloc(*data, sz) : malloc(sz);
+ if (!p) {
+ fprintf(stderr, "dynamic array resize failure\n");
+ abort();
+ }
+ *cap = c;
+ *data = p;
+ return p;
+}
+
+void *zda_fit(void **data, ptrdiff_t size, ptrdiff_t align, ptrdiff_t fit, ptrdiff_t *cap, Arena *a) {
+ ptrdiff_t C = *cap;
+ ptrdiff_t c = C;
+ if (c >= fit) return *data;
+ if (!c) c = ZDA_INIT_CAP;
+ while (c < fit) c <<= 1;
+ void *p = arena_realloc(a, *data, C * size, c * size, align);
+ *cap = c;
+ *data = p;
+ return p;
+}
+
+#endif
+#endif