/* * Dynamically Resized Array * * Authors: Alfredo K. Kojima * Dan Pascu * * This code is released to the Public Domain, but * proper credit is always appreciated :) */ #include #include #include "WUtil.h" #define INITIAL_SIZE 8 #define RESIZE_INCREMENT 8 typedef struct W_Array { void **items; /* the array data */ int itemCount; /* # of items in array */ int allocSize; /* allocated size of array */ WMFreeDataProc *destructor; /* the destructor to free elements */ } W_Array; WMArray* WMCreateArray(int initialSize) { return WMCreateArrayWithDestructor(initialSize, NULL); } WMArray* WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc *destructor) { WMArray *array; array = wmalloc(sizeof(WMArray)); if (initialSize <= 0) { initialSize = INITIAL_SIZE; } array->items = wmalloc(sizeof(void*) * initialSize); array->itemCount = 0; array->allocSize = initialSize; array->destructor = destructor; return array; } WMArray* WMCreateArrayWithArray(WMArray *array) { WMArray *newArray; newArray = wmalloc(sizeof(WMArray)); newArray->items = wmalloc(sizeof(void*) * array->allocSize); memcpy(newArray->items, array->items, sizeof(void*)*array->itemCount); newArray->itemCount = array->itemCount; newArray->allocSize = array->allocSize; newArray->destructor = NULL; return newArray; } void WMEmptyArray(WMArray *array) { if (array->destructor) { while (array->itemCount > 0) { array->itemCount--; array->destructor(array->items[array->itemCount]); } } /*memset(array->items, 0, array->itemCount * sizeof(void*));*/ array->itemCount = 0; } void WMFreeArray(WMArray *array) { WMEmptyArray(array); wfree(array->items); wfree(array); } int WMGetArrayItemCount(WMArray *array) { return array->itemCount; } void WMAppendArray(WMArray *array, WMArray *other) { if (other->itemCount == 0) return; if (array->itemCount + other->itemCount > array->allocSize) { array->allocSize += other->allocSize; array->items = wrealloc(array->items, sizeof(void*)*array->allocSize); } memcpy(array->items+array->itemCount, other->items, sizeof(void*)*other->itemCount); array->itemCount += other->itemCount; } void WMAddToArray(WMArray *array, void *item) { if (array->itemCount >= array->allocSize) { array->allocSize += RESIZE_INCREMENT; array->items = wrealloc(array->items, sizeof(void*)*array->allocSize); } array->items[array->itemCount] = item; array->itemCount++; } void WMInsertInArray(WMArray *array, int index, void *item) { wassertr(index >= 0 && index <= array->itemCount); if (array->itemCount >= array->allocSize) { array->allocSize += RESIZE_INCREMENT; array->items = wrealloc(array->items, sizeof(void*)*array->allocSize); } if (index < array->itemCount) { memmove(array->items+index+1, array->items+index, sizeof(void*)*(array->itemCount-index)); } array->items[index] = item; array->itemCount++; } void* WMReplaceInArray(WMArray *array, int index, void *item) { void *old; wassertrv(index >= 0 && index <= array->itemCount, NULL); /* is it really useful to perform append if index == array->itemCount ? -Dan */ if (index == array->itemCount) { WMAddToArray(array, item); return NULL; } old = array->items[index]; array->items[index] = item; return old; } int WMDeleteFromArray(WMArray *array, int index) { wassertrv(index >= 0 && index < array->itemCount, 0); if (array->destructor) { array->destructor(array->items[index]); } if (index < array->itemCount-1) { memmove(array->items+index, array->items+index+1, sizeof(void*)*(array->itemCount-index-1)); } array->itemCount--; return 1; } int WMRemoveFromArrayMatching(WMArray *array, WMMatchDataProc *match, void *cdata) { int i; if (match != NULL) { for (i = 0; i < array->itemCount; i++) { if ((*match)(array->items[i], cdata)) { WMDeleteFromArray(array, i); return 1; } } } else { for (i = 0; i < array->itemCount; i++) { if (array->items[i] == cdata) { WMDeleteFromArray(array, i); return 1; } } } return 0; } void* WMGetFromArray(WMArray *array, int index) { if (index < 0 || index >= array->itemCount) return NULL; return array->items[index]; } void* WMPopFromArray(WMArray *array) { array->itemCount--; return array->items[array->itemCount]; } int WMFindInArray(WMArray *array, WMMatchDataProc *match, void *cdata) { int i; if (match!=NULL) { for (i = 0; i < array->itemCount; i++) { if ((*match)(array->items[i], cdata)) return i; } } else { for (i = 0; i < array->itemCount; i++) { if (array->items[i] == cdata) return i; } } return WANotFound; } int WMCountInArray(WMArray *array, void *item) { int i, count; for (i=0, count=0; iitemCount; i++) { if (array->items[i] == item) count++; } return count; } void WMSortArray(WMArray *array, WMCompareDataProc *comparer) { if (array->itemCount > 1) { /* Don't sort empty or single element arrays */ qsort(array->items, array->itemCount, sizeof(void*), comparer); } } void WMMapArray(WMArray *array, void (*function)(void*, void*), void *data) { int i; for (i=0; iitemCount; i++) { (*function)(array->items[i], data); } } WMArray* WMGetSubarrayWithRange(WMArray* array, WMRange aRange) { WMArray *newArray; if (aRange.count <= 0) return WMCreateArray(0); if (aRange.position < 0) aRange.position = 0; if (aRange.position >= array->itemCount) aRange.position = array->itemCount - 1; if (aRange.position + aRange.count > array->itemCount) aRange.count = array->itemCount - aRange.position; newArray = WMCreateArray(aRange.count); memcpy(newArray->items, array->items+aRange.position, sizeof(void*)*aRange.count); newArray->itemCount = aRange.count; return newArray; } void* WMArrayFirst(WMArray *array, WMArrayIterator *iter) { if (array->itemCount == 0) { *iter = WANotFound; return NULL; } else { *iter = 0; return array->items[0]; } } void* WMArrayLast(WMArray *array, WMArrayIterator *iter) { if (array->itemCount == 0) { *iter = WANotFound; return NULL; } else { *iter = array->itemCount-1; return array->items[*iter]; } } void* WMArrayNext(WMArray *array, WMArrayIterator *iter) { if (*iter >= 0 && *iter < array->itemCount-1) { return array->items[++(*iter)]; } else { *iter = WANotFound; return NULL; } } void* WMArrayPrevious(WMArray *array, WMArrayIterator *iter) { if (*iter > 0 && *iter < array->itemCount) { return array->items[--(*iter)]; } else { *iter = WANotFound; return NULL; } }