From a1fdf5f0c61867bf2871f3e16c8d7bce7e86022f Mon Sep 17 00:00:00 2001 From: epochryphon Date: Mon, 25 May 2026 14:28:02 -0500 Subject: [PATCH] renamed to vector --- .../marigold_dynamic_array.h | 594 ----------------- .../internal_marigold_dynamic_array.c | 0 .../internal_marigold_dynamic_array.h | 0 .../marigold_vector.c} | 0 .../MODULE_marigold_vector/marigold_vector.h | 597 ++++++++++++++++++ .../tests/test_marigold_dynamic_array.c | 0 .../tests/test_marigold_dynamic_array.h | 0 7 files changed, 597 insertions(+), 594 deletions(-) delete mode 100644 source_code/MODULE_marigold_dynamic_array/marigold_dynamic_array.h rename source_code/{MODULE_marigold_dynamic_array => MODULE_marigold_vector}/internal/internal_marigold_dynamic_array.c (100%) rename source_code/{MODULE_marigold_dynamic_array => MODULE_marigold_vector}/internal/internal_marigold_dynamic_array.h (100%) rename source_code/{MODULE_marigold_dynamic_array/marigold_dynamic_array.c => MODULE_marigold_vector/marigold_vector.c} (100%) create mode 100644 source_code/MODULE_marigold_vector/marigold_vector.h rename source_code/{MODULE_marigold_dynamic_array => MODULE_marigold_vector}/tests/test_marigold_dynamic_array.c (100%) rename source_code/{MODULE_marigold_dynamic_array => MODULE_marigold_vector}/tests/test_marigold_dynamic_array.h (100%) diff --git a/source_code/MODULE_marigold_dynamic_array/marigold_dynamic_array.h b/source_code/MODULE_marigold_dynamic_array/marigold_dynamic_array.h deleted file mode 100644 index 9ef04a2..0000000 --- a/source_code/MODULE_marigold_dynamic_array/marigold_dynamic_array.h +++ /dev/null @@ -1,594 +0,0 @@ -#ifndef MARIGOLD_DYNAMIC_ARRAY_H -#define MARIGOLD_DYNAMIC_ARRAY_H - -#include -#include -#include -#include - -typedef enum -dynamic_array_flag_enum -{ - dynamic_array_multithread_safe = 1 << 0, - dynamic_array_read_only = 1 << 1, - dynamic_array_certainly_sorted = 1 << 2, - dynamic_array_marked_for_free = 1 << 3, - dynamic_array_debug_has_function_call_rolled_over = 1 << 4, - dynamic_array_debug_has_owner_count_rolled_over = 1 << 5, - dynamic_array_debug_has_been_resized = 1 << 6, - dynamic_array_debug_has_been_resized_rolled_over = 1 << 7 -} -dynamic_array_flag_enum; - -typedef enum -dynamic_array_growth_rate_enum -{ - dynamic_array_growth_static = 0, - dynamic_array_growth_linear = 1, - dynamic_array_growth_double = 2, - dynamic_array_growth_triple = 3, - dynamic_array_growth_quadruple = 4, - dynamic_array_growth_quintuple = 5 -} -dynamic_array_growth_rate_enum; - -typedef struct -dynamic_array_struct -{ - size_t item_size; - size_t current_capacity; - size_t current_occupancy; - void* data_pointer; - int (*comparator)(const void *, const void *); - void (*item_free)(const void *); - pthread_mutex_t* mutex_lock; - unsigned short owner_count; - uint8_t growth_strategy; - uint8_t flags; -#ifdef MARIGOLD_DEBUG - uint8_t debug_flags; - uint32_t debug_resize_count; - uint32_t debug_function_call_count; - uint32_t debug_last_error_code; - uint32_t debug_allocation_failures; - -#endif // MARIGOLD_DEBUG. -} -dynamic_array_struct; - -/** - * @brief Create a new dynamic array, it then internally does all the - * initialization. - * - * Creates a dynamic array with the specified item size and starting capacity. - * The growth_strategy determines how the array expands when capacity is - * exceeded. - * - * If is_multithread_safe is true, the internal mutex is created and initialized - * here. - * - * @param item_size Size of each element in bytes. - * @param starting_capacity Initial number of elements to allocate space for. - * @param growth_strategy Growth strategy enum. - * @param comparator Function to compare two elements. May be NULL if not - * needed. - * @param is_multithread_safe If true, enables thread-safe operations. - * @return Pointer to the initialized dynamic_array, or NULL on failure. - */ -dynamic_array_struct* -dynamic_array_create(size_t item_size, - size_t starting_capacity, - dynamic_array_growth_rate_enum growth_rate, - int (*comparator)(const void*, const void*), - void (*item_free)(const void *), - bool is_multithread_safe); - -/** - * @brief Explicitly destroy the dynamic array and free its memory. - * - * Checks the owner count. If it is 0 or 1, deallocates the internal memory - * and the struct itself. Use this for explicit cleanup. For reference-counted - * shared ownership, prefer dynamic_array_release(). - * - * If the array is thread-safe, the internal mutex is destroyed and freed here. - * - * @param array_to_destroy is the dynamic array being deallocated/destroyed. - * @return true on successful destroy, false on failure. - */ -bool -dynamic_array_destroy(dynamic_array_struct* array_to_destroy); - -/** - * @brief Set or clear a specific flag on the dynamic array. - * - * @param array Pointer to the dynamic_array. - * @param flag The flag to modify. - * @param value true to set the flag, false to clear it. - */ -void -dynamic_array_set_flag(dynamic_array_struct* array, - dynamic_array_flag_enum flag, - bool value); - -/** - * @brief Get a specific flag on the dynamic array. - * - * @param array Pointer to the dynamic_array. - * @param flag The flag to get. - * - * @return value of flag as bool (true or false) - */ -bool -dynamic_array_get_flag_value(const dynamic_array_struct* array, - dynamic_array_flag_enum flag); - -/** - * @brief Get the number of elements currently in the array. - * - * @param array Pointer to the dynamic_array. - * @return Number of elements (current_occupancy). - */ -size_t -dynamic_array_get_occupancy(const dynamic_array_struct* array); - -/** - * @brief Get the total capacity of the array. - * - * @param array Pointer to the dynamic_array. - * @return Total capacity (current_capacity). - */ -size_t -dynamic_array_get_capacity(const dynamic_array_struct* array); - -/** - * @brief Get a pointer to the element at the specified index. - * - * @param array Pointer to the dynamic_array. - * @param index Index of the element to access. - * @return Pointer to the element, or NULL if index is out of bounds. - */ -void* -dynamic_array_get_pointer_to_index(dynamic_array_struct* array, - size_t index); - -/** - * @brief Get a const pointer to the element at the specified index. - * - * @param array Pointer to the dynamic_array. - * @param index Index of the element to access. - * @return Const pointer to the element, or NULL if index is out of bounds. - */ -const void* -dynamic_array_get_const_pointer_to_index(const dynamic_array_struct* array, - size_t index); - -/** - * @brief Get a direct pointer to the underlying memory block. - * - * Useful for direct iteration or passing to C APIs expecting raw arrays. - * Does not perform bounds checking. - * - * @param array Pointer to the dynamic_array. - * @return Pointer to the raw memory block, or NULL if empty. - */ -void* -dynamic_array_get_raw_data_pointer(const dynamic_array_struct* array); - -/** - * @brief Append an element to the end of the array. - * - * Automatically resizes if current_occupancy equals current_capacity. - * - * @param array Pointer to the dynamic_array. - * @param element Pointer to the element to append. - * @return true on success, false on allocation failure. - */ -bool -dynamic_array_append(dynamic_array_struct* array, const void* element); - -/** - * @brief Insert an element at the specified index. - * - * Shifts existing elements at and after the index to the right. - * Automatically resizes if capacity is exceeded. - * - * @param array Pointer to the dynamic_array. - * @param index Index at which to insert the element. - * @param element Pointer to the element to insert. - * @return true on success, false if index is out of bounds or allocation fails. - */ -bool -dynamic_array_insert_at(dynamic_array_struct* array, - size_t index, - const void* element); - -/** - * @brief Replace the element at the specified index. - * - * @param array Pointer to the dynamic_array. - * @param index Index of the element to replace. - * @param new_element Pointer to the new element data. - * @return true on success, false if index is out of bounds. - */ -bool -dynamic_array_set_item(dynamic_array_struct* array, - size_t index, - const void* new_element); - -/** - * @brief Swap the elements at two indices. - * - * @param array Pointer to the dynamic_array. - * @param index_a First index. - * @param index_b Second index. - * @return true on success, false if either index is out of bounds. - */ -bool -dynamic_array_swap(dynamic_array_struct* array, - size_t index_a, - size_t index_b); - -/** - * @brief Remove the last element from the array. - * - * Decrements current_occupancy. Does not free the memory block. - * If item_free is set, it will be called on the removed element. - * - * @param array Pointer to the dynamic_array. - * @return true on success, false if array is empty. - */ -bool -dynamic_array_pop(dynamic_array_struct* array); - -/** - * @brief Remove an element at the specified index. - * - * Shifts subsequent elements down to fill the gap. - * If item_free is set, it will be called on the removed element. - * - * @param array Pointer to the dynamic_array. - * @param index Index of the element to remove. - * @return true on success, false if index is out of bounds. - */ -bool -dynamic_array_remove(dynamic_array_struct* array, - size_t index); - -/** - * @brief Clear all elements from the array. - * - * Sets current_occupancy to 0. Does not free the memory block. - * If item_free is set, it will be called on all removed elements. - * - * @param array Pointer to the dynamic_array. - */ -void -dynamic_array_clear(dynamic_array_struct* array); - -/** - * @brief Check if the array is empty. - * - * @param array Pointer to the dynamic_array. - * @return true if current_occupancy is 0, false otherwise. - */ -bool -dynamic_array_is_empty(const dynamic_array_struct* array); - -/** - * @brief Reserve additional capacity without changing elements. - * - * @param array Pointer to the dynamic_array. - * @param new_capacity Desired capacity. - * @return true on success, false on allocation failure. - */ -bool -dynamic_array_increase_capacity(dynamic_array_struct* array, - size_t new_capacity); - -/** - * @brief Shrink the array capacity to match current occupancy. - * - * Frees unused memory while keeping all elements intact. - * - * @param array Pointer to the dynamic_array. - * @return true on success, false on allocation failure. - */ -bool -dynamic_array_shrink_to_fit(dynamic_array_struct* array); - -/** - * @brief Increment the owner count for shared ownership. - * - * @param array Pointer to the dynamic_array. - * @return true on success, false if owner_count would overflow. - */ -bool -dynamic_array_acquire(dynamic_array_struct* array); - -/** - * @brief Decrement the owner count for shared ownership. - * - * If owner_count reaches 0, the array is automatically destroyed. - * - * @param array Pointer to the dynamic_array. - * @return true if owner_count > 0 after decrement, false if destroyed. - */ -bool -dynamic_array_release(dynamic_array_struct* array); - -/** - * @brief Get the current owner count. - * - * @param array Pointer to the dynamic_array. - * @return Current owner_count value. - */ -unsigned short -dynamic_array_get_owner_count(const dynamic_array_struct* array); - -/** - * @brief Check if the array is thread-safe. - * - * @param array Pointer to the dynamic_array. - * @return true if is_multithread_safe is set, false otherwise. - */ -bool -dynamic_array_is_thread_safe(const dynamic_array_struct* array); - -/** - * @brief Creates a shallow copy of the array. - * - * The new array will have the same capacity and occupancy, but the elements - * themselves are not copied (pointers are copied). - * - * @param array_to_copy Pointer to the array being copied. - * @return Pointer to the new shallow copy, or NULL on failure. - */ -dynamic_array_struct* -dynamic_array_shallow_copy(const dynamic_array_struct* array_to_copy); - -/** - * @brief Creates a deep copy of the array. - * - * Uses the provided item_copy function to duplicate each element. - * - * @param array_to_copy Pointer to the array being copied. - * @param item_copy Function pointer to copy a single element. - * @return Pointer to the new deep copy, or NULL on failure. - */ -dynamic_array_struct* -dynamic_array_deep_copy(const dynamic_array_struct* array_to_copy, - void* (*item_copy)(const void* item)); - -/** - * @brief Creates a shallow copy of a slice of an array. - * - * @param array_to_copy Pointer to the array being copied/sliced. - * @param starting_point Index to start the slice at. - * @param ending_point Index to end the slice at. - * @param is_start_inclusive Boolean indicator of if the starting index should - * be included. - * @param is_end_inclusive Boolean indicator of if the ending index should - * be included. - * @return Pointer to the new shallow copy of the slice, or NULL on failure. - */ -dynamic_array_struct* -dynamic_array_shallow_copy_slice(const dynamic_array_struct* array_to_copy, - size_t starting_point, - size_t ending_point, - bool is_start_inclusive, - bool is_end_inclusive); - -/** - * @brief Creates a deep copy of a slice of an array. - * - * Uses the provided item_copy function to duplicate each element in the slice. - * - * @param array_to_copy Pointer to the array being copied/sliced. - * @param item_copy Function pointer to copy a single element. - * @param starting_point Index to start the slice at. - * @param ending_point Index to end the slice at. - * @param is_start_inclusive Boolean indicator of if the starting index should - * be included. - * @param is_end_inclusive Boolean indicator of if the ending index should - * be included. - * @return Pointer to the new deep copy of the slice, or NULL on failure. - */ -dynamic_array_struct* -dynamic_array_deep_copy_slice(const dynamic_array_struct* array_to_copy, - void* (*item_copy)(const void* item), - size_t starting_point, - size_t ending_point, - bool is_start_inclusive, - bool is_end_inclusive); - -/** - * @brief Modifies the array in place so that it is sorted. - * - * @param array_to_sort Pointer to the array to be sorted. - * @param should_reverse_sort If true, inverts the order of the array. - */ -void -dynamic_array_sort_in_place(dynamic_array_struct* array_to_sort, - bool should_reverse_sort); - -/** - * @brief Sorts a slice of the array in place. - * - * @param array_to_sort Pointer to the array to be sorted. - * @param starting_point Index to start the slice at. - * @param ending_point Index to end the slice at. - * @param is_start_inclusive Boolean indicator of if the starting index should - * be included. - * @param is_end_inclusive Boolean indicator of if the ending index should - * be included. - * @param should_reverse_sort If true, inverts the order of the slice. - */ -void -dynamic_array_sort_slice(dynamic_array_struct* array_to_sort, - size_t starting_point, - size_t ending_point, - bool is_start_inclusive, - bool is_end_inclusive, - bool should_reverse_sort); - -/** - * @brief Creates a new sorted shallow copy of the array without modifying the original. - * - * @param array_to_sort Pointer to the array to be sorted. - * @param should_reverse_sort If true, inverts the order of the copy. - * @return Pointer to the new sorted array, or NULL on failure. - */ -dynamic_array_struct* -dynamic_array_get_sorted_copy(const dynamic_array_struct* array, - bool should_reverse_sort); - -/** - * @brief Reverses the order of elements in the array in place. - * - * @param array_to_reverse Pointer to the array to be reversed. - */ -void -dynamic_array_reverse(dynamic_array_struct* array_to_reverse); - -/** - * @brief Check if the array contains a specific value. - * - * Requires a valid comparator function to be set. - * - * @param array_to_search Pointer to the array to search. - * @param pointer_of_value_to_find Pointer to the value to find. - * @return true if the value is found, false otherwise. - */ -bool -dynamic_array_contains(const dynamic_array_struct* array_to_search, - const void* pointer_of_value_to_find); - -/** - * @brief Find the first index of a value in the array. - * - * Requires a valid comparator function to be set. - * - * @param array_to_search Pointer to the array to search. - * @param pointer_of_value_to_find Pointer to the value to find. - * @return Index of the first occurrence, or SIZE_MAX if not found. - */ -size_t -dynamic_array_find_first_index_of(const dynamic_array_struct* array_to_search, - const void* pointer_of_value_to_find); - -/** - * @brief Find the last index of a value in the array. - * - * Requires a valid comparator function to be set. - * - * @param array_to_search Pointer to the array to search. - * @param pointer_of_value_to_find Pointer to the value to find. - * @return Index of the last occurrence, or SIZE_MAX if not found. - */ -size_t -dynamic_array_find_final_index_of(const dynamic_array_struct* array_to_search, - const void* pointer_of_value_to_find); - -/** - * @brief Set or change the comparator function used for sorting and searching. - * - * @param array Pointer to the dynamic_array. - * @param comparator Function to compare two elements. - */ -void -dynamic_array_set_comparator_function(dynamic_array_struct *array, - int (*comparator)(const void*, const void*)); - -/** - * @brief Copies the element at the specified index into a user-provided buffer. - * - * Performs bounds checking and uses memcpy to safely extract the element's - * data. Useful when you need a standalone copy of an element rather than a - * temporary pointer. - * - * @param array Pointer to the dynamic_array. - * @param index Index of the element to retrieve. - * @param out_buffer Pointer to a buffer large enough to hold one element (at - * least item_size bytes). - * @return true on success, false if index is out of bounds or out_buffer is - * NULL. - */ -bool -dynamic_array_get_item(const dynamic_array_struct* array, - size_t index, - void* out_buffer); - -/** - * @brief Iterates over a specific range of the array. - * - * Calls the callback function for each element in the specified range. - * - * @param array Pointer to the dynamic_array. - * @param callback Function to call for each element. - * @param starting_index Index to start iteration from. - * @param ending_index Index to end iteration at. - * @param is_start_inclusive If true, includes the starting_index in iteration. - * @param is_end_inclusive If true, includes the ending_index in iteration. - */ -void -dynamic_array_iterate_over(dynamic_array_struct* array, - void (*callback)(void* element, void* user_data), - size_t starting_index, - size_t ending_index, - bool is_start_inclusive, - bool is_end_inclusive); - -/** - * @brief Iterates over every element in the array. - * - * Calls the callback function for each element in the array. - * - * @param array Pointer to the dynamic_array. - * @param callback Function to call for each element. - */ -void -dynamic_array_foreach(dynamic_array_struct* array, - void (*callback)(void* element, void* user_data)); - -/** - * @brief Performs a binary search on the array. - * - * If the array is not marked as sorted, a temporary sorted copy is created. - * For repeated searches on unsorted data, sort the array in-place first for - * better performance. - * - * @param array Pointer to the dynamic_array. - * @param value Pointer to the value to search for. - * @return Index of the element if found, or SIZE_MAX if not found. - */ -size_t -dynamic_array_binary_search(const dynamic_array_struct* array, - const void* value); - -#ifdef MARIGOLD_DEBUG -/** - * @brief Prints debug statistics about the array to stdout. - * - * @param array Pointer to the dynamic_array. - */ -void dynamic_array_debug_print_stats(const dynamic_array_struct* array); - -/** - * @brief Dumps the contents of the array to stdout. - * - * @param array Pointer to the dynamic_array. - */ -void dynamic_array_debug_dump_array(const dynamic_array_struct* array); - -/** - * @brief Validates the internal integrity of the array. - * - * Checks for consistency in capacity, occupancy, and pointers. - * - * @param array Pointer to the dynamic_array. - * @return true if the array is valid, false otherwise. - */ -bool dynamic_array_validate_integrity(const dynamic_array_struct* array); -#endif /* MARIGOLD_DEBUG */ - -#endif /* MARIGOLD_DYNAMIC_ARRAY_H */ diff --git a/source_code/MODULE_marigold_dynamic_array/internal/internal_marigold_dynamic_array.c b/source_code/MODULE_marigold_vector/internal/internal_marigold_dynamic_array.c similarity index 100% rename from source_code/MODULE_marigold_dynamic_array/internal/internal_marigold_dynamic_array.c rename to source_code/MODULE_marigold_vector/internal/internal_marigold_dynamic_array.c diff --git a/source_code/MODULE_marigold_dynamic_array/internal/internal_marigold_dynamic_array.h b/source_code/MODULE_marigold_vector/internal/internal_marigold_dynamic_array.h similarity index 100% rename from source_code/MODULE_marigold_dynamic_array/internal/internal_marigold_dynamic_array.h rename to source_code/MODULE_marigold_vector/internal/internal_marigold_dynamic_array.h diff --git a/source_code/MODULE_marigold_dynamic_array/marigold_dynamic_array.c b/source_code/MODULE_marigold_vector/marigold_vector.c similarity index 100% rename from source_code/MODULE_marigold_dynamic_array/marigold_dynamic_array.c rename to source_code/MODULE_marigold_vector/marigold_vector.c diff --git a/source_code/MODULE_marigold_vector/marigold_vector.h b/source_code/MODULE_marigold_vector/marigold_vector.h new file mode 100644 index 0000000..0f5930c --- /dev/null +++ b/source_code/MODULE_marigold_vector/marigold_vector.h @@ -0,0 +1,597 @@ +#ifndef MARIGOLD_VECTOR_H +#define MARIGOLD_VECTOR_H + +#include +#include +#include +#include + +typedef enum +vector_flag_enum +{ + vector_multithread_safe = 1 << 0, + vector_read_only = 1 << 1, + vector_certainly_sorted = 1 << 2, + vector_marked_for_free = 1 << 3, + vector_debug_has_function_call_rolled_over = 1 << 4, + vector_debug_has_owner_count_rolled_over = 1 << 5, + vector_debug_has_been_resized = 1 << 6, + vector_debug_has_been_resized_rolled_over = 1 << 7 +} +vector_flag_enum; + +typedef enum +vector_growth_rate_enum +{ + vector_growth_none = 0, + vector_growth_linear = 1, + vector_growth_double = 2, + vector_growth_triple = 3, + vector_growth_quadruple = 4, + vector_growth_quintuple = 5 +} +vector_growth_rate_enum; + +typedef struct +vector_struct +{ + size_t item_size; + size_t current_capacity; + size_t current_occupancy; + void* data_pointer; + int (*comparator)(const void *, const void *); + void (*item_free)(const void *); + pthread_mutex_t* mutex_lock; + unsigned short owner_count; + uint8_t growth_strategy; + uint8_t flags; +#ifdef MARIGOLD_DEBUG + uint8_t debug_flags; + uint32_t debug_resize_count; + uint32_t debug_function_call_count; + uint32_t debug_last_error_code; + uint32_t debug_allocation_failures; + +#endif /* MARIGOLD_DEBUG. */ +} +vector_struct; + +/** + * @brief Create a new dynamic vector, it then internally does all the + * initialization. + * + * Creates a dynamic vector with the specified item size and starting capacity. + * The growth_strategy determines how the vector expands when capacity is + * exceeded. + * + * If is_multithread_safe is true, the internal mutex is created and initialized + * here. + * + * @param item_size Size of each element in bytes. + * @param starting_capacity Initial number of elements to allocate space for. + * @param growth_strategy Growth strategy enum. + * @param comparator Function to compare two elements. May be NULL if not + * needed. + * @param is_multithread_safe If true, enables thread-safe operations. + * @return Pointer to the initialized vector, or NULL on failure. + */ +vector_struct* +vector_create(size_t item_size, + size_t starting_capacity, + vector_growth_rate_enum growth_rate, + int (*comparator)(const void*, const void*), + void (*item_free)(const void *), + bool is_multithread_safe); + +/** + * @brief Explicitly destroy the dynamic vector and free its memory. + * + * Checks the owner count. If it is 0 or 1, deallocates the internal memory + * and the struct itself. Use this for explicit cleanup. For reference-counted + * shared ownership, prefer vector_release(). + * + * If the vector is thread-safe, the internal mutex is destroyed and freed here. + * + * @param vector_to_destroy is the dynamic vector being deallocated/destroyed. + * @return true on successful destroy, false on failure. + */ +bool +vector_destroy(vector_struct* vector_to_destroy); + +/** + * @brief Set or clear a specific flag on the dynamic vector. + * + * @param vector Pointer to the vector. + * @param flag The flag to modify. + * @param value true to set the flag, false to clear it. + */ +void +vector_set_flag(vector_struct* vector, + vector_flag_enum flag, + bool value); + +/** + * @brief Get a specific flag on the dynamic vector. + * + * @param vector Pointer to the vector. + * @param flag The flag to get. + * + * @return value of flag as bool (true or false) + */ +bool +vector_get_flag_value(const vector_struct* vector, + vector_flag_enum flag); + +/** + * @brief Get the number of elements currently in the vector. + * + * @param vector Pointer to the vector. + * @return Number of elements (current_occupancy). + */ +size_t +vector_get_occupancy(const vector_struct* vector); + +/** + * @brief Get the total capacity of the vector. + * + * @param vector Pointer to the vector. + * @return Total capacity (current_capacity). + */ +size_t +vector_get_capacity(const vector_struct* vector); + +/** + * @brief Get a pointer to the element at the specified index. + * + * @param vector Pointer to the vector. + * @param index Index of the element to access. + * @return Pointer to the element, or NULL if index is out of bounds. + */ +void* +vector_get_pointer_to_index(vector_struct* vector, + size_t index); + +/** + * @brief Get a const pointer to the element at the specified index. + * + * @param vector Pointer to the vector. + * @param index Index of the element to access. + * @return Const pointer to the element, or NULL if index is out of bounds. + */ +const void* +vector_get_const_pointer_to_index(const vector_struct* vector, + size_t index); + +/** + * @brief Get a direct pointer to the underlying memory block. + * + * Useful for direct iteration or passing to C APIs expecting raw vectors. + * Does not perform bounds checking. + * + * @param vector Pointer to the vector. + * @return Pointer to the raw memory block, or NULL if empty. + */ +void* +vector_get_raw_data_pointer(const vector_struct* vector); + +/** + * @brief Append an element to the end of the vector. + * + * Automatically resizes if current_occupancy equals current_capacity. + * + * @param vector Pointer to the vector. + * @param element Pointer to the element to append. + * @return true on success, false on allocation failure. + */ +bool +vector_append(vector_struct* vector, const void* element); + +/** + * @brief Insert an element at the specified index. + * + * Shifts existing elements at and after the index to the right. + * Automatically resizes if capacity is exceeded. + * + * @param vector Pointer to the vector. + * @param index Index at which to insert the element. + * @param element Pointer to the element to insert. + * @return true on success, false if index is out of bounds or allocation fails. + */ +bool +vector_insert_at(vector_struct* vector, + size_t index, + const void* element); + +/** + * @brief Replace the element at the specified index. + * + * @param vector Pointer to the vector. + * @param index Index of the element to replace. + * @param new_element Pointer to the new element data. + * @return true on success, false if index is out of bounds. + */ +bool +vector_set_item(vector_struct* vector, + size_t index, + const void* new_element); + +/** + * @brief Swap the elements at two indices. + * + * @param vector Pointer to the vector. + * @param index_a First index. + * @param index_b Second index. + * @return true on success, false if either index is out of bounds. + */ +bool +vector_swap(vector_struct* vector, + size_t index_a, + size_t index_b); + +/** + * @brief Remove the last element from the vector. + * + * Decrements current_occupancy. Does not free the memory block. + * If item_free is set, it will be called on the removed element. + * + * @param vector Pointer to the vector. + * @return true on success, false if vector is empty. + */ +bool +vector_pop(vector_struct* vector); + +/** + * @brief Remove an element at the specified index. + * + * Shifts subsequent elements down to fill the gap. + * If item_free is set, it will be called on the removed element. + * + * @param vector Pointer to the vector. + * @param index Index of the element to remove. + * @return true on success, false if index is out of bounds. + */ +bool +vector_remove(vector_struct* vector, + size_t index); + +/** + * @brief Clear all elements from the vector. + * + * Sets current_occupancy to 0. Does not free the memory block. + * If item_free is set, it will be called on all removed elements. + * + * @param vector Pointer to the vector. + */ +void +vector_clear(vector_struct* vector); + +/** + * @brief Check if the vector is empty. + * + * @param vector Pointer to the vector. + * @return true if current_occupancy is 0, false otherwise. + */ +bool +vector_is_empty(const vector_struct* vector); + +/** + * @brief Reserve additional capacity without changing elements. + * + * @param vector Pointer to the vector. + * @param new_capacity Desired capacity. + * @return true on success, false on allocation failure. + */ +bool +vector_increase_capacity(vector_struct* vector, + size_t new_capacity); + +/** + * @brief Shrink the vector capacity to match current occupancy. + * + * Frees unused memory while keeping all elements intact. + * + * @param vector Pointer to the vector. + * @return true on success, false on allocation failure. + */ +bool +vector_shrink_to_fit(vector_struct* vector); + +/** + * @brief Increment the owner count for shared ownership. + * + * @param vector Pointer to the vector. + * @return true on success, false if owner_count would overflow. + */ +bool +vector_acquire(vector_struct* vector); + +/** + * @brief Decrement the owner count for shared ownership. + * + * If owner_count reaches 0, the vector is automatically destroyed. + * + * @param vector Pointer to the vector. + * @return true if owner_count > 0 after decrement, false if destroyed. + */ +bool +vector_release(vector_struct* vector); + +/** + * @brief Get the current owner count. + * + * @param vector Pointer to the vector. + * @return Current owner_count value. + */ +unsigned short +vector_get_owner_count(const vector_struct* vector); + +/** + * @brief Check if the vector is thread-safe. + * + * @param vector Pointer to the vector. + * @return true if is_multithread_safe is set, false otherwise. + */ +bool +vector_is_thread_safe(const vector_struct* vector); + +/** + * @brief Creates a shallow copy of the vector. + * + * The new vector will have the same capacity and occupancy, but the elements + * themselves are not copied (pointers are copied). + * + * @param vector_to_copy Pointer to the vector being copied. + * @return Pointer to the new shallow copy, or NULL on failure. + */ +vector_struct* +vector_shallow_copy(const vector_struct* vector_to_copy); + +/** + * @brief Creates a deep copy of the vector. + * + * Uses the provided item_copy function to duplicate each element. + * + * @param vector_to_copy Pointer to the vector being copied. + * @param item_copy Function pointer to copy a single element. + * @return Pointer to the new deep copy, or NULL on failure. + */ +vector_struct* +vector_deep_copy(const vector_struct* vector_to_copy, + void* (*item_copy)(const void* item)); + +/** + * @brief Creates a shallow copy of a slice of a vector. + * + * @param vector_to_copy Pointer to the vector being copied/sliced. + * @param starting_point Index to start the slice at. + * @param ending_point Index to end the slice at. + * @param is_start_inclusive Boolean indicator of if the starting index should + * be included. + * @param is_end_inclusive Boolean indicator of if the ending index should + * be included. + * @return Pointer to the new shallow copy of the slice, or NULL on failure. + */ +vector_struct* +vector_shallow_copy_slice(const vector_struct* vector_to_copy, + size_t starting_point, + size_t ending_point, + bool is_start_inclusive, + bool is_end_inclusive); + +/** + * @brief Creates a deep copy of a slice of a vector. + * + * Uses the provided item_copy function to duplicate each element in the slice. + * + * @param vector_to_copy Pointer to the vector being copied/sliced. + * @param item_copy Function pointer to copy a single element. + * @param starting_point Index to start the slice at. + * @param ending_point Index to end the slice at. + * @param is_start_inclusive Boolean indicator of if the starting index should + * be included. + * @param is_end_inclusive Boolean indicator of if the ending index should + * be included. + * @return Pointer to the new deep copy of the slice, or NULL on failure. + */ +vector_struct* +vector_deep_copy_slice(const vector_struct* vector_to_copy, + void* (*item_copy)(const void* item), + size_t starting_point, + size_t ending_point, + bool is_start_inclusive, + bool is_end_inclusive); + +/** + * @brief Modifies the vector in place so that it is sorted. + * + * @param vector_to_sort Pointer to the vector to be sorted. + * @param should_reverse_sort If true, inverts the order of the vector. + */ +void +vector_sort_in_place(vector_struct* vector_to_sort, + bool should_reverse_sort); + +/** + * @brief Sorts a slice of the vector in place. + * + * @param vector_to_sort Pointer to the vector to be sorted. + * @param starting_point Index to start the slice at. + * @param ending_point Index to end the slice at. + * @param is_start_inclusive Boolean indicator of if the starting index should + * be included. + * @param is_end_inclusive Boolean indicator of if the ending index should + * be included. + * @param should_reverse_sort If true, inverts the order of the slice. + */ +void +vector_sort_slice(vector_struct* vector_to_sort, + size_t starting_point, + size_t ending_point, + bool is_start_inclusive, + bool is_end_inclusive, + bool should_reverse_sort); + +/** + * @brief Creates a new sorted shallow copy of the vector without modifying the original. + * + * @param vector_to_sort Pointer to the vector to be sorted. + * @param should_reverse_sort If true, inverts the order of the copy. + * @return Pointer to the new sorted vector, or NULL on failure. + */ +vector_struct* +vector_get_sorted_copy(const vector_struct* vector, + bool should_reverse_sort); + +/** + * @brief Reverses the order of elements in the vector in place. + * + * @param vector_to_reverse Pointer to the vector to be reversed. + */ +void +vector_reverse(vector_struct* vector_to_reverse); + +/** + * @brief Check if the vector contains a specific value. + * + * Requires a valid comparator function to be set. + * + * @param vector_to_search Pointer to the vector to search. + * @param pointer_of_value_to_find Pointer to the value to find. + * @return true if the value is found, false otherwise. + */ +bool +vector_contains(const vector_struct* vector_to_search, + const void* pointer_of_value_to_find); + +/** + * @brief Find the first index of a value in the vector. + * + * Requires a valid comparator function to be set. + * + * @param vector_to_search Pointer to the vector to search. + * @param pointer_of_value_to_find Pointer to the value to find. + * @return Index of the first occurrence, or SIZE_MAX if not found. + */ +size_t +vector_find_first_index_of(const vector_struct* vector_to_search, + const void* pointer_of_value_to_find); + +/** + * @brief Find the last index of a value in the vector. + * + * Requires a valid comparator function to be set. + * + * @param vector_to_search Pointer to the vector to search. + * @param pointer_of_value_to_find Pointer to the value to find. + * @return Index of the last occurrence, or SIZE_MAX if not found. + */ +size_t +vector_find_final_index_of(const vector_struct* vector_to_search, + const void* pointer_of_value_to_find); + +/** + * @brief Set or change the comparator function used for sorting and searching. + * + * @param vector Pointer to the vector. + * @param comparator Function to compare two elements. + */ +void +vector_set_comparator_function(vector_struct *vector, + int (*comparator)(const void*, const void*)); + +/** + * @brief Copies the element at the specified index into a user-provided buffer. + * + * Performs bounds checking and uses memcpy to safely extract the element's + * data. Useful when you need a standalone copy of an element rather than a + * temporary pointer. + * + * @param vector Pointer to the vector. + * @param index Index of the element to retrieve. + * @param out_buffer Pointer to a buffer large enough to hold one element (at + * least item_size bytes). + * @return true on success, false if index is out of bounds or out_buffer is + * NULL. + */ +bool +vector_get_item(const vector_struct* vector, + size_t index, + void* out_buffer); + +/** + * @brief Iterates over a specific range of the vector. + * + * Calls the callback function for each element in the specified range. + * + * @param vector Pointer to the vector. + * @param callback Function to call for each element. + * @param starting_index Index to start iteration from. + * @param ending_index Index to end iteration at. + * @param is_start_inclusive If true, includes the starting_index in iteration. + * @param is_end_inclusive If true, includes the ending_index in iteration. + */ +void +vector_iterate_over(vector_struct* vector, + void (*callback)(void* element, void* user_data), + size_t starting_index, + size_t ending_index, + bool is_start_inclusive, + bool is_end_inclusive); + +/** + * @brief Iterates over every element in the vector. + * + * Calls the callback function for each element in the vector. + * + * @param vector Pointer to the vector. + * @param callback Function to call for each element. + */ +void +vector_foreach(vector_struct* vector, + void (*callback)(void* element, void* user_data)); + +/** + * @brief Performs a binary search on the vector. + * + * If the vector is not marked as sorted, a temporary sorted copy is created. + * For repeated searches on unsorted data, sort the vector in-place first for + * better performance. + * + * @param vector Pointer to the vector. + * @param value Pointer to the value to search for. + * @return Index of the element if found, or SIZE_MAX if not found. + */ +size_t +vector_binary_search(const vector_struct* vector, + const void* value); + +#ifdef MARIGOLD_DEBUG +/** + * @brief Prints debug statistics about the vector to stdout. + * + * @param vector Pointer to the vector. + */ +void +vector_debug_print_stats(const vector_struct* vector); + +/** + * @brief Dumps the contents of the vector to stdout. + * + * @param vector Pointer to the vector. + */ +void +vector_debug_dump_vector(const vector_struct* vector); + +/** + * @brief Validates the internal integrity of the vector. + * + * Checks for consistency in capacity, occupancy, and pointers. + * + * @param vector Pointer to the vector. + * @return true if the vector is valid, false otherwise. + */ +bool +vector_validate_integrity(const vector_struct* vector); +#endif /* MARIGOLD_DEBUG */ + +#endif /* MARIGOLD_VECTOR_H */ diff --git a/source_code/MODULE_marigold_dynamic_array/tests/test_marigold_dynamic_array.c b/source_code/MODULE_marigold_vector/tests/test_marigold_dynamic_array.c similarity index 100% rename from source_code/MODULE_marigold_dynamic_array/tests/test_marigold_dynamic_array.c rename to source_code/MODULE_marigold_vector/tests/test_marigold_dynamic_array.c diff --git a/source_code/MODULE_marigold_dynamic_array/tests/test_marigold_dynamic_array.h b/source_code/MODULE_marigold_vector/tests/test_marigold_dynamic_array.h similarity index 100% rename from source_code/MODULE_marigold_dynamic_array/tests/test_marigold_dynamic_array.h rename to source_code/MODULE_marigold_vector/tests/test_marigold_dynamic_array.h