summary refs log tree commit diff
diff options
context:
space:
mode:
authorWormHeamer2025-02-28 17:00:08 -0500
committerWormHeamer2025-02-28 17:00:08 -0500
commit622624ab7ac364701f0bbb9164beb6f10ddb29fd (patch)
treee8717c319851f0dc95fe89b2d3a38a0073336249
parent93608e2f90689c0eddd4714debcab9892f1dc7d7 (diff)
add zone.h (memory arenas)
-rw-r--r--zone.h97
1 files changed, 97 insertions, 0 deletions
diff --git a/zone.h b/zone.h
new file mode 100644
index 0000000..4daa2fa
--- /dev/null
+++ b/zone.h
@@ -0,0 +1,97 @@
+#ifndef ZONE_H
+#define ZONE_H
+
+#include <stdint.h>
+
+#define ZONE_FRAME_CAPACITY_DEFAULT 1024
+
+typedef struct ZoneFrame ZoneFrame;
+struct ZoneFrame {
+	ZoneFrame *prev, *next;
+	size_t length, capacity;
+	uintptr_t data[];
+};
+
+typedef struct {
+	ZoneFrame *tail, *here;
+} Zone;
+
+void zn_free(Zone *z);
+void zn_clear(Zone *z);
+
+void *zn_alloc(Zone *z, size_t n);
+char *zn_strdup(Zone *z, const char *s);
+
+#ifdef ZONE_IMPL
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "zone.h"
+
+static ZoneFrame *zn_new_frame(size_t capacity) {
+	ZoneFrame *zf = malloc(sizeof *zf + capacity * sizeof(uintptr_t));
+	if (!zf) {
+		fprintf(stderr, "failed to allocate memory zone frame\n");
+		abort();
+	}
+	zf->prev = NULL;
+	zf->next = NULL;
+	zf->length = 0;
+	zf->capacity = capacity;
+	return zf;
+}
+
+void *zn_alloc(Zone *z, size_t n) {
+	ZoneFrame *zf = NULL;
+	size_t wordsz = (n + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
+	for (ZoneFrame *f = z->here; f; f = f->next) {
+		if (f->capacity - f->length >= wordsz) {
+			zf = f;
+			break;
+		}
+	}
+	if (!zf) {
+		size_t cap = ZONE_FRAME_CAPACITY_DEFAULT;
+		while (wordsz >= cap) cap <<= 1; 
+		zf = zn_new_frame(cap);
+		zf->prev = z->tail;
+		if (z->tail) z->tail->next = zf;
+		z->tail = zf;
+	}
+	void *ptr = &zf->data[zf->length];
+	zf->length += wordsz;
+	z->here = zf;
+	return ptr;
+}
+
+void zn_free(Zone *z) {
+	ZoneFrame *p, *t;
+	t = z->tail;
+	while (t) {
+		p = t->prev;
+		free(t);
+		t = p;
+	}
+}
+
+void zn_clear(Zone *z) {
+	ZoneFrame *zf = z->here;
+	if (!zf) return;
+	for (;;) {
+		zf->length = 0;
+		if (zf->prev) zf = zf->prev;
+		else break;
+	}
+	z->tail = zf;
+}
+
+char *zn_strdup(Zone *z, const char *s) {
+	size_t n = strlen(s) + 1;
+	char *d = zn_alloc(z, n);
+	memcpy(d, s, n);
+	return d;
+}
+
+#endif
+#endif