commit d8295a48cf792eafc3d1fb12c80b2946bfa66427
parent 23be80cdbfceac075f9bc4f8744ec2f78b59fa67
Author: citbl <citbl@citbl.org>
Date: Wed, 13 May 2026 22:25:06 +1000
basic arena wip
Diffstat:
| A | src/arena.c | | | 104 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/arena.h | | | 17 | +++++++++++++++++ |
2 files changed, 121 insertions(+), 0 deletions(-)
diff --git a/src/arena.c b/src/arena.c
@@ -0,0 +1,104 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "arena.h"
+#include "check.h"
+
+// not thread safe
+
+struct Arena {
+ uint8_t* buf;
+ size_t cap;
+ size_t pos;
+};
+
+Arena* arena_init(size_t bytes)
+{
+ Arena* a;
+ if (!bytes || bytes == 0) {
+ bytes = 1024;
+ }
+ a = malloc(sizeof(Arena));
+ if (!a) {
+ fprintf(stderr, "arena_init failed to alloc\n");
+ return NULL;
+ }
+ a->buf = malloc(bytes);
+ if (!a->buf) {
+ free(a);
+ fprintf(stderr, "arena_init: failed to allocate buffer\n");
+ return NULL;
+ }
+ a->cap = bytes;
+ a->pos = 0;
+
+ return a;
+}
+
+static size_t align_to(size_t offset, size_t align)
+{
+ // align to a power of 2
+ return (offset + align - 1) & ~(align - 1);
+}
+
+void* arena_alloc(Arena* a, size_t size, size_t align)
+{
+ size_t pos, new_cap;
+ void* ptr;
+ uint8_t* p;
+
+ if (!a) {
+ fprintf(stderr, "arena: no arena given to alloc to\n");
+ return NULL;
+ }
+ if (!size) {
+ fprintf(stderr, "arena: no arena size given to alloc to\n");
+ return NULL;
+ }
+ if (!align) {
+ fprintf(stderr, "arena: no arena alignment given to alloc to\n");
+ return NULL;
+ }
+ if ((align & (align - 1)) != 0) { /* not power of two */
+ fprintf(stderr, "arena: alignment must be a power of two\n");
+ return NULL;
+ }
+
+ pos = align_to(a->pos, align);
+ if (SIZE_MAX - pos < size) {
+ fprintf(stderr, "arena_alloc: too large for available memory\n");
+ free(a->buf);
+ return NULL;
+ }
+ if (pos + size > a->cap) {
+ new_cap = a->cap == 0 ? 1024 : a->cap * 2;
+ check(new_cap <= a->cap || new_cap > SIZE_MAX / sizeof(uint8_t), "arena: could not reallocate arena, underflow or overflow\n");
+ p = realloc(a->buf, new_cap);
+ if (!p) {
+ fprintf(stderr, "arena: could not reallocate double its size!\n");
+ free(a->buf);
+ return NULL;
+ }
+ a->buf = p;
+ a->cap = new_cap;
+ }
+
+ ptr = a->buf + pos;
+ a->pos = pos + size;
+ return (void*)ptr;
+}
+
+void arena_reset(Arena* a)
+{
+ if (!a) return;
+ a->pos = 0;
+}
+
+void arena_destroy(Arena* a)
+{
+ if (!a) return;
+ free(a->buf);
+ free(a);
+}
+
diff --git a/src/arena.h b/src/arena.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <stddef.h>
+
+#define ARENA_ALLOC(arena, type) \
+ ((type*)arena_alloc((arena), sizeof(type), alignof(type)))
+
+typedef struct Arena Arena;
+
+Arena* arena_init(size_t bytes);
+
+void* arena_alloc(Arena*, size_t size, size_t align);
+
+void arena_reset(Arena*);
+
+void arena_destroy(Arena*);
+