#include "arrayList.h" #include #include #include // Write declarations of static helper functions below: static void shiftArray(int index, arrayList *const pAL); /** 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 (*cleanElem)(void *const pElem)) { arrayList *result = malloc(sizeof(arrayList)); result->capacity = dimension; result->elemSz = elemSz; result->data = calloc(result->capacity, result->elemSz); result->usage = 0; result->compareElems = compareElems; result->cleanElem = cleanElem; return result; } /** 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) { if (pAL->usage == pAL->capacity) { pAL->data = realloc(pAL->data, (2 * pAL->capacity) * pAL->elemSz); pAL->capacity += pAL->capacity; } // Checks for insertion into empty arrayList if (!pAL->usage) memcpy(pAL->data, pElem, pAL->elemSz); else { uint32_t i; // Finds correct index for object insertion for (i = 0; i < pAL->usage; i++) if (pAL->compareElems(pAL->data + (i * pAL->elemSz), pElem) > 0) break; // Call to static helper shiftArray() shiftArray(i, pAL); memcpy(pAL->data + (i * pAL->elemSz), pElem, pAL->elemSz); } pAL->usage++; return true; } /** 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) { return (void *)(pAL->data + (index * pAL->elemSz)); } /** 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) { uint32_t i; for (i = 0; i < pAL->usage; i++) // Checks to see if pElem is equal to the element at the current index if (pAL->compareElems(pAL->data + (i * pAL->elemSz), pElem) == 0) return pAL->data + (i * pAL->elemSz); return NULL; } /** 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) { uint32_t i = 0; while (i < pAL->usage) // Uses the user-specified clean function to free data within the data objects pAL->cleanElem(pAL->data + (i++ * pAL->elemSz)); free(pAL->data); pAL->usage = 0; } // Write definitions of static helper functions below: static void shiftArray(int index, arrayList *const pAL) { for (int i = pAL->usage; i > index; i--) // Shifts all elements greater than the element at index to the right by 1 memcpy(pAL->data + (i * pAL->elemSz), pAL->data + ((i - 1) * pAL->elemSz), pAL->elemSz); }