Compare commits

...

8 Commits

Author SHA1 Message Date
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
5 changed files with 120 additions and 101 deletions

View File

@@ -1,39 +1,34 @@
cmake_minimum_required(VERSION 3.20)
project(calculator VERSION 1.0 LANGUAGES C)
project(arena 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)
# Opciones
option(ARENA_BUILD_TESTS "Build arena tests" OFF)
option(ARENA_ENABLE_SANITIZERS "Enable sanitizers for tests" ON)
add_compile_options(
# Librería
add_library(arena
src/arena.c
)
target_include_directories(arena
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_compile_options(arena PRIVATE
-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)
function(enable_sanitizers target)
target_compile_options(${target} PRIVATE -fsanitize=address -fno-omit-frame-pointer)
target_link_options(${target} PRIVATE -fsanitize=address)
endfunction()
# ------------------------
# Testing
# ------------------------
enable_testing()
add_subdirectory(test)
if(ARENA_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif()

View File

@@ -6,11 +6,7 @@
#include <inttypes.h>
#include <stdbool.h>
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);

View File

@@ -5,32 +5,56 @@
#include <stdlib.h>
#include <string.h>
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};
}

View File

@@ -3,13 +3,21 @@ find_package(cmocka REQUIRED)
add_executable(test_arena test_arena.c)
target_link_libraries(test_arena
arena_lib
arena
cmocka::cmocka
)
enable_sanitizers(test_arena)
target_compile_options(test_arena PRIVATE -fsanitize=address -fno-omit-frame-pointer)
target_link_options(test_arena PRIVATE -fsanitize=address)
# Sanitizers (solo si están activados y el compilador lo soporta)
if(ARENA_ENABLE_SANITIZERS)
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(test_arena PRIVATE
-fsanitize=address
-fno-omit-frame-pointer
)
target_link_options(test_arena PRIVATE
-fsanitize=address
)
endif()
endif()
add_test(NAME arena_tests COMMAND test_arena)

View File

@@ -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);