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:
47
src/arena.c
47
src/arena.c
@@ -1,12 +1,13 @@
|
||||
#include "arena.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user