mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-21 09:29:54 +02:00
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 */
|