#pragma once #include "../ni-const/niconst.h" // If custom memory management is provided, including this // header can be skipped #ifndef NIAREA_NO_STDLIB #include #endif // The size can be defined by overriding this constant #ifndef NIARENA_ARENA_SIZE #define NIARENA_ARENA_SIZE NICONST_MIB_B(4) #endif // Custom memory management can be defined as well. // Either both or none must be defined #if (!defined(NIARENA_MALLOC) && defined(NIARENA_FREE)) || (defined(NIARENA_MALLOC) && !defined(NIARENA_FREE)) #error "Either both NIARENA_MALLOC and NIARENA_FREE have to be defined or neither of them" #endif #ifndef NIARENA_MALLOC #define NIARENA_MALLOC(sz) malloc(sz) #endif #ifndef NIARENA_FREE #define NIARENA_FREE(p) free(p) #endif // Definitions typedef struct _NIArena { void *buffer; size_t capacity; size_t offset; } NIArena; const char *niarena_get_error(void); NIArena *niarena_new(void); void *niarena_alloc(NIArena *arena, size_t size); void niarena_delete(NIArena *arena); #ifdef NIARENA_IMPLEMENTATION static const char *niarena__error_reason = ""; static void niarena_error(const char *reason) { niarena__error_reason = reason; } const char * niarena_get_error(void) { return niarena__error_reason; } NIArena * niarena_new(void) { NIArena *arena = NIARENA_MALLOC(sizeof(NIArena)); if(arena == NULL) { niarena_error("niarena_new: out of memory allocating arena"); return NULL; } arena->buffer = NIARENA_MALLOC(NIARENA_ARENA_SIZE); if(arena->buffer == NULL) { NIARENA_FREE(arena); niarena_error("niarena_new: out of memory allocating buffer"); return NULL; } arena->capacity = NIARENA_ARENA_SIZE; return arena; } void * niarena_alloc(NIArena *arena, size_t size) { if((arena->capacity - arena->offset) < size) { // The allocation is invalid, but the contents of the arena // can still be used (previous allocations). niarena_error("niarena_alloc: out of memory inside of the arena"); return NULL; } arena->offset += size; return (void *)((char *)arena->buffer + arena->offset); } void niarena_delete(NIArena *arena) { NIARENA_FREE(arena->buffer); NIARENA_FREE(arena); } #endif