diff --git a/include/arena.h b/include/arena.h index 6715694..62db6ca 100644 --- a/include/arena.h +++ b/include/arena.h @@ -8,7 +8,7 @@ typedef struct { uint8_t *buffer; - size_t size; + size_t capacity; size_t offset; } Arena; @@ -19,6 +19,7 @@ typedef enum { ARENA_NULL_ARG, ARENA_INVALID_SIZE, ARENA_INVALID_ALIGN, + ARENA_CAPACITY_OVERFLOW, } ArenaErr; typedef struct { @@ -45,14 +46,17 @@ typedef struct { }; } SizeResult; -ArenaResult arena_init(size_t size); +ArenaResult arena_init(size_t capacity); void arena_destroy(Arena *arena); ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment); ArenaErr arena_push(Arena *arena, void *data, size_t size, size_t alignment); -ArenaErr arena_realloc(Arena *arena, size_t new_size); +ArenaErr arena_realloc(Arena *arena, size_t new_capacity); SizeResult align_arena_offset(Arena *arena, size_t alignment); -SizeResult arena_compute_necessary_capacity(size_t capacity, size_t elem_size); + +// Should be moved to something like general utilities, +// i should make one for all my c projects +bool mul_size_t_safe(size_t a, size_t b, size_t *out); #endif // !ARENA_H diff --git a/src/arena.c b/src/arena.c index b25ea4f..f0e88cc 100644 --- a/src/arena.c +++ b/src/arena.c @@ -1,12 +1,13 @@ #include "arena.h" #include +#include +#include #include #include -#include -ArenaResult arena_init(size_t size) { +ArenaResult arena_init(size_t capacity) { - void *buffer = malloc(size); + void *buffer = malloc(capacity); if (buffer == NULL) { ArenaResult err = { .is_valid = false, @@ -15,7 +16,7 @@ ArenaResult arena_init(size_t size) { return err; } - if (size < 1) { + if (capacity < 1) { ArenaResult err = { .is_valid = false, .err = ARENA_INVALID_SIZE, @@ -25,7 +26,7 @@ ArenaResult arena_init(size_t size) { Arena new_arena = { .buffer = buffer, - .size = size, + .capacity = capacity, .offset = 0, }; ArenaResult val = { @@ -42,7 +43,7 @@ void arena_destroy(Arena *arena) { } arena->offset = 0; - arena->size = 0; + arena->capacity = 0; free(arena->buffer); } @@ -64,7 +65,7 @@ ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) { return err; } - if (new_offset.val + size >= arena->size) { + if (new_offset.val + size >= arena->capacity) { ArenaPointer err = { .is_valid = false, .err = ARENA_OUT_OF_SPACE, @@ -89,12 +90,17 @@ ArenaErr arena_push(Arena *arena, void *data, size_t size, size_t alignment) { ArenaPointer pointer = arena_alloc(arena, size, alignment); if (!pointer.is_valid) { - SizeResult new_size = arena_compute_necessary_capacity(arena->size, size); - if (!new_size.is_valid) { - return new_size.err; + return pointer.err; + } + while (!pointer.is_valid && pointer.err == ARENA_OUT_OF_SPACE) { + size_t new_capacity; + + bool is_overflow = mul_size_t_safe(arena->capacity, 2, &new_capacity); + if (is_overflow) { + return ARENA_CAPACITY_OVERFLOW; } - ArenaErr err = arena_realloc(arena, new_size.val); + ArenaErr err = arena_realloc(arena, new_capacity); if (err != ARENA_OK) { return err; } @@ -110,18 +116,18 @@ ArenaErr arena_push(Arena *arena, void *data, size_t size, size_t alignment) { return ARENA_OK; } -ArenaErr arena_realloc(Arena *arena, size_t new_size) { +ArenaErr arena_realloc(Arena *arena, size_t new_capacity) { if (arena == NULL) { return ARENA_NULL_ARG; } - uint8_t *tmp = realloc(arena->buffer, new_size); + uint8_t *tmp = realloc(arena->buffer, new_capacity); if (tmp == NULL) { return ARENA_BAD_ALLOC; } arena->buffer = tmp; - arena->size = new_size; + arena->capacity = new_capacity; return ARENA_OK; } @@ -151,3 +157,16 @@ SizeResult align_arena_offset(Arena *arena, size_t alignment) { return val; } +bool mul_size_t_safe(size_t a, size_t b, size_t *out) { + if (out == NULL) { + return true; + } + + if (a != 0 && b > SIZE_MAX / a) { + return true; + } + + *out = a * b; + return false; +} +