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 ****** (C) 1988-2008 Tecplot, Inc. *******
34 ******************************************************************
35 ******************************************************************
41 #include "Q_UNICODE.h"
44 #if defined TECPLOTKERNEL
45 /* CORE SOURCE CODE REMOVED */
52 using namespace tecplot::strutil
;
55 * This set of functions provide a wrapper around the array list utilities
56 * thereby making it aware of item allocation and deallocation. All strings
57 * given to the string list and returned to the client are copies. Therefore
58 * it is the client's responsibility to deallocate string results when no
64 * Destructor for cleaning up string allocations.
67 * Reference to the string item to destroy.
69 * Any client data needed for destroying the string.
72 * TRUE is a requirement
74 static Boolean_t
StringListItemDestructor(void *ItemRef
,
75 ArbParam_t ClientData
)
77 char **StringRef
= (char **)ItemRef
;
79 REQUIRE(VALID_REF(StringRef
));
80 REQUIRE(VALID_REF(*StringRef
) || *StringRef
== NULL
);
82 if (*StringRef
!= NULL
)
84 FREE_ARRAY(*StringRef
, "string");
88 ENSURE(*StringRef
== NULL
);
93 * String item duplicator.
96 * Reference to the string list item to receive the duplicate.
98 * Reference to the string list item to duplicate.
100 * Any client data required for duplication.
103 * TRUE if the duplication was a success
104 * FALSE otherwise. If the duplication failed it
105 * is the client's responsibility to cleanup any
106 * partial duplication
108 static Boolean_t
StringListItemDuplicator(void *TargetItemRef
,
110 ArbParam_t ClientData
)
112 Boolean_t IsOk
= TRUE
;
113 char **TargetStringRef
= (char **)TargetItemRef
;
114 char **SourceStringRef
= (char **)SourceItemRef
;
116 REQUIRE(VALID_REF(TargetStringRef
));
117 REQUIRE(VALID_REF(SourceStringRef
));
118 REQUIRE(VALID_REF(*SourceStringRef
) || *SourceStringRef
== NULL
);
120 if (*SourceStringRef
!= NULL
)
121 IsOk
= ((*TargetStringRef
= DupString(dontTranslate(*SourceStringRef
))) != NULL
);
123 *TargetStringRef
= NULL
;
125 ENSURE(VALID_REF(*TargetStringRef
) || *TargetStringRef
== NULL
);
126 ENSURE(VALID_BOOLEAN(IsOk
));
132 * Determine if the string list handle and its members are sane.
134 Boolean_t
StringListValid(StringList_pa stringList
)
136 Boolean_t isValid
= ArrayListIsValid((ArrayList_pa
)stringList
);
140 LgIndex_t stringCount
= ArrayListGetCount((ArrayList_pa
)stringList
);
142 #if defined PERFORM_EXPENSIVE_STRLIST_TESTS
144 for (LgIndex_t index
= 0; index
< stringCount
; index
++)
146 char *string
= ArrayListGetCharPtr((ArrayList_pa
)stringList
, index
);
147 if (string
!= NULL
&& !VALID_REF(string
))
155 /* Check first and last only */
158 char *string
= ArrayListGetCharPtr((ArrayList_pa
)stringList
, 0);
159 if (string
!= NULL
&& !VALID_REF(string
))
164 if (isValid
&& stringCount
> 1)
166 char *string
= ArrayListGetCharPtr((ArrayList_pa
)stringList
, stringCount
- 1);
167 if (string
!= NULL
&& !VALID_REF(string
))
173 #endif /* PERFORM_SKIP_EXPENSIVE_STRLIST_TESTS */
176 ENSURE(VALID_BOOLEAN(isValid
));
182 * Remove all members of the string list.
184 void StringListClear(StringList_pa StringList
)
186 REQUIRE(StringListValid(StringList
));
188 ArrayListDeleteAllItems((ArrayList_pa
)StringList
, StringListItemDestructor
, 0);
190 ENSURE(StringListValid(StringList
) && StringListCount(StringList
) == 0);
195 * Remove 'Count' strings from the list beginning at the specified offset.
196 * The members following the items removed are shifted down accordingly to
197 * fill the vacated space.
199 void StringListRemoveStrings(StringList_pa StringList
,
200 LgIndex_t StringOffset
,
203 REQUIRE(StringListValid(StringList
));
204 REQUIRE(0 <= StringOffset
&& StringOffset
<= StringListCount(StringList
) - 1);
205 REQUIRE(1 <= Count
&& StringOffset
+ Count
<= StringListCount(StringList
));
207 ArrayListDeleteItems((ArrayList_pa
)StringList
, StringOffset
, Count
,
208 StringListItemDestructor
, 0);
210 ENSURE(StringListValid(StringList
));
215 * Remove the string from the list at the specified offset. The members
216 * following the item removed are shifted down accordingly to fill the
219 void StringListRemoveString(StringList_pa StringList
,
220 LgIndex_t StringOffset
)
222 REQUIRE(StringListValid(StringList
));
223 REQUIRE(0 <= StringOffset
&& StringOffset
<= StringListCount(StringList
) - 1);
225 ArrayListDeleteItems((ArrayList_pa
)StringList
, StringOffset
, 1,
226 StringListItemDestructor
, 0);
228 ENSURE(StringListValid(StringList
));
233 * Deallocate the string list members and handle and set the handle to NULL.
235 void LIBCALL
StringListDealloc(StringList_pa
*StringList
)
237 REQUIRE(VALID_REF(StringList
));
238 REQUIRE(*StringList
== NULL
|| StringListValid(*StringList
));
240 if (*StringList
!= NULL
)
241 ArrayListDealloc((ArrayList_pa
*)StringList
, StringListItemDestructor
, 0);
243 ENSURE(*StringList
== NULL
);
248 * Allocate a string list handle. A handle of NULL is
249 * returned if sufficient memory is not available.
251 StringList_pa
StringListAlloc(void)
253 StringList_pa Result
;
255 Result
= (StringList_pa
)ArrayListAlloc(0, ArrayListType_CharPtr
, NULL
, 0);
257 ENSURE(Result
== NULL
|| StringListValid(Result
));
263 * Append a copy of the string to the string list. The string list will be
264 * expanded to accommodate the additional item. A return value of TRUE
265 * indicates the operation was successful otherwise FALSE is returned
266 * indicating that sufficient memory was not available for the additional
269 Boolean_t
StringListAppendString(StringList_pa StringList
,
274 REQUIRE(StringListValid(StringList
));
275 REQUIRE(String
== NULL
|| VALID_REF(String
));
277 IsOk
= StringListSetString(StringList
, StringListCount(StringList
), String
);
279 ENSURE(StringListValid(StringList
));
280 ENSURE(VALID_BOOLEAN(IsOk
));
286 * Return the number of strings currently in the string list.
288 LgIndex_t LIBCALL
StringListCount(StringList_pa StringList
)
292 REQUIRE(StringListValid(StringList
));
294 Result
= ArrayListGetCount((ArrayList_pa
)StringList
);
302 * Return a copy of the string at the specified offset in the string list.
304 char * LIBCALL
StringListGetString(StringList_pa StringList
,
305 LgIndex_t StringOffset
)
308 const char *StringRef
;
310 REQUIRE(StringListValid(StringList
));
311 REQUIRE(0 <= StringOffset
&& StringOffset
<= StringListCount(StringList
) - 1);
313 StringRef
= StringListGetStringRef(StringList
, StringOffset
);
314 if (StringRef
== NULL
)
317 Result
= DupString(dontTranslate(StringRef
));
319 ENSURE(Result
== NULL
|| VALID_REF(Result
));
324 #if !defined USE_MACROS_FOR_FUNCTIONS
326 * Returns actual string at the specified offset in the string list. Do not
327 * attempt to free this string. Changing this string should be done with
330 const char *StringListGetStringRef_FUNC(StringList_pa StringList
,
331 LgIndex_t StringOffset
)
335 REQUIRE(StringListValid(StringList
));
336 REQUIRE(0 <= StringOffset
&& StringOffset
<= StringListCount(StringList
) - 1);
338 Result
= StringListGetStringRef_MACRO(StringList
, StringOffset
);
340 ENSURE(Result
== NULL
|| VALID_REF(Result
));
347 * Place a copy of the specified string at the specified offset. If the offset
348 * is beyond the end of the string list it is sized accordingly and the
349 * intervening string references between the last item of the original
350 * state and the last item of the new state are assigned NULL. If a string
351 * already exists at the specified location its resources are released.
352 * A return value of TRUE indicates the operation was successful otherwise
353 * FALSE is returned indicating that sufficient memory was not available
354 * for the additional item at the specified offset.
356 Boolean_t
StringListSetString(StringList_pa StringList
,
357 LgIndex_t StringOffset
,
361 ArrayListItem_u ItemCopy
;
363 REQUIRE(StringListValid(StringList
));
364 REQUIRE(StringOffset
>= 0);
365 REQUIRE(String
== NULL
|| VALID_REF(String
));
369 ItemCopy
.CharPtr
= DupString(dontTranslate(String
));
370 IsOk
= (ItemCopy
.CharPtr
!= NULL
);
374 ItemCopy
.CharPtr
= NULL
;
379 IsOk
= ArrayListSetItem((ArrayList_pa
)StringList
, StringOffset
, ItemCopy
,
380 StringListItemDestructor
, 0);
382 ENSURE(StringListValid(StringList
));
383 ENSURE(VALID_BOOLEAN(IsOk
));
389 * Insert a copy of the string into the string list at the specified offset.
390 * The string list will be expanded to accommodate the additional item.
391 * A return value of TRUE indicates the operation was successful otherwise
392 * FALSE is returned indicating that sufficient memory was not available
393 * for the additional item.
395 Boolean_t
StringListInsertString(StringList_pa StringList
,
396 LgIndex_t StringOffset
,
400 ArrayListItem_u ItemCopy
;
402 REQUIRE(StringListValid(StringList
));
403 REQUIRE(StringOffset
>= 0);
404 REQUIRE(String
== NULL
|| VALID_REF(String
));
408 ItemCopy
.CharPtr
= DupString(dontTranslate(String
));
409 IsOk
= (ItemCopy
.CharPtr
!= NULL
);
413 ItemCopy
.CharPtr
= NULL
;
418 IsOk
= ArrayListInsertItem(
419 (ArrayList_pa
)StringList
, StringOffset
, ItemCopy
);
421 ENSURE(StringListValid(StringList
));
422 ENSURE(VALID_BOOLEAN(IsOk
));
428 * Return a handle to a duplicate of the specified string list and its contents.
429 * A handle of NULL is returned if sufficient memory is not available.
431 StringList_pa
StringListCopy(StringList_pa StringList
)
433 StringList_pa Result
;
435 REQUIRE(StringListValid(StringList
));
437 Result
= (StringList_pa
)ArrayListCopy((ArrayList_pa
)StringList
,
438 StringListItemDuplicator
, 0);
440 ENSURE(Result
== NULL
||
441 (StringListValid(Result
) &&
442 StringListCount(Result
) == StringListCount(StringList
)));
449 * Append a copy of the contents of the source list to the target list.
450 * A return value of TRUE indicates the operation was successful otherwise
451 * FALSE is returned indicating that sufficient memory was not available
454 Boolean_t
StringListAppend(StringList_pa Target
,
455 StringList_pa Source
)
458 StringList_pa SourceCopy
;
460 REQUIRE(StringListValid(Target
));
461 REQUIRE(StringListValid(Source
));
463 SourceCopy
= StringListCopy(Source
);
464 IsOk
= (SourceCopy
!= NULL
);
467 ArrayListAppend((ArrayList_pa
)Target
, (ArrayList_pa
)SourceCopy
);
468 /* deallocate the list but not the string items since Target now owns them */
469 ArrayListDealloc((ArrayList_pa
*)(void *)&SourceCopy
, NULL
, 0);
472 ENSURE(StringListValid(Target
));
473 ENSURE(VALID_BOOLEAN(IsOk
));
480 * Return a new line, '\n', separated string representation of the string list.
481 * Caller is responsible for de-allocating the result.
483 char *StringListToNLString(StringList_pa StringList
)
489 REQUIRE(StringListValid(StringList
));
491 /* determine the resulting new line, '\n', separated string length */
492 Count
= StringListCount(StringList
);
496 for (Index
= 0, Length
= strlen("\n") * (Count
- 1);
500 char *String
= ArrayListGetCharPtr((ArrayList_pa
)StringList
, Index
);
502 Length
+= strlen(String
);
506 /* create a new line, '\n', separated string */
507 Result
= ALLOC_ARRAY(Length
+ 1, char, "new line separated string");
511 for (Index
= 0, strcpy(Result
, "");
515 char *String
= ArrayListGetCharPtr(
516 (ArrayList_pa
)StringList
, Index
);
519 strcat(Result
, "\n");
522 strcat(Result
, String
);
526 ENSURE(Result
== NULL
|| VALID_REF(Result
));
532 * Create a string list from the new line, '\n', separated string. The string
533 * is copied and therefore owned and managed by the caller.
535 StringList_pa
StringListFromNLString(const char *String
)
537 StringList_pa Result
;
538 LgIndex_t StartIndex
;
541 REQUIRE(VALID_REF(String
));
543 /* create the string list and scan the entire string */
544 Result
= StringListAlloc();
545 for (StartIndex
= EndIndex
= 0; Result
!= NULL
; EndIndex
++)
547 /* end of sub-string ? */
548 if (String
[EndIndex
] == '\n' || String
[EndIndex
] == '\0')
550 /* extract the sub-string and append it to the string list */
551 LgIndex_t Length
= EndIndex
- StartIndex
;
552 char *SubString
= ALLOC_ARRAY(Length
+ 1, char, "sub string");
553 if (SubString
!= NULL
)
555 CopySubString(SubString
, String
, StartIndex
, Length
);
556 StringListAppendString(Result
, SubString
);
558 FREE_ARRAY(SubString
, "sub string");
560 if (String
[EndIndex
] != '\0')
561 StartIndex
= EndIndex
+ 1;
563 break; /* nothing left to scan */
567 /* memory allocation failure: bail out */
568 StringListDealloc(&Result
);
575 ENSURE(Result
== NULL
|| StringListValid(Result
));
581 * Return a 'C' string array representation of the string list.
582 * Caller is responsible for de-allocating the result.
584 char **StringListToArray(StringList_pa StringList
)
588 REQUIRE(StringListValid(StringList
));
590 Result
= (char **)ArrayListToArray((ArrayList_pa
)StringList
,
591 StringListItemDuplicator
, 0);
593 ENSURE(Result
== NULL
|| VALID_REF(Result
));
600 * Create a string list from the 'C' string array. The string array
601 * is copied and therefore owned and managed by the caller.
603 StringList_pa
StringListFromArray(const char **StringArray
,
606 StringList_pa Result
;
608 REQUIRE((Count
== 0 && StringArray
== NULL
) ||
609 (Count
>= 1 && VALID_REF(StringArray
)));
611 Result
= (StringList_pa
)ArrayListFromArray((void *)StringArray
,
612 Count
, ArrayListType_CharPtr
,
613 StringListItemDuplicator
, 0);
615 ENSURE(Result
== NULL
|| StringListValid(Result
));
621 #define ISJOINCHAR(c) ((c == ';') || (c == '+'))
623 static void SkipWhiteSpaceOrComma(const char **CPtr
)
625 REQUIRE(VALID_REF(CPtr
) && VALID_REF(*CPtr
));
626 while (ISWHITESPACE(**CPtr
) || (**CPtr
== ','))
631 * Obtain the next sub-string. This can be of the form:
633 * [del]any-character-sequence[del]
637 * limited-character-sequence
639 * where a limited-character-sequence cannot contain
640 * any of the following characters: +;,<space>
643 static Boolean_t
GetNextSubString(const char **OriginalCPtr
,
644 char **NextSubString
)
646 Boolean_t IsOk
= TRUE
;
649 char InsideDelimiter
= '\0';
651 REQUIRE(VALID_REF(OriginalCPtr
) && (VALID_REF(*OriginalCPtr
)));
652 REQUIRE(VALID_REF(NextSubString
));
654 *NextSubString
= NULL
;
656 CPtr
= *OriginalCPtr
;
657 SkipWhiteSpaceOrComma(&CPtr
);
659 if (*CPtr
== '"' || *CPtr
== '\'')
661 InsideDelimiter
= *CPtr
;
668 ((InsideDelimiter
&& (*CPtr
!= InsideDelimiter
)) ||
669 (!InsideDelimiter
&& (*CPtr
!= ',') &&
670 !ISJOINCHAR(*CPtr
) &&
671 !ISWHITESPACE(*CPtr
))))
673 if (InsideDelimiter
&&
675 (*(CPtr
+ 1) == InsideDelimiter
))
681 if (InsideDelimiter
&& (*CPtr
!= InsideDelimiter
))
685 if (IsOk
&& CStart
< CPtr
)
687 size_t StrLen
= (size_t)(CPtr
- CStart
);
688 *NextSubString
= ALLOC_ARRAY(StrLen
+ 1, char, "GetNextSubString: NextSubString");
691 char *NPtr
= *NextSubString
;
693 * Don't just copy the string because escaped delimiters need to have
694 * the escape removed...
696 while (CStart
< CPtr
)
698 if ((*CStart
== '\\') && (*(CStart
+ 1) == InsideDelimiter
))
712 SkipWhiteSpaceOrComma(&CPtr
);
713 *OriginalCPtr
= CPtr
;
716 ENSURE(VALID_BOOLEAN(IsOk
));
724 * Return a string list representation of a compound string.
726 * The compound String parameter has the following form:
728 * [del]<character-sequence>[del] [GroupJoinCharacter] [del]<character-sequence>[del] [GroupJoinCharacter] .....
730 * <nospace-character-sequence> <nospace-character-sequence> ...
733 * [del] is an optional single quote or a double quote. [del] must be used
734 * if <character-sequence> contains spaces, commas, or the plus symbol.
736 * GroupJoinCharacter can be either a "+" or a ";"
738 * The GroupJoinCharacter symbol is used to separate character sequences that
739 * are to be grouped together. If the GroupJoinCharacter symbol is omitted then
740 * a new group is started.
742 * Internally, the original string is converted to a list of strings where
743 * each string uses newlines to separate one sub-string from the next.
745 StringList_pa
StringListFromCompound(const char *String
)
748 StringList_pa Result
;
749 Boolean_t IsOk
= TRUE
;
750 char *CurString
= NULL
;
752 REQUIRE(VALID_REF(String
));
753 SkipWhiteSpaceOrComma(&String
);
754 REQUIRE(!ISJOINCHAR(*String
));
756 /* extract character sequences */
757 Result
= StringListAlloc();
760 while (IsOk
&& *CPtr
!= '\0')
762 char *NextSubString
= NULL
;
763 Boolean_t WantsToJoin
= FALSE
;
765 if (ISJOINCHAR(*CPtr
))
769 SkipWhiteSpaceOrComma(&CPtr
);
772 IsOk
= GetNextSubString(&CPtr
,
778 * Tack on the sub-string to the running string.
781 TackOnChar(&CurString
, '\n');
782 if (NextSubString
!= NULL
&& strlen(NextSubString
) != 0)
783 IsOk
= TackOnString(&CurString
, NextSubString
, FALSE
, FALSE
);
784 else if (CurString
== NULL
)
785 CurString
= DupString(dontTranslate(""));
788 if (NextSubString
!= NULL
)
789 FREE_ARRAY(NextSubString
, "StringListFromCompound: NextSubString");
792 * If this is the end of processing or if the next character is
793 * not a join character then add the current string to the stringlist.
796 if (IsOk
&& !ISJOINCHAR(*CPtr
))
798 StringListAppendString(Result
, CurString
);
799 if (CurString
!= NULL
)
800 FREE_ARRAY(CurString
, "current string");
805 if (CurString
!= NULL
)
806 FREE_ARRAY(CurString
, "current string");
809 StringListDealloc(&Result
);
811 ENSURE(Result
== NULL
|| StringListValid(Result
));
817 * Return a compound string representation of a string list.
819 * One common usage in Tecplot:
820 * The $!OpenLayout command in tecplot has the sub-option
821 * ALTDATALOADINSTRUCTIONS that has the form:
822 * '"instr-string1" [GroupJoinCharacter] "instr-string2" [+] ...'
824 char *StringListToCompound(StringList_pa StringList
,
825 char GroupJoinCharacter
,
826 const char *CharsToEscape
)
828 Boolean_t IsOk
= TRUE
;
833 REQUIRE(StringListValid(StringList
));
834 REQUIRE(StringListCount(StringList
) >= 1);
835 REQUIRE(ISJOINCHAR(GroupJoinCharacter
));
836 REQUIRE(VALID_REF(CharsToEscape
));
838 for (Index
= 0, Count
= StringListCount(StringList
), IsOk
= TRUE
;
839 Index
< Count
&& IsOk
;
842 char *String
= StringListGetString(StringList
, Index
);
844 if (String
!= NULL
&& strlen(String
) != 0)
848 char *EscapedString
= NULL
;
849 const char *EscChar
= NULL
;
850 char *StrChar
= NULL
;
852 /* First scan the string and escape any specified characters. */
853 /* Note that the Escape sequence is a double backslash because */
854 /* it the first escape escapes the escape for variable usage. */
855 for (StrChar
= String
; *StrChar
!= '\0'; StrChar
++)
857 for (EscChar
= CharsToEscape
; *EscChar
!= '\0'; EscChar
++)
858 if (*StrChar
== *EscChar
)
860 IsOk
= TackOnChar(&EscapedString
, '\\');
861 IsOk
= TackOnChar(&EscapedString
, '\\');
864 IsOk
= TackOnChar(&EscapedString
, *StrChar
);
867 CEnd
= EscapedString
;
868 while (IsOk
&& *CEnd
!= '\0')
874 while (*CEnd
!= '\0' && *CEnd
!= '\n')
882 TString
= ALLOC_ARRAY(Len
+ 4, char, "temp compound sub-string");
887 /* prepend the new string with either */
888 /* a space character or the plus symbol */
889 if (CStart
== EscapedString
)
892 IsOk
= TackOnChar(&Result
, ' ');
896 IsOk
= TackOnChar(&Result
, GroupJoinCharacter
);
899 /* stuff TString and append the new string */
902 while (CStart
!= CEnd
)
911 TackOnString(&Result
, TString
, FALSE
, FALSE
);
912 FREE_ARRAY(TString
, "StringListToCompound");
923 if (EscapedString
!= NULL
)
924 FREE_ARRAY(EscapedString
, "escaped string");
928 /* a null pointer or length of zero indicates an empty sub-string */
930 TackOnString(&Result
, "\"\"", FALSE
, FALSE
);
932 TackOnString(&Result
, " \"\"", FALSE
, FALSE
);
936 FREE_ARRAY(String
, "string list item");
943 FREE_ARRAY(Result
, "StringListToCompound");
948 ENSURE(Result
== NULL
|| VALID_REF(Result
));
954 * Holds the comparator function pointer.
956 static StringListStringComparator_pf ComparatorFunction
= NULL
;
960 * Forwards the comparison test to the 'Comparator' supplied to the
961 * 'StringListSort' function.
964 * Item to compare against Item2.
966 * Item to compare against Item1.
968 * Contextual information that was passed to the 'ArrayListQSort' function.
971 * -1: if Item1 is less than Item2
972 * 0: if Item1 is equal to Item2
973 * 1: if Item1 is greater than Item2
975 static int STDCALL
ComparatorProxy(ArrayListItem_u Item1
,
976 ArrayListItem_u Item2
,
977 ArbParam_t ClientData
)
979 /* forward the request */
980 return ComparatorFunction(Item1
.CharPtr
, Item2
.CharPtr
, ClientData
);
985 * Compares two strings from a list string. Note that either string may be
986 * NULL as StringLists allow for NULL elements.
989 * String to compare against String2.
991 * String to compare against String1.
993 * Contextual information that was passed to the 'StringListSort' function.
996 * - A value less than zero if String1 is less than String2.
997 * - A value of zero if String1 is equal to String2.
998 * - A value greater than zero if String1 is greater than String2.
1000 static int STDCALL
DefaultStrcmpComparator(const char *String1
,
1001 const char *String2
,
1002 ArbParam_t ClientData
)
1004 int Result
= 0; /* ...quite compiler */
1006 REQUIRE(VALID_REF(String1
) || String1
== NULL
);
1007 REQUIRE(VALID_REF(String2
) || String2
== NULL
);
1009 if (String1
!= NULL
&& String2
!= NULL
)
1011 Result
= strcmp(String1
, String2
);
1014 else if (Result
> 0)
1017 else if (String1
== NULL
&& String2
== NULL
)
1019 else if (String1
== NULL
)
1021 else if (String2
== NULL
)
1026 ENSURE((Result
== -1) || (Result
== 0) || (Result
== 1));
1031 * Sorts the string list by repeatedly calling the 'Comparator' function until
1032 * the list is in order.
1035 * String list to sort.
1037 * Function called to compare two string list strings or NULL for the
1038 * default sort. The default sorting handles NULL elements and uses the
1039 * system's strcmp utility for comparing valid strings elements.
1041 * Contextual information that is passed along to the comparator function.
1043 void StringListSort(StringList_pa StringList
,
1044 StringListStringComparator_pf Comparator
,
1045 ArbParam_t ClientData
)
1047 #if defined TECPLOTKERNEL
1048 /* CORE SOURCE CODE REMOVED */
1050 REQUIRE(VALID_REF(StringList
));
1051 REQUIRE(VALID_FN_REF(Comparator
) || Comparator
== NULL
);
1053 /* set up for comparator proxy */
1054 if (Comparator
!= NULL
)
1055 ComparatorFunction
= Comparator
;
1057 ComparatorFunction
= DefaultStrcmpComparator
;
1059 /* sort the array using the comparator proxy to forward */
1060 /* the comparison request to the supplied comparator */
1061 ArrayListQSort((ArrayList_pa
)StringList
, ComparatorProxy
, ClientData
);
1064 ComparatorFunction
= NULL
;