more functions implemented, and updated LICENSES

This commit is contained in:
2026-05-28 18:23:10 -05:00
parent df76edc97a
commit e142468c81
5 changed files with 238 additions and 16 deletions

View File

@@ -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.

View File

@@ -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 */

View File

@@ -1,5 +1,7 @@
#include "marigold_vector.h"
#include "internal/internal_marigold_macros.h"
#include <pthread.h>
#include <stdio.h>
#include <string.h>
@@ -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);
}
bool
vector_pop(vector_struct* vector)
{
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. */
}
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;
}

View File

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

View File

@@ -1,12 +1,45 @@
#include "MODULE_marigold_vector/marigold_vector.h"
#include <stddef.h>
#include <stdio.h>
#include "MODULE_marigold_dynamic_array/marigold_dynamic_array.h"
#include <time.h>
/*
_.-''''-..
.-' -_ \
/ -. \ ,_ , ' ,,-.
/ _ \ \ \ '''" /
|(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;
}