diff --git a/WINGs/ChangeLog b/WINGs/ChangeLog index e91972e7..905340a7 100644 --- a/WINGs/ChangeLog +++ b/WINGs/ChangeLog @@ -14,6 +14,7 @@ changes since wmaker 0.62.1: - restructured the directory tree. Added Documentation, Examples and Tests subdirectories - removed WMArrayBag and reorganized WMTreeBag to be WMBag. +- added WMArray class. changes since wmaker 0.62.0: diff --git a/WINGs/Makefile.am b/WINGs/Makefile.am index 1c580ae8..f7d791d4 100644 --- a/WINGs/Makefile.am +++ b/WINGs/Makefile.am @@ -26,14 +26,25 @@ EXTRA_DIST = BUGS libWINGs_a_SOURCES = \ WINGs.h \ WINGsP.h \ + array.c \ + bagtree.c \ configuration.c \ + connection.c \ + data.c \ dragdestination.c \ dragsource.c \ + error.c \ + findfile.c \ fontmanager.c \ + hashtable.c \ + host.c \ international.c \ + memory.c \ notification.c \ selection.c \ + string.c \ userdefaults.c \ + usleep.c \ wapplication.c \ wappresource.c \ wballoon.c \ @@ -64,38 +75,29 @@ libWINGs_a_SOURCES = \ wtabview.c \ wtext.c \ wtextfield.c \ - wwindow.c \ wview.c \ - error.c \ - findfile.c \ - bagtree.c \ - connection.c \ - data.c \ - hashtable.c \ - host.c \ - memory.c \ - string.c \ - usleep.c + wwindow.c libWUtil_a_SOURCES = \ WINGs.h \ WINGsP.h \ + array.c \ bagtree.c \ connection.c \ data.c \ - host.c \ - international.c \ - notification.c \ - userdefaults.c \ - wapplication.c \ - wutil.c \ error.c \ findfile.c \ hashtable.c \ + host.c \ + international.c \ memory.c \ + notification.c \ string.c \ - usleep.c + userdefaults.c \ + usleep.c \ + wapplication.c \ + wutil.c INCLUDES = -I$(top_srcdir)/wrlib -I$(top_srcdir)/src \ diff --git a/WINGs/WUtil.h b/WINGs/WUtil.h index f0349529..6d9a3b93 100644 --- a/WINGs/WUtil.h +++ b/WINGs/WUtil.h @@ -112,7 +112,8 @@ typedef enum { enum { - WBNotFound = INT_MIN /* element was not found in bag */ + WBNotFound = INT_MIN, /* element was not found in bag */ + WANotFound = -1 /* element was not found in array */ }; @@ -162,18 +163,6 @@ typedef struct { typedef void *WMBagIterator; -#if 0 -struct W_Bag { - void *data; - - void (*destructor)(void *item); - - W_BagFunctions func; -}; -#endif - - - #if 0 typedef struct { char character; /* the escape character */ @@ -317,21 +306,84 @@ extern const WMHashTableCallbacks WMStringPointerHashCallbacks; /*......................................................................*/ - /* - * Array bags use an array to store the elements. - * Item indexes may be any integer number. - * + * WMArray use an array to store the elements. + * Item indexes may be only positive integer numbers. + * The array cannot contain holes in it. + * * Pros: * Fast [O(1)] access to elements * Fast [O(1)] push/pop - * + * * Cons: * A little slower [O(n)] for insertion/deletion of elements that * aren't in the end - * Element indexes with large difference will cause large holes */ +WMArray* WMCreateArray(unsigned initialSize); + +WMArray* WMCreateArrayWithDestructor(unsigned initialSize, + void (*destructor)(void*)); + +void WMEmptyArray(WMArray *array); + +void WMFreeArray(WMArray *array); + +unsigned WMGetArrayItemCount(WMArray *array); + +/* appends other to array. other remains unchanged */ +int WMAppendArray(WMArray *array, WMArray *other); + +/* add will place the element at the end of the array */ +int WMAddToArray(WMArray *array, void *item); + +#define WMPushInArray(array, item) WMAddToArray(array, item) + +/* insert will increment the index of elements after it by 1 */ +int WMInsertInArray(WMArray *array, unsigned index, void *item); + +/* replace and set will return the old item WITHOUT calling the + * destructor on it even if its available. Free the returned item yourself. + */ +void* WMReplaceInArray(WMArray *array, unsigned index, void *item); + +#define WMSetInArray(array, index, item) WMReplaceInArray(array, index, item) + +/* delete and remove will remove the elements and cause the elements + * after them to decrement their indexes by 1. Also will call the + * destructor on the deleted element if there's one available. + */ +int WMDeleteFromArray(WMArray *array, unsigned index); + +int WMRemoveFromArray(WMArray *array, void *item); + +void* WMGetFromArray(WMArray *array, unsigned index); + +#define WMGetFirstInArray(array, item) WMFindInArray(array, NULL, item) + +/* pop will return the last element from the array, also removing it + * from the array. The destructor is NOT called, even if available. + * Free the returned element if needed by yourself + */ +void* WMPopFromArray(WMArray *array); + +int WMFindInArray(WMArray *array, int (*match)(void*, void*), void *cdata); + +unsigned WMCountInArray(WMArray *array, void *item); + +/* comparer must return: + * < 0 if a < b + * > 0 if a > b + * = 0 if a = b + */ +int WMSortArray(WMArray *array, int (*comparer)(const void*, const void*)); + +void WMMapArray(WMArray *array, void (*function)(void*, void*), void *data); + + + +/*..........................................................................*/ + /* * Tree bags use a red-black tree for storage. * Item indexes may be any integer number. @@ -353,29 +405,29 @@ WMBag* WMCreateTreeBag(void); WMBag* WMCreateTreeBagWithDestructor(void (*destructor)(void*)); -int WMGetBagItemCount(WMBag *self); +int WMGetBagItemCount(WMBag *bag); -int WMAppendBag(WMBag *self, WMBag *bag); +int WMAppendBag(WMBag *bag, WMBag *other); -int WMPutInBag(WMBag *self, void *item); +int WMPutInBag(WMBag *bag, void *item); /* insert will increment the index of elements after it by 1 */ -int WMInsertInBag(WMBag *self, int index, void *item); +int WMInsertInBag(WMBag *bag, int index, void *item); /* this is slow */ /* erase will remove the element from the bag, * but will keep the index of the other elements unchanged */ -int WMEraseFromBag(WMBag *self, int index); +int WMEraseFromBag(WMBag *bag, int index); /* delete and remove will remove the elements and cause the elements * after them to decrement their indexes by 1 */ -int WMRemoveFromBag(WMBag *self, void *item); +int WMDeleteFromBag(WMBag *bag, int index); -int WMDeleteFromBag(WMBag *self, int index); +int WMRemoveFromBag(WMBag *bag, void *item); -void* WMGetFromBag(WMBag *self, int index); +void* WMGetFromBag(WMBag *bag, int index); -void* WMReplaceInBag(WMBag *self, int index, void *item); +void* WMReplaceInBag(WMBag *bag, int index, void *item); #define WMSetInBag(bag, index, item) WMReplaceInBag(bag, index, item) @@ -384,29 +436,29 @@ void* WMReplaceInBag(WMBag *self, int index, void *item); * > 0 if a > b * = 0 if a = b */ -int WMSortBag(WMBag *self, int (*comparer)(const void*, const void*)); +int WMSortBag(WMBag *bag, int (*comparer)(const void*, const void*)); -void WMEmptyBag(WMBag *self); +void WMEmptyBag(WMBag *bag); -void WMFreeBag(WMBag *self); +void WMFreeBag(WMBag *bag); -void WMMapBag(WMBag *self, void (*function)(void*, void*), void *data); +void WMMapBag(WMBag *bag, void (*function)(void*, void*), void *data); -int WMGetFirstInBag(WMBag *self, void *item); +int WMGetFirstInBag(WMBag *bag, void *item); -int WMCountInBag(WMBag *self, void *item); +int WMCountInBag(WMBag *bag, void *item); -int WMFindInBag(WMBag *self, int (*match)(void*,void*), void *cdata); +int WMFindInBag(WMBag *bag, int (*match)(void*,void*), void *cdata); -void* WMBagFirst(WMBag *self, WMBagIterator *ptr); +void* WMBagFirst(WMBag *bag, WMBagIterator *ptr); -void* WMBagLast(WMBag *self, WMBagIterator *ptr); +void* WMBagLast(WMBag *bag, WMBagIterator *ptr); -void* WMBagNext(WMBag *self, WMBagIterator *ptr); +void* WMBagNext(WMBag *bag, WMBagIterator *ptr); -void* WMBagPrevious(WMBag *self, WMBagIterator *ptr); +void* WMBagPrevious(WMBag *bag, WMBagIterator *ptr); -void* WMBagIteratorAtIndex(WMBag *self, int index, WMBagIterator *ptr); +void* WMBagIteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr); int WMBagIndexForIterator(WMBag *bag, WMBagIterator ptr); diff --git a/WINGs/array.c b/WINGs/array.c index cdfdfe3f..55080e6b 100644 --- a/WINGs/array.c +++ b/WINGs/array.c @@ -19,10 +19,10 @@ #define RESIZE_INCREMENT 8 -typedef struct { +typedef struct W_Array { void **items; /* the array data */ - unsigned int length; /* # of items in array */ - unsigned int allocSize; /* allocated size of array */ + unsigned itemCount; /* # of items in array */ + unsigned allocSize; /* allocated size of array */ void (*destructor)(void *item); /* the destructor to free elements */ } W_Array; @@ -47,7 +47,7 @@ WMCreateArrayWithDestructor(unsigned initialSize, void (*destructor)(void*)) array->items = wmalloc(sizeof(void*) * initialSize); - array->length = 0; + array->itemCount = 0; array->allocSize = initialSize; array->destructor = destructor; @@ -59,12 +59,13 @@ void WMEmptyArray(WMArray *array) { if (array->destructor) { - while (array->length-- > 0) { - array->destructor(array->items[array->length]); + while (array->itemCount > 0) { + array->itemCount--; + array->destructor(array->items[array->itemCount]); } } - /*memset(array->items, 0, array->length * sizeof(void*));*/ - array->length = 0; + /*memset(array->items, 0, array->itemCount * sizeof(void*));*/ + array->itemCount = 0; } @@ -77,123 +78,205 @@ WMFreeArray(WMArray *array) } +unsigned +WMGetArrayItemCount(WMArray *array) +{ + return array->itemCount; +} + + +int +WMAppendArray(WMArray *array, WMArray *other) +{ + if (other->itemCount == 0) + return 1; + + 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; + + return 1; +} + + +int +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++; + + return 1; +} + + +int +WMInsertInArray(WMArray *array, unsigned index, void *item) +{ + wassertrv(index <= array->itemCount, 0); + + 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++; + + return 1; +} + + void* -WMReplaceInArray(WMArray *array, unsigned int index, void *data) +WMReplaceInArray(WMArray *array, unsigned index, void *item) { void *old; - wassertrv(index > array->length, 0); + wassertrv(index > array->itemCount, 0); - if (index == array->length) { - WMArrayAppend(array, data); + if (index == array->itemCount) { + WMAddToArray(array, item); return NULL; } old = array->items[index]; - array->items[index] = data; + array->items[index] = item; return old; } -void* -WMGetArrayElement(WMArray *array, unsigned int index) +static void +deleteFromArray(WMArray *array, unsigned index) { - if (index >= array->length) + /*wassertr(index < array->itemCount);*/ + + if (index < array->itemCount-1) { + memmove(array->items+index, array->items+index+1, + sizeof(void*)*(array->itemCount-index-1)); + } + + array->itemCount--; +} + + +int +WMDeleteFromArray(WMArray *array, unsigned index) +{ + if (index >= array->itemCount) + return 0; + + if (array->destructor) { + array->destructor(array->items[index]); + } + + deleteFromArray(array, index); + + return 1; +} + + +int +WMRemoveFromArray(WMArray *array, void *item) +{ + unsigned i; + + for (i = 0; i < array->itemCount; i++) { + if (array->items[i] == item) { + return WMDeleteFromArray(array, i); + } + } + + return 0; +} + + +void* +WMGetFromArray(WMArray *array, unsigned index) +{ + if (index >= array->itemCount) return NULL; return array->items[index]; } -#if 0 -int -WMAppendToArray(WMArray *array, void *data) -{ - if (array->length >= array->allocSize) { - array->allocSize += RESIZE_INCREMENT; - array->items = wrealloc(array->items, sizeof(void*)*array->allocSize); - } - array->items[array->length++] = data; - - return 1; -} -#endif - - -int -WMInsertInArray(WMArray *array, unsigned index, void *data) -{ - wassertrv(index <= array->length, 0); - - if (array->length >= array->allocSize) { - array->allocSize += RESIZE_INCREMENT; - array->items = wrealloc(array->items, sizeof(void*)*array->allocSize); - } - if (index < array->length) - memmove(array->items+index+1, array->items+index, - sizeof(void*)*(array->length-index)); - array->items[index] = data; - - array->length++; - - return 1; -} - - -int -WMAppendToArray(WMArray *array, void *data) -{ - return WMInsertInArray(array, array->length, data); -} - - -static void -removeFromArray(WMArray *array, unsigned index) -{ - /*wassertr(index < array->length);*/ - - memmove(array->items+index, array->items+index+1, - sizeof(void*)*(array->length-index-1)); - - array->length--; -} - - -void -WMDeleteFromArray(WMArray *array, unsigned index) -{ - wassertr(index < array->length); - - if (array->destructor) { - array->destructor(array->items[index]); - } - - removeFromArray(array, index); -} - - void* -WMArrayPop(WMArray *array) +WMPopFromArray(WMArray *array) { - void *last = array->items[length-1]; + void *last = array->items[array->itemCount-1]; - removeFromArray(array, array->length-1); + deleteFromArray(array, array->itemCount-1); return last; } int -WMIndexForArrayElement(WMArray *array, void *data) +WMFindInArray(WMArray *array, int (*match)(void*, void*), void *cdata) { unsigned i; - for (i = 0; i < array->length; i++) - if (array->items[i] == data) - return 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 -1; + return WANotFound; +} + + +unsigned +WMCountInArray(WMArray *array, void *item) +{ + unsigned i, count; + + for (i=0, count=0; iitemCount; i++) { + if (array->items[i] == item) + count++; + } + + return count; +} + + +int +WMSortArray(WMArray *array, int (*comparer)(const void*, const void*)) +{ + qsort(array->items, array->itemCount, sizeof(void*), comparer); + + return 1; +} + + +void +WMMapArray(WMArray *array, void (*function)(void*, void*), void *data) +{ + unsigned i; + + for (i=0; iitemCount; i++) { + (*function)(array->items[i], data); + } }