summary refs log tree commit diff
path: root/arena.h
diff options
context:
space:
mode:
Diffstat (limited to 'arena.h')
-rw-r--r--arena.h56
1 files changed, 56 insertions, 0 deletions
diff --git a/arena.h b/arena.h
new file mode 100644
index 0000000..2058559
--- /dev/null
+++ b/arena.h
@@ -0,0 +1,56 @@
+#ifndef ARENA_H
+#define ARENA_H
+
+#include "typ.h"
+
+typedef struct {
+	char *beg, *end;
+} Arena;
+
+#define new(a, t)\
+	zeroed(alloc(a, sizeof(t), _Alignof(t)), sizeof(t))
+
+#define new_arr(a, t, n)\
+	alloc(a, sizeof(t) * n, _Alignof(t))
+
+#define resize(a, p, old, new)\
+	re_alloc(a, p, (old) * sizeof(*(p)), (new) * sizeof(*(p)),\
+			_Alignof(__typeof__(*(p))))
+
+void *alloc(Arena *a, isize n, isize align);
+void *re_alloc(Arena *a, void *ptr, isize old, isize new, isize align);
+void *zeroed(void *p, usize n);
+
+#ifdef ARENA_IMPL
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void *alloc(Arena *a, isize n, isize align) {
+	char *p = a->beg + (-(uintptr_t)a->beg & (align - 1));
+	if (p + n >= a->end) {
+		fprintf(stderr, "out of arena memory!\n");
+		abort();
+	}
+	a->beg = p + n;
+	return p;
+}
+
+void *zeroed(void *p, usize n) {
+	memset(p, 0, n);
+	return p;
+}
+
+void *re_alloc(Arena *a, void *ptr, isize old, isize new, isize align) {
+	if (ptr && a->beg - old == ptr && a->beg - old + new < a->end) {
+		a->beg = a->beg - old + new;
+		return ptr;
+	} else {
+		void *p = alloc(a, new, align);
+		if (ptr) memcpy(p, ptr, old);
+		return p;
+	}
+}
+
+#endif
+#endif