/** * Copyright (c) 2021 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "array.h" void * arrayGet(size_t size, void *array, int32_t index) { ASSERT_GREATER_THAN(size, 0); ASSERT_NOT_NULL(array); ASSERT_GREATER_THAN_EQUAL_TO(index, 0); return (char *)array + (index * (size/sizeof(char))); } void arraySet(size_t size, void *array, int32_t index, void *data) { ASSERT_GREATER_THAN(size, 0); ASSERT_NOT_NULL(array); ASSERT_GREATER_THAN_EQUAL_TO(index, 0); memcpy(arrayGet(size, array, index), data, size); } void arrayShuffle(size_t size, void *array, int32_t arrayLength) { int32_t x, y; void *itemDest, *itemSource, *temporary; ASSERT_GREATER_THAN(size, 0); ASSERT_NOT_NULL(array); ASSERT_GREATER_THAN_EQUAL_TO(arrayLength, 0); temporary = malloc(size); ASSERT_NOT_NULL(temporary); for(x = 0; x < arrayLength-1; x++) { // Select random element from remaining elements. y = randUint8Range(x, arrayLength); itemDest = arrayGet(size, array, y); itemSource = arrayGet(size, array, x); // Copy the data into temporary variable memcpy(temporary, itemDest, size); // Take the item at this current index, and store from where we just took memcpy(itemDest, itemSource, size); // Store the thing from where we just took into here. memcpy(itemSource, temporary, size); } // Cleanup free(temporary); } int32_t arrayFind(size_t size, void *array, int32_t length, void *value) { int32_t i; void *item; ASSERT_GREATER_THAN(size, 0); ASSERT_GREATER_THAN_EQUAL_TO(length, 0); ASSERT_NOT_NULL(array); ASSERT_NOT_NULL(value); for(i = 0; i < length; i++) { // Get the item and compare. item = arrayGet(size, array, i); if(memcmp(item, value, size) == 0) return i; } // No find. return -1; } int32_t arrayFindCallback( size_t size, void *array, int32_t length, arrayiterationcallback_t *callback ) { int32_t i; void *item; ASSERT_GREATER_THAN(size, 0); ASSERT_GREATER_THAN(length, 0); ASSERT_NOT_NULL(array); ASSERT_NOT_NULL(callback); for(i = 0; i < length; i++) { item = arrayGet(size, array, i); if(callback(i, item)) return i; } return -1; } bool arrayContains(size_t size, void *array, int32_t length, void *value) { int32_t i = arrayFind(size, array, length, value); return i != -1; } void arrayCopy(size_t size, void *source, int32_t length, void *dest) { ASSERT_GREATER_THAN(size, 0); ASSERT_NOT_NULL(source); ASSERT_GREATER_THAN_EQUAL_TO(length, 0); ASSERT_NOT_NULL(dest); memcpy(dest, source, size * length); } void arraySort(size_t size, void *array, int32_t length, arraysort_t *sort) { ASSERT_GREATER_THAN(size, 0); ASSERT_NOT_NULL(array); ASSERT_GREATER_THAN_EQUAL_TO(length, 0); ASSERT_NOT_NULL(sort); qsort(array, length, size, sort); } // Common Sorters: void arraySortInt32(int32_t *array, int32_t length) { arraySort(sizeof(int32_t), array, length, &_arraySorterInt32); } int32_t _arraySorterInt32(const void* left, const void* right) { return *((int32_t *)left) - *((int32_t *)right); } void arraySortUint8(uint8_t *array, int32_t length) { arraySort(sizeof(uint8_t), array, length, &_arraySorterUint8); } int32_t _arraySorterUint8(const void* left, const void* right) { return *((uint8_t *)left) - *((uint8_t *)right); } int32_t arrayFindString(char **array, int32_t arrayLength, char *value) { int32_t i; ASSERT_NOT_NULL(array); ASSERT_NOT_NULL(value); ASSERT_GREATER_THAN_EQUAL_TO(arrayLength, 0); for(i = 0; i < arrayLength; i++) { ASSERT_NOT_NULL(array[i]); if(strcmp(array[i], value) == 0) return i; } return -1; } void arrayRewind(size_t size, void *source, int32_t length, int32_t start, int32_t count ) { void *temporary; ASSERT_GREATER_THAN(size, 0); ASSERT_NOT_NULL(source); ASSERT_GREATER_THAN_EQUAL_TO(length, 0); ASSERT_GREATER_THAN_EQUAL_TO(start, 0); ASSERT_GREATER_THAN_EQUAL_TO(count, -1); if(count == -1) count = length - start; // Create a temporary new array to house the data. temporary = malloc(size * count); ASSERT_NOT_NULL(temporary); // Copy the data from the source to the temporary array. arrayCopy(size, arrayGet(size, source, start), count, temporary); // Now copy the data back to the source array. arrayCopy(size, temporary, count, source); // Cleanup the temporary array. free(temporary); } void arraySplice( size_t size, void *array, int32_t start, int32_t count, int32_t length ) { int32_t takeStart, takeLength; void *temporary; ASSERT_GREATER_THAN(size, 0); ASSERT_NOT_NULL(array); ASSERT_GREATER_THAN_EQUAL_TO(start, 0); ASSERT_GREATER_THAN_EQUAL_TO(count, 0); ASSERT_GREATER_THAN_EQUAL_TO(length, 0); // Take the end of the array... takeStart = start + count; takeLength = length - takeStart; temporary = malloc(size * takeLength); ASSERT_NOT_NULL(temporary); arrayCopy(size, arrayGet(size, array, takeStart), takeLength, temporary); // Now copy it back into the original array arrayCopy(size, temporary, takeLength, arrayGet(size, array, start)); free(temporary); } int32_t arraySum( size_t size, void *array, int32_t length, arrayiterationcallback_t *callback ) { int32_t i, count; ASSERT_GREATER_THAN(size, 0); ASSERT_NOT_NULL(array); ASSERT_GREATER_THAN_EQUAL_TO(length, 0); ASSERT_NOT_NULL(callback); count = 0; for(i = 0; i < length; i++) { if(!callback(i, arrayGet(size, array, i))) continue; count++; } return count; }