735 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			735 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
#include <common.h>
 | 
						|
#include <malloc.h>
 | 
						|
#include <lists.h>
 | 
						|
 | 
						|
#define MAX(a,b) 	(((a)>(b)) ? (a) : (b))
 | 
						|
#define MIN(a,b) 	(((a)<(b)) ? (a) : (b))
 | 
						|
#define CAT4CHARS(a,b,c,d)	((a<<24) | (b<<16) | (c<<8) | d)
 | 
						|
 | 
						|
/* increase list size by 10% every time it is full */
 | 
						|
#define kDefaultAllocationPercentIncrease	10
 | 
						|
 | 
						|
/* always increase list size by 4 items when it is full */
 | 
						|
#define kDefaultAllocationminNumItemsIncrease	4
 | 
						|
 | 
						|
/*
 | 
						|
 * how many items to expand the list by when it becomes full
 | 
						|
 * = current listSize (in items) + (hiword percent of list size) + loword
 | 
						|
 */
 | 
						|
#define NUMITEMSPERALLOC(list)	MAX(((*list)->listSize * \
 | 
						|
				    ((*list)->percentIncrease + 100)) / 100, \
 | 
						|
				    (*list)->minNumItemsIncrease )
 | 
						|
 | 
						|
#define ITEMPTR(list,item)	&(((char *)&(*list)->itemList)[(*(list))->itemSize * (item)])
 | 
						|
 | 
						|
#define LIST_SIGNATURE		CAT4CHARS('L', 'I', 'S', 'T');
 | 
						|
 | 
						|
#define calloc(size,num)	malloc(size*num)
 | 
						|
 | 
						|
/********************************************************************/
 | 
						|
 | 
						|
Handle NewHandle (unsigned int numBytes)
 | 
						|
{
 | 
						|
	void *memPtr;
 | 
						|
	HandleRecord *hanPtr;
 | 
						|
 | 
						|
	memPtr = calloc (numBytes, 1);
 | 
						|
	hanPtr = (HandleRecord *) calloc (sizeof (HandleRecord), 1);
 | 
						|
	if (hanPtr && (memPtr || numBytes == 0)) {
 | 
						|
		hanPtr->ptr = memPtr;
 | 
						|
		hanPtr->size = numBytes;
 | 
						|
		return (Handle) hanPtr;
 | 
						|
	} else {
 | 
						|
		free (memPtr);
 | 
						|
		free (hanPtr);
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
}
 | 
						|
/********************************************************************/
 | 
						|
 | 
						|
void DisposeHandle (Handle handle)
 | 
						|
{
 | 
						|
	if (handle) {
 | 
						|
		free (*handle);
 | 
						|
		free ((void *) handle);
 | 
						|
	}
 | 
						|
}
 | 
						|
/********************************************************************/
 | 
						|
 | 
						|
unsigned int GetHandleSize (Handle handle)
 | 
						|
{
 | 
						|
	return ((HandleRecord *) handle)->size;
 | 
						|
}
 | 
						|
/********************************************************************/
 | 
						|
 | 
						|
int SetHandleSize (Handle handle, unsigned int newSize)
 | 
						|
{
 | 
						|
	HandleRecord *hanRecPtr = (HandleRecord *) handle;
 | 
						|
	void *newPtr, *oldPtr;
 | 
						|
	unsigned int oldSize;
 | 
						|
 | 
						|
 | 
						|
	oldPtr = hanRecPtr->ptr;
 | 
						|
	oldSize = hanRecPtr->size;
 | 
						|
 | 
						|
	if (oldSize == newSize)
 | 
						|
		return 1;
 | 
						|
 | 
						|
	if (oldPtr == NULL) {
 | 
						|
		newPtr = malloc (newSize);
 | 
						|
	} else {
 | 
						|
		newPtr = realloc (oldPtr, newSize);
 | 
						|
	}
 | 
						|
	if (newPtr || (newSize == 0)) {
 | 
						|
		hanRecPtr->ptr = newPtr;
 | 
						|
		hanRecPtr->size = newSize;
 | 
						|
		if (newSize > oldSize)
 | 
						|
			memset ((char *) newPtr + oldSize, 0, newSize - oldSize);
 | 
						|
		return 1;
 | 
						|
	} else
 | 
						|
		return 0;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef	CFG_ALL_LIST_FUNCTIONS
 | 
						|
 | 
						|
/*  Used to compare list elements by their raw data contents */
 | 
						|
static int ListMemBlockCmp (void *a, void *b, int size)
 | 
						|
{
 | 
						|
	return memcmp (a, b, size);
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * Binary search numElements of size elementSize in array for a match
 | 
						|
 * to the. item. Return the index of the element that matches
 | 
						|
 * (0 - numElements - 1). If no match is found return the -i-1 where
 | 
						|
 * i is the index (0 - numElements) where the item should be placed.
 | 
						|
 * (*theCmp)(a,b) should return <0 if a<b, 0 if a==b, >0 if a>b.
 | 
						|
 *
 | 
						|
 * This function is like the C-Library function bsearch() except that
 | 
						|
 * this function returns the index where the item should be placed if
 | 
						|
 * it is not found.
 | 
						|
 */
 | 
						|
int BinSearch ( void *array, int numElements, int elementSize,
 | 
						|
		void *itemPtr, CompareFunction compareFunction)
 | 
						|
{
 | 
						|
	int low, high, mid, cmp;
 | 
						|
	void *arrayItemPtr;
 | 
						|
 | 
						|
	for (low = 0, high = numElements - 1, mid = 0, cmp = -1; low <= high;) {
 | 
						|
		mid = (low + high) >> 1;
 | 
						|
 | 
						|
		arrayItemPtr = (void *) (((char *) array) + (mid * elementSize));
 | 
						|
		cmp = compareFunction
 | 
						|
			? compareFunction (itemPtr, arrayItemPtr)
 | 
						|
			: ListMemBlockCmp (itemPtr, arrayItemPtr, elementSize);
 | 
						|
		if (cmp == 0) {
 | 
						|
			return mid;
 | 
						|
		} else if (cmp < 0) {
 | 
						|
			high = mid - 1;
 | 
						|
		} else {
 | 
						|
			low = mid + 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (cmp > 0)
 | 
						|
		mid++;
 | 
						|
 | 
						|
	return -mid - 1;
 | 
						|
}
 | 
						|
 | 
						|
#endif	/* CFG_ALL_LIST_FUNCTIONS */
 | 
						|
 | 
						|
/*******************************************************************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * If numNewItems == 0 then expand the list by the number of items
 | 
						|
 * indicated by its allocation policy.
 | 
						|
 * If numNewItems > 0 then expand the list by exactly the number of
 | 
						|
 * items indicated.
 | 
						|
 * If numNewItems < 0 then expand the list by the absolute value of
 | 
						|
 * numNewItems plus the number of items indicated by its allocation
 | 
						|
 * policy.
 | 
						|
 * Returns 1 for success, 0 if out of memory
 | 
						|
*/
 | 
						|
static int ExpandListSpace (list_t list, int numNewItems)
 | 
						|
{
 | 
						|
	if (numNewItems == 0) {
 | 
						|
		numNewItems = NUMITEMSPERALLOC (list);
 | 
						|
	} else if (numNewItems < 0) {
 | 
						|
		numNewItems = (-numNewItems) + NUMITEMSPERALLOC (list);
 | 
						|
	}
 | 
						|
 | 
						|
	if (SetHandleSize ((Handle) list,
 | 
						|
			   sizeof (ListStruct) +
 | 
						|
			   ((*list)->listSize +
 | 
						|
			   numNewItems) * (*list)->itemSize)) {
 | 
						|
		(*list)->listSize += numNewItems;
 | 
						|
		return 1;
 | 
						|
	} else {
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
#ifdef	CFG_ALL_LIST_FUNCTIONS
 | 
						|
 | 
						|
/*
 | 
						|
 * This function reallocate the list, minus any currently unused
 | 
						|
 * portion of its allotted memory.
 | 
						|
 */
 | 
						|
void ListCompact (list_t list)
 | 
						|
{
 | 
						|
 | 
						|
	if (!SetHandleSize ((Handle) list,
 | 
						|
			    sizeof (ListStruct) +
 | 
						|
			    (*list)->numItems * (*list)->itemSize)) {
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	(*list)->listSize = (*list)->numItems;
 | 
						|
}
 | 
						|
 | 
						|
#endif	/* CFG_ALL_LIST_FUNCTIONS */
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
list_t ListCreate (int elementSize)
 | 
						|
{
 | 
						|
	list_t list;
 | 
						|
 | 
						|
	list = (list_t) (NewHandle (sizeof (ListStruct)));  /* create empty list */
 | 
						|
	if (list) {
 | 
						|
		(*list)->signature = LIST_SIGNATURE;
 | 
						|
		(*list)->numItems = 0;
 | 
						|
		(*list)->listSize = 0;
 | 
						|
		(*list)->itemSize = elementSize;
 | 
						|
		(*list)->percentIncrease = kDefaultAllocationPercentIncrease;
 | 
						|
		(*list)->minNumItemsIncrease =
 | 
						|
				kDefaultAllocationminNumItemsIncrease;
 | 
						|
	}
 | 
						|
 | 
						|
	return list;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
void ListSetAllocationPolicy (list_t list, int minItemsPerAlloc,
 | 
						|
			      int percentIncreasePerAlloc)
 | 
						|
{
 | 
						|
	(*list)->percentIncrease = percentIncreasePerAlloc;
 | 
						|
	(*list)->minNumItemsIncrease = minItemsPerAlloc;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
void ListDispose (list_t list)
 | 
						|
{
 | 
						|
	DisposeHandle ((Handle) list);
 | 
						|
}
 | 
						|
/*******************************/
 | 
						|
 | 
						|
#ifdef	CFG_ALL_LIST_FUNCTIONS
 | 
						|
 | 
						|
void ListDisposePtrList (list_t list)
 | 
						|
{
 | 
						|
	int index;
 | 
						|
	int numItems;
 | 
						|
 | 
						|
	if (list) {
 | 
						|
		numItems = ListNumItems (list);
 | 
						|
 | 
						|
		for (index = 1; index <= numItems; index++)
 | 
						|
			free (*(void **) ListGetPtrToItem (list, index));
 | 
						|
 | 
						|
		ListDispose (list);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * keeps memory, resets the number of items to 0
 | 
						|
 */
 | 
						|
void ListClear (list_t list)
 | 
						|
{
 | 
						|
	if (!list)
 | 
						|
		return;
 | 
						|
	(*list)->numItems = 0;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * copy is only as large as necessary
 | 
						|
 */
 | 
						|
list_t ListCopy (list_t originalList)
 | 
						|
{
 | 
						|
	list_t tempList = NULL;
 | 
						|
	int numItems;
 | 
						|
 | 
						|
	if (!originalList)
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	tempList = ListCreate ((*originalList)->itemSize);
 | 
						|
	if (tempList) {
 | 
						|
		numItems = ListNumItems (originalList);
 | 
						|
 | 
						|
		if (!SetHandleSize ((Handle) tempList,
 | 
						|
				    sizeof (ListStruct) +
 | 
						|
				    numItems * (*tempList)->itemSize)) {
 | 
						|
			ListDispose (tempList);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
 | 
						|
		(*tempList)->numItems = (*originalList)->numItems;
 | 
						|
		(*tempList)->listSize = (*originalList)->numItems;
 | 
						|
		(*tempList)->itemSize = (*originalList)->itemSize;
 | 
						|
		(*tempList)->percentIncrease = (*originalList)->percentIncrease;
 | 
						|
		(*tempList)->minNumItemsIncrease =
 | 
						|
				(*originalList)->minNumItemsIncrease;
 | 
						|
 | 
						|
		memcpy (ITEMPTR (tempList, 0), ITEMPTR (originalList, 0),
 | 
						|
				numItems * (*tempList)->itemSize);
 | 
						|
	}
 | 
						|
 | 
						|
	return tempList;
 | 
						|
}
 | 
						|
 | 
						|
/********************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * list1 = list1 + list2
 | 
						|
 */
 | 
						|
int ListAppend (list_t list1, list_t list2)
 | 
						|
{
 | 
						|
	int numItemsL1, numItemsL2;
 | 
						|
 | 
						|
	if (!list2)
 | 
						|
		return 1;
 | 
						|
 | 
						|
	if (!list1)
 | 
						|
		return 0;
 | 
						|
	if ((*list1)->itemSize != (*list2)->itemSize)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	numItemsL1 = ListNumItems (list1);
 | 
						|
	numItemsL2 = ListNumItems (list2);
 | 
						|
 | 
						|
	if (numItemsL2 == 0)
 | 
						|
		return 1;
 | 
						|
 | 
						|
	if (!SetHandleSize ((Handle) list1,
 | 
						|
			    sizeof (ListStruct) + (numItemsL1 + numItemsL2) *
 | 
						|
					(*list1)->itemSize)) {
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	(*list1)->numItems = numItemsL1 + numItemsL2;
 | 
						|
	(*list1)->listSize = numItemsL1 + numItemsL2;
 | 
						|
 | 
						|
	memmove (ITEMPTR (list1, numItemsL1),
 | 
						|
		 ITEMPTR (list2, 0),
 | 
						|
		 numItemsL2 * (*list2)->itemSize);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
#endif	/* CFG_ALL_LIST_FUNCTIONS */
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * returns 1 if the item is inserted, returns 0 if out of memory or
 | 
						|
 * bad arguments were passed.
 | 
						|
 */
 | 
						|
int ListInsertItem (list_t list, void *ptrToItem, int itemPosition)
 | 
						|
{
 | 
						|
	return ListInsertItems (list, ptrToItem, itemPosition, 1);
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
int ListInsertItems (list_t list, void *ptrToItems, int firstItemPosition,
 | 
						|
		     int numItemsToInsert)
 | 
						|
{
 | 
						|
	int numItems = (*list)->numItems;
 | 
						|
 | 
						|
	if (firstItemPosition == numItems + 1)
 | 
						|
		firstItemPosition = LIST_END;
 | 
						|
	else if (firstItemPosition > numItems)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	if ((*list)->numItems >= (*list)->listSize) {
 | 
						|
		if (!ExpandListSpace (list, -numItemsToInsert))
 | 
						|
			return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	if (firstItemPosition == LIST_START) {
 | 
						|
		if (numItems == 0) {
 | 
						|
			/* special case for empty list */
 | 
						|
			firstItemPosition = LIST_END;
 | 
						|
		} else {
 | 
						|
			firstItemPosition = 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (firstItemPosition == LIST_END) {	/* add at the end of the list */
 | 
						|
		if (ptrToItems)
 | 
						|
			memcpy (ITEMPTR (list, numItems), ptrToItems,
 | 
						|
					(*list)->itemSize * numItemsToInsert);
 | 
						|
		else
 | 
						|
			memset (ITEMPTR (list, numItems), 0,
 | 
						|
					(*list)->itemSize * numItemsToInsert);
 | 
						|
 | 
						|
		(*list)->numItems += numItemsToInsert;
 | 
						|
	} else {					/* move part of list up to make room for new item */
 | 
						|
		memmove (ITEMPTR (list, firstItemPosition - 1 + numItemsToInsert),
 | 
						|
			 ITEMPTR (list, firstItemPosition - 1),
 | 
						|
			 (numItems + 1 - firstItemPosition) * (*list)->itemSize);
 | 
						|
 | 
						|
		if (ptrToItems)
 | 
						|
			memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems,
 | 
						|
					 (*list)->itemSize * numItemsToInsert);
 | 
						|
		else
 | 
						|
			memset (ITEMPTR (list, firstItemPosition - 1), 0,
 | 
						|
					(*list)->itemSize * numItemsToInsert);
 | 
						|
 | 
						|
		(*list)->numItems += numItemsToInsert;
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef CFG_ALL_LIST_FUNCTIONS
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
int ListEqual (list_t list1, list_t list2)
 | 
						|
{
 | 
						|
	if (list1 == list2)
 | 
						|
		return 1;
 | 
						|
 | 
						|
	if (list1 == NULL || list2 == NULL)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	if ((*list1)->itemSize == (*list1)->itemSize) {
 | 
						|
	    if ((*list1)->numItems == (*list2)->numItems) {
 | 
						|
		return (memcmp (ITEMPTR (list1, 0), ITEMPTR (list2, 0),
 | 
						|
				(*list1)->itemSize * (*list1)->numItems) == 0);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * The item pointed to by ptrToItem is copied over the current item
 | 
						|
 * at itemPosition
 | 
						|
 */
 | 
						|
void ListReplaceItem (list_t list, void *ptrToItem, int itemPosition)
 | 
						|
{
 | 
						|
	ListReplaceItems (list, ptrToItem, itemPosition, 1);
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * The item pointed to by ptrToItems is copied over the current item
 | 
						|
 * at itemPosition
 | 
						|
 */
 | 
						|
void ListReplaceItems ( list_t list, void *ptrToItems,
 | 
						|
			int firstItemPosition, int numItemsToReplace)
 | 
						|
{
 | 
						|
 | 
						|
	if (firstItemPosition == LIST_END)
 | 
						|
		firstItemPosition = (*list)->numItems;
 | 
						|
	else if (firstItemPosition == LIST_START)
 | 
						|
		firstItemPosition = 1;
 | 
						|
 | 
						|
	memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems,
 | 
						|
			 (*list)->itemSize * numItemsToReplace);
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
void ListGetItem (list_t list, void *itemDestination, int itemPosition)
 | 
						|
{
 | 
						|
	ListGetItems (list, itemDestination, itemPosition, 1);
 | 
						|
}
 | 
						|
 | 
						|
#endif	/* CFG_ALL_LIST_FUNCTIONS */
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
#if defined(CFG_ALL_LIST_FUNCTIONS) || defined(CFG_DEVICE_DEREGISTER)
 | 
						|
 | 
						|
void ListRemoveItem (list_t list, void *itemDestination, int itemPosition)
 | 
						|
{
 | 
						|
	ListRemoveItems (list, itemDestination, itemPosition, 1);
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
void ListRemoveItems (list_t list, void *itemsDestination,
 | 
						|
		      int firstItemPosition, int numItemsToRemove)
 | 
						|
{
 | 
						|
	int firstItemAfterChunk, numToMove;
 | 
						|
 | 
						|
	if (firstItemPosition == LIST_START)
 | 
						|
		firstItemPosition = 1;
 | 
						|
	else if (firstItemPosition == LIST_END)
 | 
						|
		firstItemPosition = (*list)->numItems;
 | 
						|
 | 
						|
	if (itemsDestination != NULL)
 | 
						|
		memcpy (itemsDestination, ITEMPTR (list, firstItemPosition - 1),
 | 
						|
				(*list)->itemSize * numItemsToRemove);
 | 
						|
 | 
						|
	firstItemAfterChunk = firstItemPosition + numItemsToRemove;
 | 
						|
	numToMove = (*list)->numItems - (firstItemAfterChunk - 1);
 | 
						|
 | 
						|
	if (numToMove > 0) {
 | 
						|
		/*
 | 
						|
		 * move part of list down to cover hole left by removed item
 | 
						|
		 */
 | 
						|
		memmove (ITEMPTR (list, firstItemPosition - 1),
 | 
						|
				 ITEMPTR (list, firstItemAfterChunk - 1),
 | 
						|
				 (*list)->itemSize * numToMove);
 | 
						|
	}
 | 
						|
 | 
						|
	(*list)->numItems -= numItemsToRemove;
 | 
						|
}
 | 
						|
#endif	/* CFG_ALL_LIST_FUNCTIONS || CFG_DEVICE_DEREGISTER */
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
void ListGetItems (list_t list, void *itemsDestination,
 | 
						|
		   int firstItemPosition, int numItemsToGet)
 | 
						|
{
 | 
						|
 | 
						|
	if (firstItemPosition == LIST_START)
 | 
						|
		firstItemPosition = 1;
 | 
						|
	else if (firstItemPosition == LIST_END)
 | 
						|
		firstItemPosition = (*list)->numItems;
 | 
						|
 | 
						|
	memcpy (itemsDestination,
 | 
						|
		ITEMPTR (list, firstItemPosition - 1),
 | 
						|
		(*list)->itemSize * numItemsToGet);
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * Returns a pointer to the item at itemPosition. returns null if an
 | 
						|
 * errors occurred.
 | 
						|
 */
 | 
						|
void *ListGetPtrToItem (list_t list, int itemPosition)
 | 
						|
{
 | 
						|
	if (itemPosition == LIST_START)
 | 
						|
		itemPosition = 1;
 | 
						|
	else if (itemPosition == LIST_END)
 | 
						|
		itemPosition = (*list)->numItems;
 | 
						|
 | 
						|
	return ITEMPTR (list, itemPosition - 1);
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * returns a pointer the lists data (abstraction violation for
 | 
						|
 * optimization)
 | 
						|
 */
 | 
						|
void *ListGetDataPtr (list_t list)
 | 
						|
{
 | 
						|
	return &((*list)->itemList[0]);
 | 
						|
}
 | 
						|
 | 
						|
/********************************/
 | 
						|
 | 
						|
#ifdef	CFG_ALL_LIST_FUNCTIONS
 | 
						|
 | 
						|
int ListApplyToEach (list_t list, int ascending,
 | 
						|
		     ListApplicationFunc funcToApply,
 | 
						|
		     void *callbackData)
 | 
						|
{
 | 
						|
	int result = 0, index;
 | 
						|
 | 
						|
	if (!list || !funcToApply)
 | 
						|
		goto Error;
 | 
						|
 | 
						|
	if (ascending) {
 | 
						|
		for (index = 1; index <= ListNumItems (list); index++) {
 | 
						|
			result = funcToApply (index,
 | 
						|
					      ListGetPtrToItem (list, index),
 | 
						|
					      callbackData);
 | 
						|
			if (result < 0)
 | 
						|
				goto Error;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		for (index = ListNumItems (list);
 | 
						|
		     index > 0 && index <= ListNumItems (list);
 | 
						|
		     index--) {
 | 
						|
			result = funcToApply (index,
 | 
						|
					      ListGetPtrToItem (list, index),
 | 
						|
					      callbackData);
 | 
						|
			if (result < 0)
 | 
						|
				goto Error;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
Error:
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* CFG_ALL_LIST_FUNCTIONS */
 | 
						|
 | 
						|
/********************************/
 | 
						|
 | 
						|
int ListGetItemSize (list_t list)
 | 
						|
{
 | 
						|
	return (*list)->itemSize;
 | 
						|
}
 | 
						|
 | 
						|
/********************************/
 | 
						|
 | 
						|
int ListNumItems (list_t list)
 | 
						|
{
 | 
						|
	return (*list)->numItems;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
#ifdef	CFG_ALL_LIST_FUNCTIONS
 | 
						|
 | 
						|
void ListRemoveDuplicates (list_t list, CompareFunction compareFunction)
 | 
						|
{
 | 
						|
	int numItems, index, startIndexForFind, duplicatesIndex;
 | 
						|
 | 
						|
	numItems = ListNumItems (list);
 | 
						|
 | 
						|
	for (index = 1; index < numItems; index++) {
 | 
						|
		startIndexForFind = index + 1;
 | 
						|
		while (startIndexForFind <= numItems) {
 | 
						|
			duplicatesIndex =
 | 
						|
				ListFindItem (list,
 | 
						|
					      ListGetPtrToItem (list, index),
 | 
						|
					      startIndexForFind,
 | 
						|
					      compareFunction);
 | 
						|
			if (duplicatesIndex > 0) {
 | 
						|
				ListRemoveItem (list, NULL, duplicatesIndex);
 | 
						|
				numItems--;
 | 
						|
				startIndexForFind = duplicatesIndex;
 | 
						|
			} else {
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
int ListFindItem (list_t list, void *ptrToItem, int startingPosition,
 | 
						|
		  CompareFunction compareFunction)
 | 
						|
{
 | 
						|
	int numItems, size, index, cmp;
 | 
						|
	void *listItemPtr;
 | 
						|
 | 
						|
	if ((numItems = (*list)->numItems) == 0)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	size = (*list)->itemSize;
 | 
						|
 | 
						|
	if (startingPosition == LIST_START)
 | 
						|
		startingPosition = 1;
 | 
						|
	else if (startingPosition == LIST_END)
 | 
						|
		startingPosition = numItems;
 | 
						|
 | 
						|
	for (index = startingPosition; index <= numItems; index++) {
 | 
						|
		listItemPtr = ITEMPTR (list, index - 1);
 | 
						|
		cmp = compareFunction
 | 
						|
			? compareFunction (ptrToItem, listItemPtr)
 | 
						|
			: ListMemBlockCmp (ptrToItem, listItemPtr, size);
 | 
						|
		if (cmp == 0)
 | 
						|
			return index;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
int ShortCompare (void *a, void *b)
 | 
						|
{
 | 
						|
	if (*(short *) a < *(short *) b)
 | 
						|
		return -1;
 | 
						|
	if (*(short *) a > *(short *) b)
 | 
						|
		return 1;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
int IntCompare (void *a, void *b)
 | 
						|
{
 | 
						|
	if (*(int *) a < *(int *) b)
 | 
						|
		return -1;
 | 
						|
	if (*(int *) a > *(int *) b)
 | 
						|
		return 1;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
int CStringCompare (void *a, void *b)
 | 
						|
{
 | 
						|
	return strcmp (*(char **) a, *(char **) b);
 | 
						|
}
 | 
						|
 | 
						|
/*******************************/
 | 
						|
 | 
						|
 | 
						|
int ListBinSearch (list_t list, void *ptrToItem,
 | 
						|
		   CompareFunction compareFunction)
 | 
						|
{
 | 
						|
	int index;
 | 
						|
 | 
						|
	index = BinSearch (ITEMPTR (list, 0),
 | 
						|
			   (int) (*list)->numItems,
 | 
						|
			   (int) (*list)->itemSize, ptrToItem,
 | 
						|
			   compareFunction);
 | 
						|
 | 
						|
	if (index >= 0)
 | 
						|
		index++;			/* lists start from 1 */
 | 
						|
	else
 | 
						|
		index = 0;			/* item not found */
 | 
						|
 | 
						|
	return index;
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * Reserves memory for numItems in the list. If it succeeds then
 | 
						|
 * numItems items can be inserted without possibility of an out of
 | 
						|
 * memory error (useful to simplify error recovery in complex
 | 
						|
 * functions). Returns 1 if success, 0 if out of memory.
 | 
						|
 */
 | 
						|
int ListPreAllocate (list_t list, int numItems)
 | 
						|
{
 | 
						|
	if ((*list)->listSize - (*list)->numItems < numItems) {
 | 
						|
		return ExpandListSpace (list,
 | 
						|
					numItems - ((*list)->listSize -
 | 
						|
						(*list)->numItems));
 | 
						|
	} else {
 | 
						|
		return 1;	/* enough items are already pre-allocated */
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
#endif /* CFG_ALL_LIST_FUNCTIONS */
 |