5 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
6 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
7 #define CAT4CHARS(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d)
9 /* increase list size by 10% every time it is full */
10 #define kDefaultAllocationPercentIncrease 10
12 /* always increase list size by 4 items when it is full */
13 #define kDefaultAllocationminNumItemsIncrease 4
16 * how many items to expand the list by when it becomes full
17 * = current listSize (in items) + (hiword percent of list size) + loword
19 #define NUMITEMSPERALLOC(list) MAX(((*list)->listSize * \
20 ((*list)->percentIncrease + 100)) / 100, \
21 (*list)->minNumItemsIncrease )
23 #define ITEMPTR(list,item) &(((char *)&(*list)->itemList)[(*(list))->itemSize * (item)])
25 #define LIST_SIGNATURE CAT4CHARS('L', 'I', 'S', 'T');
27 #define calloc(size,num) malloc(size*num)
29 /********************************************************************/
31 Handle NewHandle (unsigned int numBytes)
36 memPtr = calloc (numBytes, 1);
37 hanPtr = (HandleRecord *) calloc (sizeof (HandleRecord), 1);
38 if (hanPtr && (memPtr || numBytes == 0)) {
40 hanPtr->size = numBytes;
41 return (Handle) hanPtr;
48 /********************************************************************/
50 void DisposeHandle (Handle handle)
54 free ((void *) handle);
57 /********************************************************************/
59 unsigned int GetHandleSize (Handle handle)
61 return ((HandleRecord *) handle)->size;
63 /********************************************************************/
65 int SetHandleSize (Handle handle, unsigned int newSize)
67 HandleRecord *hanRecPtr = (HandleRecord *) handle;
68 void *newPtr, *oldPtr;
72 oldPtr = hanRecPtr->ptr;
73 oldSize = hanRecPtr->size;
75 if (oldSize == newSize)
79 newPtr = malloc (newSize);
81 newPtr = realloc (oldPtr, newSize);
83 if (newPtr || (newSize == 0)) {
84 hanRecPtr->ptr = newPtr;
85 hanRecPtr->size = newSize;
86 if (newSize > oldSize)
87 memset ((char *) newPtr + oldSize, 0, newSize - oldSize);
93 #ifdef CFG_ALL_LIST_FUNCTIONS
95 /* Used to compare list elements by their raw data contents */
96 static int ListMemBlockCmp (void *a, void *b, int size)
98 return memcmp (a, b, size);
101 /***************************************************************************/
104 * Binary search numElements of size elementSize in array for a match
105 * to the. item. Return the index of the element that matches
106 * (0 - numElements - 1). If no match is found return the -i-1 where
107 * i is the index (0 - numElements) where the item should be placed.
108 * (*theCmp)(a,b) should return <0 if a<b, 0 if a==b, >0 if a>b.
110 * This function is like the C-Library function bsearch() except that
111 * this function returns the index where the item should be placed if
114 int BinSearch ( void *array, int numElements, int elementSize,
115 void *itemPtr, CompareFunction compareFunction)
117 int low, high, mid, cmp;
120 for (low = 0, high = numElements - 1, mid = 0, cmp = -1; low <= high;) {
121 mid = (low + high) >> 1;
123 arrayItemPtr = (void *) (((char *) array) + (mid * elementSize));
124 cmp = compareFunction
125 ? compareFunction (itemPtr, arrayItemPtr)
126 : ListMemBlockCmp (itemPtr, arrayItemPtr, elementSize);
129 } else if (cmp < 0) {
141 #endif /* CFG_ALL_LIST_FUNCTIONS */
143 /*******************************************************************************/
146 * If numNewItems == 0 then expand the list by the number of items
147 * indicated by its allocation policy.
148 * If numNewItems > 0 then expand the list by exactly the number of
150 * If numNewItems < 0 then expand the list by the absolute value of
151 * numNewItems plus the number of items indicated by its allocation
153 * Returns 1 for success, 0 if out of memory
155 static int ExpandListSpace (list_t list, int numNewItems)
157 if (numNewItems == 0) {
158 numNewItems = NUMITEMSPERALLOC (list);
159 } else if (numNewItems < 0) {
160 numNewItems = (-numNewItems) + NUMITEMSPERALLOC (list);
163 if (SetHandleSize ((Handle) list,
164 sizeof (ListStruct) +
166 numNewItems) * (*list)->itemSize)) {
167 (*list)->listSize += numNewItems;
174 /*******************************/
176 #ifdef CFG_ALL_LIST_FUNCTIONS
179 * This function reallocate the list, minus any currently unused
180 * portion of its allotted memory.
182 void ListCompact (list_t list)
185 if (!SetHandleSize ((Handle) list,
186 sizeof (ListStruct) +
187 (*list)->numItems * (*list)->itemSize)) {
191 (*list)->listSize = (*list)->numItems;
194 #endif /* CFG_ALL_LIST_FUNCTIONS */
196 /*******************************/
198 list_t ListCreate (int elementSize)
202 list = (list_t) (NewHandle (sizeof (ListStruct))); /* create empty list */
204 (*list)->signature = LIST_SIGNATURE;
205 (*list)->numItems = 0;
206 (*list)->listSize = 0;
207 (*list)->itemSize = elementSize;
208 (*list)->percentIncrease = kDefaultAllocationPercentIncrease;
209 (*list)->minNumItemsIncrease =
210 kDefaultAllocationminNumItemsIncrease;
216 /*******************************/
218 void ListSetAllocationPolicy (list_t list, int minItemsPerAlloc,
219 int percentIncreasePerAlloc)
221 (*list)->percentIncrease = percentIncreasePerAlloc;
222 (*list)->minNumItemsIncrease = minItemsPerAlloc;
225 /*******************************/
227 void ListDispose (list_t list)
229 DisposeHandle ((Handle) list);
231 /*******************************/
233 #ifdef CFG_ALL_LIST_FUNCTIONS
235 void ListDisposePtrList (list_t list)
241 numItems = ListNumItems (list);
243 for (index = 1; index <= numItems; index++)
244 free (*(void **) ListGetPtrToItem (list, index));
250 /*******************************/
253 * keeps memory, resets the number of items to 0
255 void ListClear (list_t list)
259 (*list)->numItems = 0;
262 /*******************************/
265 * copy is only as large as necessary
267 list_t ListCopy (list_t originalList)
269 list_t tempList = NULL;
275 tempList = ListCreate ((*originalList)->itemSize);
277 numItems = ListNumItems (originalList);
279 if (!SetHandleSize ((Handle) tempList,
280 sizeof (ListStruct) +
281 numItems * (*tempList)->itemSize)) {
282 ListDispose (tempList);
286 (*tempList)->numItems = (*originalList)->numItems;
287 (*tempList)->listSize = (*originalList)->numItems;
288 (*tempList)->itemSize = (*originalList)->itemSize;
289 (*tempList)->percentIncrease = (*originalList)->percentIncrease;
290 (*tempList)->minNumItemsIncrease =
291 (*originalList)->minNumItemsIncrease;
293 memcpy (ITEMPTR (tempList, 0), ITEMPTR (originalList, 0),
294 numItems * (*tempList)->itemSize);
300 /********************************/
303 * list1 = list1 + list2
305 int ListAppend (list_t list1, list_t list2)
307 int numItemsL1, numItemsL2;
314 if ((*list1)->itemSize != (*list2)->itemSize)
317 numItemsL1 = ListNumItems (list1);
318 numItemsL2 = ListNumItems (list2);
323 if (!SetHandleSize ((Handle) list1,
324 sizeof (ListStruct) + (numItemsL1 + numItemsL2) *
325 (*list1)->itemSize)) {
329 (*list1)->numItems = numItemsL1 + numItemsL2;
330 (*list1)->listSize = numItemsL1 + numItemsL2;
332 memmove (ITEMPTR (list1, numItemsL1),
334 numItemsL2 * (*list2)->itemSize);
339 #endif /* CFG_ALL_LIST_FUNCTIONS */
341 /*******************************/
344 * returns 1 if the item is inserted, returns 0 if out of memory or
345 * bad arguments were passed.
347 int ListInsertItem (list_t list, void *ptrToItem, int itemPosition)
349 return ListInsertItems (list, ptrToItem, itemPosition, 1);
352 /*******************************/
354 int ListInsertItems (list_t list, void *ptrToItems, int firstItemPosition,
355 int numItemsToInsert)
357 int numItems = (*list)->numItems;
359 if (firstItemPosition == numItems + 1)
360 firstItemPosition = LIST_END;
361 else if (firstItemPosition > numItems)
364 if ((*list)->numItems >= (*list)->listSize) {
365 if (!ExpandListSpace (list, -numItemsToInsert))
369 if (firstItemPosition == LIST_START) {
371 /* special case for empty list */
372 firstItemPosition = LIST_END;
374 firstItemPosition = 1;
378 if (firstItemPosition == LIST_END) { /* add at the end of the list */
380 memcpy (ITEMPTR (list, numItems), ptrToItems,
381 (*list)->itemSize * numItemsToInsert);
383 memset (ITEMPTR (list, numItems), 0,
384 (*list)->itemSize * numItemsToInsert);
386 (*list)->numItems += numItemsToInsert;
387 } else { /* move part of list up to make room for new item */
388 memmove (ITEMPTR (list, firstItemPosition - 1 + numItemsToInsert),
389 ITEMPTR (list, firstItemPosition - 1),
390 (numItems + 1 - firstItemPosition) * (*list)->itemSize);
393 memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems,
394 (*list)->itemSize * numItemsToInsert);
396 memset (ITEMPTR (list, firstItemPosition - 1), 0,
397 (*list)->itemSize * numItemsToInsert);
399 (*list)->numItems += numItemsToInsert;
405 #ifdef CFG_ALL_LIST_FUNCTIONS
407 /*******************************/
409 int ListEqual (list_t list1, list_t list2)
414 if (list1 == NULL || list2 == NULL)
417 if ((*list1)->itemSize == (*list1)->itemSize) {
418 if ((*list1)->numItems == (*list2)->numItems) {
419 return (memcmp (ITEMPTR (list1, 0), ITEMPTR (list2, 0),
420 (*list1)->itemSize * (*list1)->numItems) == 0);
427 /*******************************/
430 * The item pointed to by ptrToItem is copied over the current item
433 void ListReplaceItem (list_t list, void *ptrToItem, int itemPosition)
435 ListReplaceItems (list, ptrToItem, itemPosition, 1);
438 /*******************************/
441 * The item pointed to by ptrToItems is copied over the current item
444 void ListReplaceItems ( list_t list, void *ptrToItems,
445 int firstItemPosition, int numItemsToReplace)
448 if (firstItemPosition == LIST_END)
449 firstItemPosition = (*list)->numItems;
450 else if (firstItemPosition == LIST_START)
451 firstItemPosition = 1;
453 memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems,
454 (*list)->itemSize * numItemsToReplace);
457 /*******************************/
459 void ListGetItem (list_t list, void *itemDestination, int itemPosition)
461 ListGetItems (list, itemDestination, itemPosition, 1);
464 #endif /* CFG_ALL_LIST_FUNCTIONS */
466 /*******************************/
468 #if defined(CFG_ALL_LIST_FUNCTIONS) || defined(CFG_DEVICE_DEREGISTER)
470 void ListRemoveItem (list_t list, void *itemDestination, int itemPosition)
472 ListRemoveItems (list, itemDestination, itemPosition, 1);
475 /*******************************/
477 void ListRemoveItems (list_t list, void *itemsDestination,
478 int firstItemPosition, int numItemsToRemove)
480 int firstItemAfterChunk, numToMove;
482 if (firstItemPosition == LIST_START)
483 firstItemPosition = 1;
484 else if (firstItemPosition == LIST_END)
485 firstItemPosition = (*list)->numItems;
487 if (itemsDestination != NULL)
488 memcpy (itemsDestination, ITEMPTR (list, firstItemPosition - 1),
489 (*list)->itemSize * numItemsToRemove);
491 firstItemAfterChunk = firstItemPosition + numItemsToRemove;
492 numToMove = (*list)->numItems - (firstItemAfterChunk - 1);
496 * move part of list down to cover hole left by removed item
498 memmove (ITEMPTR (list, firstItemPosition - 1),
499 ITEMPTR (list, firstItemAfterChunk - 1),
500 (*list)->itemSize * numToMove);
503 (*list)->numItems -= numItemsToRemove;
505 #endif /* CFG_ALL_LIST_FUNCTIONS || CFG_DEVICE_DEREGISTER */
507 /*******************************/
509 void ListGetItems (list_t list, void *itemsDestination,
510 int firstItemPosition, int numItemsToGet)
513 if (firstItemPosition == LIST_START)
514 firstItemPosition = 1;
515 else if (firstItemPosition == LIST_END)
516 firstItemPosition = (*list)->numItems;
518 memcpy (itemsDestination,
519 ITEMPTR (list, firstItemPosition - 1),
520 (*list)->itemSize * numItemsToGet);
523 /*******************************/
526 * Returns a pointer to the item at itemPosition. returns null if an
529 void *ListGetPtrToItem (list_t list, int itemPosition)
531 if (itemPosition == LIST_START)
533 else if (itemPosition == LIST_END)
534 itemPosition = (*list)->numItems;
536 return ITEMPTR (list, itemPosition - 1);
539 /*******************************/
542 * returns a pointer the lists data (abstraction violation for
545 void *ListGetDataPtr (list_t list)
547 return &((*list)->itemList[0]);
550 /********************************/
552 #ifdef CFG_ALL_LIST_FUNCTIONS
554 int ListApplyToEach (list_t list, int ascending,
555 ListApplicationFunc funcToApply,
558 int result = 0, index;
560 if (!list || !funcToApply)
564 for (index = 1; index <= ListNumItems (list); index++) {
565 result = funcToApply (index,
566 ListGetPtrToItem (list, index),
572 for (index = ListNumItems (list);
573 index > 0 && index <= ListNumItems (list);
575 result = funcToApply (index,
576 ListGetPtrToItem (list, index),
587 #endif /* CFG_ALL_LIST_FUNCTIONS */
589 /********************************/
591 int ListGetItemSize (list_t list)
593 return (*list)->itemSize;
596 /********************************/
598 int ListNumItems (list_t list)
600 return (*list)->numItems;
603 /*******************************/
605 #ifdef CFG_ALL_LIST_FUNCTIONS
607 void ListRemoveDuplicates (list_t list, CompareFunction compareFunction)
609 int numItems, index, startIndexForFind, duplicatesIndex;
611 numItems = ListNumItems (list);
613 for (index = 1; index < numItems; index++) {
614 startIndexForFind = index + 1;
615 while (startIndexForFind <= numItems) {
618 ListGetPtrToItem (list, index),
621 if (duplicatesIndex > 0) {
622 ListRemoveItem (list, NULL, duplicatesIndex);
624 startIndexForFind = duplicatesIndex;
632 /*******************************/
635 /*******************************/
637 int ListFindItem (list_t list, void *ptrToItem, int startingPosition,
638 CompareFunction compareFunction)
640 int numItems, size, index, cmp;
643 if ((numItems = (*list)->numItems) == 0)
646 size = (*list)->itemSize;
648 if (startingPosition == LIST_START)
649 startingPosition = 1;
650 else if (startingPosition == LIST_END)
651 startingPosition = numItems;
653 for (index = startingPosition; index <= numItems; index++) {
654 listItemPtr = ITEMPTR (list, index - 1);
655 cmp = compareFunction
656 ? compareFunction (ptrToItem, listItemPtr)
657 : ListMemBlockCmp (ptrToItem, listItemPtr, size);
665 /*******************************/
667 int ShortCompare (void *a, void *b)
669 if (*(short *) a < *(short *) b)
671 if (*(short *) a > *(short *) b)
676 /*******************************/
678 int IntCompare (void *a, void *b)
680 if (*(int *) a < *(int *) b)
682 if (*(int *) a > *(int *) b)
687 /*******************************/
689 int CStringCompare (void *a, void *b)
691 return strcmp (*(char **) a, *(char **) b);
694 /*******************************/
697 int ListBinSearch (list_t list, void *ptrToItem,
698 CompareFunction compareFunction)
702 index = BinSearch (ITEMPTR (list, 0),
703 (int) (*list)->numItems,
704 (int) (*list)->itemSize, ptrToItem,
708 index++; /* lists start from 1 */
710 index = 0; /* item not found */
715 /**************************************************************************/
718 * Reserves memory for numItems in the list. If it succeeds then
719 * numItems items can be inserted without possibility of an out of
720 * memory error (useful to simplify error recovery in complex
721 * functions). Returns 1 if success, 0 if out of memory.
723 int ListPreAllocate (list_t list, int numItems)
725 if ((*list)->listSize - (*list)->numItems < numItems) {
726 return ExpandListSpace (list,
727 numItems - ((*list)->listSize -
730 return 1; /* enough items are already pre-allocated */
734 #endif /* CFG_ALL_LIST_FUNCTIONS */