diff --git a/include/arena.h b/include/arena.h index 2fd778b..121bedd 100644 --- a/include/arena.h +++ b/include/arena.h @@ -6,11 +6,7 @@ #include #include -typedef struct { - uint8_t *buffer; - size_t capacity; - size_t offset; -} Arena; +typedef struct Arena Arena; typedef enum { ARENA_OK = 0, @@ -37,7 +33,7 @@ typedef struct { bool is_valid; union { ArenaErr err; - Arena arena; + Arena *arena; }; } ArenaResult; @@ -49,8 +45,8 @@ typedef struct { }; } ArenaSizeResult; -ArenaResult arena_init(size_t capacity); -void arena_destroy(Arena *arena); +ArenaErr arena_init(Arena **arena, size_t capacity); +ArenaErr arena_destroy(Arena **arena); ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment); ArenaPointer arena_push(Arena *arena, void *data, size_t size, size_t alignment); diff --git a/src/arena.c b/src/arena.c index 46bc52a..7d7c34d 100644 --- a/src/arena.c +++ b/src/arena.c @@ -5,32 +5,56 @@ #include #include +struct Arena { + uint8_t *buffer; + size_t capacity; + size_t offset; +}; -ArenaResult arena_init(size_t capacity) { +ArenaErr arena_init(Arena **arena, size_t capacity) { + if (arena == NULL) { + return ARENA_NULL_ARG; + } + if (capacity < 1) { - return (ArenaResult) {.is_valid = false, .err = ARENA_INVALID_SIZE}; + return ARENA_INVALID_SIZE; + } + + Arena *new_arena = malloc(sizeof(Arena)); + if (new_arena == NULL) { + return ARENA_BAD_ALLOC; } void *buffer = malloc(capacity); if (buffer == NULL) { - return (ArenaResult) {.is_valid = false, .err = ARENA_BAD_ALLOC}; + return ARENA_BAD_ALLOC; } - Arena new_arena = { + *new_arena = (Arena) { .buffer = buffer, .capacity = capacity, .offset = 0, }; - return (ArenaResult) {.is_valid = true, .arena = new_arena}; + *arena = new_arena; + + return ARENA_OK; } -void arena_destroy(Arena *arena) { - free(arena->buffer); - arena->buffer = NULL; - arena->offset = 0; - arena->capacity = 0; +ArenaErr arena_destroy(Arena **arena) { + if (arena == NULL || *arena == NULL) { + return ARENA_NULL_ARG; + } + + free((*arena)->buffer); + (*arena)->buffer = NULL; + (*arena)->offset = 0; + (*arena)->capacity = 0; + free(*arena); + *arena = NULL; + + return ARENA_OK; } ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) { @@ -51,6 +75,11 @@ ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) { return (ArenaPointer) {.is_valid = false, .err = padding.err}; } + ArenaErr cap_err = arena_ensure_capacity(arena, size, alignment); + if(cap_err != ARENA_OK) { + return (ArenaPointer) {.is_valid = false, .err = ARENA_OUT_OF_SPACE}; + } + if (arena->offset + padding.val + size > arena->capacity) { return (ArenaPointer) {.is_valid = false, .err = ARENA_OUT_OF_SPACE}; } diff --git a/test/test_arena.c b/test/test_arena.c index 93190a5..756b524 100644 --- a/test/test_arena.c +++ b/test/test_arena.c @@ -14,23 +14,22 @@ static void test_push_3_ints(void **state) { (void) state; - ArenaResult value = arena_init(sizeof(int) * 3); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, sizeof(int) * 3), ARENA_OK); int int_to_push = 20; - ArenaPointer result = arena_push(&arena, &int_to_push, sizeof(int), alignof(int)); + ArenaPointer result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); assert_int_equal(20, *(int*)arena_unwrap_pointer(result)); assert_int_equal(20, *(int*)arena_unwrap_pointer(result)); int_to_push = 30; - result = arena_push(&arena, &int_to_push, sizeof(int), alignof(int)); + result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); assert_int_equal(30, *(int*)arena_unwrap_pointer(result)); int_to_push = 40; - result = arena_push(&arena, &int_to_push, sizeof(int), alignof(int)); + result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); assert_int_equal(40, *(int*)arena_unwrap_pointer(result)); @@ -40,32 +39,34 @@ static void test_push_3_ints(void **state) { static void test_push_3_ints_2_doubles(void **state) { (void) state; - ArenaResult value = arena_init((sizeof(int) * 3) + (sizeof(double) * 2)); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal( + arena_init(&arena, (sizeof(int) * 3) + (sizeof(double) * 2)), + ARENA_OK + ); int int_to_push = 20; - ArenaPointer result = arena_push(&arena, &int_to_push, sizeof(int), alignof(int)); + ArenaPointer result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); assert_int_equal(20, *(int*)arena_unwrap_pointer(result)); double double_to_push = 4.57; - result = arena_push(&arena, &double_to_push, sizeof(double), alignof(double)); + result = arena_push(arena, &double_to_push, sizeof(double), alignof(double)); assert_true(result.is_valid); assert_double_equal(4.57, *(double*)arena_unwrap_pointer(result), 1e-6); int_to_push = 30; - result = arena_push(&arena, &int_to_push, sizeof(int), alignof(int)); + result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); assert_int_equal(30, *(int*)arena_unwrap_pointer(result)); int_to_push = 40; - result = arena_push(&arena, &int_to_push, sizeof(int), alignof(int)); + result = arena_push(arena, &int_to_push, sizeof(int), alignof(int)); assert_true(result.is_valid); assert_int_equal(40, *(int*)arena_unwrap_pointer(result)); double_to_push = 267.33; - result = arena_push(&arena, &double_to_push, sizeof(double), alignof(double)); + result = arena_push(arena, &double_to_push, sizeof(double), alignof(double)); assert_true(result.is_valid); assert_double_equal(267.33, *(double*)arena_unwrap_pointer(result), 1e-6); @@ -75,19 +76,17 @@ static void test_push_3_ints_2_doubles(void **state) { static void test_init_arena_0_cap(void **state) { (void) state; - ArenaResult arena = arena_init(0); - assert_false(arena.is_valid); - assert_int_equal(arena.err, ARENA_INVALID_SIZE); + Arena *arena; + assert_int_equal(arena_init(&arena, 0), ARENA_INVALID_SIZE); } static void test_arena_alloc_size_0(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaPointer pointer = arena_alloc(&arena, 0, alignof(int)); + ArenaPointer pointer = arena_alloc(arena, 0, alignof(int)); assert_false(pointer.is_valid); assert_int_equal(pointer.err, ARENA_INVALID_SIZE); @@ -97,11 +96,10 @@ static void test_arena_alloc_size_0(void **state) { static void test_arena_alloc_size_max(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaPointer pointer = arena_alloc(&arena, SIZE_MAX, alignof(int)); + ArenaPointer pointer = arena_alloc(arena, SIZE_MAX, alignof(int)); assert_false(pointer.is_valid); assert_int_equal(pointer.err, ARENA_OUT_OF_SPACE); @@ -111,11 +109,10 @@ static void test_arena_alloc_size_max(void **state) { static void test_arena_alloc_align_0(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaPointer pointer = arena_alloc(&arena, sizeof(int), 0); + ArenaPointer pointer = arena_alloc(arena, sizeof(int), 0); assert_false(pointer.is_valid); assert_int_equal(pointer.err, ARENA_INVALID_ALIGN); @@ -125,11 +122,10 @@ static void test_arena_alloc_align_0(void **state) { static void test_arena_alloc_align_max(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaPointer pointer = arena_alloc(&arena, sizeof(int), SIZE_MAX); + ArenaPointer pointer = arena_alloc(arena, sizeof(int), SIZE_MAX); assert_false(pointer.is_valid); assert_int_equal(pointer.err, ARENA_INVALID_ALIGN); @@ -139,11 +135,10 @@ static void test_arena_alloc_align_max(void **state) { static void test_arena_align_size_0(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaPointer pointer = arena_alloc(&arena, sizeof(int), 0); + ArenaPointer pointer = arena_alloc(arena, sizeof(int), 0); assert_false(pointer.is_valid); assert_int_equal(pointer.err, ARENA_INVALID_ALIGN); @@ -153,11 +148,10 @@ static void test_arena_align_size_0(void **state) { static void test_arena_ensure_capacity_size_0(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaErr err = arena_ensure_capacity(&arena, 0, alignof(int)); + ArenaErr err = arena_ensure_capacity(arena, 0, alignof(int)); assert_int_equal(err, ARENA_INVALID_SIZE); arena_destroy(&arena); @@ -166,11 +160,10 @@ static void test_arena_ensure_capacity_size_0(void **state) { static void test_arena_ensure_capacity_size_max(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaErr err = arena_ensure_capacity(&arena, SIZE_MAX, alignof(int)); + ArenaErr err = arena_ensure_capacity(arena, SIZE_MAX, alignof(int)); assert_int_equal(err, ARENA_INVALID_SIZE); arena_destroy(&arena); @@ -179,11 +172,10 @@ static void test_arena_ensure_capacity_size_max(void **state) { static void test_arena_ensure_capacity_align_0(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaErr err = arena_ensure_capacity(&arena, sizeof(int), 0); + ArenaErr err = arena_ensure_capacity(arena, sizeof(int), 0); assert_int_equal(err, ARENA_INVALID_ALIGN); arena_destroy(&arena); @@ -192,11 +184,10 @@ static void test_arena_ensure_capacity_align_0(void **state) { static void test_arena_ensure_capacity_align_max(void **state) { (void) state; - ArenaResult value = arena_init(64); - assert_true(value.is_valid); - Arena arena = value.arena; + Arena *arena; + assert_uint_equal(arena_init(&arena, 64), ARENA_OK); - ArenaErr err = arena_ensure_capacity(&arena, sizeof(int), SIZE_MAX); + ArenaErr err = arena_ensure_capacity(arena, sizeof(int), SIZE_MAX); assert_int_equal(err, ARENA_INVALID_ALIGN); arena_destroy(&arena);