summaryrefslogtreecommitdiff
path: root/src/arena.c
diff options
context:
space:
mode:
authorLinnnus <[email protected]>2024-02-01 22:59:38 +0100
committerLinnnus <[email protected]>2024-02-04 09:58:06 +0100
commitd38f82f6462af4e5aad6a2c776f5c00ce5b13c87 (patch)
tree01a222792dfb10473ae4370b4fc90f3a48e1a499 /src/arena.c
feat: initial commit
Here is a small overview of the state of the project at this first commit. I have basic Git Repo -> HTML working, and a plan for how setting up an actual server would work (mainly, NGINX + a git hook to rebuild). The main thing I'm working on right now is parsing WikiCreole, though I am starting to wonder if this is the right langauge. WikiCreole is pretty irregular and has a lot of edge cases (e.g. around emphasis).
Diffstat (limited to 'src/arena.c')
-rw-r--r--src/arena.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/arena.c b/src/arena.c
new file mode 100644
index 0000000..3782b79
--- /dev/null
+++ b/src/arena.c
@@ -0,0 +1,56 @@
+#include "arena.h"
+
+#include <assert.h> // assert
+#include <stdint.h> // uintptr_t
+#include <stdio.h> // fprintf
+#include <stdlib.h> // abort, malloc
+#include <stdnoreturn.h> // noreturn
+#include <string.h> // memset
+
+static noreturn void arena_panic(const char *reason) {
+ fprintf(stderr, "Memory allocation failed: %s", reason);
+ abort();
+}
+
+struct arena arena_create(size_t capacity) {
+ struct arena arena = {
+ .root = malloc(capacity),
+ .capacity = capacity,
+ .used = 0,
+ };
+ if (arena.root == NULL) {
+ arena_panic("cannot allocate system memory");
+ }
+ return arena;
+}
+
+void *arena_alloc(struct arena *arena, size_t size, size_t alignment, unsigned flags) {
+ // Alignment must be a power of two.
+ // See: https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
+ assert(alignment != 0 && (alignment & (alignment - 1)) == 0);
+ size_t padding = -(uintptr_t)(arena->root + arena->used) & (alignment - 1);
+
+ // If no more memory is available, we fall back to our error strategy.
+ assert(arena->capacity >= arena->used);
+ if (arena->used + padding + size > arena->capacity) {
+ if (flags & ARENA_NO_PANIC) {
+ return NULL;
+ } else {
+ arena_panic("out of preallocated memory");
+ }
+ }
+
+ // Reserve memory from arena.
+ void *ptr = arena->root + arena->used + padding;
+ arena->used += padding + size;
+
+ if (~flags & ARENA_NO_ZERO) {
+ memset(ptr, 0, size);
+ }
+
+ return ptr;
+}
+
+void arena_destroy(struct arena *arena) {
+ free(arena->root);
+}