#ifndef ARENA_H #define ARENA_H #include typedef uint8_t err_t; struct arena { uint8_t *data; size_t cur; size_t cap; }; struct void_p_err_t { void *ptr; err_t err; }; struct arena_void_p_err_t { struct arena arena; void *ptr; err_t err; }; struct arena_err_t { struct arena arena; err_t err; }; enum arena_err { ARENA_ERR_OK = 0, ARENA_ERR_MALLOC_FAIL, ARENA_ERR_HIT_CAP }; struct arena_err_t arena_create(size_t cap); err_t arena_destroy(struct arena arena); struct void_p_err_t arena_alloc(struct arena *arena, size_t size); struct arena_void_p_err_t arena_alloc_pure(struct arena arena, size_t size); err_t arena_forget(struct arena *arena); struct arena_err_t arena_forget_pure(struct arena arena); #if defined(ARENA_IMP) || defined(IMP) #include struct arena_err_t arena_create(size_t cap) { void *data = calloc(cap, sizeof(uint8_t)); if ( data == NULL ) { return (struct arena_err_t) { .err = ARENA_ERR_MALLOC_FAIL }; } struct arena arena = { .data = data, .cap = cap, .cur = 0 }; return (struct arena_err_t) { .arena = arena, .err = ARENA_ERR_OK }; } err_t arena_destroy(struct arena arena) { free(arena.data); return ARENA_ERR_OK; } struct void_p_err_t arena_alloc(struct arena *arena, size_t size) { if ( arena->cur + size >= arena->cap ) { return (struct void_p_err_t) { .ptr = NULL, .err = ARENA_ERR_HIT_CAP }; } void * ptr = (void *) (arena->data + arena->cur); arena->cur += size; return (struct void_p_err_t) { .ptr = ptr, .err = ARENA_ERR_OK }; } struct arena_void_p_err_t arena_alloc_pure(struct arena arena, size_t size) { struct void_p_err_t vpet = arena_alloc(&arena, size); return (struct arena_void_p_err_t) { .arena = arena, .ptr = vpet.ptr, .err = vpet.err }; } err_t arena_forget(struct arena *arena) { arena->cur = 0; return ARENA_ERR_OK; } struct arena_err_t arena_forget_pure(struct arena arena) { err_t err = arena_forget(&arena); return (struct arena_err_t) { .arena = arena, .err = err }; } #endif /* ARENA_IMP || IMPLEMENTATIONS */ #endif /* ARENA_H */