diff --git a/src/arena_allocator.c b/src/arena_allocator.c new file mode 100644 index 00000000..0cfb0f97 --- /dev/null +++ b/src/arena_allocator.c @@ -0,0 +1,44 @@ +#include "arena_allocator.h" + +#include +#include + +void lxl_arena_init(lua_State *L, lxl_arena *arena) { + lua_newtable(L); + arena->L = L; arena->ref = lua_gettop(L); +} + +void *lxl_arena_malloc(lxl_arena *arena, size_t size) { + if (!arena || !arena->L) return NULL; + if (!lua_istable(arena->L, arena->ref)) luaL_error(arena->L, "invalid arena reference"); + void *data = lua_newuserdata(arena->L, size); + lua_pushlightuserdata(arena->L, data); + lua_pushvalue(arena->L, -2); + lua_settable(arena->L, arena->ref); + lua_pop(arena->L, 1); + return data; +} + +void *lxl_arena_zero(lxl_arena *arena, size_t size) { + void *v = lxl_arena_malloc(arena, size); + return v ? memset(v, 0, size) : NULL; +} + +char *lxl_arena_strdup(lxl_arena *arena, const char *str) { + if (!str) return NULL; + return lxl_arena_copy(arena, (void *) str, (strlen(str) + 1) * sizeof(char)); +} + +char *lxl_arena_copy(lxl_arena *arena, void *ptr, size_t len) { + if (!ptr) return NULL; + char *output = lxl_arena_malloc(arena, sizeof(char) * len); + return output ? memcpy(output, ptr, len) : NULL; +} + +void lxl_arena_free(lxl_arena *arena, void *ptr) { + if (!arena || !arena->L || !ptr) return; + if (!lua_istable(arena->L, arena->ref)) luaL_error(arena->L, "invalid arena reference"); + lua_pushlightuserdata(arena->L, ptr); + lua_pushnil(arena->L); + lua_settable(arena->L, arena->ref); +} \ No newline at end of file diff --git a/src/arena_allocator.h b/src/arena_allocator.h new file mode 100644 index 00000000..2ef6decc --- /dev/null +++ b/src/arena_allocator.h @@ -0,0 +1,25 @@ +/** + * An arena allocator using the Lua state; similar to luaL_Buffer. + * Initialize the arena with lxl_arena_init(), and you can use lxl_arena_malloc(), + * lxl_arena_zero() to allocate (and optionally zero) the memory. + * lxl_arena_free() can be optionally used to free memory, but this is generally not needed. + */ + +#ifndef LUA_ALLOCATOR_H +#define LUA_ALLOCATOR_H + +#include + +typedef struct lxl_arena { + lua_State *L; + int ref; +} lxl_arena; + +void lxl_arena_init(lua_State *L, lxl_arena *arena); +void *lxl_arena_malloc(lxl_arena *arena, size_t size); +void *lxl_arena_zero(lxl_arena *arena, size_t size); +char *lxl_arena_copy(lxl_arena *arena, void *ptr, size_t len); +char *lxl_arena_strdup(lxl_arena *arena, const char *str); +void lxl_arena_free(lxl_arena *arena, void *ptr); + +#endif \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index 60acf45c..76ac1c89 100644 --- a/src/meson.build +++ b/src/meson.build @@ -6,6 +6,7 @@ lite_sources = [ 'api/system.c', 'api/process.c', 'api/utf8.c', + 'arena_allocator.c', 'renderer.c', 'renwindow.c', 'rencache.c',