#ifndef ARENA_H #define ARENA_H #include #include typedef uint8_t err_t; struct arena_chunk { uintptr_t start; size_t size; }; struct arena { uint8_t *data; size_t cur; size_t cap; struct { struct arena_chunk *items; size_t size; size_t cap; } chunks; }; struct arena_err_t { struct arena arena; err_t err; }; struct arena_void_p_err_t { struct arena arena; err_t err; void *ptr; }; enum arena_err { ARENA_ERR_OK = 0, ARENA_ERR_MALLOC_FAIL, ARENA_ERR_HIT_CAP, ARENA_ERR_INVALID_PTR }; struct arena_err_t arena_create(size_t cap); err_t arena_destroy(struct arena arena); struct arena_void_p_err_t arena_alloc(struct arena arena, size_t size, _Bool zero_it); struct arena_err_t arena_free(struct arena arena, void *ptr); struct arena_err_t arena_forget(struct arena arena, _Bool zero_it); err_t arena_dump_chunks(struct arena arena); #if defined(ARENA_IMP) || defined(IMP) #include #include #include "da.h" 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 }; DA_CREATE(arena.chunks, sizeof(struct arena_chunk)); return (struct arena_err_t) { .arena = arena, .err = ARENA_ERR_OK }; } err_t arena_destroy(struct arena arena) { free(arena.data); DA_DESTROY(arena.chunks); return ARENA_ERR_OK; } struct arena_void_p_err_t arena_alloc(struct arena arena, size_t size, _Bool zero_it) { if ( arena.cur + size >= arena.cap ) { return (struct arena_void_p_err_t) { .arena = arena, .ptr = NULL, .err = ARENA_ERR_HIT_CAP }; } void *ptr = (void *) (arena.data + arena.cur); arena.cur += size; struct arena_chunk chunk = { .start = (uintptr_t) ptr, .size = size }; DA_APPEND(arena.chunks, chunk); if ( zero_it != 0 ) { memset(ptr, 0, size); } return (struct arena_void_p_err_t) { .arena = arena, .ptr = ptr, .err = ARENA_ERR_OK }; } struct arena_err_t arena_free(struct arena arena, void *ptr) { uintptr_t p = (uintptr_t) ptr; struct arena_chunk ac = {0}; _Bool found = 0; size_t chunk_index = 0; for ( ; chunk_index < arena.chunks.size; ++chunk_index ) { ac = arena.chunks.items[chunk_index]; if ( ac.start == p ) { found = 1; break; } } if ( found == 0 ) { return (struct arena_err_t) { .arena = arena, .err = ARENA_ERR_INVALID_PTR }; } DA_DELETE(arena.chunks, chunk_index); return (struct arena_err_t) { .arena = arena, .err = ARENA_ERR_OK }; } struct arena_err_t arena_forget(struct arena arena, _Bool zero_it) { arena.cur = 0; if ( zero_it != 0 ) { memset(arena.data, 0, arena.cap); } DA_CLEAR(arena.chunks); return (struct arena_err_t) { .arena = arena, .err = ARENA_ERR_OK }; } #include err_t arena_dump_chunks(struct arena arena) { struct arena_chunk ac = {0}; printf("Allocated Chunks (%li)\n", arena.chunks.size); for ( size_t i = 0; i < arena.chunks.size; ++i ) { ac = arena.chunks.items[i]; printf("\tstart: %ld, size: %li\n", ac.start, ac.size); } return ARENA_ERR_OK; } #endif /* ARENA_IMP || IMPLEMENTATIONS */ #endif /* ARENA_H */