Compare commits

37 Commits

Author SHA1 Message Date
0af6a0f104 test/refactor: lock approach taken, best one 2026-06-10 10:21:43 -06:00
73dc05bc63 addition: allocator generator and functions 2026-06-08 19:10:38 -06:00
2dcef95b2e refactor: arena uses Allocator 2026-06-06 09:48:18 -06:00
f3a5ecf807 refactor: changed to xmake, added lae_allocator dep 2026-06-06 09:15:59 -06:00
203b60cf65 refactor: xmake is now in use 2026-05-26 13:52:28 -06:00
78640a3288 fix: formatting 2026-05-26 13:11:10 -06:00
ff97f5fc2f Change cmakelists 2026-05-20 18:53:21 -06:00
a91123b71a Fix for test construction 2026-05-20 17:00:02 -06:00
b2bbb85fcc Merge pull request 'refactor-consistency' (#1) from refactor-consistency into main
Reviewed-on: #1
2026-05-13 20:32:20 -06:00
fb832eab06 refactor: tests adapted and succesfully passed 2026-05-13 20:25:55 -06:00
6c91e1f681 refactor: init and destroy, alloc now first ensures cap
its better usability and is better that it ensures capacity in alloc
like that is what is supposed to be like damn, why i did it like that
2026-05-13 20:10:40 -06:00
f981ba92a8 refactor: Arena is opaque, init returns error code
Is to make it more consistent, i need to change also later arraylist the
init function so its also more consistent, next is making alloc ensure
capacity first so no using it first or some shit.
2026-05-13 19:57:49 -06:00
7c7c68381c Update test/CMakeLists.txt 2026-04-23 12:09:34 -06:00
7af0ca7556 Update CMakeLists.txt 2026-04-23 12:09:07 -06:00
945aa9a27f better compatility cmake 2026-04-23 12:00:35 -06:00
8ebaf06d11 changed project name 2026-04-23 11:58:59 -06:00
3d3b8596cc fix: ArenaSizeResult definition 2026-04-11 22:29:01 -06:00
14eef43f8c refactor: Changed SizeResult to ArenaSizeResult 2026-04-11 21:19:16 -06:00
54522fece5 delete: Deleted helper utility funcitons 2026-04-11 21:17:38 -06:00
15b5cc382f test/refactor: changed things for working with more edge cases 2026-04-11 21:15:31 -06:00
d069a108ce test: Added a buch of tests, also fixes :) 2026-04-11 18:21:40 -06:00
6cea0ddf25 test: Added further testing and fixed functions for edge cases 2026-04-11 11:30:04 -06:00
19a6faf40f test: Tested new ArenaPointerDefinition 2026-04-10 21:09:51 -06:00
121261e24b refactor: Modified ArenaPointer
ArenaPointer now contains a reference to the original arena and an
offset instad of a raw address. Change was made to avoid invalidating
addresses and keeping a more consise system. arena_unwrap_pointer was
also included as a helper function.
2026-04-10 20:54:02 -06:00
cf848f2e37 refactor: Changed Result types return sytaxis 2026-04-03 15:57:54 -06:00
a207018511 fix: Moved padding declaration in arena_ensure_capacity
descripcion mas detallada
2026-04-03 12:51:49 -06:00
0c2e819c2b refactor(all): Fixed alloc and moved growing logic to another function
OK, so evrything was a fucknig mess, it still kinda is, AI helped
me to clean my own mess, it really sucks but the fucking debugger
and address sanitizer were not working, also, there were small
small errors so no big deal but still, a bit sad, also changed a
the way i cast from uint8_t to double and int in the tests, may
change that i guess, verything else i might say is good :)
2026-04-03 12:44:01 -06:00
39dfded924 test and rework: Added push test and cahnged arena_push return
So added a little test that just adds 3 ints to an arena, nothing much
but the basics work, also changed arena_push because it only pushed and
didn't returned a ponter (wich is fucking useless) so also fixed that,
everything seems fine now, need more tests.

# Tipos:
# feat, fix, refactor, docs, style, test, chore
2026-03-31 19:15:37 -06:00
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
10 changed files with 768 additions and 52 deletions

8
.gitignore vendored
View File

@@ -7,6 +7,12 @@ out/
out/Debug/
out/Release/
# xmake
xmake/
xmake/*
.xmake
.xmake/*
# Cmake files
CMakeCache.txt
CMakeFiles/
@@ -52,3 +58,5 @@ rules.ninja
*.swo
*~
# Git
COMMIT_MESSAGE

View File

@@ -1,33 +0,0 @@
cmake_minimum_required(VERSION 3.20)
project(calculator VERSION 1.0 LANGUAGES C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
# Export compile_commands.json (para clangd)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_options(
-Wall
-Wextra
-Wpedantic
)
include_directories(include)
add_library(arena_lib
src/arena.c
)
add_executable(arena_main src/main.c)
target_link_libraries(arena_main arena_lib)
# ------------------------
# Testing
# ------------------------
enable_testing()
add_subdirectory(test)

View File

@@ -1,4 +0,0 @@
#ifndef ARENA_H
#define ARENA_H
#endif // !ARENA_H

72
include/lae_arena.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef LAE_ARENA_H
#define LAE_ARENA_H
#include "lae_allocator.h"
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct Arena 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,
ARENA_LOCKED,
} ArenaErr;
typedef struct {
bool is_valid;
union {
ArenaErr err;
struct {
Arena *arena;
size_t offset;
};
};
} ArenaPointer;
typedef struct {
bool is_valid;
union {
ArenaErr err;
Allocator allocator;
};
} ArenaAllocator;
typedef struct {
bool is_valid;
union {
ArenaErr err;
size_t val;
};
} ArenaSizeResult;
ArenaErr arena_init(Arena **arena, Allocator allocator, size_t capacity);
ArenaErr arena_destroy(Arena **arena);
ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment);
ArenaPointer
arena_push_data(Arena *arena, void *data, size_t size, size_t alignment);
ArenaErr arena_resize(Arena *arena, size_t new_capacity);
void *arena_unwrap_pointer(ArenaPointer p);
ArenaSizeResult arena_get_align_padding(Arena *arena, size_t alignment);
// can take big sizes but of sourse there is a limit,
// its protected against SIZE_MAX but anything that
// is big may break it, still, is an edge case that
// I shouldn't cover.
ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment);
ArenaErr arena_lock_growth(Arena *arena);
ArenaErr arena_unlock_growth(Arena *arena);
ArenaAllocator arena_get_allocator(Arena *arena);
#endif // !RENA_H

View File

@@ -1 +0,0 @@
#include "arena.h"

313
src/lae_arena.c Normal file
View File

@@ -0,0 +1,313 @@
#include "lae_arena.h"
#include "lae_allocator.h"
#include <stdalign.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
struct Arena {
uint8_t *buffer;
size_t capacity;
size_t offset;
bool growth_locked;
Allocator allocator;
};
static void *arena_allocator_alloc(void *ctx, size_t size, size_t alignment);
static void *arena_allocator_realloc(
void *ctx,
void *pointer,
size_t old_size,
size_t new_size,
size_t alignment);
static void
arena_allocator_free(void *ctx, void *pointer, size_t size, size_t alignment);
ArenaErr arena_init(Arena **arena, Allocator allocator, size_t capacity) {
if (arena == NULL) {
return ARENA_NULL_ARG;
}
if (capacity < 1) {
return ARENA_INVALID_SIZE;
}
Arena *new_arena =
allocator.alloc(allocator.ctx, sizeof(Arena), alignof(Arena));
if (new_arena == NULL) {
return ARENA_BAD_ALLOC;
}
void *buffer = allocator.alloc(allocator.ctx, capacity, 0);
if (buffer == NULL) {
allocator.free(allocator.ctx, new_arena, capacity, 0);
return ARENA_BAD_ALLOC;
}
*new_arena = (Arena){
.buffer = buffer,
.capacity = capacity,
.offset = 0,
.growth_locked = false,
.allocator = allocator,
};
*arena = new_arena;
return ARENA_OK;
}
ArenaErr arena_destroy(Arena **arena) {
if (arena == NULL || *arena == NULL) {
return ARENA_NULL_ARG;
}
Arena *tmp = *arena;
tmp->allocator.free(tmp->allocator.ctx, tmp->buffer, tmp->capacity, 0);
tmp->buffer = NULL;
tmp->offset = 0;
tmp->capacity = 0;
tmp->growth_locked = false;
tmp->allocator
.free(tmp->allocator.ctx, *arena, sizeof(Arena), alignof(Arena));
*arena = NULL;
return ARENA_OK;
}
ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) {
if (arena == NULL) {
return (ArenaPointer){.is_valid = false, .err = ARENA_NULL_ARG};
}
if (size < 1) {
return (ArenaPointer){.is_valid = false, .err = ARENA_INVALID_SIZE};
}
if (alignment < 1) {
return (ArenaPointer){.is_valid = false, .err = ARENA_INVALID_ALIGN};
}
ArenaSizeResult padding = arena_get_align_padding(arena, alignment);
if (!padding.is_valid) {
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};
}
if (arena->offset > SIZE_MAX - padding.val - size) {
return (ArenaPointer){.is_valid = false,
.err = ARENA_CAPACITY_OVERFLOW};
}
size_t aligned_offset = arena->offset + padding.val;
arena->offset = aligned_offset + size;
return (ArenaPointer){.is_valid = true,
.offset = aligned_offset,
.arena = arena};
}
ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment) {
if (arena == NULL) {
return ARENA_NULL_ARG;
}
if (size == 0 || size == SIZE_MAX) {
return ARENA_INVALID_SIZE;
}
if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
return ARENA_INVALID_ALIGN;
}
ArenaSizeResult padding_res = arena_get_align_padding(arena, alignment);
if (!padding_res.is_valid) {
return padding_res.err;
}
size_t padding = padding_res.val;
while (true) {
size_t required;
if (arena->offset > SIZE_MAX - padding) {
return ARENA_CAPACITY_OVERFLOW;
}
required = arena->offset + padding;
if (required > SIZE_MAX - size) {
return ARENA_CAPACITY_OVERFLOW;
}
required += size;
if (required <= arena->capacity) {
return ARENA_OK;
}
size_t new_capacity;
if (arena->capacity > SIZE_MAX / 2) {
return ARENA_CAPACITY_OVERFLOW;
}
new_capacity = arena->capacity * 2;
if (new_capacity < required) {
new_capacity = required;
}
ArenaErr err = arena_resize(arena, new_capacity);
if (err != ARENA_OK) {
return err;
}
}
}
ArenaPointer
arena_push_data(Arena *arena, void *data, size_t size, size_t alignment) {
if (arena == NULL || data == NULL) {
return (ArenaPointer){.is_valid = false, .err = ARENA_NULL_ARG};
}
if (size < 1) {
return (ArenaPointer){.is_valid = false, .err = ARENA_INVALID_SIZE};
}
if (size < 1) {
return (ArenaPointer){.is_valid = false, .err = ARENA_INVALID_ALIGN};
}
ArenaErr err = arena_ensure_capacity(arena, size, alignment);
if (err != ARENA_OK) {
return (ArenaPointer){.is_valid = false, .err = err};
}
ArenaPointer pointer = arena_alloc(arena, size, alignment);
if (!pointer.is_valid) {
return pointer;
}
memcpy(arena_unwrap_pointer(pointer), data, size);
return pointer;
}
ArenaErr arena_resize(Arena *arena, size_t new_capacity) {
if (arena == NULL) {
return ARENA_NULL_ARG;
}
if (new_capacity < 1) {
return ARENA_INVALID_SIZE;
}
if (arena->growth_locked) {
return ARENA_LOCKED;
}
uint8_t *tmp = arena->allocator.realloc(
arena->allocator.ctx,
arena->buffer,
arena->capacity,
new_capacity,
0);
if (tmp == NULL) {
return ARENA_BAD_ALLOC;
}
arena->buffer = tmp;
arena->capacity = new_capacity;
return ARENA_OK;
}
ArenaSizeResult arena_get_align_padding(Arena *arena, size_t alignment) {
if (arena == NULL) {
return (ArenaSizeResult){.is_valid = false, .err = ARENA_NULL_ARG};
}
if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
return (ArenaSizeResult){.is_valid = false, .err = ARENA_INVALID_ALIGN};
}
uintptr_t current_address = (uintptr_t)(arena->buffer + arena->offset);
size_t mask = alignment - 1;
size_t padding = (size_t)(-current_address) & mask;
return (ArenaSizeResult){.is_valid = true, .val = padding};
}
ArenaErr arena_lock_growth(Arena *arena) {
if (arena == NULL) {
return ARENA_NULL_ARG;
}
arena->growth_locked = true;
return ARENA_OK;
}
ArenaErr arena_unlock_growth(Arena *arena) {
if (arena == NULL) {
return ARENA_NULL_ARG;
}
arena->growth_locked = false;
return ARENA_OK;
}
void *arena_unwrap_pointer(ArenaPointer p) {
if (!p.is_valid) {
return NULL;
}
return p.arena->buffer + p.offset;
}
static void *arena_allocator_alloc(void *ctx, size_t size, size_t alignment) {
Arena *arena = ctx;
return arena_unwrap_pointer(arena_alloc(arena, size, alignment));
}
static void *arena_allocator_realloc(
void *ctx,
void *pointer,
size_t old_size,
size_t new_size,
size_t alignment) {
return NULL;
}
static void
arena_allocator_free(void *ctx, void *pointer, size_t size, size_t alignment) {
return;
}
ArenaAllocator arena_get_allocator(Arena *arena) {
if (arena == NULL) {
return (ArenaAllocator){
.is_valid = false,
.err = ARENA_NULL_ARG,
};
}
arena->growth_locked = true;
Allocator allocator = {
.alloc = arena_allocator_alloc,
.realloc = arena_allocator_realloc,
.free = arena_allocator_free,
.ctx = arena};
return (ArenaAllocator){.is_valid = true, .allocator = allocator};
}

View File

@@ -1,4 +1,4 @@
#include "arena.h"
#include "lae_arena.h"
#include <stdlib.h>
int main(void) {

View File

@@ -1,10 +0,0 @@
find_package(cmocka REQUIRED)
add_executable(test_arena test_arena.c)
target_link_libraries(test_arena
arena_lib
cmocka::cmocka
)
add_test(NAME arena_tests COMMAND test_arena)

View File

@@ -1,6 +1,283 @@
#include "arena.h"
#include <stdlib.h>
#include <cmocka.h>
#include <limits.h>
#include <setjmp.h>
#include <stdalign.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "lae_allocator.h"
#include "lae_arena.h"
static void test_push_3_ints(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(
arena_init(&arena, allocator_default(), sizeof(int) * 3),
ARENA_OK);
int int_to_push = 20;
ArenaPointer result =
arena_push_data(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_data(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_data(arena, &int_to_push, sizeof(int), alignof(int));
assert_true(result.is_valid);
assert_int_equal(40, *(int *)arena_unwrap_pointer(result));
arena_destroy(&arena);
}
static void test_push_3_ints_2_doubles(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(
arena_init(
&arena,
allocator_default(),
(sizeof(int) * 3) + (sizeof(double) * 2)),
ARENA_OK);
int int_to_push = 20;
ArenaPointer result =
arena_push_data(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_data(
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_data(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_data(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_data(
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);
arena_destroy(&arena);
}
static void test_init_arena_0_cap(void **state) {
(void)state;
Arena *arena;
assert_int_equal(
arena_init(&arena, allocator_default(), 0),
ARENA_INVALID_SIZE);
}
static void test_arena_alloc_size_0(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaPointer pointer = arena_alloc(arena, 0, alignof(int));
assert_false(pointer.is_valid);
assert_int_equal(pointer.err, ARENA_INVALID_SIZE);
arena_destroy(&arena);
}
static void test_arena_alloc_size_max(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaPointer pointer = arena_alloc(arena, SIZE_MAX, alignof(int));
assert_false(pointer.is_valid);
assert_int_equal(pointer.err, ARENA_OUT_OF_SPACE);
arena_destroy(&arena);
}
static void test_arena_alloc_align_0(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaPointer pointer = arena_alloc(arena, sizeof(int), 0);
assert_false(pointer.is_valid);
assert_int_equal(pointer.err, ARENA_INVALID_ALIGN);
arena_destroy(&arena);
}
static void test_arena_alloc_align_max(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaPointer pointer = arena_alloc(arena, sizeof(int), SIZE_MAX);
assert_false(pointer.is_valid);
assert_int_equal(pointer.err, ARENA_INVALID_ALIGN);
arena_destroy(&arena);
}
static void test_arena_align_size_0(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaPointer pointer = arena_alloc(arena, sizeof(int), 0);
assert_false(pointer.is_valid);
assert_int_equal(pointer.err, ARENA_INVALID_ALIGN);
arena_destroy(&arena);
}
static void test_arena_ensure_capacity_size_0(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaErr err = arena_ensure_capacity(arena, 0, alignof(int));
assert_int_equal(err, ARENA_INVALID_SIZE);
arena_destroy(&arena);
}
static void test_arena_ensure_capacity_size_max(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaErr err = arena_ensure_capacity(arena, SIZE_MAX, alignof(int));
assert_int_equal(err, ARENA_INVALID_SIZE);
arena_destroy(&arena);
}
static void test_arena_ensure_capacity_align_0(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaErr err = arena_ensure_capacity(arena, sizeof(int), 0);
assert_int_equal(err, ARENA_INVALID_ALIGN);
arena_destroy(&arena);
}
static void test_arena_ensure_capacity_align_max(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaErr err = arena_ensure_capacity(arena, sizeof(int), SIZE_MAX);
assert_int_equal(err, ARENA_INVALID_ALIGN);
arena_destroy(&arena);
}
static void test_arena_allocator_valid_allocation(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaAllocator result = arena_get_allocator(arena);
assert_true(result.is_valid);
Allocator arena_allocator = result.allocator;
int *x =
arena_allocator.alloc(arena_allocator.ctx, sizeof(int), alignof(int));
assert_non_null(x);
*x = 34;
assert_int_equal(*x, 34);
arena_destroy(&arena);
}
static void test_arena_allocatro_many_allocations(void **state) {
(void)state;
Arena *arena;
assert_uint_equal(arena_init(&arena, allocator_default(), 64), ARENA_OK);
ArenaAllocator result = arena_get_allocator(arena);
assert_true(result.is_valid);
Allocator arena_allocator = result.allocator;
for (int i = 0; i < 10; i++) {
int *x = arena_allocator.alloc(
arena_allocator.ctx,
sizeof(int),
alignof(int));
assert_non_null(x);
}
arena_destroy(&arena);
}
static void test_arena_allocator_from_null_arena(void **state) {
(void)state;
Arena *arena = NULL;
ArenaAllocator result = arena_get_allocator(arena);
assert_false(result.is_valid);
}
int main(void) {
return EXIT_SUCCESS;
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_push_3_ints),
cmocka_unit_test(test_push_3_ints_2_doubles),
cmocka_unit_test(test_init_arena_0_cap),
cmocka_unit_test(test_arena_alloc_size_0),
cmocka_unit_test(test_arena_alloc_size_max),
cmocka_unit_test(test_arena_alloc_align_0),
cmocka_unit_test(test_arena_alloc_align_max),
cmocka_unit_test(test_arena_align_size_0),
cmocka_unit_test(test_arena_ensure_capacity_align_0),
cmocka_unit_test(test_arena_ensure_capacity_align_max),
cmocka_unit_test(test_arena_ensure_capacity_size_0),
cmocka_unit_test(test_arena_ensure_capacity_size_max),
cmocka_unit_test(test_arena_allocator_valid_allocation),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

94
xmake.lua Normal file
View File

@@ -0,0 +1,94 @@
set_project("lae_arena")
set_version("1.0.0")
set_languages("c11")
add_rules("mode.debug", "mode.release")
-- clang compile commands
add_rules("plugin.compile_commands.autoupdate")
-- =========================================================
-- Options
-- =========================================================
option("tests")
set_default(false)
set_showmenu(true)
option_end()
option("example")
set_default(false)
set_showmenu(true)
option_end()
option("asan")
set_default(false)
set_showmenu(true)
option_end()
-- =========================================================
-- Packages
-- =========================================================
-- Run xmake repo --add lae-repo https://laentropia-homelab.tail7368da.ts.net/laentropia/xmake-repo.git
-- to add my repo :)
add_requires("cmocka", { optional = true }) -- For tests
add_requires("lae_allocator")
-- =========================================================
-- Library
-- =========================================================
target("lae_arena")
set_kind("static")
add_packages("lae_allocator", { public = true })
add_files("src/lae_arena.c")
add_headerfiles("include/*.h")
add_includedirs("include", { public = true })
if is_mode("debug") then
add_cflags("-Wall", "-Wextra", "-Wpedantic")
end
-- =========================================================
-- Example executable
-- =========================================================
if has_config("example") then
target("example")
set_kind("binary")
add_deps("lae_arena")
add_packages("lae_allocator")
add_files("src/main.c")
end
-- =========================================================
-- Tests
-- =========================================================
if has_config("tests") then
target("test_arena")
set_kind("binary")
add_files("test/test_arena.c")
add_deps("lae_arena")
add_packages("cmocka")
add_tests("default")
if has_config("asan") then
add_cflags("-fsanitize=address", "-fno-omit-frame-pointer", { force = true })
add_ldflags("-fsanitize=address", { force = true })
end
end