95 lines
2.1 KiB
C
95 lines
2.1 KiB
C
|
|
#pragma once
|
||
|
|
|
||
|
|
#include "../ni-const/niconst.h"
|
||
|
|
|
||
|
|
// If custom memory management is provided, including this
|
||
|
|
// header can be skipped
|
||
|
|
#ifndef NIAREA_NO_STDLIB
|
||
|
|
#include <stdlib.h>
|
||
|
|
#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
|