Compare commits

..

9 Commits

Author SHA1 Message Date
0401069a63 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
2026-03-30 11:26:05 -06:00
d6b613df10 feat: Added align_arena_offset
Added it, it should work, no testing by now so damn, but its fine,
used aformula from stack overflow :)
2026-03-29 21:08:34 -06:00
a8423ca80f refactor: Changed align_arena to arena_align and changed signatrue, added arena_calculate_capacity
I need to assure that capacity is enough, i mean, for something like
an array just doubling size is good because you are storing things
that are the same size but for something like an arena you could actually
store anything so we need to make sure the growth factor stays cool while
an overflow doesn't occur, that's why the change with arena_calculate_capacity
and also changing signatrues to use results, A LOT of boilerplate but
i guess is fine for me.
2026-03-29 20:59:32 -06:00
00942d3bd6 feat: Added arena_push and arena_realloc
decided that arena_push will handle everything, will use alloc then push into it,
also, used realloc as a separate function for better handling resize and shit, next
is creating a save function that calculates the size needed for the element
and if it's too fucking much then throw an error. A bit overkill but yeah, i'm like
that all the time, this is suppossed to be a library to support my calculator like
damn but ok.
2026-03-29 19:06:49 -06:00
cde457593e feat: Added arena_alloc
Added arena_alloc and decided to change the arena pointer type from void *
to uint8_t * because i need to support 1 byte pointer arithmetic, thought of
using uintptr_t but not sure, the support seems really weird from what i read
online so i'm sticking with good old uint8_t * (wich i know works).
2026-03-29 18:35:13 -06:00
47c0a04166 feat and fix: Made arena_init use malloc and added arena_destroy
Realized that if i want to use malloc and free i either have to make some
sort of interface that lets you use a custom allocator and deallocator
or just use them by default. Maybe later it would be cool to change it
to that but for now is out of the scope of my project.

# Tipos:
# feat, fix, refactor, docs, style, test, chore
2026-03-29 18:00:57 -06:00
d95d7f2b51 feat(arena.c): Added arena init and added ArenaResult
Want to handle errors with results, even if it meas boilerplate
2026-03-29 17:53:10 -06:00
9e9875de6b fix(.gitignore): Changed gitignore to ignore text files for commit messages
# Tipos:
# feat, fix, refactor, docs, style, test, chore
2026-03-29 17:42:17 -06:00
e8270791a4 feat(header): added signatures for devolping further functions 2026-03-29 17:30:01 -06:00
3 changed files with 231 additions and 0 deletions

2
.gitignore vendored
View File

@@ -52,3 +52,5 @@ rules.ninja
*.swo
*~
# Git
COMMIT_MESSAGE

View File

@@ -1,4 +1,62 @@
#ifndef ARENA_H
#define ARENA_H
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdbool.h>
typedef struct {
uint8_t *buffer;
size_t capacity;
size_t offset;
} Arena;
typedef enum {
ARENA_OK = 0,
ARENA_BAD_ALLOC,
ARENA_OUT_OF_SPACE,
ARENA_NULL_ARG,
ARENA_INVALID_SIZE,
ARENA_INVALID_ALIGN,
ARENA_CAPACITY_OVERFLOW,
} ArenaErr;
typedef struct {
bool is_valid;
union {
ArenaErr err;
uint8_t *address;
};
} ArenaPointer;
typedef struct {
bool is_valid;
union {
ArenaErr err;
Arena arena;
};
} ArenaResult;
typedef struct {
bool is_valid;
union {
ArenaErr err;
size_t val;
};
} SizeResult;
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_capacity);
SizeResult align_arena_offset(Arena *arena, size_t alignment);
// 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

View File

@@ -1 +1,172 @@
#include "arena.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
ArenaResult arena_init(size_t capacity) {
void *buffer = malloc(capacity);
if (buffer == NULL) {
ArenaResult err = {
.is_valid = false,
.err = ARENA_BAD_ALLOC,
};
return err;
}
if (capacity < 1) {
ArenaResult err = {
.is_valid = false,
.err = ARENA_INVALID_SIZE,
};
return err;
}
Arena new_arena = {
.buffer = buffer,
.capacity = capacity,
.offset = 0,
};
ArenaResult val = {
.is_valid = true,
.arena = new_arena,
};
return val;
}
void arena_destroy(Arena *arena) {
if (arena == NULL) {
return;
}
arena->offset = 0;
arena->capacity = 0;
free(arena->buffer);
}
ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) {
if (arena == NULL) {
ArenaPointer err = {
.is_valid = false,
.err = ARENA_NULL_ARG,
};
return err;
}
SizeResult new_offset = align_arena_offset(arena, alignment);
if (!new_offset.is_valid) {
ArenaPointer err = {
.is_valid = false,
.err = new_offset.err,
};
return err;
}
if (new_offset.val + size >= arena->capacity) {
ArenaPointer err = {
.is_valid = false,
.err = ARENA_OUT_OF_SPACE,
};
return err;
}
arena->offset = new_offset.val;
ArenaPointer val = {
.is_valid = true,
.address = arena->buffer + arena->offset,
};
return val;
}
ArenaErr arena_push(Arena *arena, void *data, size_t size, size_t alignment) {
if (arena == NULL || data == NULL) {
return ARENA_NULL_ARG;
}
ArenaPointer pointer = arena_alloc(arena, size, alignment);
if (!pointer.is_valid) {
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_capacity);
if (err != ARENA_OK) {
return err;
}
pointer = arena_alloc(arena, size, alignment);
}
memcpy(
pointer.address,
data,
size);
return ARENA_OK;
}
ArenaErr arena_realloc(Arena *arena, size_t new_capacity) {
if (arena == NULL) {
return ARENA_NULL_ARG;
}
uint8_t *tmp = realloc(arena->buffer, new_capacity);
if (tmp == NULL) {
return ARENA_BAD_ALLOC;
}
arena->buffer = tmp;
arena->capacity = new_capacity;
return ARENA_OK;
}
SizeResult align_arena_offset(Arena *arena, size_t alignment) {
if (arena == NULL) {
SizeResult err = {
.is_valid = false,
.err = ARENA_NULL_ARG,
};
return err;
}
if (alignment < 1) {
SizeResult err = {
.is_valid = false,
.err = ARENA_INVALID_ALIGN,
};
return err;
}
SizeResult val = {
.is_valid = true,
.val = ((arena->offset + (alignment - 1)) & ~(alignment - 1)),
// Formula for alignment, found at stackoverflow, i came up with one
// but it involved 3 divisions, this one is way faster :)
};
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;
}