foam to Tecplot360 converter
[OpenFOAM-1.6.x.git] / applications / utilities / postProcessing / dataConversion / foamToTecplot360 / tecio / tecsrc / arrlist.cpp
blobc4955817eeda7aa202f00045874afd301ccaf495
1 /*
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.
17 * Tecplot, Inc.
18 * 3535 Factoria Blvd, Ste. 550
19 * Bellevue, WA 98006, USA
20 * Phone: +1 425 653 1200
21 * http://www.tecplot.com/
24 #include "stdafx.h"
25 #include "MASTER.h"
26 #define TECPLOTENGINEMODULE
29 *****************************************************************
30 *****************************************************************
31 ******* ********
32 ****** Copyright (C) 1988-2008 Tecplot, Inc. ********
33 ******* All Rights Reserved. ********
34 ******* ********
35 *****************************************************************
36 *****************************************************************
39 #define ARRLISTMODULE
40 #include "GLOBAL.h"
41 #include "TASSERT.h"
42 #include "ALLOC.h"
43 #if defined TECPLOTKERNEL
44 /* CORE SOURCE CODE REMOVED */
45 #endif
46 #include "ARRLIST.h"
48 #if defined TECPLOTKERNEL
49 /* CORE SOURCE CODE REMOVED */
50 #endif
53 * ABSTRACT:
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.
63 /**
64 * Copies the private array items from the specified source to the target
65 * location. The buffers may overlap.
67 * note
68 * Originally this function was a macro that called memmove
69 * directly:
71 * #define CopyArrayItems(TargetArray, TargetOffset, \
72 * SourceArray, SourceOffset, \
73 * Count, ItemSize) \
74 * (memmove(&((TargetArray)[(TargetOffset)*ItemSize]), \
75 * &((SourceArray)[(SourceOffset)*ItemSize]), \
76 * Count*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.
83 * param TargetArray
84 * Base address of the target array to receive the items.
85 * param TargetOffset
86 * Target offset of the first item.
87 * param SourceArray
88 * Base address of the source array supplying the items.
89 * param SourceOffset
90 * Source offset of the first item.
91 * param Count
92 * Number of items to copy.
93 * param ItemSize
94 * Item size in bytes.
96 static void CopyArrayItems(char *TargetArray,
97 LgIndex_t TargetOffset,
98 char *SourceArray,
99 LgIndex_t SourceOffset,
100 LgIndex_t Count,
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]);
108 REQUIRE(Count >= 1);
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.
124 * param ArrayList
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.
130 * param ClientData
131 * Any client data needed for the adjustment.
133 * return
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)
142 LgIndex_t Result;
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;
153 else
155 const LgIndex_t DEFAULT_CAPACITY = 32;
156 LgIndex_t BlockSize = MAX(DEFAULT_CAPACITY, CurrentCapacity / 2);
157 if (RequestedCapacity == 0)
158 Result = DEFAULT_CAPACITY;
159 else
160 Result = ((RequestedCapacity - 1) / BlockSize + 1) * BlockSize;
163 ENSURE(Result == 0 || Result >= RequestedCapacity);
164 return Result;
169 * Gets the size of an individual element.
171 * param Type
172 * Array list element type.
174 * return
175 * Element size corresponding to the type.
177 static SmInteger_t GetElementSize(ArrayListType_e Type)
179 SmInteger_t Result;
181 REQUIRE(VALID_ENUM(Type, ArrayListType_e));
183 switch (Type)
185 case ArrayListType_UnsignedChar:
186 Result = (SmInteger_t)sizeof(unsigned char);
187 break;
188 case ArrayListType_UnsignedShort:
189 Result = (SmInteger_t)sizeof(unsigned short);
190 break;
191 case ArrayListType_UnsignedInt:
192 Result = (SmInteger_t)sizeof(unsigned int);
193 break;
194 case ArrayListType_UnsignedLong:
195 Result = (SmInteger_t)sizeof(unsigned long);
196 break;
197 case ArrayListType_Int64:
198 Result = (SmInteger_t)sizeof(Int64_t);
199 break;
200 case ArrayListType_Char:
201 Result = (SmInteger_t)sizeof(char);
202 break;
203 case ArrayListType_Short:
204 Result = (SmInteger_t)sizeof(short);
205 break;
206 case ArrayListType_Int:
207 Result = (SmInteger_t)sizeof(int);
208 break;
209 case ArrayListType_Long:
210 Result = (SmInteger_t)sizeof(long);
211 break;
212 case ArrayListType_Float:
213 Result = (SmInteger_t)sizeof(float);
214 break;
215 case ArrayListType_Double:
216 Result = (SmInteger_t)sizeof(double);
217 break;
218 case ArrayListType_LgIndex:
219 Result = (SmInteger_t)sizeof(LgIndex_t);
220 break;
221 case ArrayListType_EntIndex:
222 Result = (SmInteger_t)sizeof(EntIndex_t);
223 break;
224 case ArrayListType_SmInteger:
225 Result = (SmInteger_t)sizeof(SmInteger_t);
226 break;
227 case ArrayListType_Boolean:
228 Result = (SmInteger_t)sizeof(Boolean_t);
229 break;
230 case ArrayListType_ArbParam:
231 Result = (SmInteger_t)sizeof(ArbParam_t);
232 break;
234 case ArrayListType_UnsignedCharPtr:
235 Result = (SmInteger_t)sizeof(unsigned char *);
236 break;
237 case ArrayListType_UnsignedShortPtr:
238 Result = (SmInteger_t)sizeof(unsigned short *);
239 break;
240 case ArrayListType_UnsignedIntPtr:
241 Result = (SmInteger_t)sizeof(unsigned int *);
242 break;
243 case ArrayListType_UnsignedLongPtr:
244 Result = (SmInteger_t)sizeof(unsigned long *);
245 break;
246 case ArrayListType_Int64Ptr:
247 Result = (SmInteger_t)sizeof(Int64_t *);
248 break;
249 case ArrayListType_CharPtr:
250 Result = (SmInteger_t)sizeof(char *);
251 break;
252 case ArrayListType_ShortPtr:
253 Result = (SmInteger_t)sizeof(short *);
254 break;
255 case ArrayListType_IntPtr:
256 Result = (SmInteger_t)sizeof(int *);
257 break;
258 case ArrayListType_LongPtr:
259 Result = (SmInteger_t)sizeof(long *);
260 break;
261 case ArrayListType_FloatPtr:
262 Result = (SmInteger_t)sizeof(float *);
263 break;
264 case ArrayListType_DoublePtr:
265 Result = (SmInteger_t)sizeof(double *);
266 break;
267 case ArrayListType_LgIndexPtr:
268 Result = (SmInteger_t)sizeof(LgIndex_t *);
269 break;
270 case ArrayListType_EntIndexPtr:
271 Result = (SmInteger_t)sizeof(EntIndex_t *);
272 break;
273 case ArrayListType_SmIntegerPtr:
274 Result = (SmInteger_t)sizeof(SmInteger_t *);
275 break;
276 case ArrayListType_BooleanPtr:
277 Result = (SmInteger_t)sizeof(Boolean_t *);
278 break;
279 case ArrayListType_ArbParamPtr:
280 Result = (SmInteger_t)sizeof(ArbParam_t *);
281 break;
283 case ArrayListType_VoidPtr:
284 Result = (SmInteger_t)sizeof(void *);
285 break;
286 case ArrayListType_FunctionPtr:
287 Result = (SmInteger_t)sizeof(void (*)());
288 break;
289 case ArrayListType_Any: /* allows a mixed bag of items */
290 Result = (SmInteger_t)sizeof(ArrayListItem_u);
291 break;
293 default:
294 Result = 0; /* make some compilers happy. */
295 CHECK(FALSE);
296 break;
299 ENSURE(1 <= Result && Result <= (SmInteger_t)sizeof(ArrayListItem_u));
300 return Result;
305 * Calls the item destructor for each item specified.
307 * param ArrayList
308 * Array list needing its items destroyed.
309 * param ItemOffset
310 * Offset to the first item to destroy in the list.
311 * param ItemSize
312 * Size of each array list item.
313 * param Count
314 * Number of items to destroy.
315 * param ItemDestructor
316 * Function called for each array list item.
317 * param CientData
318 * Any client data needed for the destructor.
320 static void DestroyItems(ArrayList_pa ArrayList,
321 LgIndex_t ItemOffset,
322 SmInteger_t ItemSize,
323 LgIndex_t Count,
324 ArrayListItemDestructor_pf ItemDestructor,
325 ArbParam_t ClientData)
327 LgIndex_t Index;
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));
334 for (Index = 0;
335 Index < Count;
336 Index++)
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 */
342 #else
343 ItemDestructor((void *)&ArrayList->Array[ItemIndex], ClientData);
344 #endif
350 * Calls the item duplicator for each item specified.
352 * param TargetArray
353 * Target array needing its items duplicated.
354 * param TargetItemOffset
355 * Target offset to the first duplicated item.
356 * param SourceArray
357 * Source array needing its items duplicated.
358 * param SourceItemOffset
359 * Source offset to the first item to duplicate in the list.
360 * param ItemSize
361 * Size of each array list item.
362 * param Count
363 * Number of items to duplicate.
364 * param ItemDuplicator
365 * Function called for each array list item.
366 * param CientData
367 * Any client data needed for the destructor.
369 * return
370 * TRUE if the duplication was a success
371 * FALSE otherwise
373 static Boolean_t DuplicateItems(char *TargetArray,
374 LgIndex_t TargetItemOffset,
375 char *SourceArray,
376 LgIndex_t SourceItemOffset,
377 SmInteger_t ItemSize,
378 LgIndex_t Count,
379 ArrayListItemDuplicator_pf ItemDuplicator,
380 ArbParam_t ClientData)
382 Boolean_t IsOk = TRUE;
383 LgIndex_t Index;
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));
391 REQUIRE(Count >= 1);
392 REQUIRE(VALID_FN_REF(ItemDuplicator));
394 for (Index = 0;
395 Index < Count && IsOk;
396 Index++)
398 LgIndex_t TargetItemIndex = (Index + TargetItemOffset) * ItemSize;
399 LgIndex_t SourceItemIndex = (Index + SourceItemOffset) * ItemSize;
400 IsOk = ItemDuplicator((void *) & TargetArray[TargetItemIndex],
401 (void *) & SourceArray[SourceItemIndex],
402 ClientData);
405 ENSURE(VALID_BOOLEAN(IsOk));
406 return IsOk;
411 * Determine if the list handle is sane.
413 * param ArrayList
414 * Array list in question.
416 * return
417 * TRUE if the array list is valid, otherwise FALSE.
419 Boolean_t ArrayListIsValid(ArrayList_pa ArrayList)
421 Boolean_t IsValid;
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));
434 return IsValid;
439 * Gets the specified array list's type.
441 * param ArrayList
442 * Array list of which the type is desired.
444 * return
445 * Array list type.
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));
456 return Result;
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.
467 * param ArrayList
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.
472 * return
473 * TRUE if the list could be enlarged (or was large enough),
474 * otherwise FALSE.
476 Boolean_t ArrayListEnlargeCapacity(ArrayList_pa ArrayList,
477 LgIndex_t RequestedCapacity)
479 Boolean_t IsOk;
480 LgIndex_t AdjustedCapacity;
481 char *EnlargedArray;
483 REQUIRE(ArrayListIsValid(ArrayList));
484 REQUIRE(IMPLICATION(RequestedCapacity == 0, ArrayList->Capacity == 0));
486 if (RequestedCapacity == 0 ||
487 RequestedCapacity > ArrayList->Capacity)
489 AdjustedCapacity =
490 ArrayList->CapacityRequestAdjuster(ArrayList,
491 ArrayList->Capacity,
492 RequestedCapacity,
493 ArrayList->CapacityRequestAdjusterClientData);
494 CHECK(AdjustedCapacity == 0 ||
495 AdjustedCapacity >= RequestedCapacity);
497 IsOk = (AdjustedCapacity != 0); /* ...were we able to meet the request? */
498 if (IsOk)
500 EnlargedArray = ALLOC_ARRAY(AdjustedCapacity * ArrayList->ItemSize,
501 char, "array list");
502 if (EnlargedArray == NULL)
504 /* try again with minimum capacity request */
505 if (RequestedCapacity != 0)
506 AdjustedCapacity = RequestedCapacity;
507 else
508 AdjustedCapacity = 1; /* can't get smaller than this */
509 EnlargedArray = ALLOC_ARRAY(AdjustedCapacity * ArrayList->ItemSize,
510 char, "array list");
512 IsOk = (EnlargedArray != NULL);
515 if (IsOk)
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,
528 ArrayList->Array, 0,
529 ArrayList->Count,
530 ArrayList->ItemSize);
531 FREE_ARRAY(ArrayList->Array, "array list");
534 ArrayList->Array = EnlargedArray;
535 ArrayList->Capacity = AdjustedCapacity;
538 else
540 IsOk = TRUE;
543 ENSURE(ArrayListIsValid(ArrayList));
544 ENSURE(VALID_BOOLEAN(IsOk));
545 return 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
556 * default capacity.
557 * param Type
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.
565 * return
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)
574 ArrayList_pa Result;
576 REQUIRE(EstimatedCapacity >= 0);
577 REQUIRE(VALID_ENUM(Type, ArrayListType_e));
579 Result = ALLOC_ITEM(ArrayList_s, "ArrayList structure");
580 if (Result != NULL)
582 Result->Array = NULL;
583 Result->Type = Type;
584 Result->ItemSize = GetElementSize(Type);
585 Result->Count = 0;
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;
594 else
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));
608 return Result;
613 * Deallocates the list handle and set the handle to NULL.
615 * param ArrayList
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.
620 * param ClientData
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");
644 *ArrayList = NULL;
647 ENSURE(*ArrayList == NULL);
651 #if !defined USE_MACROS_FOR_FUNCTIONS
653 * Gets the number of items currently maintained by the list.
655 * param
656 * Array list in question.
658 * return
659 * Number of items maintained by the list.
661 LgIndex_t ArrayListGetCount_FUNC(ArrayList_pa ArrayList)
663 LgIndex_t Result;
665 REQUIRE(ArrayListIsValid(ArrayList));
667 Result = ArrayListGetCount_MACRO(ArrayList);
669 ENSURE(Result >= 0);
670 return Result;
672 #endif
676 * Empties the array list of all items.
678 * param ArrayList
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.
683 * param ClientData
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.
716 * param ArrayList
717 * Array list containing the items to delete.
718 * param ItemOffset
719 * Offset to the first item to delete in the list.
720 * param Count
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.
725 * param ClientData
726 * Any client data needed for cleanup.
728 void ArrayListDeleteItems(ArrayList_pa ArrayList,
729 LgIndex_t ItemOffset,
730 LgIndex_t Count,
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.
770 * param ArrayList
771 * Array list containing the item to delete.
772 * param ItemOffset
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.
777 * param ClientData
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.
800 * param ArrayList
801 * Array list containing the items to remove.
802 * param ItemOffset
803 * Offset to the first item to remove in the list.
804 * param Count
805 * Number of items to remove.
807 * return
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,
813 LgIndex_t Count)
815 ArrayList_pa Result;
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);
824 if (Result != NULL)
825 ArrayListDeleteItems(ArrayList, ItemOffset, Count, NULL, 0);
827 ENSURE(ArrayListIsValid(ArrayList));
828 ENSURE(ArrayListIsValid(Result) || Result == NULL);
829 return Result;
834 * Removes an item from the array list. The members following the item
835 * removed are shifted down accordingly to fill the vacated space.
837 * param ArrayList
838 * Array list containing the item to remove.
839 * param ItemOffset
840 * Offset to the item in the list.
842 * return
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));
863 return Result;
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.
872 * param Target
873 * Array list receiving the source items.
874 * param ItemOffset
875 * Offset at which to insert the source list items.
876 * param Source
877 * Array list supplying the source items.
879 * return
880 * TRUE if sufficient memory permitted the operation, otherwise FALSE.
882 Boolean_t ArrayListInsert(ArrayList_pa Target,
883 LgIndex_t ItemOffset,
884 ArrayList_pa Source)
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;
902 else
903 NeededCapacity = Target->Count + Source->Count;
904 if (NeededCapacity > Target->Capacity)
905 IsOk = ArrayListEnlargeCapacity(Target, NeededCapacity);
907 if (IsOk)
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,
917 Target->ItemSize);
918 Target->Count += Source->Count;
920 else
922 /* no shifting to do, just update the count */
923 if (ItemOffset > Target->Count)
924 Target->Count = ItemOffset + Source->Count;
925 else
926 Target->Count += Source->Count;
929 /* insert the items and update the count */
930 CopyArrayItems(Target->Array, ItemOffset,
931 Source->Array, 0,
932 Source->Count, Source->ItemSize);
936 ENSURE(ArrayListIsValid(Target));
937 ENSURE(VALID_BOOLEAN(IsOk));
938 return 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.
949 * param ArrayList
950 * Array list target in which to insert the item.
951 * param ItemOffset
952 * Offset at which to insert the item.
953 * param Item
954 * Item to insert at the specified offset.
956 * return
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;
973 else
974 NeededCapacity = ArrayList->Count + 1;
975 if (NeededCapacity > ArrayList->Capacity)
976 IsOk = ArrayListEnlargeCapacity(ArrayList, NeededCapacity);
978 if (IsOk)
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);
988 ArrayList->Count++;
990 else
992 /* no shifting to do, just update the count */
993 if (ItemOffset > ArrayList->Count)
994 ArrayList->Count = ItemOffset + 1;
995 else
996 ArrayList->Count++;
999 /* insert the item */
1000 CopyArrayItems(ArrayList->Array, ItemOffset,
1001 (char *)&Item, 0,
1002 1, ArrayList->ItemSize);
1005 ENSURE(ArrayListIsValid(ArrayList));
1006 ENSURE(VALID_BOOLEAN(IsOk));
1007 return IsOk;
1012 * Visits array list items calling the item visitor for each item.
1014 * param ArrayList
1015 * Array list needing its items destroyed.
1016 * param ItemOffset
1017 * Offset to the first item to visit from the list.
1018 * param Count
1019 * Number of items to visit.
1020 * param ItemVisitor
1021 * Function called for each array list item.
1022 * param CientData
1023 * Any client data needed for the visitor.
1025 * return
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,
1031 LgIndex_t Count,
1032 ArrayListItemVisitor_pf ItemVisitor,
1033 ArbParam_t ClientData)
1035 Boolean_t DoContinue = TRUE;
1036 Boolean_t IsVisitingItems;
1037 SmInteger_t ItemSize;
1038 LgIndex_t Index;
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;
1048 Index++)
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));
1058 return 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.
1067 * param ArrayList
1068 * Array list containing the items to copy.
1069 * param ItemOffset
1070 * Offset to the first item to copy from the list.
1071 * param Count
1072 * Number of items to copy.
1074 * return
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,
1080 LgIndex_t Count)
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);
1091 if (Result != NULL)
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);
1102 return Result;
1107 * Gets the item at the specified offset in the list.
1109 * param ArrayList
1110 * Array list containing the desired item.
1111 * param ItemOffset
1112 * Offset to the item in the list.
1114 * return
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);
1129 return Result;
1133 #if !defined USE_MACROS_FOR_FUNCTIONS
1135 * Gets the item's internal reference at the specified offset in the list.
1137 * WARNING:
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.
1145 * param ArrayList
1146 * Array list containing the desired item.
1147 * param ItemOffset
1148 * Offset to the item in the list.
1150 * return
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));
1161 return Result;
1163 #endif
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.
1172 * param ArrayList
1173 * Array list target in which to set the item.
1174 * param ItemOffset
1175 * Offset of the item.
1176 * param 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.
1181 * param ClientData
1182 * Any client data needed for cleanup.
1184 * return
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);
1210 if (IsOk)
1212 if (ItemOffset + 1 > ArrayList->Count)
1213 ArrayList->Count = ItemOffset + 1;
1214 CopyArrayItems(ArrayList->Array, ItemOffset,
1215 (char *)&Item, 0,
1216 1, ArrayList->ItemSize);
1219 ENSURE(ArrayListIsValid(ArrayList));
1220 ENSURE(VALID_BOOLEAN(IsOk));
1221 return IsOk;
1226 * Appends the item to the list. The list will be expanded
1227 * to accommodate the additional item.
1229 * param ArrayList
1230 * Array list target to which the item is to be appended.
1231 * param Item
1232 * Item to append to the array list.
1234 * return
1235 * TRUE if sufficient memory permitted the operation, otherwise FALSE.
1237 Boolean_t ArrayListAppendItem(ArrayList_pa ArrayList,
1238 ArrayListItem_u Item)
1240 Boolean_t IsOk;
1242 REQUIRE(ArrayListIsValid(ArrayList));
1243 REQUIRE(!ArrayList->IsVisitingItems);
1245 IsOk = ArrayListInsertItem(ArrayList, ArrayList->Count, Item);
1247 ENSURE(ArrayListIsValid(ArrayList));
1248 ENSURE(VALID_BOOLEAN(IsOk));
1249 return IsOk;
1254 * Appends copies of the items from the source list to the target list.
1255 * The source list remains unchanged.
1257 * param Target
1258 * Array list receiving the source items.
1259 * param Source
1260 * Array list supplying the source items.
1262 * return
1263 * TRUE if sufficient memory permitted the operation, otherwise FALSE.
1265 Boolean_t ArrayListAppend(ArrayList_pa Target,
1266 ArrayList_pa Source)
1268 Boolean_t IsOk;
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));
1280 return IsOk;
1285 * Copies the items of the array list.
1287 * param ArrayList
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.
1293 * param ClientData
1294 * Any client data needed for duplication.
1296 * return
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);
1321 else
1322 /* copy the original items into the result */
1323 CopyArrayItems(Result->Array, 0,
1324 ArrayList->Array, 0,
1325 ArrayList->Count,
1326 ArrayList->ItemSize);
1327 if (IsOk)
1328 Result->Count = ArrayList->Count;
1329 else
1330 ArrayListDealloc(&Result, NULL, 0);
1333 ENSURE(Result == NULL ||
1334 (ArrayListIsValid(Result) && Result->Count == ArrayList->Count));
1335 return Result;
1340 * Creates a native 'C' array containing copies of the items held in the
1341 * source array list.
1343 * param Source
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.
1349 * param ClientData
1350 * Any client data needed for duplication.
1352 * return
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)
1363 void *Result;
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");
1371 else
1372 Result = NULL;
1374 if (Result != NULL)
1376 Boolean_t IsOk = TRUE;
1377 if (ItemDuplicator != NULL)
1378 /* client defines how the item duplication is performed */
1379 IsOk = DuplicateItems((char*)Result, 0,
1380 Source->Array, 0,
1381 Source->ItemSize, Source->Count,
1382 ItemDuplicator, ClientData);
1383 else
1384 /* copy the original items into the result */
1385 CopyArrayItems((char *)Result, 0,
1386 Source->Array, 0,
1387 Source->Count,
1388 Source->ItemSize);
1389 if (!IsOk)
1391 /* Hack to remove delete warning... */
1392 char *Tmp = (char *)Result;
1393 FREE_ARRAY(Tmp, "native array");
1397 ENSURE(VALID_REF(Result) || Result == NULL);
1398 return Result;
1403 * Creates an array list containing copies of the items held in the
1404 * native 'C' array.
1406 * param Source
1407 * Native 'C' array containing the items of interest.
1408 * param Count
1409 * Number of items contained in the native 'C' array.
1410 * param Type
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.
1416 * param ClientData
1417 * Any client data needed for duplication.
1419 * return
1420 * Array list handle containing copies of the items held in the
1421 * native 'C' array if sufficient memory was available, otherwise
1422 * a handle to NULL.
1424 ArrayList_pa ArrayListFromArray(void *Source,
1425 LgIndex_t Count,
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,
1444 (char*)Source, 0,
1445 Result->ItemSize, Count,
1446 ItemDuplicator, ClientData);
1447 else
1448 /* copy the original items into the result */
1449 CopyArrayItems(Result->Array, 0,
1450 (char *)Source, 0,
1451 Count, Result->ItemSize);
1452 if (IsOk)
1453 Result->Count = Count;
1454 else
1455 ArrayListDealloc(&Result, NULL, 0);
1458 ENSURE(ArrayListIsValid(Result) || Result == NULL);
1459 return Result;
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.
1486 * param Item1Ref
1487 * Reference to base address of Item1.
1488 * param Item2Ref
1489 * Reference to base address of Item2.
1491 * return
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)
1499 int Result;
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);
1518 return Result;
1521 #if defined TECPLOTKERNEL
1522 /* CORE SOURCE CODE REMOVED */
1523 #endif
1525 #if defined TECPLOTKERNEL
1526 /* CORE SOURCE CODE REMOVED */
1527 #endif
1529 #if defined TECPLOTKERNEL
1530 /* CORE SOURCE CODE REMOVED */
1531 #endif
1534 * Sorts the array list using the qsort algorithm.
1536 * param ArrayList
1537 * Array list to sort.
1538 * param Comparator
1539 * Function called to compare two array list elements.
1540 * param ClientData
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 */
1553 #endif
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);
1571 /* cleanup */
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.
1585 * param ArrayList
1586 * Array list to sort.
1587 * param Item
1588 * The item for which to search.
1589 * param Comparator
1590 * Function called to compare the Item to the array list elements.
1591 * param ClientData
1592 * Contextual information that is passed along to the comparator function.
1593 * param ItemIndex
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.
1598 * result
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;
1626 else
1627 Found = TRUE;
1630 if (ItemIndex != NULL)
1632 if (Found || NumItems == 0 || FirstItemIndex < NumItems)
1633 *ItemIndex = MiddleItemIndex;
1634 else
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));
1641 return Found;
1644 #if !defined USE_MACROS_FOR_FUNCTIONS
1646 * Gets the array list's internal buffer representation.
1648 * WARNING:
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.
1656 * param ArrayList
1657 * Array list for which a reference to the internal
1658 * buffer is desired.
1660 * return
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));
1669 return Result;
1671 #endif