Cytoplasm/src/include/Array.h

189 lines
6.7 KiB
C

/*
* Copyright (C) 2022-2024 Jordan Bancino <@jordan:bancino.net>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef CYTOPLASM_ARRAY_H
#define CYTOPLASM_ARRAY_H
/***
* @Nm Array
* @Nd A simple dynamic array data structure.
* @Dd November 24 2022
* @Xr HashMap Queue
*
* These functions implement a simple array data structure that is
* automatically resized as necessary when new values are added. This
* implementation does not actually store the values of the items in it;
* it only stores pointers to the data. As such, you will still have to
* manually maintain all your data. The advantage of this is that these
* functions don't have to copy data, and thus don't care how big the
* data is. Furthermore, arbitrary data can be stored in the array.
* .Pp
* This array implementation is optimized for storage space and
* appending. Deletions are expensive in that all the items of the list
* above a deletion are moved down to fill the hole where the deletion
* occurred. Insertions are also expensive in that all the elements
* above the given index must be shifted up to make room for the new
* element.
* .Pp
* Due to these design choices, this array implementation is best
* suited to linear writing, and then linear or random reading.
*/
#include <stddef.h>
#include <stdarg.h>
#include <stdbool.h>
/**
* The functions in this API operate on an array structure which is
* opaque to the caller.
*/
typedef struct Array Array;
/**
* Allocate a new array. This function returns a pointer that can be
* used with the other functions in this API, or NULL if there was an
* error allocating memory for the array.
*/
extern Array *ArrayCreate(void);
/**
* Deallocate an array. Note that this function does not free any of
* the values stored in the array; it is the caller's job to manage the
* memory for each item. Typically, the caller would iterate over all
* the items in the array and free them before freeing the array.
*/
extern void ArrayFree(Array *);
/**
* Get the size, in number of elements, of the given array.
*/
extern size_t ArraySize(Array *);
/**
* Get the element at the specified index from the specified array.
* This function will return NULL if the array is NULL, or the index
* is out of bounds. Otherwise, it will return a pointer to a value
* put into the array using
* .Fn ArrayInsert
* or
* .Fn ArraySet .
*/
extern void *ArrayGet(Array *, size_t);
/**
* Insert the specified element at the specified index in the specified
* array. This function will shift the element currently at that index,
* and any elements after it before inserting the given element.
* .Pp
* This function returns a boolean value indicating whether or not it
* suceeded.
*/
extern bool ArrayInsert(Array *, size_t, void *);
/**
* Set the value at the specified index in the specified array to the
* specified value. This function will return the old value at that
* index, if any.
*/
extern void *ArraySet(Array *, size_t, void *);
/**
* Append the specified element to the end of the specified array. This
* function uses
* .Fn ArrayInsert
* under the hood to insert an element at the end. It thus has the same
* return value as
* .Fn ArrayInsert .
*/
extern bool ArrayAdd(Array *, void *);
/**
* Remove the element at the specified index from the specified array.
* This function returns the element removed, if any.
*/
extern void *ArrayDelete(Array *, size_t);
/**
* Sort the specified array using the specified sort function. The
* sort function compares two elements. It takes two void pointers as
* parameters, and returns an integer. The return value indicates to
* the sorting algorithm how the elements relate to each other. A
* return value of 0 indicates that the elements are identical. A
* return value greater than 0 indicates that the first item is
* ``bigger'' than the second item and should thus appear after it in
* the array. A return value less than 0 indicates the opposite: the
* second element should appear after the first in the array.
*/
extern void ArraySort(Array *, int (*) (void *, void *));
/**
* Remove all duplicates from an array by using the given comparison
* function to sort the array, then remove matching values. This
* function returns a new array with all duplicates removed. The
* original array is unaffected. Note that arrays only store pointers
* to values, usually values on the heap. Thus, it is possible to lose
* pointers to duplicate values and have them leak.
* .P
* This is a relatively expensive operation. The array must first be
* duplicated. Then it is sorted, then it is iterated from beginning
* to end to remove duplicate entries. Note that the comparison
* function is executed on each element at least twice.
*/
extern Array *ArrayUnique(Array *, int (*) (void *, void *));
/**
* Reverses the order of all elements in the array into a new array on
* the heap, to be freed using
* .Fn ArrayFree .
*/
extern Array *ArrayReverse(Array *);
/**
* If possible, reduce the amount of memory allocated to this array
* by calling
* .Fn Realloc
* on the internal structure to perfectly fit the elements in the
* array. This function is intended to be used by functions that return
* relatively read-only arrays that will be long-lived.
*/
extern bool ArrayTrim(Array *);
/**
* Convert a variadic arguments list into an Array. In most cases, the
* Array API is much easier to work with than
* .Fn va_arg
* and friends.
*/
extern Array *ArrayFromVarArgs(size_t, va_list);
/**
* Duplicate an existing array. Note that arrays only hold pointers to
* their data, not the data itself, so the duplicated array will point
* to the same places in memory as the original array.
*/
extern Array *ArrayDuplicate(Array *);
#endif /* CYTOPLASM_ARRAY_H */