mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 13:47:58 +03:00
317 lines
14 KiB
C
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_
|