From 3b5dc6cb388012253bc52e73a5d91a5563546a56 Mon Sep 17 00:00:00 2001 From: Randy Jordan Date: Thu, 25 Jun 2026 20:48:45 -0500 Subject: [PATCH] Arena allocation --- include/ci2.h | 1 + include/platform/mem/ci2_arena.h | 62 ++++++++++++++++++++++ src/ci2_arena.c | 91 ++++++++++++++++++++++++++++++++ src/ci2_mem.c | 10 ++-- 4 files changed, 159 insertions(+), 5 deletions(-) create mode 100644 include/platform/mem/ci2_arena.h create mode 100644 src/ci2_arena.c diff --git a/include/ci2.h b/include/ci2.h index fc4262d..135831b 100644 --- a/include/ci2.h +++ b/include/ci2.h @@ -32,6 +32,7 @@ You get to decide which parts of that platform layer you'd like to use. /* Then you import which parts of the platform layer, you'd like. */ #include "./platform/error/ci2_exception.h" +#include "./platform/mem/ci2_arena.h" #include "./platform/mem/ci2_mem.h" #include "./platform/try/ci2_try.h" diff --git a/include/platform/mem/ci2_arena.h b/include/platform/mem/ci2_arena.h new file mode 100644 index 0000000..375a6b2 --- /dev/null +++ b/include/platform/mem/ci2_arena.h @@ -0,0 +1,62 @@ +/* - | Copyright / About | ---------------------------------------------------- + Copyright (c) 2026 Randy Jordan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * --------------------------------------------------------------------------*/ +#ifndef CI2_ARENA_H +#define CI2_ARENA_H + +#include "../ci2_platform.h" +#include + +struct Arena +{ + char* beg; + char* end; +}; +typedef struct Arena Arena; + +/* Initialize an Arena with an existing buffer */ +CI2_DEF void +ci2_arena_back(struct Arena* a, char* buf, ptrdiff_t len); + +/* Allocate a new Arena */ +CI2_DEF struct Arena +ci2_arena_new(ptrdiff_t cap); + +/* Get the current capacity of an Arena */ +CI2_DEF ptrdiff_t +ci2_arena_capacity(struct Arena a); + +/* Make an allocation from an Arena and do not zero.*/ +CI2_DEF void* +ci2_arena_malloc(struct Arena* a, + ptrdiff_t size, + ptrdiff_t align, + ptrdiff_t count); + +/* Make an allocation from an Arena and zero.*/ +CI2_DEF void* +ci2_arena_calloc(struct Arena* a, + ptrdiff_t size, + ptrdiff_t align, + ptrdiff_t count); + +#endif // ci2_arena.h diff --git a/src/ci2_arena.c b/src/ci2_arena.c new file mode 100644 index 0000000..a34f40c --- /dev/null +++ b/src/ci2_arena.c @@ -0,0 +1,91 @@ +/* - | Copyright / About | ---------------------------------------------------- + Copyright (c) 2026 Randy Jordan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * --------------------------------------------------------------------------*/ + +#include "../include/platform/mem/ci2_arena.h" +#include +#include +#include + +/* Initialize an Arena with an existing buffer */ +void +ci2_arena_back(struct Arena* a, char* buf, ptrdiff_t len) +{ + CI2_ASSERT(a != NULL); + CI2_ASSERT(buf != NULL); + a->beg = buf; + a->end = buf + len; +} + +/* Allocate a new Arena */ +struct Arena +ci2_arena_new(ptrdiff_t cap) +{ + struct Arena a = { 0 }; + a.beg = malloc(cap); + a.end = a.beg ? a.beg + cap : 0; + return a; +} + +/* Get the current capacity of an Arena */ +ptrdiff_t +ci2_arena_capacity(struct Arena a) +{ + ptrdiff_t res = a.end - a.beg; + return res; +} + +/* Make an allocation from an Arena and do not zero.*/ +void* +ci2_arena_calloc(struct Arena* a, + ptrdiff_t size, + ptrdiff_t align, + ptrdiff_t count) +{ + ptrdiff_t padding = -(uintptr_t)a->beg & (align - 1); + ptrdiff_t available = a->end - a->beg - padding; + if (available < 0 || count > available / size) { + return NULL; + } + ptrdiff_t total = padding + count * size; + void* p = a->beg + total; + a->beg += total; + return memset(p, 0, total); +} + +/* Make an allocation from an Arena and zero.*/ +void* +ci2_arena_malloc(struct Arena* a, + ptrdiff_t size, + ptrdiff_t align, + ptrdiff_t count) +{ + ptrdiff_t padding = -(uintptr_t)a->beg & (align - 1); + ptrdiff_t available = a->end - a->beg - padding; + if (available < 0 || count > available / size) { + return NULL; + } + ptrdiff_t total = padding + count * size; + void* p = a->beg + total; + a->beg += total; + return p; +} diff --git a/src/ci2_mem.c b/src/ci2_mem.c index 906780c..5fa4d84 100644 --- a/src/ci2_mem.c +++ b/src/ci2_mem.c @@ -34,7 +34,7 @@ void* ci2_alloc(size_t nbytes, const char* file, int line) { void* ptr; - ci2_rt_assert(nbytes > 0); + CI2_ASSERT(nbytes > 0); ptr = malloc(nbytes); if (ptr == NULL) { if (file == NULL) @@ -49,8 +49,8 @@ void* ci2_calloc(size_t count, size_t nbytes, const char* file, int line) { void* ptr; - ci2_rt_assert(count > 0); - ci2_rt_assert(nbytes > 0); + CI2_ASSERT(count > 0); + CI2_ASSERT(nbytes > 0); ptr = calloc(count, nbytes); if (ptr == NULL) { if (file == NULL) @@ -74,8 +74,8 @@ ci2_free(void* ptr, const char* file, int line) void* ci2_resize(void* ptr, size_t nbytes, const char* file, int line) { - // ci2_rt_assert(ptr); // ? Maybe - // ci2_rt_assert(nbytes > 0);// ? Maybe + // CI2_ASSERT(ptr); // ? Maybe + // CI2_ASSERT(nbytes > 0);// ? Maybe void* tmp = realloc(ptr, nbytes); if (tmp == NULL) { if (file == NULL)