Initial commit, yay
This commit is contained in:
commit
25e26756cd
85 changed files with 7077 additions and 0 deletions
1
src/dynamicarray/CMakeLists.txt
Normal file
1
src/dynamicarray/CMakeLists.txt
Normal file
|
@ -0,0 +1 @@
|
|||
add_library(dynamicarray STATIC dynamicarray.c)
|
309
src/dynamicarray/dynamicarray.c
Normal file
309
src/dynamicarray/dynamicarray.c
Normal 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;
|
||||
}
|
141
src/dynamicarray/dynamicarray.h
Normal file
141
src/dynamicarray/dynamicarray.h
Normal 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_ */
|
Loading…
Add table
Add a link
Reference in a new issue