Compare commits

..

24 Commits

Author SHA1 Message Date
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
310b25ce1f updates to cmake 2026-04-23 12:23:52 -06:00
af03e25979 README update
d
2026-04-23 11:38:29 -06:00
9fbd7d87ce Merge pull request 'implementation_ArrayListSlice' (#1) from implementation_ArrayListSlice into main
Reviewed-on: #1
2026-04-23 11:25:37 -06:00
d940b68eef test: tests for arrayslice to aray done 2026-04-23 11:22:57 -06:00
51f1166f31 test: advance tests done 2026-04-23 10:47:23 -06:00
a515f8eaf2 test: reset tests done 2026-04-23 10:29:53 -06:00
e04fc30f4e test: next tests done 2026-04-23 10:03:55 -06:00
9920b518bf test: peek tests done 2026-04-23 09:39:59 -06:00
4a1575e833 addtition: slice to array, needs testing 2026-04-23 09:18:18 -06:00
dd992cf6b9 addtition: reset and advance, need testing 2026-04-23 08:59:12 -06:00
e8aaa006de addition: next and peek, need testing 2026-04-23 08:47:45 -06:00
94dc859a8f test: added tests for slice_destroy 2026-04-22 17:55:14 -06:00
b34fb9902f test: added tests for slice_unsafe 2026-04-22 17:26:49 -06:00
198997e2b6 test: arraylist_slice tested 2026-04-21 19:57:58 -06:00
b313045153 test: Check for borrows before changing array state 2026-04-21 11:16:11 -06:00
dafaa5b87e fix: fixed problems with init and destroy slice 2026-04-21 09:10:53 -06:00
6088895ad0 addition: create slice and unsafe, also destroy 2026-04-20 08:43:58 -06:00
04a52e3455 addtition: Added function declarations 2026-04-19 21:57:28 -06:00
4b2389ad62 feature: Added structure for ArrayListSlices 2026-04-19 12:32:11 -06:00
6 changed files with 1319 additions and 167 deletions

View File

@@ -1,39 +1,48 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(calculator VERSION 1.0 LANGUAGES C) project(arraylist VERSION 1.0 LANGUAGES C)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
# Export compile_commands.json (para clangd) # clangd
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_options( # Opciones
option(ARRAYLIST_BUILD_TESTS "Build arraylist tests" ON)
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 -Wall
-Wextra -Wextra
-Wpedantic -Wpedantic
) )
# ------------------------
# Example (opcional)
# ------------------------
add_executable(arraylist_example src/main.c)
include_directories(include) target_link_libraries(arraylist_example
arraylist
add_library(arraylist_lib
src/arraylist.c
) )
add_executable(arraylist_main src/main.c)
target_link_libraries(arraylist_main arraylist_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 # Testing
# ------------------------ # ------------------------
if(ARRAYLIST_BUILD_TESTS)
enable_testing() enable_testing()
add_subdirectory(test) add_subdirectory(test)
endif()

1
README.md Normal file
View File

@@ -0,0 +1 @@
# Hola

View File

@@ -7,15 +7,7 @@
typedef struct ArrayList ArrayList; typedef struct ArrayList ArrayList;
// FUCK, i forgot one of the main reasons i wanted to typedef struct ArraySlice ArraySlice;
// implement arrays myself was because i needed
// array slices or something like this and i completely
// forgot, fuck, guess i will implement it once i get
// the tests done.
typedef struct {
ArrayList *array;
size_t offset;
} ArrayListSlice;
typedef enum { typedef enum {
ARRLIST_OK = 0, ARRLIST_OK = 0,
@@ -26,11 +18,17 @@ typedef enum {
ARRLIST_NULL_ARG, ARRLIST_NULL_ARG,
ARRLIST_INVALID_ELEM_SIZE, ARRLIST_INVALID_ELEM_SIZE,
ARRLIST_INVALID_CAPACITY, ARRLIST_INVALID_CAPACITY,
ARRLIST_IS_BORROWED,
ARRLIST_INVALID_SLICE,
ARRLIST_INVALID_ARR,
ARRLIST_INVALID_START,
ARRLIST_BORROW_UNDERFLOW,
} ArrayListErr; } ArrayListErr;
ArrayList *arraylist_init(size_t capacity, size_t elem_size); ArrayListErr arraylist_init(ArrayList **arr, size_t capacity, size_t elem_size);
ArrayListErr arraylist_destroy(ArrayList **arr); ArrayListErr arraylist_destroy(ArrayList **arr);
ArrayListErr arraylist_clear(ArrayList *arr); ArrayListErr arraylist_clear(ArrayList *arr);
ArrayList *arraylist_clone(const ArrayList *arr);
size_t arraylist_size(const ArrayList *arr); size_t arraylist_size(const ArrayList *arr);
size_t arraylist_capacity(const ArrayList *arr); size_t arraylist_capacity(const ArrayList *arr);
@@ -51,4 +49,22 @@ ArrayListErr arraylist_set(ArrayList *arr, size_t index, void *data);
ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity); ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity);
ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve); ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve);
//Slice stuff
ArrayListErr arraylist_slice(ArraySlice **slice, ArrayList *arr, size_t start, size_t len);
ArrayListErr arraylist_slice_unsafe(ArraySlice **slice, ArrayList *arr, size_t start, size_t len);
ArrayListErr arrayslice_destroy(ArraySlice **slice);
bool arrayslice_is_valid(const ArraySlice *slice);
size_t arrayslice_size(const ArraySlice *slice);
// peek and next can be null, get can't, like, why would you use get without
// actually getting something?, for validating an index?, use size idiot
ArrayListErr arrayslice_peek(const ArraySlice *slice, void *out);
ArrayListErr arrayslice_next(ArraySlice *slice, void *out);
ArrayListErr arrayslice_reset(ArraySlice *slice);
ArrayListErr arrayslice_advance(ArraySlice *slice, size_t n);
ArrayListErr arrayslice_to_arraylist(ArrayList **arr, const ArraySlice *slice);
#endif #endif

View File

@@ -9,6 +9,15 @@ struct ArrayList{
size_t capacity; size_t capacity;
size_t len; size_t len;
size_t elem_size; size_t elem_size;
size_t borrows;
};
struct ArraySlice {
ArrayList *arr;
size_t start;
size_t end;
size_t current;
bool is_safe;
}; };
// Grow and shrink factor is 2, 1.5 might give different results i guess // Grow and shrink factor is 2, 1.5 might give different results i guess
@@ -17,33 +26,42 @@ struct ArrayList{
static ArrayListErr arraylist_grow(ArrayList *arr); static ArrayListErr arraylist_grow(ArrayList *arr);
static ArrayListErr arraylist_shrink(ArrayList *arr); static ArrayListErr arraylist_shrink(ArrayList *arr);
ArrayList *arraylist_init(size_t capacity, size_t elem_size) { ArrayListErr arraylist_init(ArrayList **arr, size_t capacity, size_t elem_size) {
if (arr == NULL) {
return ARRLIST_NULL_ARG;
}
*arr = NULL;
if (capacity == 0) { if (capacity == 0) {
return NULL; return ARRLIST_INVALID_CAPACITY;
} }
if (elem_size == 0) { if (elem_size == 0) {
return NULL; return ARRLIST_INVALID_ELEM_SIZE;
} }
if (capacity > SIZE_MAX / elem_size) { if (capacity > SIZE_MAX / elem_size) {
return NULL; return ARRLIST_INVALID_CAPACITY;
} }
ArrayList *arr = malloc(sizeof(ArrayList)); ArrayList *new_arr = malloc(sizeof(ArrayList));
if (arr == NULL) { if (new_arr == NULL) {
return NULL; return ARRLIST_BAD_ALLOC;
}
arr->capacity = capacity;
arr->elem_size = elem_size;
arr->len = 0;
arr->buffer = malloc(capacity * elem_size);
if (arr->buffer == NULL) {
free(arr);
return NULL;
} }
return arr; new_arr->capacity = capacity;
new_arr->elem_size = elem_size;
new_arr->len = 0;
new_arr->borrows = 0;
new_arr->buffer = malloc(capacity * elem_size);
if (new_arr->buffer == NULL) {
free(new_arr);
return ARRLIST_BAD_ALLOC;
}
*arr = new_arr;
return ARRLIST_OK;
} }
ArrayListErr arraylist_destroy(ArrayList **arr) { ArrayListErr arraylist_destroy(ArrayList **arr) {
@@ -51,6 +69,10 @@ ArrayListErr arraylist_destroy(ArrayList **arr) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if ((*arr)->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
// No problem on using free on NULL :) // No problem on using free on NULL :)
free((*arr)->buffer); free((*arr)->buffer);
free(*arr); free(*arr);
@@ -64,6 +86,10 @@ ArrayListErr arraylist_clear(ArrayList *arr) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
arr->len = 0; arr->len = 0;
return ARRLIST_OK; return ARRLIST_OK;
} }
@@ -131,6 +157,10 @@ ArrayListErr arraylist_push_back(ArrayList *arr, void *data) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
if (arr->len >= arr->capacity) { if (arr->len >= arr->capacity) {
ArrayListErr err = arraylist_grow(arr); ArrayListErr err = arraylist_grow(arr);
@@ -149,6 +179,10 @@ ArrayListErr arraylist_push_front(ArrayList *arr, void *data) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
if (arr->len >= arr->capacity) { if (arr->len >= arr->capacity) {
ArrayListErr err = arraylist_grow(arr); ArrayListErr err = arraylist_grow(arr);
@@ -179,6 +213,10 @@ ArrayListErr arraylist_insert(ArrayList *arr, size_t index, void *data) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
if (index > arr->len) { if (index > arr->len) {
return ARRLIST_OUT_OF_BOUNDS; return ARRLIST_OUT_OF_BOUNDS;
} }
@@ -209,6 +247,10 @@ ArrayListErr arraylist_pop_back(ArrayList *arr, void *out) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
if (arr->len < 1) { if (arr->len < 1) {
return ARRLIST_EMPTY; return ARRLIST_EMPTY;
} }
@@ -237,6 +279,10 @@ ArrayListErr arraylist_pop_front(ArrayList *arr, void *out) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
if (arr->len < 1) { if (arr->len < 1) {
return ARRLIST_EMPTY; return ARRLIST_EMPTY;
} }
@@ -271,6 +317,10 @@ ArrayListErr arraylist_remove_at(ArrayList *arr, size_t index, void *out) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
if (index >= arr->len) { if (index >= arr->len) {
return ARRLIST_OUT_OF_BOUNDS; return ARRLIST_OUT_OF_BOUNDS;
} }
@@ -336,6 +386,10 @@ ArrayListErr arraylist_resize(ArrayList *arr, size_t new_capacity) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
if (new_capacity < 1) { if (new_capacity < 1) {
return ARRLIST_INVALID_CAPACITY; return ARRLIST_INVALID_CAPACITY;
} }
@@ -359,6 +413,10 @@ ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve) {
return ARRLIST_NULL_ARG; return ARRLIST_NULL_ARG;
} }
if (arr->borrows > 0) {
return ARRLIST_IS_BORROWED;
}
if (arr->capacity + size_to_reserve > SIZE_MAX / arr->elem_size || if (arr->capacity + size_to_reserve > SIZE_MAX / arr->elem_size ||
size_to_reserve > SIZE_MAX / arr->elem_size) { size_to_reserve > SIZE_MAX / arr->elem_size) {
@@ -377,3 +435,192 @@ ArrayListErr arraylist_reserve(ArrayList *arr, size_t size_to_reserve) {
arr->capacity += size_to_reserve; arr->capacity += size_to_reserve;
return ARRLIST_OK; return ARRLIST_OK;
} }
ArrayListErr arraylist_slice(ArraySlice **slice, ArrayList *arr, size_t start, size_t len) {
if (arr == NULL || slice == NULL) {
return ARRLIST_NULL_ARG;
}
if (arr->len == 0) {
return ARRLIST_INVALID_ARR;
}
if (start > SIZE_MAX - len) {
return ARRLIST_INVALID_CAPACITY;
}
if (start + len > arr->len || len == 0) {
return ARRLIST_INVALID_START;
}
ArraySlice *new_slice = malloc(sizeof(ArraySlice));
if (new_slice == NULL) {
return ARRLIST_BAD_ALLOC;
}
new_slice->arr = arr;
new_slice->start = start;
new_slice->end = start + len;
new_slice->current = start;
new_slice->is_safe = true;
arr->borrows++;
*slice = new_slice;
return ARRLIST_OK;
}
ArrayListErr arraylist_slice_unsafe(ArraySlice **slice, ArrayList *arr, size_t start, size_t len) {
if (arr == NULL || slice == NULL) {
return ARRLIST_NULL_ARG;
}
if (arr->len == 0) {
return ARRLIST_INVALID_ARR;
}
if (start > SIZE_MAX - len) {
return ARRLIST_INVALID_CAPACITY;
}
if (start + len > arr->len || len == 0) {
return ARRLIST_INVALID_START;
}
ArraySlice *new_slice = malloc(sizeof(ArraySlice));
if (new_slice == NULL) {
return ARRLIST_BAD_ALLOC;
}
new_slice->arr = arr;
new_slice->start = start;
new_slice->end = start + len;
new_slice->current = start;
new_slice->is_safe = false;
*slice = new_slice;
return ARRLIST_OK;
}
ArrayListErr arrayslice_destroy(ArraySlice **slice) {
if (slice == NULL || *slice == NULL) {
return ARRLIST_NULL_ARG;
}
if ((*slice)->is_safe) {
(*slice)->arr->borrows--;
}
free(*slice);
*slice = NULL;
return ARRLIST_OK;
}
bool arrayslice_is_valid(const ArraySlice *slice) {
if (slice == NULL) {
return false;
}
return slice->current != slice->end;
}
size_t arrayslice_size(const ArraySlice *slice) {
if (slice == NULL) {
return 0;
}
return slice->end - slice->start;
}
ArrayListErr arrayslice_peek(const ArraySlice *slice, void *out) {
if (slice == NULL || out == NULL) {
return ARRLIST_NULL_ARG;
}
if (slice->current >= slice->end) {
return ARRLIST_INVALID_SLICE;
}
arraylist_get(slice->arr, slice->current, out);
return ARRLIST_OK;
}
ArrayListErr arrayslice_next(ArraySlice *slice, void *out) {
// HERE, it makes sense that you want to advance to the next
// without actually getting the value so it's good
if (slice == NULL) {
return ARRLIST_NULL_ARG;
}
if (slice->current == slice->end) {
return ARRLIST_INVALID_SLICE;
}
arraylist_get(slice->arr, slice->current, out);
slice->current++;
return ARRLIST_OK;
}
ArrayListErr arrayslice_reset(ArraySlice *slice) {
if (slice == NULL) {
return ARRLIST_NULL_ARG;
}
slice->current = slice->start;
return ARRLIST_OK;
}
ArrayListErr arrayslice_advance(ArraySlice *slice, size_t n) {
if (slice == NULL) {
return ARRLIST_NULL_ARG;
}
if (n > SIZE_MAX - slice->current || slice->current + n > slice->end) {
return ARRLIST_OUT_OF_BOUNDS;
}
slice->current += n;
return ARRLIST_OK;
}
ArrayListErr arrayslice_to_arraylist(ArrayList **arr, const ArraySlice *slice) {
if (slice == NULL || slice->arr == NULL) {
return ARRLIST_NULL_ARG;
}
if (arr == NULL) {
return ARRLIST_NULL_ARG;
}
if (slice->start >= slice->end) {
return ARRLIST_INVALID_SLICE;
}
size_t len = slice->end - slice->start;
ArrayList *new_arr;
ArrayListErr init_err = arraylist_init(
&new_arr,
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
);
new_arr->len = len;
*arr = new_arr;
return ARRLIST_OK;
}

View File

@@ -3,13 +3,21 @@ find_package(cmocka REQUIRED)
add_executable(test_arraylist test_arraylist.c) add_executable(test_arraylist test_arraylist.c)
target_link_libraries(test_arraylist target_link_libraries(test_arraylist
arraylist_lib arraylist
cmocka::cmocka cmocka::cmocka
) )
enable_sanitizers(test_arraylist) # 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()
target_compile_options(test_arraylist PRIVATE -fsanitize=address -fno-omit-frame-pointer) add_test(NAME arraylist_tests COMMAND test_arraylist)
target_link_options(test_arraylist PRIVATE -fsanitize=address)
add_test(NAME arraylist_tests COMMAND arraylists_arena)

File diff suppressed because it is too large Load Diff