Compare commits

...

12 Commits

Author SHA1 Message Date
feccaca57f Merge pull request 'refactor-xmake' (#2) from refactor-xmake into main
Reviewed-on: #2
2026-06-10 14:52:54 -06:00
1a0afd331c test: done for refactor, ready to merge 2026-06-10 14:49:28 -06:00
c983fd22ad refactor: ArrayList and ArraySlice uses Allocator 2026-06-10 13:33:26 -06:00
a057f23798 refactor: xmake in use, compiles and tests fine 2026-06-10 11:18:10 -06:00
5734af33db Test cfix 2026-05-20 17:37:59 -06:00
e8e31a3539 Fix for cmakelist 2026-05-20 17:35:46 -06:00
098e469b4e Fix for test construction 2026-05-20 16:46:50 -06:00
e0c8b46bfa refactor: tests work, all fine 2026-05-14 08:20:56 -06:00
0a0350c1c1 refactor: changed arrayslice init 2026-05-14 06:59:25 -06:00
36bd2a37c7 refactor: changed arrayslice_to_arraylsit 2026-05-14 06:53:38 -06:00
dc274787e3 refactor: slices take same approach for init 2026-05-14 06:48:56 -06:00
d69a74dad2 refactor: init takes pointer to pointer for compatibliity
Its better for me this way, its just this little change at least, next
is fucking going and fixig all damn tests, the fucking wors part
2026-05-13 20:42:04 -06:00
7 changed files with 1069 additions and 591 deletions

6
.gitignore vendored
View File

@@ -7,6 +7,12 @@ out/
out/Debug/
out/Release/
# xmake
xmake/
xmake/*
.xmake
.xmake/*
# Cmake files
CMakeCache.txt
CMakeFiles/

View File

@@ -1,48 +0,0 @@
cmake_minimum_required(VERSION 3.20)
project(arraylist VERSION 1.0 LANGUAGES C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
# clangd
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Opciones
option(ARRAYLIST_BUILD_TESTS "Build arraylist tests" OFF)
option(ARRAYLIST_ENABLE_SANITIZERS "Enable sanitizers for tests" ON)
# ------------------------
# Library
# ------------------------
add_library(arraylist
src/arraylist.c
)
target_include_directories(arraylist
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_compile_options(arraylist PRIVATE
-Wall
-Wextra
-Wpedantic
)
# ------------------------
# Example (opcional)
# ------------------------
add_executable(arraylist_example src/main.c)
target_link_libraries(arraylist_example
arraylist
)
# ------------------------
# Testing
# ------------------------
if(ARRAYLIST_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif()

View File

@@ -1,9 +1,10 @@
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
#ifndef LAE_ARRAYLIST_H
#define LAE_ARRAYLIST_H
#include "lae_allocator.h"
#include <inttypes.h>
#include <stddef.h>
#include <stdbool.h>
#include <stddef.h>
typedef struct ArrayList ArrayList;
@@ -20,9 +21,16 @@ typedef enum {
ARRLIST_INVALID_CAPACITY,
ARRLIST_IS_BORROWED,
ARRLIST_INVALID_SLICE,
ARRLIST_INVALID_ARR,
ARRLIST_INVALID_START,
ARRLIST_BORROW_UNDERFLOW,
} ArrayListErr;
ArrayList *arraylist_init(size_t capacity, size_t elem_size);
ArrayListErr arraylist_init(
ArrayList **arr,
Allocator allocator,
size_t capacity,
size_t elem_size);
ArrayListErr arraylist_destroy(ArrayList **arr);
ArrayListErr arraylist_clear(ArrayList *arr);
ArrayList *arraylist_clone(const ArrayList *arr);
@@ -32,8 +40,8 @@ size_t arraylist_capacity(const ArrayList *arr);
bool arraylist_is_empty(const ArrayList *arr);
ArrayListErr arraylist_push_back(ArrayList *arr, void *data);
ArrayListErr arraylist_insert(ArrayList*arr, size_t index, void *data);
ArrayListErr arraylist_push_front(ArrayList* arr, void *data);
ArrayListErr arraylist_insert(ArrayList *arr, size_t index, void *data);
ArrayListErr arraylist_push_front(ArrayList *arr, void *data);
// Here out can be null for not having anything writen
ArrayListErr arraylist_pop_back(ArrayList *arr, void *out);
@@ -46,9 +54,21 @@ ArrayListErr arraylist_set(ArrayList *arr, size_t index, void *data);
ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity);
ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve);
//Slice stuff
ArraySlice *arraylist_slice(ArrayList *arr, size_t start, size_t len);
ArraySlice *arraylist_slice_unsafe(ArrayList *arr, size_t start, size_t len);
// Slice stuff
ArrayListErr arraylist_slice(
ArraySlice **slice,
Allocator allocator,
ArrayList *arr,
size_t start,
size_t len);
ArrayListErr arraylist_slice_unsafe(
ArraySlice **slice,
Allocator allocator,
ArrayList *arr,
size_t start,
size_t len);
ArrayListErr arrayslice_destroy(ArraySlice **slice);
bool arrayslice_is_valid(const ArraySlice *slice);
@@ -62,6 +82,9 @@ ArrayListErr arrayslice_next(ArraySlice *slice, void *out);
ArrayListErr arrayslice_reset(ArraySlice *slice);
ArrayListErr arrayslice_advance(ArraySlice *slice, size_t n);
ArrayList *arrayslice_to_arraylist(const ArraySlice *slice);
ArrayListErr arrayslice_to_arraylist(
ArrayList **arr,
Allocator allocator,
const ArraySlice *slice);
#endif

View File

@@ -1,15 +1,19 @@
#include "arraylist.h"
#include "lae_arraylist.h"
#include "lae_allocator.h"
#include <stdalign.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
struct ArrayList{
struct ArrayList {
uint8_t *buffer;
size_t capacity;
size_t len;
size_t elem_size;
size_t borrows;
Allocator allocator;
};
struct ArraySlice {
@@ -18,6 +22,8 @@ struct ArraySlice {
size_t end;
size_t current;
bool is_safe;
Allocator allocator;
};
// Grow and shrink factor is 2, 1.5 might give different results i guess
@@ -26,34 +32,52 @@ struct ArraySlice {
static ArrayListErr arraylist_grow(ArrayList *arr);
static ArrayListErr arraylist_shrink(ArrayList *arr);
ArrayList *arraylist_init(size_t capacity, size_t elem_size) {
ArrayListErr arraylist_init(
ArrayList **arr,
Allocator allocator,
size_t capacity,
size_t elem_size) {
if (arr == NULL) {
return ARRLIST_NULL_ARG;
}
*arr = NULL;
if (capacity == 0) {
return NULL;
return ARRLIST_INVALID_CAPACITY;
}
if (elem_size == 0) {
return NULL;
return ARRLIST_INVALID_ELEM_SIZE;
}
if (capacity > SIZE_MAX / elem_size) {
return NULL;
return ARRLIST_INVALID_CAPACITY;
}
ArrayList *arr = malloc(sizeof(ArrayList));
if (arr == NULL) {
return NULL;
}
arr->capacity = capacity;
arr->elem_size = elem_size;
arr->len = 0;
arr->borrows = 0;
arr->buffer = malloc(capacity * elem_size);
if (arr->buffer == NULL) {
free(arr);
return NULL;
ArrayList *new_arr =
allocator.alloc(allocator.ctx, sizeof(ArrayList), alignof(ArrayList));
if (new_arr == NULL) {
return ARRLIST_BAD_ALLOC;
}
return arr;
new_arr->capacity = capacity;
new_arr->elem_size = elem_size;
new_arr->len = 0;
new_arr->borrows = 0;
new_arr->buffer = allocator.alloc(allocator.ctx, capacity * elem_size, 0);
new_arr->allocator = allocator;
if (new_arr->buffer == NULL) {
allocator.free(
allocator.ctx,
new_arr,
sizeof(ArrayList),
alignof(ArrayList));
return ARRLIST_BAD_ALLOC;
}
*arr = new_arr;
return ARRLIST_OK;
}
ArrayListErr arraylist_destroy(ArrayList **arr) {
@@ -65,9 +89,12 @@ ArrayListErr arraylist_destroy(ArrayList **arr) {
return ARRLIST_IS_BORROWED;
}
ArrayList *tmp = *arr;
// No problem on using free on NULL :)
free((*arr)->buffer);
free(*arr);
tmp->allocator.free(tmp->allocator.ctx, tmp->buffer, tmp->capacity, 0);
tmp->allocator
.free(tmp->allocator.ctx, tmp, sizeof(ArrayList), alignof(ArrayList));
*arr = NULL;
return ARRLIST_OK;
@@ -114,7 +141,7 @@ static ArrayListErr arraylist_grow(ArrayList *arr) {
size_t new_capacity = arr->capacity * 2;
if (new_capacity > SIZE_MAX / arr->elem_size) {
return ARRLIST_ALLOC_OVERFLOW;
return ARRLIST_ALLOC_OVERFLOW;
}
void *tmp = realloc(arr->buffer, new_capacity * arr->elem_size);
@@ -131,10 +158,10 @@ static ArrayListErr arraylist_shrink(ArrayList *arr) {
size_t new_capacity = arr->capacity / 2;
if (new_capacity > SIZE_MAX / arr->elem_size) {
return ARRLIST_ALLOC_OVERFLOW;
return ARRLIST_ALLOC_OVERFLOW;
}
void *tmp = realloc(arr->buffer, new_capacity *arr->elem_size);
void *tmp = realloc(arr->buffer, new_capacity * arr->elem_size);
if (tmp == NULL) {
return ARRLIST_BAD_ALLOC;
}
@@ -187,13 +214,9 @@ ArrayListErr arraylist_push_front(ArrayList *arr, void *data) {
memmove(
arr->buffer + arr->elem_size,
arr->buffer,
(arr->len) * arr->elem_size
);
(arr->len) * arr->elem_size);
memcpy(
arr->buffer,
data,
arr->elem_size);
memcpy(arr->buffer, data, arr->elem_size);
arr->len++;
@@ -225,9 +248,7 @@ ArrayListErr arraylist_insert(ArrayList *arr, size_t index, void *data) {
arr->buffer + (index * arr->elem_size),
(arr->len - index) * arr->elem_size);
memcpy(arr->buffer + (index * arr->elem_size),
data,
arr->elem_size);
memcpy(arr->buffer + (index * arr->elem_size), data, arr->elem_size);
arr->len++;
@@ -287,11 +308,7 @@ ArrayListErr arraylist_pop_front(ArrayList *arr, void *out) {
}
if (out != NULL) {
memcpy(
out,
arr->buffer,
arr->elem_size
);
memcpy(out, arr->buffer, arr->elem_size);
}
memmove(
@@ -322,11 +339,7 @@ ArrayListErr arraylist_remove_at(ArrayList *arr, size_t index, void *out) {
}
if (out != NULL) {
memcpy(
out,
arr->buffer + (index * arr->elem_size),
arr->elem_size
);
memcpy(out, arr->buffer + (index * arr->elem_size), arr->elem_size);
}
memmove(
@@ -348,10 +361,7 @@ ArrayListErr arraylist_get(const ArrayList *arr, size_t index, void *out) {
return ARRLIST_OUT_OF_BOUNDS;
}
memcpy(
out,
arr->buffer + (index * arr->elem_size),
arr->elem_size);
memcpy(out, arr->buffer + (index * arr->elem_size), arr->elem_size);
return ARRLIST_OK;
}
@@ -365,10 +375,7 @@ ArrayListErr arraylist_set(ArrayList *arr, size_t index, void *data) {
return ARRLIST_OUT_OF_BOUNDS;
}
memcpy(
arr->buffer + (index * arr->elem_size),
data,
arr->elem_size);
memcpy(arr->buffer + (index * arr->elem_size), data, arr->elem_size);
return ARRLIST_OK;
}
@@ -387,7 +394,7 @@ ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity) {
}
if (new_capacity > SIZE_MAX / arr->elem_size) {
return ARRLIST_ALLOC_OVERFLOW;
return ARRLIST_ALLOC_OVERFLOW;
}
uint8_t *tmp = realloc(arr->buffer, new_capacity * arr->elem_size);
@@ -412,7 +419,7 @@ ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve) {
if (arr->capacity + size_to_reserve > SIZE_MAX / arr->elem_size ||
size_to_reserve > SIZE_MAX / arr->elem_size) {
return ARRLIST_ALLOC_OVERFLOW;
return ARRLIST_ALLOC_OVERFLOW;
}
uint8_t *tmp = realloc(
@@ -428,68 +435,83 @@ ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve) {
return ARRLIST_OK;
}
ArraySlice *arraylist_slice(ArrayList *arr, size_t start, size_t len) {
if (arr == NULL) {
return NULL;
ArrayListErr arraylist_slice(
ArraySlice **slice,
Allocator allocator,
ArrayList *arr,
size_t start,
size_t len) {
if (arr == NULL || slice == NULL) {
return ARRLIST_NULL_ARG;
}
if (arr->len == 0 || len == 0) {
return NULL;
if (arr->len == 0) {
return ARRLIST_INVALID_ARR;
}
if (start > SIZE_MAX / arr->elem_size || len > SIZE_MAX / arr->elem_size) {
return NULL;
if (start > SIZE_MAX - len) {
return ARRLIST_INVALID_CAPACITY;
}
if (start + len > arr->len) {
return NULL;
if (start + len > arr->len || len == 0) {
return ARRLIST_INVALID_START;
}
ArraySlice *slice = malloc(sizeof(ArraySlice));
if (slice == NULL) {
return NULL;
ArraySlice *new_slice =
allocator.alloc(allocator.ctx, sizeof(ArraySlice), alignof(ArraySlice));
if (new_slice == NULL) {
return ARRLIST_BAD_ALLOC;
}
slice->arr = arr;
slice->start = start;
slice->end = start + len;
slice->current = start;
slice->is_safe = true;
new_slice->arr = arr;
new_slice->start = start;
new_slice->end = start + len;
new_slice->current = start;
new_slice->is_safe = true;
new_slice->allocator = allocator;
arr->borrows++;
return slice;
*slice = new_slice;
return ARRLIST_OK;
}
ArraySlice *arraylist_slice_unsafe(ArrayList *arr, size_t start, size_t len) {
if (arr == NULL) {
return NULL;
ArrayListErr arraylist_slice_unsafe(
ArraySlice **slice,
Allocator allocator,
ArrayList *arr,
size_t start,
size_t len) {
if (arr == NULL || slice == NULL) {
return ARRLIST_NULL_ARG;
}
if (arr->len == 0 || len == 0) {
return NULL;
if (arr->len == 0) {
return ARRLIST_INVALID_ARR;
}
if (start > SIZE_MAX / arr->elem_size || len > SIZE_MAX / arr->elem_size) {
return NULL;
if (start > SIZE_MAX - len) {
return ARRLIST_INVALID_CAPACITY;
}
if (start + len > arr->len) {
return NULL;
if (start + len > arr->len || len == 0) {
return ARRLIST_INVALID_START;
}
ArraySlice *slice = malloc(sizeof(ArraySlice));
if (slice == NULL) {
return NULL;
ArraySlice *new_slice =
allocator.alloc(allocator.ctx, sizeof(ArraySlice), alignof(ArraySlice));
if (new_slice == NULL) {
return ARRLIST_BAD_ALLOC;
}
slice->arr = arr;
slice->start = start;
slice->end = start + len;
slice->current = start;
slice->is_safe = false;
new_slice->arr = arr;
new_slice->start = start;
new_slice->end = start + len;
new_slice->current = start;
new_slice->is_safe = false;
new_slice->allocator = allocator;
return slice;
*slice = new_slice;
return ARRLIST_OK;
}
ArrayListErr arrayslice_destroy(ArraySlice **slice) {
@@ -501,7 +523,11 @@ ArrayListErr arrayslice_destroy(ArraySlice **slice) {
(*slice)->arr->borrows--;
}
free(*slice);
(*slice)->allocator.free(
(*slice)->allocator.ctx,
*slice,
sizeof(ArraySlice),
alignof(ArraySlice));
*slice = NULL;
return ARRLIST_OK;
@@ -572,35 +598,48 @@ ArrayListErr arrayslice_advance(ArraySlice *slice, size_t n) {
if (n > SIZE_MAX - slice->current || slice->current + n > slice->end) {
return ARRLIST_OUT_OF_BOUNDS;
}
slice->current += n;
return ARRLIST_OK;
}
ArrayList *arrayslice_to_arraylist(const ArraySlice *slice) {
ArrayListErr arrayslice_to_arraylist(
ArrayList **arr,
Allocator allocator,
const ArraySlice *slice) {
if (slice == NULL || slice->arr == NULL) {
return NULL;
return ARRLIST_NULL_ARG;
}
if (arr == NULL) {
return ARRLIST_NULL_ARG;
}
if (slice->start >= slice->end) {
return NULL;
return ARRLIST_INVALID_SLICE;
}
size_t len = slice->end - slice->start;
ArrayList *new_arr = arraylist_init(arraylist_capacity(slice->arr), slice->arr->elem_size);
if (new_arr == NULL) {
return NULL;
ArrayList *new_arr;
ArrayListErr init_err = arraylist_init(
&new_arr,
allocator,
arraylist_capacity(slice->arr),
slice->arr->elem_size);
if (init_err != ARRLIST_OK) {
return init_err;
}
memcpy(
new_arr->buffer,
slice->arr->buffer + (slice->start * slice->arr->elem_size),
slice->arr->elem_size * len
);
slice->arr->elem_size * len);
new_arr->len = len;
return new_arr;
*arr = new_arr;
return ARRLIST_OK;
}

View File

@@ -1,23 +0,0 @@
find_package(cmocka REQUIRED)
add_executable(test_arraylist test_arraylist.c)
target_link_libraries(test_arraylist
arraylist
cmocka::cmocka
)
# Sanitizers (portables)
if(ARRAYLIST_ENABLE_SANITIZERS)
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(test_arraylist PRIVATE
-fsanitize=address
-fno-omit-frame-pointer
)
target_link_options(test_arraylist PRIVATE
-fsanitize=address
)
endif()
endif()
add_test(NAME arraylist_tests COMMAND test_arraylist)

File diff suppressed because it is too large Load Diff

94
xmake.lua Normal file
View File

@@ -0,0 +1,94 @@
set_project("lae_arraylist")
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_arraylist")
set_kind("static")
add_packages("lae_allocator", { public = true })
add_files("src/lae_arraylist.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_arraylist")
add_packages("lae_allocator")
add_files("src/main.c")
end
-- =========================================================
-- Tests
-- =========================================================
if has_config("tests") then
target("test_arraylist")
set_kind("binary")
add_files("test/test_arraylist.c")
add_deps("lae_arraylist")
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