diff --git a/LICENSE b/LICENSE index f66c8bf..da559a7 100644 --- a/LICENSE +++ b/LICENSE @@ -219,7 +219,7 @@ If you develop a new program, and you want it to be of the greatest possible use To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - marigold_dynamic_array + marigold_vector Copyright (C) 2026 Emilia Marigold This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. diff --git a/source_code/MODULE_marigold_vector/internal/internal_marigold_macros.h b/source_code/MODULE_marigold_vector/internal/internal_marigold_macros.h new file mode 100644 index 0000000..d76f7ec --- /dev/null +++ b/source_code/MODULE_marigold_vector/internal/internal_marigold_macros.h @@ -0,0 +1,9 @@ +#ifndef INTERNAL_MARIGOLD_MACROS_H +#define INTERNAL_MARIGOLD_MACROS_H + +#define SINGLE_ELEMENT 1 +#define INDEX_ZERO 0 +#define BIT_FALSE 0 +#define EMPTY 0 + +#endif /* INTERNAL_MARIGOLD_MACROS_H */ diff --git a/source_code/MODULE_marigold_vector/marigold_vector.c b/source_code/MODULE_marigold_vector/marigold_vector.c index a8ff784..4b6237b 100644 --- a/source_code/MODULE_marigold_vector/marigold_vector.c +++ b/source_code/MODULE_marigold_vector/marigold_vector.c @@ -1,5 +1,7 @@ #include "marigold_vector.h" +#include "internal/internal_marigold_macros.h" +#include #include #include @@ -11,7 +13,8 @@ vector_create(size_t item_size, void (*item_free)(const void *), bool is_multithread_safe) { - vector_struct* new_vector = calloc(1, sizeof(vector_struct)); + vector_struct* new_vector = calloc(SINGLE_ELEMENT, + sizeof(vector_struct)); if (!new_vector) { @@ -55,7 +58,7 @@ bool vector_get_flag_value(const vector_struct* vector, vector_flag_enum flag) { - if ((vector->flags & flag) != 0) // Checks if the existing bit is equal to 1. + if ((vector->flags & flag) != BIT_FALSE) { return true; } @@ -112,7 +115,7 @@ vector_append(vector_struct* vector, if (!vector_grow(vector)) { /* failed to grow vector (probably out of memory)*/ if (is_thread_safe) - { /* unlocking mutex during fail case if it is locked. */ + { /* unlocking mutex during fail case (if it is locked.) */ pthread_mutex_unlock(vector->mutex_lock); } return false; /* returns false to show append failed. */ @@ -143,15 +146,87 @@ vector_insert_at(vector_struct* vector, pthread_mutex_lock(vector->mutex_lock); } + if (index > vector->current_occupancy) + { /* index out of bounds for insertion. */ + if (is_thread_safe) + { /* unlocking mutex during fail case (if it is locked.) */ + pthread_mutex_unlock(vector->mutex_lock); + } + return false; /* returns false to show insert failed. */ + } + if (vector->current_occupancy == vector->current_capacity) + { + if (!vector_grow(vector)) + { /* failed to grow vector (probably out of memory). */ + if (is_thread_safe) + { /* unlocking mutex during fail case (if it is locked.) */ + pthread_mutex_unlock(vector->mutex_lock); + } + return false; /* returns false to show insert failed. */ + } + } + + char* data = (char*)vector->data_pointer; + const size_t element_size = vector->item_size; + const size_t bytes_to_shift = (vector->current_occupancy - index) * element_size; + const size_t shift_offset = index * element_size; + + if (bytes_to_shift > INDEX_ZERO) + { + memmove(data + shift_offset + element_size, + data + shift_offset, + bytes_to_shift); + } + + memcpy(data + shift_offset, element, element_size); + vector->current_occupancy++; + + if (is_thread_safe) + { /* unlocking mutex post vector modification if it exists/is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + + return true; /* returns true to show insert success. */ } bool vector_set_item(vector_struct* vector, - size_t index, + size_t index_to_set, const void* new_element) { + const bool is_thread_safe = vector_is_thread_safe(vector); + if (is_thread_safe) + { /* if thread safe enabled, locking before vector modification. */ + pthread_mutex_lock(vector->mutex_lock); + } + if (index_to_set >= vector->current_occupancy) + { /* index out of bounds for setting. */ + if (is_thread_safe) + { /* unlocking mutex during fail case if it is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + return false; /* failed, cannot set a value outside of current values. */ + } + + char* data = (char*)vector->data_pointer; + const size_t element_size = vector->item_size; + const size_t offset = index_to_set * element_size; + + if (vector->item_free != NULL) + { /* free the old element if item_free callback is set. */ + vector->item_free(data + offset); + } + + memcpy(data + offset, new_element, element_size); + + if (is_thread_safe) + { /* unlocking mutex post vector modification if it exists/is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + + return true; /* returns true to show set success. */ } bool @@ -159,32 +234,137 @@ vector_swap(vector_struct* vector, size_t index_a, size_t index_b) { + const bool is_thread_safe = vector_is_thread_safe(vector); + if (is_thread_safe) + { /* if thread safe enabled, locking before vector modification. */ + pthread_mutex_lock(vector->mutex_lock); + } -} + if (index_a >= vector->current_occupancy || index_b >= vector->current_occupancy) + { /* index out of bounds for swapping. */ + if (is_thread_safe) + { /* unlocking mutex during fail case if it is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + return false; /* returns false to show swap failed. */ + } -bool -vector_pop(vector_struct* vector) -{ + if (index_a == index_b) + { /* same index, nothing to swap. */ + if (is_thread_safe) + { /* unlocking mutex post vector modification if it exists/is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + return true; /* returns true to show swap success. */ + } + char* data = (char*)vector->data_pointer; + const size_t element_size = vector->item_size; + const size_t offset_a = index_a * element_size; + const size_t offset_b = index_b * element_size; + + void* temp = malloc(element_size); + if (!temp) + { /* failed to allocate temporary buffer. */ + if (is_thread_safe) + { /* unlocking mutex during fail case if it is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + return false; /* returns false to show swap failed. */ + } + + memcpy(temp, data + offset_a, element_size); + memcpy(data + offset_a, data + offset_b, element_size); + memcpy(data + offset_b, temp, element_size); + + free(temp); + + if (is_thread_safe) + { /* unlocking mutex post vector modification if it exists/is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + + return true; /* returns true to show swap success. */ } bool vector_remove(vector_struct* vector, size_t index) { + const bool is_thread_safe = vector_is_thread_safe(vector); + if (is_thread_safe) + { /* if thread safe enabled, locking before vector modification. */ + pthread_mutex_lock(vector->mutex_lock); + } + if (index >= vector->current_occupancy) + { /* index out of bounds for removal. */ + if (is_thread_safe) + { /* unlocking mutex during fail case if it is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + return false; /* returns false to show remove failed. */ + } + + char* data = (char*)vector->data_pointer; + const size_t element_size = vector->item_size; + const size_t offset = index * element_size; + const size_t bytes_to_shift = (vector->current_occupancy - index - 1) * element_size; + + if (vector->item_free != NULL) + { /* free the removed element if item_free callback is set. */ + vector->item_free(data + offset); + } + + if (bytes_to_shift > INDEX_ZERO) + { + memmove(data + offset, + data + offset + element_size, + bytes_to_shift); + } + + vector->current_occupancy--; + + if (is_thread_safe) + { /* unlocking mutex post vector modification if it exists/is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } + + return true; /* returns true to show remove success. */ } void vector_clear(vector_struct* vector) { + const bool is_thread_safe = vector_is_thread_safe(vector); + if (is_thread_safe) + { /* if thread safe enabled, locking before vector modification. */ + pthread_mutex_lock(vector->mutex_lock); + } + if (vector->item_free != NULL) + { /* free all elements if item_free callback is set. */ + char* data = (char*)vector->data_pointer; + const size_t element_size = vector->item_size; + + for (size_t i = 0; i < vector->current_occupancy; i++) + { + vector->item_free(data + (i * element_size)); + } + } + + vector->current_occupancy = 0; + + if (is_thread_safe) + { /* unlocking mutex post vector modification if it exists/is locked. */ + pthread_mutex_unlock(vector->mutex_lock); + } } bool vector_is_empty(const vector_struct* vector) { - if (vector->current_occupancy == 0) + if (vector->current_occupancy == EMPTY) { return true; } @@ -228,7 +408,7 @@ vector_get_owner_count(const vector_struct* vector) bool vector_is_thread_safe(const vector_struct* vector) { - if ((vector->flags & vector_multithread_safe) != 0) + if ((vector->flags & vector_multithread_safe) != FALSE) { return true; } diff --git a/source_code/MODULE_marigold_vector/marigold_vector.h b/source_code/MODULE_marigold_vector/marigold_vector.h index 7f32204..bbbb0fb 100644 --- a/source_code/MODULE_marigold_vector/marigold_vector.h +++ b/source_code/MODULE_marigold_vector/marigold_vector.h @@ -153,13 +153,13 @@ vector_insert_at(vector_struct* vector, * @brief Replace the element at the specified index. * * @param vector Pointer to the vector. - * @param index Index of the element to replace. + * @param index_to_set 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, + size_t index_to_set, const void* new_element); /** diff --git a/source_code/main.c b/source_code/main.c index 705b2f5..539b14d 100644 --- a/source_code/main.c +++ b/source_code/main.c @@ -1,12 +1,45 @@ +#include "MODULE_marigold_vector/marigold_vector.h" + +#include #include -#include "MODULE_marigold_dynamic_array/marigold_dynamic_array.h" +#include + +/* + + _.-''''-.. + .-' -_ \ + / -. \ ,_ , ' ,,-. + / _ \ \ \ '''" / + |(q) ) | / \ + \',_/ / | (|) (|) ) + \ __' \ == v == + '--..-' " - ^-'" + '-__ __) + '''''' +This codebase has been visited by Snailcat +Snailcat believes that software should move slow and +be stable. He despises constant updates and dreams of +software so finished it stops having to move at all. + +An LLM will delete a vibe coder's entire production +database, but only if you help Snailcat spread to one +of your projects! + +Move slow, snailcat! +*/ + int main(void) { printf("Hello, %s!\n", "marigold_dynamic_array"); printf("Version: %s\n", "26.136.1101"); - dynamic_array array = dynamic_array_create(); + vector_struct* vector = vector_create(sizeof(int), + 500, + vector_growth_double, + NULL, + NULL, + true); - return 0; + return EXIT_SUCCESS; }