openmohaa/code/gamespy/darray.h
2025-02-28 18:11:09 +01:00

317 lines
14 KiB
C

#ifndef _DARRAY_H
#define _DARRAY_H
/* File: darray.h
* --------------
* Defines the interface for the DynamicArray ADT.
* The DArray allows the client to store any number of elements of any desired
* base type and is appropriate for a wide variety of storage problems. It
* supports efficient element access, and appending/inserting/deleting elements
* as well as optional sorting and searching. In all cases, the DArray imposes
* no upper bound on the number of elements and deals with all its own memory
* management. The client specifies the size (in bytes) of the elements that
* will be stored in the array when it is created. Thereafter the client and
* the DArray can refer to elements via (void*) ptrs.
*/
#ifdef __cplusplus
extern "C" {
#endif
/* Type: DArray
* ----------------
* Defines the DArray type itself. The client can declare variables of type
* DArray, but these variables must be initialized with the result of ArrayNew.
* The DArray is implemented with pointers, so all client copies in variables
* or parameters will be "shallow" -- they will all actually point to the
* same DArray structure. Only calls to ArrayNew create new arrays.
* The struct declaration below is "incomplete"- the implementation
* details are literally not visible in the client .h file.
*/
typedef struct DArrayImplementation *DArray;
/* ArrayCompareFn
* --------------
* ArrayCompareFn is a pointer to a client-supplied function which the
* DArray uses to sort or search the elements. The comparator takes two
* (const void*) pointers (these will point to elements) and returns an int.
* The comparator should indicate the ordering of the two elements
* using the same convention as the strcmp library function:
* If elem1 is "less than" elem2, return a negative number.
* If elem1 is "greater than" elem2, return a positive number.
* If the two elements are "equal", return 0.
*/
#if defined(WIN32)
typedef int (__cdecl *ArrayCompareFn)(const void *elem1, const void *elem2);
#else
typedef int (*ArrayCompareFn)(const void *elem1, const void *elem2);
#endif
/* ArrayMapFn
* ----------
* ArrayMapFn defines the space of functions that can be used to map over
* the elements in a DArray. A map function is called with a pointer to
* the element and a client data pointer passed in from the original
* caller.
*/
typedef void (*ArrayMapFn)(void *elem, void *clientData);
/* ArrayMapFn2
* ----------_
* Same as ArrayMapFn, but can return 0 to stop the mapping.
* Used by ArrayMap2
*/
typedef int (*ArrayMapFn2)(void *elem, void *clientData);
/* ArrayElementFreeFn
* ------------------
* ArrayElementFreeFn defines the space of functions that can be used as the
* clean-up function for an element as it is deleted from the array
* or when the entire array of elements is freed. The cleanup function is
* called with a pointer to an element about to be deleted.
*/
typedef void (*ArrayElementFreeFn)(void *elem);
/* ArrayNew
* --------
* Creates a new DArray and returns it. There are zero elements in the array.
* to start. The elemSize parameter specifies the number of bytes that a single
* element of this array should take up. For example, if you want to store
* elements of type Binky, you would pass sizeof(Binky) as this parameter.
* An assert is raised if the size is not greater than zero.
*
* The numElemsToAllocate parameter specifies the initial allocated length
* of the array, as well as the dynamic reallocation increment for when the
* array grows. Rather than growing the array one element at a time as
* elements are added (which is rather inefficient), you will grow the array
* in chunks of numElemsToAllocate size. The "allocated length" is the number
* of elements that have been allocated, the "logical length" is the number of
* those slots actually being currently used.
*
* A new array is initially allocated to the size of numElemsToAllocate, the
* logical length is zero. As elements are added, those allocated slots fill
* up and when the initial allocation is all used, grow the array by another
* numElemsToAllocate elements. You will continue growing the array in chunks
* like this as needed. Thus the allocated length will always be a multiple
* of numElemsToAllocate. Don't worry about using realloc to shrink the array
* allocation if many elements are deleted from the array. It turns out that
* many implementations of realloc don't even pay attention to such a request
* so there is little point in asking. Just leave the array over-allocated.
*
* The numElemsToAllocate is the client's opportunity to tune the resizing
* behavior for their particular needs. If constructing large arrays,
* specifying a large allocation chunk size will result in fewer resizing
* operations. If using small arrays, a small allocation chunk size will
* result in less space going unused. If the client passes 0 for
* numElemsToAllocate, the implementation will use the default value of 8.
*
* The elemFreeFn is the function that will be called on an element that
* is about to be deleted (using ArrayDeleteAt) or on each element in the
* array when the entire array is being freed (using ArrayFree). This function
* is your chance to do any deallocation/cleanup required for the element
* (such as freeing any pointers contained in the element). The client can pass
* NULL for the cleanupFn if the elements don't require any handling on free.
*/
DArray ArrayNew(int elemSize, int numElemsToAllocate,
ArrayElementFreeFn elemFreeFn);
/* ArrayFree
* ----------
* Frees up all the memory for the array and elements. It DOES NOT
* automatically free memory owned by pointers embedded in the elements.
* This would require knowledge of the structure of the elements which the
* DArray does not have. However, it will iterate over the elements calling
* the elementFreeFn earlier supplied to ArrayNew and therefore, the client,
* who knows what the elements are, can do the appropriate deallocation of any
* embedded pointers through that function. After calling this, the value of
* what array is pointing to is undefined.
*/
void ArrayFree(DArray array);
/* ArrayLength
* -----------
* Returns the logical length of the array, i.e. the number of elements
* currently in the array. Must run in constant time.
*/
int ArrayLength(const DArray array);
/* ArrayNth
* --------
* Returns a pointer to the element numbered n in the specified array.
* Numbering begins with 0. An assert is raised if n is less than 0 or greater
* than the logical length minus 1. Note this function returns a pointer into
* the DArray's element storage, so the pointer should be used with care.
* This function must operate in constant time.
*
* We could have written the DArray without this sort of access, but it
* is useful and efficient to offer it, although the client needs to be
* careful when using it. In particular, a pointer returned by ArrayNth
* becomes invalid after any calls which involve insertion, deletion or
* sorting the array, as all of these may rearrange the element storage.
*/
void *ArrayNth(DArray array, int n);
/* ArrayAppend
* -----------
* Adds a new element to the end of the specified array. The element is
* passed by address, the element contents are copied from the memory pointed
* to by newElem. Note that right after this call, the new element will be
* the last in the array; i.e. its element number will be the logical length
* minus 1. This function must run in constant time (neglecting
* the memory reallocation time which may be required occasionally).
*/
void ArrayAppend(DArray array, const void *newElem);
/* ArrayInsertAt
* -------------
* Inserts a new element into the array, placing it at the position n.
* An assert is raised if n is less than 0 or greater than the logical length.
* The array elements after position n will be shifted over to make room. The
* element is passed by address, the new element's contents are copied from
* the memory pointed to by newElem. This function runs in linear time.
*/
void ArrayInsertAt(DArray array, const void *newElem, int n);
/* ArrayInsertSorted
* -------------
* Inserts a new element into the array, placing it at the position indicated by
* a binary search of the array using comparator.
* The array MUST be sorted prior to calling InsertSorted.
* Note that if you only ever call InsertSorted, the array will always be sorted.
*/
void ArrayInsertSorted(DArray array, const void *newElem, ArrayCompareFn comparator);
/* ArrayDeleteAt
* -------------
* Deletes the element numbered n from the array. Before being removed,
* the elemFreeFn that was supplied to ArrayNew will be called on the element.
* An assert is raised if n is less than 0 or greater than the logical length
* minus one. All the elements after position n will be shifted over to fill
* the gap. This function runs in linear time. It does not shrink the
* allocated size of the array when an element is deleted, the array just
* stays over-allocated.
*/
void ArrayDeleteAt(DArray array, int n);
/* ArrayDeleteAt
* -------------
* Removes the element numbered n from the array. The element will not be freed
* before being removed. All the elements after position n will be shifted over to fill
* the gap. This function runs in linear time. It does not shrink the
* allocated size of the array when an element is deleted, the array just
* stays over-allocated.
*/
void ArrayRemoveAt(DArray array, int n);
/* ArrayReplaceAt
* -------------
* Overwrites the element numbered n from the array with a new value. Before
* being overwritten, the elemFreeFn that was supplied to ArrayNew is called
* on the old element. Then that position in the array will get a new value by
* copying the new element's contents from the memory pointed to by newElem.
* An assert is raised if n is less than 0 or greater than the logical length
* minus one. None of the other elements are affected or rearranged by this
* operation and the size of the array remains constant. This function must
* operate in constant time.
*/
void ArrayReplaceAt(DArray array, const void *newElem, int n);
/* ArraySort
* ---------
* Sorts the specified array into ascending order according to the supplied
* comparator. The numbering of the elements will change to reflect the
* new ordering. An assert is raised if the comparator is NULL.
*/
void ArraySort(DArray array, ArrayCompareFn comparator);
#define NOT_FOUND -1 // returned when a search fails to find the key
/* ArraySearch
* -----------
* Searches the specified array for an element whose contents match
* the element passed as the key. Uses the comparator argument to test
* for equality. The "fromIndex" parameter controls where the search
* starts looking from. If the client desires to search the entire array,
* they should pass 0 as the fromIndex. The function will search from
* there to the end of the array. The "isSorted" parameter allows the client
* to specify that the array is already in sorted order, and thus it uses a
* faster binary search. If isSorted is false, a simple linear search is
* used. If a match is found, the position of the matching element is returned
* else the function returns NOT_FOUND. Calling this function does not
* re-arrange or change contents of DArray or modify the key in any way.
* An assert is raised if fromIndex is less than 0 or greater than
* the logical length (although searching from logical length will never
* find anything, allowing this case means you can search an entirely empty
* array from 0 without getting an assert). An assert is raised if the
* comparator is NULL.
*/
int ArraySearch(DArray array, const void *key, ArrayCompareFn comparator,
int fromIndex, int isSorted);
/* ArrayMap
* -----------
* Iterates through each element in the array in order (from element 0 to
* element n-1) and calls the function fn for that element. The function is
* called with the address of the array element and the clientData pointer.
* The clientData value allows the client to pass extra state information to
* the client-supplied function, if necessary. If no client data is required,
* this argument should be NULL. An assert is raised if map function is NULL.
*/
void ArrayMap(DArray array, ArrayMapFn fn, void *clientData);
/* ArrayMapBackwards
* -----------
* Same as ArrayMap, but goes through the array from end to front. This
* makes it safe to free elements during the mapping.
*/
void ArrayMapBackwards(DArray array, ArrayMapFn fn, void *clientData);
/* ArrayMap2
* -----------
* Same as ArrayMap, but allows the mapping to be stopped by returning 0
* from the mapping function. If the mapping was stopped, the element
* it was stopped at will be returned. If it wasn't stopped, then NULL
* will be returned.
*/
void * ArrayMap2(DArray array, ArrayMapFn2 fn, void *clientData);
/* ArrayMapBackwards2
* ------------
* Goes through the array backwards, and allows you to stop the mapping.
*/
void * ArrayMapBackwards2(DArray array, ArrayMapFn2 fn, void *clientData);
/* ArrayClear
* -----------
* Deletes all elements in the array, but without freeing the array.
*/
void ArrayClear(DArray array);
/* ArrayGetDataPtr
* -----------
* Obtain the pointer to the actual data storage
*/
void *ArrayGetDataPtr(DArray array);
/* ArraySetDataPtr
* -----------
* Set the pointer to the actual data storage, which must be allocated with malloc
*/
void ArraySetDataPtr(DArray array, void *ptr, int count, int capacity);
#ifdef __cplusplus
}
#endif
#endif //_DARRAY_