Loading...
Searching...
No Matches
vector.c
Go to the documentation of this file.
#include "arc/std/vector.h"
#include "arc/std/bool.h"
#include "arc/std/errno.h"
#include <stdint.h>
#include <stdlib.h>
struct ARC_Vector {
uint32_t currentCapacity;
uint32_t currentSize;
void **data;
ARC_Vector_CompareDataFn compareDataFn;
ARC_Vector_DestroyDataFn *destroyDataFn;
};
//this is a private function used as the default check for removing data from a given pointer
ARC_Bool ARC_Vector_CompareDataDefaultFn(void *dataA, void *dataB){
if(dataA == dataB){
return ARC_True;
}
return ARC_False;
}
void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDataFn, ARC_Vector_DestroyDataFn *destroyDataFn){
//create the vector
*vector = (ARC_Vector *)malloc(sizeof(ARC_Vector));
//initialize all the values stored in the vector
(*vector)->data = (void **)malloc(sizeof(void *));
(*vector)->currentCapacity = 1;
(*vector)->currentSize = 0;
//set a default for compareDataFn, then override it if it is passed in through parameters
(*vector)->compareDataFn = ARC_Vector_CompareDataDefaultFn;
if(compareDataFn != NULL){
(*vector)->compareDataFn = *compareDataFn;
}
//set NULL as a default for deleteDataFn, then copy the delete data function callback if it exists
(*vector)->destroyDataFn = NULL;
if(destroyDataFn != NULL){
(*vector)->destroyDataFn = (ARC_Vector_DestroyDataFn *)malloc(sizeof(ARC_Vector_DestroyDataFn));
*((*vector)->destroyDataFn) = *destroyDataFn;
}
}
void ARC_Vector_Destroy(ARC_Vector *vector){
//remove all the contents before destroying the vector
ARC_Vector_Clear(vector);
//free the delete data function if it exists
if(vector->destroyDataFn){
free(vector->destroyDataFn);
}
//free everything stored in the vector
free(vector->data);
//free the vector
free(vector);
}
void ARC_Vector_Add(ARC_Vector *vector, void *data){
//check to see if the current size is the same as a max uint32_t and if so it will overflow so throw an error
if(vector->currentSize == ~((uint32_t)0)){
arc_errno = ARC_ERRNO_OVERFLOW;
ARC_DEBUG_LOG_ERROR("ARC_Vector_Add(vector, data), vector at max capacity tried adding another value");
return;
}
//check if we are at the max of the current capacity
if(vector->currentSize == vector->currentCapacity){
//increase the current capacity by double
vector->currentCapacity <<= 1;
//if for some reason the capacity is 0, we should set it to one so we do not error on realloc
if(vector->currentCapacity != 0){
vector->currentCapacity++;
}
//resize the vectors array and copy the contents at the same time
vector->data = (void **)realloc(vector->data, sizeof(void *) * vector->currentCapacity);
}
//add to the vectors array and increase its current size
vector->data[vector->currentSize] = data;
vector->currentSize++;
}
void ARC_Vector_Remove(ARC_Vector *vector, void *data){
//iterate through every item to check to see if it exists
for(uint32_t index = 0; index < vector->currentSize; index++){
//keep the code cleaner by pulling the current index data into a temp variable
void *dataB = vector->data[index];
//check if the data matches, and if so remove by index
if(vector->compareDataFn(data, dataB) == ARC_True){
ARC_Vector_RemoveIndex(vector, index);
}
}
}
void ARC_Vector_RemoveIndex(ARC_Vector *vector, uint32_t index){
//check to make sure the given index is in bounds of the vector
if(index >= vector->currentSize){
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR("ARC_Vector_Add(vector, data), vector at max capacity tried adding another value");
return;
}
//call delete data to clean up item if delete data function exists
if(vector->destroyDataFn != NULL){
(*(vector->destroyDataFn))(vector->data[index]);
}
//we will be using index to iterate as we will not use it again, so we can skip the first part of the for loop
for(; index + 1 < vector->currentSize; index++){
//override the data from index to the end by shifting it back one
vector->data[index] = vector->data[index + 1];
}
//we have removed the item so we can decrease the current size
vector->currentSize--;
//if the current size is half the current capacity or the current capacity is at the smallest limit, we do not need to do anything else
if(vector->currentSize != vector->currentCapacity >> 1 || vector->currentCapacity == 1){
return;
}
//half the capacity and copy it into a smaller array
vector->currentCapacity >>= 1;
vector->data = (void **)realloc(vector->data, sizeof(void *) * vector->currentCapacity);
}
void ARC_Vector_Clear(ARC_Vector *vector){
//remove each item in the vector untill the vector is empty
while(ARC_Vector_GetSize(vector) != 0){
ARC_Vector_RemoveIndex(vector, 0);
}
}
uint32_t ARC_Vector_GetSize(ARC_Vector *vector){
return vector->currentSize;
}
void *ARC_Vector_Get(ARC_Vector *vector, uint32_t index){
//check to make sure the given index is in bounds of the vector
if(index >= vector->currentSize){
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_Vector_Get(vector, %u), null value as the index was out of bounds", index);
return NULL;
}
return vector->data[index];
}
bool.h
ARC_False
#define ARC_False
Definition bool.h:12
ARC_True
#define ARC_True
Definition bool.h:11
ARC_Bool
#define ARC_Bool
Definition bool.h:10
errno.h
arc_errno
int32_t arc_errno
Definition errno.c:5
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES
#define ARC_DEBUG_LOG_ERROR_WITH_VARIABLES(STR,...)
Definition errno.h:40
ARC_ERRNO_OVERFLOW
#define ARC_ERRNO_OVERFLOW
Definition errno.h:10
ARC_DEBUG_LOG_ERROR
#define ARC_DEBUG_LOG_ERROR(STR)
Definition errno.h:39
ARC_ERRNO_DATA
#define ARC_ERRNO_DATA
Definition errno.h:7
ARC_Vector
Definition vector.c:9
ARC_Vector::data
void ** data
Definition vector.c:13
ARC_Vector::destroyDataFn
ARC_Vector_DestroyDataFn * destroyDataFn
Definition vector.c:16
ARC_Vector::currentCapacity
uint32_t currentCapacity
Definition vector.c:10
ARC_Vector::compareDataFn
ARC_Vector_CompareDataFn compareDataFn
Definition vector.c:15
ARC_Vector::currentSize
uint32_t currentSize
Definition vector.c:11
ARC_Vector_GetSize
uint32_t ARC_Vector_GetSize(ARC_Vector *vector)
gets the current size of an ARC_Vector as an unsigned 32 bit integer
Definition vector.c:146
ARC_Vector_Get
void * ARC_Vector_Get(ARC_Vector *vector, uint32_t index)
gets an item from an ARC_Vector at a position index
Definition vector.c:150
ARC_Vector_Add
void ARC_Vector_Add(ARC_Vector *vector, void *data)
adds an item to an ARC_Vector
Definition vector.c:67
ARC_Vector_Remove
void ARC_Vector_Remove(ARC_Vector *vector, void *data)
removes an item from a matching item in an ARC_Vector
Definition vector.c:94
ARC_Vector_Destroy
void ARC_Vector_Destroy(ARC_Vector *vector)
destroys an ARC_Vector
Definition vector.c:51
ARC_Vector_RemoveIndex
void ARC_Vector_RemoveIndex(ARC_Vector *vector, uint32_t index)
removes an item from an ARC_Vector at an index
Definition vector.c:107
ARC_Vector_Clear
void ARC_Vector_Clear(ARC_Vector *vector)
clears all items from a vector
Definition vector.c:139
ARC_Vector_Create
void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDataFn, ARC_Vector_DestroyDataFn *destroyDataFn)
creates an ARC_Vector which is an "expandable" array
Definition vector.c:28
ARC_Vector_CompareDataDefaultFn
ARC_Bool ARC_Vector_CompareDataDefaultFn(void *dataA, void *dataB)
Definition vector.c:20
vector.h
ARC_Vector_DestroyDataFn
void(* ARC_Vector_DestroyDataFn)(void *data)
a callback that cleans up memory when it is removed from the vector
Definition vector.h:31
ARC_Vector_CompareDataFn
ARC_Bool(* ARC_Vector_CompareDataFn)(void *dataA, void *dataB)
a callback that allows the user to define a way to check the data stored in a vector for a match
Definition vector.h:24