#ifndef ARENA_ #define ARENA_ #include #include #include #define ARENA_BLOCK_SIZE 256 #include "byte_slice.c" struct arena { uint8_t *ptr; size_t len; size_t capacity; }; int arena_init(struct arena *arena) { arena->ptr = malloc(ARENA_BLOCK_SIZE); if (!arena->ptr) { return -1; } arena->len = 0; arena->capacity = ARENA_BLOCK_SIZE; return 0; } void arena_deinit(struct arena *arena) { free(arena->ptr); arena->ptr = NULL; } static uint64_t div_round_up(uint64_t a, uint64_t b) { return a % b == 0 ? a / b * b : (a / b + 1) * b; } void *arena_alloc(struct arena *arena, size_t size) { if (arena->ptr == NULL && arena_init(arena)) { return NULL; } if (arena->len + size > arena->capacity) { size_t new_capacity = div_round_up(arena->len + size, ARENA_BLOCK_SIZE); void *new_ptr = realloc(arena->ptr, new_capacity); if (!new_ptr) { return NULL; } arena->ptr = new_ptr; arena->capacity = new_capacity; } void *result = (void*)&arena->ptr[arena->len]; arena->len += size; return result; } void *arena_dupe(struct arena *arena, void *ptr, size_t len) { void *new_ptr = arena_alloc(arena, len); if (!new_ptr) { return NULL; } if (ptr) { memcpy(new_ptr, ptr, len); } return new_ptr; } struct byte_slice arena_dupe_slice(struct arena *arena, struct byte_slice slice) { void *new_ptr = arena_dupe(arena, slice.ptr, slice.len); if (!new_ptr) { return byte_slice_init_zero(); } return byte_slice_init(new_ptr, slice.len); } #endif //ARENA_