#ifndef ARRAYLIST_H
#define ARRAYLIST_H
#include <inttypes.h>
#include <stdbool.h>
/** Generic data structure using contiguous storage for user data objects,
* which are stored in ascending order, as defined by a user-supplied
* comparison function. The interface of the comparison function must
* conform to the following requirements:
*
* int32_t compareElems(const void* const pLeft, const void* const pRight);
* Returns: < 0 if *pLeft < *pRight
* 0 if *pLeft = *pRight
* > 0 if *pLeft > *pRight
*
* An arrayList will increase the amount of storage, as needed, as objects
* are inserted.
*
* If the user's data object involves dynammically-allocated memory, the
* arrayList depends on a second user-supplied function:
*
* void cleanElem(void* const pElem);
*
* If this is not needed, the user should supply a NULL pointer in lieu
* of a function pointer.
*
* The use of a void* in several of the relevant functions allows the
* user's data object to of any type; but it burdens the user with the
* responsibility to ensure that element pointers that are passed to
* arrayList functions do point to objects of the correct type.
*
* An arrayList object AL is proper iff:
* - AL.data points to an array large enough to hold AL.capacity
* objects that each contain AL.elemSz bytes,
* or
* AL.data == NULL and AL.capacity == 0
* - Cells 0 to AL.usage - 1 hold user data objects, or AL.usage == 0
*/
struct _arrayList {
uint8_t* data; // points to block of memory used to store user data
uint32_t elemSz; // size (in bytes) of the user's data objects
uint32_t capacity; // maximum number of user data objects that can be stored
uint32_t usage; // actual number of user data objects currently stored
// User-supplied function to compare user data objects
int32_t (*compareElems)(const void* const pLeft, const void* const pRight);
// User-supplied function to deallocate dynamic content in user data object.
void (*cleanElem)(void* const pElem);
};
typedef struct _arrayList arrayList;
/** Creates a new, empty arrayList object such that:
*
* - capacity equals dimension
* - elemSz equals the size (in bytes) of the data objects the user
* will store in the arrayList
* - data points to a block of memory large enough to hold capacity
* user data objects
* - usage is zero
* - the user's comparison function is correctly installed
* - the user's clean function is correctly installed, if provided
* Returns: new arrayList object
*/
arrayList* AL_create(uint32_t dimension, uint32_t elemSz,
int32_t (*compareElems)(const void* const pLeft, const void* const pRight),
void (*freeElem)(void* const pElem));
/** Inserts the user's data object into the arrayList.
*
* Pre: *pAL is a proper arrayList object
* *pElem is a valid user data object
* Post: a copy of the user's data object has been inserted, at the
* position defined by the user's compare function
* Returns: true unless the insertion fails (unlikely unless it's not
* possible to increase the size of the arrayList
*/
bool AL_insert(arrayList* const pAL, const void* const pElem);
/** Returns pointer to the data object at the given index.
*
* Pre: *pAL is a proper arrayList object
* indexis a valid index for *pAL
* Returns: pointer to the data object at index in *pAL; NULL if no
* such data object exists
*/
void* AL_elemAt(const arrayList* const pAL, uint32_t index);
/** Searches for a matching object in the arrayList.
*
* Pre: *pAL is a proper arrayList object
* *pElem is a valid user data object
* Returns: pointer to a matching data object in *pAL; NULL if no
* match can be found
*/
void* AL_find(const arrayList* const pAL, const void* const pElem);
/** Deallocates all dynamic content in the arrayList, including any
* dynamic content in the user data objects in the arrayList.
*
* Pre: *pAL is a proper arrayList object
* Post: the data array in *pAL has been freed, as has any dynamic
* memory associated with the user data objects that were in
* that array (via the user-supplied clean function); all the
* fields in *pAL are set to 0 or NULL, as appropriate.
*/
void AL_clean(arrayList* const pAL);
#endif