2 * NOTICE and LICENSE for Tecplot Input/Output Library (TecIO) - OpenFOAM
4 * Copyright (C) 1988-2009 Tecplot, Inc. All rights reserved worldwide.
6 * Tecplot hereby grants OpenCFD limited authority to distribute without
7 * alteration the source code to the Tecplot Input/Output library, known
8 * as TecIO, as part of its distribution of OpenFOAM and the
9 * OpenFOAM_to_Tecplot converter. Users of this converter are also hereby
10 * granted access to the TecIO source code, and may redistribute it for the
11 * purpose of maintaining the converter. However, no authority is granted
12 * to alter the TecIO source code in any form or manner.
14 * This limited grant of distribution does not supersede Tecplot, Inc.'s
15 * copyright in TecIO. Contact Tecplot, Inc. for further information.
18 * 3535 Factoria Blvd, Ste. 550
19 * Bellevue, WA 98006, USA
20 * Phone: +1 425 653 1200
21 * http://www.tecplot.com/
26 #define TECPLOTENGINEMODULE
29 *****************************************************************
30 *****************************************************************
32 ****** Copyright (C) 1988-2008 Tecplot, Inc. ********
33 ******* All Rights Reserved. ********
35 *****************************************************************
36 *****************************************************************
43 #if defined TECPLOTKERNEL
44 /* CORE SOURCE CODE REMOVED */
48 #if defined TECPLOTKERNEL
49 /* CORE SOURCE CODE REMOVED */
55 * This general purpose list uses an array implementation. The high use member
56 * functions have macro covers to make the implementation both efficient with
57 * respect to speed without compromising the internal representation. The
58 * internal array is allocated to fit the requested type's item size. Most
59 * intrinsic 'C' and Tecplot types are available.
64 * Copies the private array items from the specified source to the target
65 * location. The buffers may overlap.
68 * Originally this function was a macro that called memmove
71 * #define CopyArrayItems(TargetArray, TargetOffset, \
72 * SourceArray, SourceOffset, \
74 * (memmove(&((TargetArray)[(TargetOffset)*ItemSize]), \
75 * &((SourceArray)[(SourceOffset)*ItemSize]), \
78 * This however proved troublesome as some machines replaced the memmove
79 * with a call to memcpy in the linker. The memcpy function does not support
80 * overlapping moves so I could not use it. This function should be just
81 * about as fast however so it is no big deal.
84 * Base address of the target array to receive the items.
86 * Target offset of the first item.
88 * Base address of the source array supplying the items.
90 * Source offset of the first item.
92 * Number of items to copy.
96 static void CopyArrayItems(char *TargetArray
,
97 LgIndex_t TargetOffset
,
99 LgIndex_t SourceOffset
,
101 SmInteger_t ItemSize
)
103 REQUIRE(VALID_REF(TargetArray
));
104 REQUIRE(TargetOffset
>= 0);
105 REQUIRE(VALID_REF(SourceArray
));
106 REQUIRE(SourceOffset
>= 0);
107 REQUIRE(&TargetArray
[TargetOffset
] != &SourceArray
[SourceOffset
]);
109 REQUIRE(1 <= ItemSize
&& ItemSize
<= (SmInteger_t
)sizeof(ArrayListItem_u
));
111 void* TargetPtr
= &TargetArray
[TargetOffset
* ItemSize
];
112 void* SourcePtr
= &SourceArray
[SourceOffset
* ItemSize
];
113 memmove(TargetPtr
, SourcePtr
, ((size_t)Count
) * ItemSize
);
118 * Adjusts the capacity request as necessary to minimize memory reallocations
119 * for large lists. Unless the request exceeds the maximum the adjusted
120 * capacity will be at least as big as requested however it may be larger if it
121 * is determined that the space requirement is growing faster. If the maximum
122 * is exceeded zero should be returned.
125 * Array list requesting the change in capacity.
126 * param CurrentCapacity
127 * Current capacity of the array list.
128 * param RequestedCapacity
129 * Capacity request or zero for default size.
131 * Any client data needed for the adjustment.
134 * Adjusted capacity that is at least as large as the request or zero if
135 * unable to satisfy the requested capacity.
137 static LgIndex_t
AdjustCapacityRequest(ArrayList_pa ArrayList
,
138 LgIndex_t CurrentCapacity
,
139 LgIndex_t RequestedCapacity
,
140 ArbParam_t ClientData
)
144 REQUIRE(ArrayListIsValid(ArrayList
));
145 REQUIRE((RequestedCapacity
== 0 && CurrentCapacity
== 0) ||
146 RequestedCapacity
> CurrentCapacity
);
148 if (RequestedCapacity
!= 0 && CurrentCapacity
== 0)
150 /* first allocation; assume the request is the desired capacityy */
151 Result
= RequestedCapacity
;
155 const LgIndex_t DEFAULT_CAPACITY
= 32;
156 LgIndex_t BlockSize
= MAX(DEFAULT_CAPACITY
, CurrentCapacity
/ 2);
157 if (RequestedCapacity
== 0)
158 Result
= DEFAULT_CAPACITY
;
160 Result
= ((RequestedCapacity
- 1) / BlockSize
+ 1) * BlockSize
;
163 ENSURE(Result
== 0 || Result
>= RequestedCapacity
);
169 * Gets the size of an individual element.
172 * Array list element type.
175 * Element size corresponding to the type.
177 static SmInteger_t
GetElementSize(ArrayListType_e Type
)
181 REQUIRE(VALID_ENUM(Type
, ArrayListType_e
));
185 case ArrayListType_UnsignedChar
:
186 Result
= (SmInteger_t
)sizeof(unsigned char);
188 case ArrayListType_UnsignedShort
:
189 Result
= (SmInteger_t
)sizeof(unsigned short);
191 case ArrayListType_UnsignedInt
:
192 Result
= (SmInteger_t
)sizeof(unsigned int);
194 case ArrayListType_UnsignedLong
:
195 Result
= (SmInteger_t
)sizeof(unsigned long);
197 case ArrayListType_Int64
:
198 Result
= (SmInteger_t
)sizeof(Int64_t
);
200 case ArrayListType_Char
:
201 Result
= (SmInteger_t
)sizeof(char);
203 case ArrayListType_Short
:
204 Result
= (SmInteger_t
)sizeof(short);
206 case ArrayListType_Int
:
207 Result
= (SmInteger_t
)sizeof(int);
209 case ArrayListType_Long
:
210 Result
= (SmInteger_t
)sizeof(long);
212 case ArrayListType_Float
:
213 Result
= (SmInteger_t
)sizeof(float);
215 case ArrayListType_Double
:
216 Result
= (SmInteger_t
)sizeof(double);
218 case ArrayListType_LgIndex
:
219 Result
= (SmInteger_t
)sizeof(LgIndex_t
);
221 case ArrayListType_EntIndex
:
222 Result
= (SmInteger_t
)sizeof(EntIndex_t
);
224 case ArrayListType_SmInteger
:
225 Result
= (SmInteger_t
)sizeof(SmInteger_t
);
227 case ArrayListType_Boolean
:
228 Result
= (SmInteger_t
)sizeof(Boolean_t
);
230 case ArrayListType_ArbParam
:
231 Result
= (SmInteger_t
)sizeof(ArbParam_t
);
234 case ArrayListType_UnsignedCharPtr
:
235 Result
= (SmInteger_t
)sizeof(unsigned char *);
237 case ArrayListType_UnsignedShortPtr
:
238 Result
= (SmInteger_t
)sizeof(unsigned short *);
240 case ArrayListType_UnsignedIntPtr
:
241 Result
= (SmInteger_t
)sizeof(unsigned int *);
243 case ArrayListType_UnsignedLongPtr
:
244 Result
= (SmInteger_t
)sizeof(unsigned long *);
246 case ArrayListType_Int64Ptr
:
247 Result
= (SmInteger_t
)sizeof(Int64_t
*);
249 case ArrayListType_CharPtr
:
250 Result
= (SmInteger_t
)sizeof(char *);
252 case ArrayListType_ShortPtr
:
253 Result
= (SmInteger_t
)sizeof(short *);
255 case ArrayListType_IntPtr
:
256 Result
= (SmInteger_t
)sizeof(int *);
258 case ArrayListType_LongPtr
:
259 Result
= (SmInteger_t
)sizeof(long *);
261 case ArrayListType_FloatPtr
:
262 Result
= (SmInteger_t
)sizeof(float *);
264 case ArrayListType_DoublePtr
:
265 Result
= (SmInteger_t
)sizeof(double *);
267 case ArrayListType_LgIndexPtr
:
268 Result
= (SmInteger_t
)sizeof(LgIndex_t
*);
270 case ArrayListType_EntIndexPtr
:
271 Result
= (SmInteger_t
)sizeof(EntIndex_t
*);
273 case ArrayListType_SmIntegerPtr
:
274 Result
= (SmInteger_t
)sizeof(SmInteger_t
*);
276 case ArrayListType_BooleanPtr
:
277 Result
= (SmInteger_t
)sizeof(Boolean_t
*);
279 case ArrayListType_ArbParamPtr
:
280 Result
= (SmInteger_t
)sizeof(ArbParam_t
*);
283 case ArrayListType_VoidPtr
:
284 Result
= (SmInteger_t
)sizeof(void *);
286 case ArrayListType_FunctionPtr
:
287 Result
= (SmInteger_t
)sizeof(void (*)());
289 case ArrayListType_Any
: /* allows a mixed bag of items */
290 Result
= (SmInteger_t
)sizeof(ArrayListItem_u
);
294 Result
= 0; /* make some compilers happy. */
299 ENSURE(1 <= Result
&& Result
<= (SmInteger_t
)sizeof(ArrayListItem_u
));
305 * Calls the item destructor for each item specified.
308 * Array list needing its items destroyed.
310 * Offset to the first item to destroy in the list.
312 * Size of each array list item.
314 * Number of items to destroy.
315 * param ItemDestructor
316 * Function called for each array list item.
318 * Any client data needed for the destructor.
320 static void DestroyItems(ArrayList_pa ArrayList
,
321 LgIndex_t ItemOffset
,
322 SmInteger_t ItemSize
,
324 ArrayListItemDestructor_pf ItemDestructor
,
325 ArbParam_t ClientData
)
329 REQUIRE(ArrayListIsValid(ArrayList
));
330 REQUIRE(0 <= ItemOffset
&& ItemOffset
<= ArrayList
->Count
- 1);
331 REQUIRE(1 <= Count
&& ItemOffset
+ Count
<= ArrayList
->Count
);
332 REQUIRE(VALID_FN_REF(ItemDestructor
));
338 LgIndex_t ItemIndex
= (Index
+ ItemOffset
) * ItemSize
;
339 #if !defined NO_ASSERTS
340 Boolean_t DoContinue
= ItemDestructor((void *) & ArrayList
->Array
[ItemIndex
], ClientData
);
341 CHECK(DoContinue
); /* this is a requirement of ArrayListItemDestructor_pf */
343 ItemDestructor((void *)&ArrayList
->Array
[ItemIndex
], ClientData
);
350 * Calls the item duplicator for each item specified.
353 * Target array needing its items duplicated.
354 * param TargetItemOffset
355 * Target offset to the first duplicated item.
357 * Source array needing its items duplicated.
358 * param SourceItemOffset
359 * Source offset to the first item to duplicate in the list.
361 * Size of each array list item.
363 * Number of items to duplicate.
364 * param ItemDuplicator
365 * Function called for each array list item.
367 * Any client data needed for the destructor.
370 * TRUE if the duplication was a success
373 static Boolean_t
DuplicateItems(char *TargetArray
,
374 LgIndex_t TargetItemOffset
,
376 LgIndex_t SourceItemOffset
,
377 SmInteger_t ItemSize
,
379 ArrayListItemDuplicator_pf ItemDuplicator
,
380 ArbParam_t ClientData
)
382 Boolean_t IsOk
= TRUE
;
385 REQUIRE(VALID_REF(TargetArray
));
386 REQUIRE(TargetItemOffset
>= 0);
387 REQUIRE(VALID_REF(SourceArray
));
388 REQUIRE(SourceItemOffset
>= 0);
389 REQUIRE(1 <= ItemSize
&&
390 ItemSize
<= (SmInteger_t
)sizeof(ArrayListItem_u
));
392 REQUIRE(VALID_FN_REF(ItemDuplicator
));
395 Index
< Count
&& IsOk
;
398 LgIndex_t TargetItemIndex
= (Index
+ TargetItemOffset
) * ItemSize
;
399 LgIndex_t SourceItemIndex
= (Index
+ SourceItemOffset
) * ItemSize
;
400 IsOk
= ItemDuplicator((void *) & TargetArray
[TargetItemIndex
],
401 (void *) & SourceArray
[SourceItemIndex
],
405 ENSURE(VALID_BOOLEAN(IsOk
));
411 * Determine if the list handle is sane.
414 * Array list in question.
417 * TRUE if the array list is valid, otherwise FALSE.
419 Boolean_t
ArrayListIsValid(ArrayList_pa ArrayList
)
423 /* this just makes sure that the NULL item global was initialized */
424 INVARIANT(ArrayListNullItem
.Double
== 0.0);
426 IsValid
= (VALID_REF(ArrayList
) &&
427 VALID_ENUM(ArrayList
->Type
, ArrayListType_e
) &&
428 (1 <= ArrayList
->ItemSize
&&
429 ArrayList
->ItemSize
<= (SmInteger_t
)sizeof(ArrayListItem_u
)) &&
430 (0 <= ArrayList
->Count
&&
431 ArrayList
->Count
<= ArrayList
->Capacity
));
433 ENSURE(VALID_BOOLEAN(IsValid
));
439 * Gets the specified array list's type.
442 * Array list of which the type is desired.
447 ArrayListType_e
ArrayListGetType(ArrayList_pa ArrayList
)
449 ArrayListType_e Result
;
451 REQUIRE(ArrayListIsValid(ArrayList
));
453 Result
= ArrayList
->Type
;
455 ENSURE(VALID_ENUM(Result
, ArrayListType_e
));
461 * Enlarge the list capacity to accommodate, at a minimum, the requested
462 * capacity (number of items). The enlarged section is initialized with zeros.
463 * This function can be called by clients who want to ensure that calls to
464 * the ArrayListSetXxx class of functions will never fail for offsets within
465 * the RequestedCapacity.
468 * Current capacity used as a helpful hint for the adjustment algorythm.
469 * param RequestedCapacity
470 * Capacity (number ot items) request or zero for default size.
473 * TRUE if the list could be enlarged (or was large enough),
476 Boolean_t
ArrayListEnlargeCapacity(ArrayList_pa ArrayList
,
477 LgIndex_t RequestedCapacity
)
480 LgIndex_t AdjustedCapacity
;
483 REQUIRE(ArrayListIsValid(ArrayList
));
484 REQUIRE(IMPLICATION(RequestedCapacity
== 0, ArrayList
->Capacity
== 0));
486 if (RequestedCapacity
== 0 ||
487 RequestedCapacity
> ArrayList
->Capacity
)
490 ArrayList
->CapacityRequestAdjuster(ArrayList
,
493 ArrayList
->CapacityRequestAdjusterClientData
);
494 CHECK(AdjustedCapacity
== 0 ||
495 AdjustedCapacity
>= RequestedCapacity
);
497 IsOk
= (AdjustedCapacity
!= 0); /* ...were we able to meet the request? */
500 EnlargedArray
= ALLOC_ARRAY(AdjustedCapacity
* ArrayList
->ItemSize
,
502 if (EnlargedArray
== NULL
)
504 /* try again with minimum capacity request */
505 if (RequestedCapacity
!= 0)
506 AdjustedCapacity
= RequestedCapacity
;
508 AdjustedCapacity
= 1; /* can't get smaller than this */
509 EnlargedArray
= ALLOC_ARRAY(AdjustedCapacity
* ArrayList
->ItemSize
,
512 IsOk
= (EnlargedArray
!= NULL
);
518 * Initialize the expanded section of the array with zeros. This default
519 * value of zero is necessary for many other array list operations.
521 memset(&EnlargedArray
[ArrayList
->Count
*ArrayList
->ItemSize
], 0,
522 (AdjustedCapacity
- ArrayList
->Count
)*ArrayList
->ItemSize
);
524 if (ArrayList
->Array
!= NULL
)
526 if (ArrayList
->Count
!= 0)
527 CopyArrayItems(EnlargedArray
, 0,
530 ArrayList
->ItemSize
);
531 FREE_ARRAY(ArrayList
->Array
, "array list");
534 ArrayList
->Array
= EnlargedArray
;
535 ArrayList
->Capacity
= AdjustedCapacity
;
543 ENSURE(ArrayListIsValid(ArrayList
));
544 ENSURE(VALID_BOOLEAN(IsOk
));
550 * Allocates an array list handle with the estimated capacity
551 * or a suitable default if an estimate is unavailable.
553 * param EstimatedCapacity
554 * Clients best guess at the estimated capacity (number of items) needed.
555 * If an estimate is not available zero the zero should be used to get the
558 * Type of array list being allocated.
559 * param CapacityRequestAdjuster
560 * Function to use to adjust any capacity change requests or
561 * NULL if the default adjuster is good enough.
562 * param CapacityRequestAdjusterClientData
563 * Any client data needed for the capacity adjustment.
566 * Array list handle if sufficient memory was available,
567 * otherwise a handle to NULL.
569 ArrayList_pa
ArrayListAlloc(LgIndex_t EstimatedCapacity
,
570 ArrayListType_e Type
,
571 ArrayListCapacityRequestAdjuster_pf CapacityRequestAdjuster
,
572 ArbParam_t CapacityRequestAdjusterClientData
)
576 REQUIRE(EstimatedCapacity
>= 0);
577 REQUIRE(VALID_ENUM(Type
, ArrayListType_e
));
579 Result
= ALLOC_ITEM(ArrayList_s
, "ArrayList structure");
582 Result
->Array
= NULL
;
584 Result
->ItemSize
= GetElementSize(Type
);
586 Result
->Capacity
= 0;
587 Result
->IsVisitingItems
= FALSE
;
588 if (CapacityRequestAdjuster
!= NULL
)
590 /* install the client's capacity request adjuster */
591 Result
->CapacityRequestAdjuster
= CapacityRequestAdjuster
;
592 Result
->CapacityRequestAdjusterClientData
= CapacityRequestAdjusterClientData
;
596 /* install the default capacity request adjuster */
597 Result
->CapacityRequestAdjuster
= AdjustCapacityRequest
;
598 Result
->CapacityRequestAdjusterClientData
= 0;
601 /* enalarge the list to the estimated capacity */
602 if (!ArrayListEnlargeCapacity(Result
, EstimatedCapacity
))
603 ArrayListDealloc(&Result
, NULL
, 0);
606 ENSURE(ArrayListIsValid(Result
) || Result
== NULL
);
607 ENSURE(IMPLICATION(Result
!= NULL
, Result
->Capacity
>= EstimatedCapacity
));
613 * Deallocates the list handle and set the handle to NULL.
616 * Reference to an array list handle.
617 * param ItemDestructor
618 * Destructor responsible for array list item cleanup or
619 * NULL if no item cleanup is desired.
621 * Any client data needed for cleanup.
623 void ArrayListDealloc(ArrayList_pa
*ArrayList
,
624 ArrayListItemDestructor_pf ItemDestructor
,
625 ArbParam_t ClientData
)
627 REQUIRE(VALID_REF(ArrayList
));
628 REQUIRE(ArrayListIsValid(*ArrayList
) || *ArrayList
== NULL
);
629 REQUIRE(VALID_FN_REF(ItemDestructor
) || ItemDestructor
== NULL
);
631 if (*ArrayList
!= NULL
)
633 /* request item cleanup if a destructor was supplied */
634 if (ItemDestructor
!= NULL
&& (*ArrayList
)->Count
!= 0)
635 DestroyItems(*ArrayList
, 0, (*ArrayList
)->ItemSize
, (*ArrayList
)->Count
,
636 ItemDestructor
, ClientData
);
638 /* release the list */
639 if ((*ArrayList
)->Capacity
!= 0)
640 FREE_ARRAY((*ArrayList
)->Array
, "array list");
642 /* release the list structure itself */
643 FREE_ITEM(*ArrayList
, "ArrayList structure");
647 ENSURE(*ArrayList
== NULL
);
651 #if !defined USE_MACROS_FOR_FUNCTIONS
653 * Gets the number of items currently maintained by the list.
656 * Array list in question.
659 * Number of items maintained by the list.
661 LgIndex_t
ArrayListGetCount_FUNC(ArrayList_pa ArrayList
)
665 REQUIRE(ArrayListIsValid(ArrayList
));
667 Result
= ArrayListGetCount_MACRO(ArrayList
);
676 * Empties the array list of all items.
679 * Array list from which to delete all items.
680 * param ItemDestructor
681 * Destructor responsible for array list item cleanup or
682 * NULL if no item cleanup is desired.
684 * Any client data needed for cleanup.
686 void ArrayListDeleteAllItems(ArrayList_pa ArrayList
,
687 ArrayListItemDestructor_pf ItemDestructor
,
688 ArbParam_t ClientData
)
690 REQUIRE(ArrayListIsValid(ArrayList
));
691 REQUIRE(VALID_FN_REF(ItemDestructor
) || ItemDestructor
== NULL
);
692 REQUIRE(!ArrayList
->IsVisitingItems
);
694 /* request item cleanup if a destructor was supplied */
695 if (ItemDestructor
!= NULL
&& ArrayList
->Count
!= 0)
696 DestroyItems(ArrayList
, 0, ArrayList
->ItemSize
, ArrayList
->Count
,
697 ItemDestructor
, ClientData
);
700 * Fill the vacated items with zeros. This default value of zero is necessary
701 * for many other array list operations.
703 if (ArrayList
->Count
!= 0)
704 memset(&ArrayList
->Array
[0], 0, ArrayList
->Count
*ArrayList
->ItemSize
);
706 ArrayList
->Count
= 0;
708 ENSURE(ArrayListIsValid(ArrayList
) && ArrayList
->Count
== 0);
713 * Deletes 'Count' items from the array list. The members following the
714 * items deleted are shifted down accordingly to fill the vacated space.
717 * Array list containing the items to delete.
719 * Offset to the first item to delete in the list.
721 * Number of items to delete.
722 * param ItemDestructor
723 * Destructor responsible for array list item cleanup or
724 * NULL if no item cleanup is desired.
726 * Any client data needed for cleanup.
728 void ArrayListDeleteItems(ArrayList_pa ArrayList
,
729 LgIndex_t ItemOffset
,
731 ArrayListItemDestructor_pf ItemDestructor
,
732 ArbParam_t ClientData
)
734 REQUIRE(ArrayListIsValid(ArrayList
));
735 REQUIRE(0 <= ItemOffset
&& ItemOffset
<= ArrayList
->Count
- 1);
736 REQUIRE(1 <= Count
&& ItemOffset
+ Count
<= ArrayList
->Count
);
737 REQUIRE(VALID_FN_REF(ItemDestructor
) || ItemDestructor
== NULL
);
738 REQUIRE(!ArrayList
->IsVisitingItems
);
740 /* release the items if a destructor is installed */
741 if (ItemDestructor
!= NULL
)
742 DestroyItems(ArrayList
, ItemOffset
, ArrayList
->ItemSize
, Count
,
743 ItemDestructor
, ClientData
);
745 /* if we deleted the items from the middle of the array then */
746 /* shift the end items down by 'Count' to fill the vacated space */
747 if (ItemOffset
+ Count
< ArrayList
->Count
)
748 CopyArrayItems(ArrayList
->Array
, ItemOffset
,
749 ArrayList
->Array
, ItemOffset
+ Count
,
750 ArrayList
->Count
- (ItemOffset
+ Count
),
751 ArrayList
->ItemSize
);
753 * Fill the vacated items with zeros. This default value of zero is necessary
754 * for many other array list operations.
756 memset(&ArrayList
->Array
[(ArrayList
->Count
- Count
)*ArrayList
->ItemSize
],
757 0, Count
*ArrayList
->ItemSize
);
759 /* update the count but leave the capacity alone */
760 ArrayList
->Count
-= Count
;
762 ENSURE(ArrayListIsValid(ArrayList
));
767 * Deletes an item from the array list. The members following the item
768 * deleted are shifted down accordingly to fill the vacated space.
771 * Array list containing the item to delete.
773 * Offset to the item in the list.
774 * param ItemDestructor
775 * Destructor responsible for array list item cleanup or
776 * NULL if no item cleanup is desired.
778 * Any client data needed for cleanup.
780 void ArrayListDeleteItem(ArrayList_pa ArrayList
,
781 LgIndex_t ItemOffset
,
782 ArrayListItemDestructor_pf ItemDestructor
,
783 ArbParam_t ClientData
)
785 REQUIRE(ArrayListIsValid(ArrayList
));
786 REQUIRE(0 <= ItemOffset
&& ItemOffset
<= ArrayList
->Count
- 1);
787 REQUIRE(VALID_FN_REF(ItemDestructor
) || ItemDestructor
== NULL
);
789 ArrayListDeleteItems(ArrayList
, ItemOffset
, 1, ItemDestructor
, ClientData
);
791 ENSURE(ArrayListIsValid(ArrayList
));
796 * Removes 'Count' items from the array list beginning at the specified
797 * item offset. The members following the items removed are shifted down
798 * accordingly to fill the vacated space.
801 * Array list containing the items to remove.
803 * Offset to the first item to remove in the list.
805 * Number of items to remove.
808 * Array list handle referring to the removed items if sufficient
809 * memory was available, otherwise a handle to NULL.
811 ArrayList_pa
ArrayListRemoveItems(ArrayList_pa ArrayList
,
812 LgIndex_t ItemOffset
,
817 REQUIRE(ArrayListIsValid(ArrayList
));
818 REQUIRE(0 <= ItemOffset
&& ItemOffset
<= ArrayList
->Count
- 1);
819 REQUIRE(1 <= Count
&& ItemOffset
+ Count
<= ArrayList
->Count
);
820 REQUIRE(!ArrayList
->IsVisitingItems
);
822 /* get a copy of the items and delete them from the source */
823 Result
= ArrayListGetItems(ArrayList
, ItemOffset
, Count
);
825 ArrayListDeleteItems(ArrayList
, ItemOffset
, Count
, NULL
, 0);
827 ENSURE(ArrayListIsValid(ArrayList
));
828 ENSURE(ArrayListIsValid(Result
) || Result
== NULL
);
834 * Removes an item from the array list. The members following the item
835 * removed are shifted down accordingly to fill the vacated space.
838 * Array list containing the item to remove.
840 * Offset to the item in the list.
843 * Item removed from the array list.
845 ArrayListItem_u
ArrayListRemoveItem(ArrayList_pa ArrayList
,
846 LgIndex_t ItemOffset
)
848 ArrayListItem_u Result
;
850 REQUIRE(ArrayListIsValid(ArrayList
));
851 REQUIRE(0 <= ItemOffset
&& ItemOffset
<= ArrayList
->Count
- 1);
852 REQUIRE(!ArrayList
->IsVisitingItems
);
854 /* record the original item */
855 CopyArrayItems((char *)&Result
, 0,
856 ArrayList
->Array
, ItemOffset
,
857 1, ArrayList
->ItemSize
);
859 /* delete the item from the array */
860 ArrayListDeleteItems(ArrayList
, ItemOffset
, 1, NULL
, 0);
862 ENSURE(ArrayListIsValid(ArrayList
));
868 * Inserts copies of the items from the source list to the target list at
869 * the specified offset. The target list will expand to accommodate the
870 * additional items. The source list remains unchanged.
873 * Array list receiving the source items.
875 * Offset at which to insert the source list items.
877 * Array list supplying the source items.
880 * TRUE if sufficient memory permitted the operation, otherwise FALSE.
882 Boolean_t
ArrayListInsert(ArrayList_pa Target
,
883 LgIndex_t ItemOffset
,
886 Boolean_t IsOk
= TRUE
;
888 REQUIRE(ArrayListIsValid(Target
));
889 REQUIRE(ItemOffset
>= 0);
890 REQUIRE(ArrayListIsValid(Source
));
891 REQUIRE(Target
!= Source
);
892 REQUIRE(Target
->Type
== Source
->Type
);
893 REQUIRE(!Target
->IsVisitingItems
);
895 if (Source
->Count
!= 0)
897 LgIndex_t NeededCapacity
;
899 /* if necessary enlarge the target list to accommodate the request */
900 if (ItemOffset
> Target
->Count
)
901 NeededCapacity
= ItemOffset
+ Source
->Count
;
903 NeededCapacity
= Target
->Count
+ Source
->Count
;
904 if (NeededCapacity
> Target
->Capacity
)
905 IsOk
= ArrayListEnlargeCapacity(Target
, NeededCapacity
);
909 if (ItemOffset
< Target
->Count
)
911 /* shift all items in the target list ahead of the */
912 /* insert position up by the number of items in the */
913 /* source list to make room for the new items */
914 CopyArrayItems(Target
->Array
, ItemOffset
+ Source
->Count
,
915 Target
->Array
, ItemOffset
,
916 Target
->Count
- ItemOffset
,
918 Target
->Count
+= Source
->Count
;
922 /* no shifting to do, just update the count */
923 if (ItemOffset
> Target
->Count
)
924 Target
->Count
= ItemOffset
+ Source
->Count
;
926 Target
->Count
+= Source
->Count
;
929 /* insert the items and update the count */
930 CopyArrayItems(Target
->Array
, ItemOffset
,
932 Source
->Count
, Source
->ItemSize
);
936 ENSURE(ArrayListIsValid(Target
));
937 ENSURE(VALID_BOOLEAN(IsOk
));
943 * Inserts the item into the array list at the specified offset. The list will
944 * be expanded to accommodate the additional item. If the offset is beyond the
945 * end of the list it is sized accordingly and the intervening items between
946 * the last item of the original state and the last item of the new state are
947 * guaranteed to be 0.
950 * Array list target in which to insert the item.
952 * Offset at which to insert the item.
954 * Item to insert at the specified offset.
957 * TRUE if sufficient memory permitted the operation, otherwise FALSE.
959 Boolean_t
ArrayListInsertItem(ArrayList_pa ArrayList
,
960 LgIndex_t ItemOffset
,
961 ArrayListItem_u Item
)
963 Boolean_t IsOk
= TRUE
;
964 LgIndex_t NeededCapacity
;
966 REQUIRE(ArrayListIsValid(ArrayList
));
967 REQUIRE(ItemOffset
>= 0);
968 REQUIRE(!ArrayList
->IsVisitingItems
);
970 /* if necessary enlarge the list to accommodate the request */
971 if (ItemOffset
> ArrayList
->Count
)
972 NeededCapacity
= ItemOffset
+ 1;
974 NeededCapacity
= ArrayList
->Count
+ 1;
975 if (NeededCapacity
> ArrayList
->Capacity
)
976 IsOk
= ArrayListEnlargeCapacity(ArrayList
, NeededCapacity
);
980 if (ItemOffset
< ArrayList
->Count
)
982 /* shift all items in the target list ahead of the insert */
983 /* position up by one to make room for the new item */
984 CopyArrayItems(ArrayList
->Array
, ItemOffset
+ 1,
985 ArrayList
->Array
, ItemOffset
,
986 ArrayList
->Count
- ItemOffset
,
987 ArrayList
->ItemSize
);
992 /* no shifting to do, just update the count */
993 if (ItemOffset
> ArrayList
->Count
)
994 ArrayList
->Count
= ItemOffset
+ 1;
999 /* insert the item */
1000 CopyArrayItems(ArrayList
->Array
, ItemOffset
,
1002 1, ArrayList
->ItemSize
);
1005 ENSURE(ArrayListIsValid(ArrayList
));
1006 ENSURE(VALID_BOOLEAN(IsOk
));
1012 * Visits array list items calling the item visitor for each item.
1015 * Array list needing its items destroyed.
1017 * Offset to the first item to visit from the list.
1019 * Number of items to visit.
1021 * Function called for each array list item.
1023 * Any client data needed for the visitor.
1026 * TRUE if the all element were visited, otherwise
1027 * FALSE if the visitation was terminated early
1029 Boolean_t
ArrayListVisitItems(ArrayList_pa ArrayList
,
1030 LgIndex_t ItemOffset
,
1032 ArrayListItemVisitor_pf ItemVisitor
,
1033 ArbParam_t ClientData
)
1035 Boolean_t DoContinue
= TRUE
;
1036 Boolean_t IsVisitingItems
;
1037 SmInteger_t ItemSize
;
1040 REQUIRE(ArrayListIsValid(ArrayList
));
1041 REQUIRE(VALID_FN_REF(ItemVisitor
));
1043 IsVisitingItems
= ArrayList
->IsVisitingItems
;
1044 ArrayList
->IsVisitingItems
= TRUE
; /* guards against structure changes */
1046 for (Index
= 0, ItemSize
= ArrayList
->ItemSize
;
1047 Index
< Count
&& DoContinue
;
1050 LgIndex_t ItemIndex
= (Index
+ ItemOffset
) * ItemSize
;
1051 DoContinue
= ItemVisitor((void *) & ArrayList
->Array
[ItemIndex
], ClientData
);
1054 ArrayList
->IsVisitingItems
= IsVisitingItems
;
1056 ENSURE(ArrayList
->IsVisitingItems
== IsVisitingItems
);
1057 ENSURE(VALID_BOOLEAN(DoContinue
));
1063 * Gets copies of 'Count' items from the array list beginning at the
1064 * specified item offset. Note that if the items are pointer types
1065 * the copies are of the pointers and not the pointees.
1068 * Array list containing the items to copy.
1070 * Offset to the first item to copy from the list.
1072 * Number of items to copy.
1075 * Array list handle referring to the copied items if sufficient
1076 * memory was available, otherwise a handle to NULL.
1078 ArrayList_pa
ArrayListGetItems(ArrayList_pa ArrayList
,
1079 LgIndex_t ItemOffset
,
1082 ArrayList_pa Result
;
1084 REQUIRE(ArrayListIsValid(ArrayList
));
1085 REQUIRE(0 <= ItemOffset
&& ItemOffset
<= ArrayList
->Count
- 1);
1086 REQUIRE(1 <= Count
&& ItemOffset
+ Count
<= ArrayList
->Count
);
1088 Result
= ArrayListAlloc(Count
, ArrayList
->Type
,
1089 ArrayList
->CapacityRequestAdjuster
,
1090 ArrayList
->CapacityRequestAdjusterClientData
);
1093 /* copy the original items into the result */
1094 CopyArrayItems(Result
->Array
, 0,
1095 ArrayList
->Array
, ItemOffset
,
1096 Count
, ArrayList
->ItemSize
);
1097 Result
->Count
= Count
;
1100 ENSURE(ArrayListIsValid(ArrayList
));
1101 ENSURE(ArrayListIsValid(Result
) || Result
== NULL
);
1107 * Gets the item at the specified offset in the list.
1110 * Array list containing the desired item.
1112 * Offset to the item in the list.
1115 * The requested item.
1117 ArrayListItem_u
ArrayListGetItem(ArrayList_pa ArrayList
,
1118 LgIndex_t ItemOffset
)
1120 ArrayListItem_u Result
;
1122 REQUIRE(ArrayListIsValid(ArrayList
));
1123 REQUIRE(0 <= ItemOffset
&& ItemOffset
<= ArrayList
->Count
- 1);
1125 CopyArrayItems((char *)&Result
, 0,
1126 ArrayList
->Array
, ItemOffset
,
1127 1, ArrayList
->ItemSize
);
1133 #if !defined USE_MACROS_FOR_FUNCTIONS
1135 * Gets the item's internal reference at the specified offset in the list.
1138 * Some array list functions modify the internal buffer.
1139 * This will invalidate this reference however it is
1140 * the client's responsibility not to make further use
1141 * of it. In addition, this reference should never be
1142 * deallocated directly as the array list assumes the
1143 * responsible for the cleanup.
1146 * Array list containing the desired item.
1148 * Offset to the item in the list.
1151 * The internal reference to the requested item.
1153 const void *ArrayListGetItemInternalRef_FUNC(ArrayList_pa ArrayList
,
1154 LgIndex_t ItemOffset
)
1156 REQUIRE(ArrayListIsValid(ArrayList
));
1157 REQUIRE(0 <= ItemOffset
&& ItemOffset
<= ArrayList
->Count
- 1);
1159 const void *Result
= ArrayListGetItemInternalRef_MACRO(ArrayList
, ItemOffset
);
1160 ENSURE(Result
== NULL
|| VALID_REF(Result
));
1167 * Places the item at the specified offset. If the offset is beyond the
1168 * end of the list it is sized accordingly and the intervening items
1169 * between the last item of the original state and the last item of the
1170 * new state are guaranteed to be 0.
1173 * Array list target in which to set the item.
1175 * Offset of the item.
1177 * Item to set at the specified offset.
1178 * param ItemDestructor
1179 * Destructor responsible for array list item cleanup or
1180 * NULL if no item cleanup is desired.
1182 * Any client data needed for cleanup.
1185 * TRUE if sufficient memory permitted the operation, otherwise FALSE.
1187 Boolean_t
ArrayListSetItem(ArrayList_pa ArrayList
,
1188 LgIndex_t ItemOffset
,
1189 ArrayListItem_u Item
,
1190 ArrayListItemDestructor_pf ItemDestructor
,
1191 ArbParam_t ClientData
)
1193 Boolean_t IsOk
= TRUE
;
1195 REQUIRE(ArrayListIsValid(ArrayList
));
1196 REQUIRE(ItemOffset
>= 0);
1197 REQUIRE(VALID_FN_REF(ItemDestructor
) || ItemDestructor
== NULL
);
1198 REQUIRE(IMPLICATION(ItemOffset
+ 1 > ArrayList
->Count
,
1199 !ArrayList
->IsVisitingItems
));
1201 /* release the item if a destructor is installed */
1202 if (ItemDestructor
!= NULL
&& ItemOffset
< ArrayList
->Count
)
1203 DestroyItems(ArrayList
, ItemOffset
, ArrayList
->ItemSize
, 1,
1204 ItemDestructor
, ClientData
);
1206 /* if necessary enlarge the list to accommodate the request */
1207 if (ItemOffset
+ 1 > ArrayList
->Capacity
)
1208 IsOk
= ArrayListEnlargeCapacity(ArrayList
, ItemOffset
+ 1);
1212 if (ItemOffset
+ 1 > ArrayList
->Count
)
1213 ArrayList
->Count
= ItemOffset
+ 1;
1214 CopyArrayItems(ArrayList
->Array
, ItemOffset
,
1216 1, ArrayList
->ItemSize
);
1219 ENSURE(ArrayListIsValid(ArrayList
));
1220 ENSURE(VALID_BOOLEAN(IsOk
));
1226 * Appends the item to the list. The list will be expanded
1227 * to accommodate the additional item.
1230 * Array list target to which the item is to be appended.
1232 * Item to append to the array list.
1235 * TRUE if sufficient memory permitted the operation, otherwise FALSE.
1237 Boolean_t
ArrayListAppendItem(ArrayList_pa ArrayList
,
1238 ArrayListItem_u Item
)
1242 REQUIRE(ArrayListIsValid(ArrayList
));
1243 REQUIRE(!ArrayList
->IsVisitingItems
);
1245 IsOk
= ArrayListInsertItem(ArrayList
, ArrayList
->Count
, Item
);
1247 ENSURE(ArrayListIsValid(ArrayList
));
1248 ENSURE(VALID_BOOLEAN(IsOk
));
1254 * Appends copies of the items from the source list to the target list.
1255 * The source list remains unchanged.
1258 * Array list receiving the source items.
1260 * Array list supplying the source items.
1263 * TRUE if sufficient memory permitted the operation, otherwise FALSE.
1265 Boolean_t
ArrayListAppend(ArrayList_pa Target
,
1266 ArrayList_pa Source
)
1270 REQUIRE(ArrayListIsValid(Target
));
1271 REQUIRE(ArrayListIsValid(Source
));
1272 REQUIRE(Target
!= Source
);
1273 REQUIRE(Target
->Type
== Source
->Type
);
1274 REQUIRE(!Target
->IsVisitingItems
);
1276 IsOk
= ArrayListInsert(Target
, Target
->Count
, Source
);
1278 ENSURE(ArrayListIsValid(Target
));
1279 ENSURE(VALID_BOOLEAN(IsOk
));
1285 * Copies the items of the array list.
1288 * Array list to copy.
1289 * param ItemDuplicator
1290 * Duplicator responsible for array list item duplication or
1291 * NULL if an exact item copy is desired. In other words for
1292 * pointer types the effect is copy by reference.
1294 * Any client data needed for duplication.
1297 * Handle to a duplicate of the specified array list if sufficient
1298 * memory permitted the operation, otherwise NULL.
1300 ArrayList_pa
ArrayListCopy(ArrayList_pa ArrayList
,
1301 ArrayListItemDuplicator_pf ItemDuplicator
,
1302 ArbParam_t ClientData
)
1304 ArrayList_pa Result
;
1306 REQUIRE(ArrayListIsValid(ArrayList
));
1307 REQUIRE(VALID_FN_REF(ItemDuplicator
) || ItemDuplicator
== NULL
);
1309 Result
= ArrayListAlloc(ArrayList
->Count
, ArrayList
->Type
,
1310 ArrayList
->CapacityRequestAdjuster
,
1311 ArrayList
->CapacityRequestAdjusterClientData
);
1312 if (Result
!= NULL
&& ArrayList
->Count
!= 0)
1314 Boolean_t IsOk
= TRUE
;
1315 if (ItemDuplicator
!= NULL
)
1316 /* client defines how the item duplication is performed */
1317 IsOk
= DuplicateItems(Result
->Array
, 0,
1318 ArrayList
->Array
, 0,
1319 ArrayList
->ItemSize
, ArrayList
->Count
,
1320 ItemDuplicator
, ClientData
);
1322 /* copy the original items into the result */
1323 CopyArrayItems(Result
->Array
, 0,
1324 ArrayList
->Array
, 0,
1326 ArrayList
->ItemSize
);
1328 Result
->Count
= ArrayList
->Count
;
1330 ArrayListDealloc(&Result
, NULL
, 0);
1333 ENSURE(Result
== NULL
||
1334 (ArrayListIsValid(Result
) && Result
->Count
== ArrayList
->Count
));
1340 * Creates a native 'C' array containing copies of the items held in the
1341 * source array list.
1344 * Array list containing the items of interest.
1345 * param ItemDuplicator
1346 * Duplicator responsible for array list item duplication or
1347 * NULL if an exact item copy is desired. In other words for
1348 * pointer types the effect is copy by reference.
1350 * Any client data needed for duplication.
1353 * Allocated array populated with copies of the members of the array list
1354 * or NULL if there are no items in the list or if the allocation was
1355 * not successful. The caller is responsible for deallocation of the
1356 * array (but not the individual members unless a item duplication function
1357 * was supplied) when it is no longer needed.
1359 void *ArrayListToArray(ArrayList_pa Source
,
1360 ArrayListItemDuplicator_pf ItemDuplicator
,
1361 ArbParam_t ClientData
)
1365 REQUIRE(ArrayListIsValid(Source
));
1366 REQUIRE(VALID_FN_REF(ItemDuplicator
) || ItemDuplicator
== NULL
);
1368 if (Source
->Count
!= 0)
1369 Result
= (void *)ALLOC_ARRAY(Source
->Count
* Source
->ItemSize
,
1370 char, "native array");
1376 Boolean_t IsOk
= TRUE
;
1377 if (ItemDuplicator
!= NULL
)
1378 /* client defines how the item duplication is performed */
1379 IsOk
= DuplicateItems((char*)Result
, 0,
1381 Source
->ItemSize
, Source
->Count
,
1382 ItemDuplicator
, ClientData
);
1384 /* copy the original items into the result */
1385 CopyArrayItems((char *)Result
, 0,
1391 /* Hack to remove delete warning... */
1392 char *Tmp
= (char *)Result
;
1393 FREE_ARRAY(Tmp
, "native array");
1397 ENSURE(VALID_REF(Result
) || Result
== NULL
);
1403 * Creates an array list containing copies of the items held in the
1407 * Native 'C' array containing the items of interest.
1409 * Number of items contained in the native 'C' array.
1411 * Type of items contained in the native 'C' array.
1412 * param ItemDuplicator
1413 * Duplicator responsible for array list item duplication or
1414 * NULL if an exact item copy is desired. In other words for
1415 * pointer types the effect is copy by reference.
1417 * Any client data needed for duplication.
1420 * Array list handle containing copies of the items held in the
1421 * native 'C' array if sufficient memory was available, otherwise
1424 ArrayList_pa
ArrayListFromArray(void *Source
,
1426 ArrayListType_e Type
,
1427 ArrayListItemDuplicator_pf ItemDuplicator
,
1428 ArbParam_t ClientData
)
1430 ArrayList_pa Result
;
1432 REQUIRE(VALID_REF(Source
));
1433 REQUIRE(Count
>= 0);
1434 REQUIRE(VALID_ENUM(Type
, ArrayListType_e
));
1435 REQUIRE(VALID_FN_REF(ItemDuplicator
) || ItemDuplicator
== NULL
);
1437 Result
= ArrayListAlloc(Count
, Type
, NULL
, 0);
1438 if (Result
!= NULL
&& Count
!= 0)
1440 Boolean_t IsOk
= TRUE
;
1441 if (ItemDuplicator
!= NULL
)
1442 /* client defines how the item duplication is performed */
1443 IsOk
= DuplicateItems(Result
->Array
, 0,
1445 Result
->ItemSize
, Count
,
1446 ItemDuplicator
, ClientData
);
1448 /* copy the original items into the result */
1449 CopyArrayItems(Result
->Array
, 0,
1451 Count
, Result
->ItemSize
);
1453 Result
->Count
= Count
;
1455 ArrayListDealloc(&Result
, NULL
, 0);
1458 ENSURE(ArrayListIsValid(Result
) || Result
== NULL
);
1464 * Holds the comparator function pointer for sorting.
1466 static ArrayListItemComparator_pf ComparatorFunction
= NULL
;
1470 * Holds the context for comparisons. This information is forwarded to
1471 * the item comparator function for sorting.
1473 static ArbParam_t ComparatorClientData
= 0;
1477 * Holds the item size of the individual array components for sorting.
1479 static SmInteger_t ComparatorItemSize
= 0;
1483 * Forwards the comparison test to the 'Comparator' supplied to the
1484 * 'ArrayListQSort' function.
1487 * Reference to base address of Item1.
1489 * Reference to base address of Item2.
1492 * - A value less than zero if Item1 is less than Item2.
1493 * - A value of zero if Item1 is equal to Item2.
1494 * - A value greater than zero if Item1 is greater than Item2.
1496 static int QSortCompareItemsAdapter(const void *Item1Ref
,
1497 const void *Item2Ref
)
1500 ArrayListItem_u Item1
;
1501 ArrayListItem_u Item2
;
1503 REQUIRE(Item1Ref
!= NULL
);
1504 REQUIRE(Item2Ref
!= NULL
);
1506 /* collect up the items */
1507 CopyArrayItems((char *)&Item1
, 0,
1508 (char *)Item1Ref
, 0,
1509 1, ComparatorItemSize
);
1510 CopyArrayItems((char *)&Item2
, 0,
1511 (char *)Item2Ref
, 0,
1512 1, ComparatorItemSize
);
1514 /* forward the call */
1515 Result
= ComparatorFunction(Item1
, Item2
, ComparatorClientData
);
1517 ENSURE(Result
== -1 || Result
== 0 || Result
== 1);
1521 #if defined TECPLOTKERNEL
1522 /* CORE SOURCE CODE REMOVED */
1525 #if defined TECPLOTKERNEL
1526 /* CORE SOURCE CODE REMOVED */
1529 #if defined TECPLOTKERNEL
1530 /* CORE SOURCE CODE REMOVED */
1534 * Sorts the array list using the qsort algorithm.
1537 * Array list to sort.
1539 * Function called to compare two array list elements.
1541 * Contextual information that is passed along to the comparator function.
1543 void ArrayListQSort(ArrayList_pa ArrayList
,
1544 ArrayListItemComparator_pf Comparator
,
1545 ArbParam_t ClientData
)
1547 ArrayListItemComparator_pf CurComparatorFunction
;
1548 ArbParam_t CurComparatorClientData
;
1549 SmInteger_t CurComparatorItemSize
;
1551 #if defined TECPLOTKERNEL
1552 /* CORE SOURCE CODE REMOVED */
1554 REQUIRE(ArrayListIsValid(ArrayList
));
1555 REQUIRE(VALID_FN_REF(Comparator
));
1557 /* to support sort recursion we need to save off the current values */
1558 CurComparatorFunction
= ComparatorFunction
;
1559 CurComparatorClientData
= ComparatorClientData
;
1560 CurComparatorItemSize
= ComparatorItemSize
;
1562 /* set up for comparison proxy */
1563 ComparatorFunction
= Comparator
;
1564 ComparatorClientData
= ClientData
;
1565 ComparatorItemSize
= ArrayList
->ItemSize
;
1567 /* sort the array */
1568 qsort(ArrayList
->Array
, ArrayList
->Count
,
1569 ArrayList
->ItemSize
, QSortCompareItemsAdapter
);
1572 ComparatorFunction
= CurComparatorFunction
;
1573 ComparatorClientData
= CurComparatorClientData
;
1574 ComparatorItemSize
= CurComparatorItemSize
;
1576 ENSURE(ArrayListIsValid(ArrayList
));
1580 * Binary searches a sorted array looking for a match using the supplied
1581 * comparator function. If a match is found the resulting item index refers to
1582 * the location otherwise it refers to the location where the item could be
1583 * inserted in sorted order.
1586 * Array list to sort.
1588 * The item for which to search.
1590 * Function called to compare the Item to the array list elements.
1592 * Contextual information that is passed along to the comparator function.
1594 * Pointer to the resulting position where the item was found or where the
1595 * item could be inserted in sorted order. If the pointer is NULL the
1596 * result position is not returned.
1599 * TRUE if the item was found in the list, FALSE otherwise.
1601 Boolean_t
ArrayListBSearch(ArrayList_pa ArrayList
,
1602 ArrayListItem_u Item
,
1603 ArrayListItemComparator_pf Comparator
,
1604 ArbParam_t ClientData
,
1605 LgIndex_t
*ItemIndex
)
1607 REQUIRE(ArrayListIsValid(ArrayList
));
1608 REQUIRE(VALID_FN_REF(Comparator
));
1609 REQUIRE(ItemIndex
== NULL
|| VALID_REF(ItemIndex
));
1611 LgIndex_t MiddleItemIndex
= 0;
1612 LgIndex_t FirstItemIndex
= 0;
1613 LgIndex_t NumItems
= ArrayListGetCount(ArrayList
);
1614 LgIndex_t LastItemIndex
= NumItems
- 1;
1615 Boolean_t Found
= FALSE
;
1616 while (FirstItemIndex
<= LastItemIndex
&& !Found
)
1618 /* calculate the middle item index for current sub-range */
1619 MiddleItemIndex
= (FirstItemIndex
+ LastItemIndex
) / 2;
1621 int CompareResult
= Comparator(ArrayListGetItem(ArrayList
, MiddleItemIndex
), Item
, ClientData
);
1622 if (CompareResult
> 0)
1623 LastItemIndex
= MiddleItemIndex
- 1;
1624 else if (CompareResult
< 0)
1625 FirstItemIndex
= MiddleItemIndex
+ 1;
1630 if (ItemIndex
!= NULL
)
1632 if (Found
|| NumItems
== 0 || FirstItemIndex
< NumItems
)
1633 *ItemIndex
= MiddleItemIndex
;
1635 *ItemIndex
= NumItems
; /* ...in other words it goes on the end */
1638 ENSURE(IMPLICATION(ItemIndex
!= NULL
,
1639 0 <= *ItemIndex
&& *ItemIndex
<= ArrayListGetCount(ArrayList
)));
1640 ENSURE(VALID_BOOLEAN(Found
));
1644 #if !defined USE_MACROS_FOR_FUNCTIONS
1646 * Gets the array list's internal buffer representation.
1649 * Some array list functions modify the internal buffer.
1650 * This will invalidate this reference however it is
1651 * the client's responsibility not to make further use
1652 * of it. In addition, this reference should never be
1653 * deallocated directly as the array list assumes the
1654 * responsible for the cleanup.
1657 * Array list for which a reference to the internal
1658 * buffer is desired.
1661 * Reference to the array list's internal buffer.
1663 const void *ArrayListGetInternalRef_FUNC(ArrayList_pa ArrayList
)
1665 REQUIRE(ArrayListIsValid(ArrayList
));
1667 const void *Result
= ArrayListGetInternalRef_MACRO(ArrayList
);
1668 ENSURE(Result
== NULL
|| VALID_REF(Result
));