feat and refactor: Added mult_size_t_safe and changed how new capacity is calculated for an arena

I wanted to separate things but i was getting confused on how exactly to do it
so i did the best i could, just multiply everithing by 2 and if it overflows then
well, return error, should be enough for most cases to be honest
This commit is contained in:
2026-03-30 11:26:05 -06:00
parent d6b613df10
commit 0401069a63
2 changed files with 41 additions and 18 deletions

View File

@@ -8,7 +8,7 @@
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
size_t size; size_t capacity;
size_t offset; size_t offset;
} Arena; } Arena;
@@ -19,6 +19,7 @@ typedef enum {
ARENA_NULL_ARG, ARENA_NULL_ARG,
ARENA_INVALID_SIZE, ARENA_INVALID_SIZE,
ARENA_INVALID_ALIGN, ARENA_INVALID_ALIGN,
ARENA_CAPACITY_OVERFLOW,
} ArenaErr; } ArenaErr;
typedef struct { typedef struct {
@@ -45,14 +46,17 @@ typedef struct {
}; };
} SizeResult; } SizeResult;
ArenaResult arena_init(size_t size); ArenaResult arena_init(size_t capacity);
void arena_destroy(Arena *arena); void arena_destroy(Arena *arena);
ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment); 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_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 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 #endif // !ARENA_H

View File

@@ -1,12 +1,13 @@
#include "arena.h" #include "arena.h"
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
ArenaResult arena_init(size_t size) { ArenaResult arena_init(size_t capacity) {
void *buffer = malloc(size); void *buffer = malloc(capacity);
if (buffer == NULL) { if (buffer == NULL) {
ArenaResult err = { ArenaResult err = {
.is_valid = false, .is_valid = false,
@@ -15,7 +16,7 @@ ArenaResult arena_init(size_t size) {
return err; return err;
} }
if (size < 1) { if (capacity < 1) {
ArenaResult err = { ArenaResult err = {
.is_valid = false, .is_valid = false,
.err = ARENA_INVALID_SIZE, .err = ARENA_INVALID_SIZE,
@@ -25,7 +26,7 @@ ArenaResult arena_init(size_t size) {
Arena new_arena = { Arena new_arena = {
.buffer = buffer, .buffer = buffer,
.size = size, .capacity = capacity,
.offset = 0, .offset = 0,
}; };
ArenaResult val = { ArenaResult val = {
@@ -42,7 +43,7 @@ void arena_destroy(Arena *arena) {
} }
arena->offset = 0; arena->offset = 0;
arena->size = 0; arena->capacity = 0;
free(arena->buffer); free(arena->buffer);
} }
@@ -64,7 +65,7 @@ ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) {
return err; return err;
} }
if (new_offset.val + size >= arena->size) { if (new_offset.val + size >= arena->capacity) {
ArenaPointer err = { ArenaPointer err = {
.is_valid = false, .is_valid = false,
.err = ARENA_OUT_OF_SPACE, .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); ArenaPointer pointer = arena_alloc(arena, size, alignment);
if (!pointer.is_valid) { if (!pointer.is_valid) {
SizeResult new_size = arena_compute_necessary_capacity(arena->size, size); return pointer.err;
if (!new_size.is_valid) { }
return new_size.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) { if (err != ARENA_OK) {
return err; return err;
} }
@@ -110,18 +116,18 @@ ArenaErr arena_push(Arena *arena, void *data, size_t size, size_t alignment) {
return ARENA_OK; return ARENA_OK;
} }
ArenaErr arena_realloc(Arena *arena, size_t new_size) { ArenaErr arena_realloc(Arena *arena, size_t new_capacity) {
if (arena == NULL) { if (arena == NULL) {
return ARENA_NULL_ARG; return ARENA_NULL_ARG;
} }
uint8_t *tmp = realloc(arena->buffer, new_size); uint8_t *tmp = realloc(arena->buffer, new_capacity);
if (tmp == NULL) { if (tmp == NULL) {
return ARENA_BAD_ALLOC; return ARENA_BAD_ALLOC;
} }
arena->buffer = tmp; arena->buffer = tmp;
arena->size = new_size; arena->capacity = new_capacity;
return ARENA_OK; return ARENA_OK;
} }
@@ -151,3 +157,16 @@ SizeResult align_arena_offset(Arena *arena, size_t alignment) {
return val; 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;
}