Initial commit, yay

This commit is contained in:
VegOwOtenks 2024-06-13 15:28:21 +02:00
commit 25e26756cd
85 changed files with 7077 additions and 0 deletions

View file

@ -0,0 +1 @@
add_library(dynamicarray STATIC dynamicarray.c)

View file

@ -0,0 +1,309 @@
/*
* This code is part of the strategy game operational-space.
* operational-space comes with ABSOLUTELY NO WARRANTY and is licensed under GPL-2.0.
* Copyright (C) 2024 VegOwOtenks, Sleppo04
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "dynamicarray.h"
int DynamicArray_Create(DynamicArray* target, size_t object_size, size_t initial_capacity, allocator_t* allocator)
{
if (target == NULL) {
return EDESTADDRREQ;
}
if (object_size == 0) {
return ERANGE;
}
if (initial_capacity == 0) {
return EINVAL;
}
target->memory = Allocator_Allocate(allocator, object_size * initial_capacity);
if (target->memory == NULL) {
return ENOMEM;
}
target->object_size = object_size;
target->capacity = initial_capacity;
target->allocator = allocator;
target->reserved = 0;
return EXIT_SUCCESS;
}
int DynamicArray_Clone(DynamicArray* target, DynamicArray* original)
{
if (target == NULL) {
return EDESTADDRREQ;
}
if (original == NULL) {
return EINVAL;
}
*target = *original;
target->memory = Allocator_AllocateArray(target->allocator, target->object_size, target->capacity);
if (target->memory == NULL) {
return ENOMEM;
}
memcpy(target->memory, original->memory, original->object_size * original->capacity);
return EXIT_SUCCESS;
}
int DynamicArray_DeepClone(DynamicArray* target, DynamicArray* original, DynamicArrayCloneFunction clone, void* xarg)
{
if (target == NULL) {
return EDESTADDRREQ;
}
if (original == NULL) {
return EINVAL;
}
if (clone == NULL) {
return EINVAL;
}
*target = *original;
target->memory = Allocator_AllocateArray(target->allocator, target->object_size, target->capacity);
if (target->memory == NULL) {
return ENOMEM;
}
DYNAMICARRAY_FOREACH(*original, i) {
void* clone_current = DynamicArray_GetPointer(target, i);
void* original_current = DynamicArray_GetPointer(target, i);
int clone_code = clone(clone_current, original_current, xarg);
if (clone_code) {
return ECANCELED;
}
}
return EXIT_SUCCESS;
}
int DynamicArray_ResizeObjects(DynamicArray* array, size_t new_object_size)
{
if (array == NULL) {
return EDESTADDRREQ;
}
if (new_object_size == 0) {
return ERANGE;
}
size_t old_object_size = array->object_size;
size_t old_size = old_object_size * array->capacity;
size_t new_size = new_object_size * array->capacity;
void* new_array = Allocator_Reallocate(array->allocator, array->memory, old_size, new_size);
if (new_array == NULL) {
return ENOMEM;
}
array->memory = new_array;
if (array->reserved != 0) {
// move old stuff
void* current = advancep(array->memory, old_object_size * (array->reserved - 1));
size_t index = array->reserved - 1;
while (index != 0) {
void* location = current;
void* destination = DynamicArray_GetPointer(array, index);
memmove(destination, location, old_object_size);
current = rewindp(current, old_object_size);
index--;
}
}
array->object_size = new_object_size;
return EXIT_SUCCESS;
}
int DynamicArray_Resize(DynamicArray* array, size_t new_capacity)
{
if (array == NULL) {
return EDESTADDRREQ;
}
if (new_capacity == 0) {
return ERANGE;
}
size_t old_size = array->object_size * array->capacity;
size_t new_size = array->object_size * new_capacity;
void* new_array = Allocator_Reallocate(array->allocator, array->memory, old_size, new_size);
if (new_array == NULL) {
return ENOMEM;
}
array->memory = new_array;
array->capacity = new_capacity;
return EXIT_SUCCESS;
}
int DynamicArray_Append(DynamicArray* array, void* object)
{
if (array == NULL) {
return EDESTADDRREQ;
}
if (object == NULL) {
return EINVAL;
}
if (array->capacity == array->reserved) {
if (DynamicArray_Resize(array, array->capacity * 2)) {
return ENOMEM;
}
}
void* destination = advancep(array->memory, array->reserved * array->object_size);
memcpy(destination, object, array->object_size);
array->reserved++;
return EXIT_SUCCESS;
}
int DynamicArray_AppendEmpty(DynamicArray* array, void** pointer)
{
if (array == NULL) {
return EDESTADDRREQ;
}
if (array->capacity == array->reserved) {
if (DynamicArray_Resize(array, array->capacity * 2)) {
*pointer = NULL;
return ENOMEM;
}
}
array->reserved++;
*pointer = DynamicArray_GetPointer(array, array->reserved - 1);
return EXIT_SUCCESS;
}
int DynamicArray_Remove(DynamicArray* array, size_t index)
{
if (array == NULL) {
return EDESTADDRREQ;
}
if (index >= array->reserved) {
return EBOUNDS;
}
if (index != array->reserved - 1) {
void* to = advancep(array->memory, array->object_size * index);
void* from = advancep(to, array->object_size);
size_t size = array->object_size * (array->reserved - index);
memmove(to, from, size);
}
array->reserved--;
return EXIT_SUCCESS;
}
int DynamicArray_RemoveFast(DynamicArray* array, size_t index)
{
if (array == NULL) {
return EDESTADDRREQ;
}
if (index >= array->reserved) {
return EBOUNDS;
}
if (array->capacity > 1) {
void* to = DynamicArray_GetPointer(array, index);
void* from = DynamicArray_GetPointer(array, array->reserved - 1);
memcpy(to, from, array->object_size);
}
array->reserved--;
return EXIT_SUCCESS;
}
size_t DynamicArray_FindFunction(DynamicArray* array, DynamicArrayFindFunction function, void* xarg)
{
if (array == NULL) return SIZE_MAX;
if (function == NULL) return SIZE_MAX;
DYNAMICARRAY_FOREACH(*array, i) {
void* current = DynamicArray_GetPointer(array, i);
if (function(current, xarg)) {
return i;
}
}
return SIZE_MAX;
}
size_t DynamicArray_FindFunctionLinear(DynamicArray* array, DynamicArrayLinearFindFunction function, void* xarg)
{
if (array == NULL) return SIZE_MAX;
if (function == NULL) return SIZE_MAX;
size_t bot = 0;
size_t top = array->reserved;
size_t mid = bot + (top - bot) / 2;
int eval = -1;
while (bot != top) {
void* current = DynamicArray_GetPointer(array, mid);
eval = function(current, xarg);
if (eval > 0) {
bot = mid + 1;
} else if (eval < 0) {
top = mid - 1;
} else {
bot = top;
}
}
if (eval != 0) {
return SIZE_MAX;
}
return mid;
}
void* DynamicArray_GetPointer(DynamicArray* array, size_t index)
{
if (array == NULL) {
return NULL;
}
if (index >= array->reserved) {
return NULL;
}
size_t offset = index * array->object_size;
return advancep(array->memory, offset);
}
size_t DynamicArray_GetLength(DynamicArray* array)
{
return array->reserved;
}
void DynamicArray_Destroy(DynamicArray* array)
{
if (array == NULL) {
return;
}
Allocator_Free(array->allocator, array->memory, array->object_size * array->capacity);
memset(array, 0, sizeof(*array));
return;
}

View file

@ -0,0 +1,141 @@
/*
* This code is part of the strategy game operational-space.
* operational-space comes with ABSOLUTELY NO WARRANTY and is licensed under GPL-2.0.
* Copyright (C) 2024 VegOwOtenks, Sleppo04
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef COMMON_DYNAMICARRAY_DYNAMICARRAY_H_
#define COMMON_DYNAMICARRAY_DYNAMICARRAY_H_
#define DYNAMICARRAY_FOREACH(da, i) for (size_t i = 0; i < (da).reserved; i++)
typedef int (*DynamicArrayFindFunction) (void* element, void* xarg);
// -1 look to the left
// 1 look to the right
// 0 found
typedef DynamicArrayFindFunction DynamicArrayLinearFindFunction;
typedef int (*DynamicArrayCloneFunction) (void* to, void* from, void* xarg);
#include "../pointers/pointers.h"
#include "../allocator-interface/allocator-interface.h"
typedef struct DynamicArray_s {
size_t object_size;
size_t capacity;
size_t reserved;
void* memory;
allocator_t* allocator;
} DynamicArray;
/// @brief Initializes a new dynamic-array at the target memory location
/// @param target target memory location
/// @param object_size size of the objects this array will contain
/// @param initial_capacity expected needed capacity of the array
/// @param allocator allocator that provides memory for this array
/// @return EDESTADDRREQ, ERANGE, EINVAL, ENOMEM, EXIT_SUCCESS
int DynamicArray_Create(DynamicArray* target, size_t object_size, size_t initial_capacity, allocator_t* allocator);
/** @brief Initializes a new dynamic-array at the target, copying data from original
* This is a 'shallow copy', the elements are by no means deep-copied themselves.
* Use DeepClone for that
**/
/// @param target target memory location
/// @param original original dynamic array, data will be copied from here
/// @return EDESTADDRREQ, ERANGE, EINVAL, ENOMEM, EXIT_SUCCESS
int DynamicArray_Clone(DynamicArray* target, DynamicArray* original);
/** @brief Initializes a new dynamic-array at the target, copying data from original
* This is a 'shallow copy', the elements are by no means deep-copied themselves.
* Use DeepClone for that
**/
/// @param target target memory location
/// @param original original dynamic array, data will be copied from here
/// @param clone Function to apply on each element of the array for copying
/// @param xarg Extra Argument that will be supplied to the clone function
/// @return EDESTADDRREQ, ERANGE, EINVAL, ENOMEM, EXIT_SUCCESS
int DynamicArray_DeepClone(DynamicArray* target, DynamicArray* original, DynamicArrayCloneFunction clone, void* xarg);
/// @brief Resize the array to a new capacity, eventually dropping elements out-of-bounds
/// @param array `this`
/// @param new_capacity Capacity the array shall have after resizing
/// @return EDESTADDRREQ, ERANGE, ENOMEM, EXIT_SUCCESS
int DynamicArray_Resize(DynamicArray* array, size_t new_capacity);
/// @brief Resize the objects stored in the array, truncating the values or leaving it uninitialized
/// @param array `this`
/// @param new_object_size New object size to apply
/// @return EDESTADDRREQ, ERANGE, ENOMEM, EXIT_SUCCESS
int DynamicArray_ResizeObjects(DynamicArray* array, size_t new_object_size);
/// @brief Copy object of size array->object_size into the array memory
/// @param array `this`
/// @param object Address of the object that will be copied
/// @return EDESTADDRREQ, ERANGE, ENOMEM, EXIT_SUCCESS
int DynamicArray_Append(DynamicArray* array, void* object);
/// @brief Append a zero-ed structure and return the pointer to it
/// @param array `this`
/// @param pointer The pointer to the structure will be stored here
/// @return EDESTADDRREQ, ERANGE, ENOMEM, EXIT_SUCCESS
int DynamicArray_AppendEmpty(DynamicArray* array, void** pointer);
/// @brief Remove the object at the index from the array, shifting all objects behind to the left
/// @param array `this`
/// @param index Index of the removed object
/// @return EDESTADDRREQ, ERANGE, ENOMEM, EXIT_SUCCESS
int DynamicArray_Remove(DynamicArray* array, size_t index);
/// @brief Remove the object at the index from the array, moving the rightmost object to that index
/// @param array `this`
/// @param index Index to alter
/// @return EDESTADDRREQ, ERANGE, ENOMEM, EXIT_SUCCESS
int DynamicArray_RemoveFast(DynamicArray* array, size_t index);
/// @brief Find a element by applying a function
/// @param array `this`
/// @param function function to call on each element
/// @param xarg extra argument for the called function
/// @return index, SIZE_MAX
size_t DynamicArray_FindFunction(DynamicArray* array, DynamicArrayFindFunction function, void* xarg);
/// @brief Find a element using linear search by applying a function
/// @param array `this`
/// @param function function to call on each element for comparison
/// @param xarg extra argument for the called function, should be some sort of search key
/// @return index, SIZE_MAX
size_t DynamicArray_FindFunctionLinear(DynamicArray* array, DynamicArrayLinearFindFunction function, void* xarg);
/// @brief Return a pointer to the object at the index
/// @param array `this`
/// @param index Retrieved objects index
/// @return NULL, Pointer
void* DynamicArray_GetPointer(DynamicArray* array, size_t index);
/// @brief Calculate the length of the array
/// @param array `this`
/// @return array->reserved
size_t DynamicArray_GetLength(DynamicArray* array);
/// @brief Destroy the array and all contents irreversibly
/// @param array `this`
/// @return void
void DynamicArray_Destroy(DynamicArray* array);
#endif /* SRC_COMMON_DYNAMICARRAY_DYNAMICARRAY_H_ */