more functions implemented, and updated LICENSES
This commit is contained in:
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user