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 *****************************************************************
42 #include "Q_UNICODE.h"
48 #if defined TECPLOTKERNEL
49 /* CORE SOURCE CODE REMOVED */
54 using namespace tecplot::strutil
;
57 * Private auxiliary data item structure.
68 * Private auxiliary data item container structure.
70 typedef struct _AuxData_s
72 /* invariant: ItemList is case-insensitive sorted by AuxDataItem->Name */
73 ArrayList_pa ItemList
; /* <AuxDataItem_s *>[dynamic] */
76 static Mutex_pa AuxDataMutex
= NULL
;
80 * A valid auxiliary data name character must begin with a '_' or alpha
81 * character and may be followed by one or more '_', '.', alpha or digit
84 Boolean_t
AuxDataIsValidNameChar(char Char
,
87 Boolean_t IsValidNameChar
;
89 REQUIRE("Char can be any value");
90 REQUIRE(VALID_BOOLEAN(IsLeadChar
));
92 IsValidNameChar
= (Char
== '_' ||
95 IsValidNameChar
= (IsValidNameChar
||
99 ENSURE(VALID_BOOLEAN(IsValidNameChar
));
100 return IsValidNameChar
;
104 * Indicates if the auxiliary data name is valid. A valid auxiliary data name
105 * must begin with a '_' or alpha character and may be followed by one or
106 * more '_', '.', alpha or digit characters.
108 Boolean_t
AuxDataIsValidName(const char *Name
)
110 Boolean_t IsValidName
;
112 REQUIRE(VALID_REF(Name
));
114 for (NPtr
= Name
, IsValidName
= AuxDataIsValidNameChar(*NPtr
, TRUE
);
115 IsValidName
&& *NPtr
!= '\0';
118 IsValidName
= AuxDataIsValidNameChar(*NPtr
, FALSE
);
121 ENSURE(VALID_BOOLEAN(IsValidName
));
126 * Deallocates an auxiliary data item and its contents and sets the target to
130 * Reference to an auxiliary data item.
132 static void AuxDataItemDealloc(AuxDataItem_s
**AuxDataItem
)
134 REQUIRE(VALID_REF(AuxDataItem
));
135 REQUIRE(VALID_REF(*AuxDataItem
) || *AuxDataItem
== NULL
);
137 if (*AuxDataItem
!= NULL
)
139 char *Name
= (char *)(*AuxDataItem
)->Name
;
141 FREE_ARRAY(Name
, "auxiliary name");
143 if ((*AuxDataItem
)->Type
== AuxDataType_String
)
145 char *Value
= (char *)(*AuxDataItem
)->Value
;
147 FREE_ARRAY(Value
, "auxiliary value");
152 FREE_ITEM(*AuxDataItem
, "auxiliary data item");
156 ENSURE(*AuxDataItem
== NULL
);
160 * Allocates an auxiliary data item.
162 * NOTE: Copies are made of the name and value.
165 * Auxiliary data item's name (case insenstive).
167 * Auxiliary data item's value.
169 * Auxiliary data item's value type.
171 * Indicates if the auxiliary data item should persist. In other words
172 * copied, saved, etc.
175 * A new auxiliary data item or NULL if sufficient memory was not
178 static AuxDataItem_s
*AuxDataItemAlloc(const char *Name
,
183 AuxDataItem_s
*Result
;
185 REQUIRE(VALID_REF(Name
) && AuxDataIsValidName(Name
));
186 REQUIRE(IMPLICATION(Type
== AuxDataType_String
,
187 (VALID_REF((char *)Value
) ||
188 (char *)Value
== NULL
)));
189 REQUIRE(VALID_ENUM(Type
, AuxDataType_e
));
190 REQUIRE(VALID_BOOLEAN(Retain
));
192 Result
= ALLOC_ITEM(AuxDataItem_s
, "auxiliary data item");
197 Result
->Retain
= Retain
;
198 Result
->Name
= DupString(dontTranslate(Name
));
199 IsOk
= (Result
->Name
!= NULL
);
200 Result
->Value
= 0; /* to satisfy some compilers' uninitialized warnings */
201 if (IsOk
&& Type
== AuxDataType_String
)
203 char *strValue
= (char *)Value
;
204 if (strValue
!= NULL
)
206 char *strCopy
= DupString(dontTranslate(strValue
));
207 Result
->Value
= (ArbParam_t
)strCopy
;
208 IsOk
= (strCopy
!= NULL
);
211 Result
->Value
= (ArbParam_t
)NULL
;
217 AuxDataItemDealloc(&Result
);
220 ENSURE(VALID_REF(Result
) || Result
== NULL
);
225 * Destroys an auxiliary data item list item. This is an item destructor
226 * callback for ArrayList's private data.
229 * Reference to the auxiliary data item to cleanup.
234 * TRUE is a requirement
236 static Boolean_t
AuxDataItemListItemDestructor(void *ItemRef
,
237 ArbParam_t ClientData
)
239 AuxDataItem_s
**AuxDataItemRef
= (AuxDataItem_s
**)ItemRef
;
241 REQUIRE(VALID_REF(AuxDataItemRef
));
242 REQUIRE(VALID_REF(*AuxDataItemRef
) || *AuxDataItemRef
== NULL
);
244 if (*AuxDataItemRef
!= NULL
)
245 AuxDataItemDealloc(AuxDataItemRef
);
247 ENSURE(*AuxDataItemRef
== NULL
);
252 * Destroys an auxiliary data item. This is an item destructor
253 * callback for ArrayList's private data.
256 * Reference to the auxiliary data to cleanup.
261 * TRUE is a requirement
263 Boolean_t
AuxDataItemDestructor(void *ItemRef
,
264 ArbParam_t ClientData
)
266 AuxData_pa
*AuxDataRef
= (AuxData_pa
*)ItemRef
;
268 REQUIRE(VALID_REF(AuxDataRef
));
269 REQUIRE(VALID_REF(*AuxDataRef
) || *AuxDataRef
== NULL
);
271 if (*AuxDataRef
!= NULL
)
272 AuxDataDealloc(AuxDataRef
);
274 ENSURE(*AuxDataRef
== NULL
);
280 * Duplicates an auxiliary data item if its Retain flag is TRUE or if directed
281 * by the callback data. This is an item duplicator callback for ArrayList.
283 * param TargetItemRef
284 * Reference to the auxiliary data item to receive duplicate.
285 * param SourceItemRef
286 * Reference to the auxiliary data item to duplicate.
288 * Boolean indicating if the Retain flag should be considered.
291 * TRUE if the duplication was a success
294 static Boolean_t
AuxDataItemDuplicator(void *TargetItemRef
,
296 ArbParam_t ClientData
)
298 Boolean_t IsOk
= TRUE
;
299 AuxDataItem_s
**TargetAuxDataItemRef
= (AuxDataItem_s
**)TargetItemRef
;
300 AuxDataItem_s
**SourceAuxDataItemRef
= (AuxDataItem_s
**)SourceItemRef
;
301 Boolean_t ConsiderRetain
;
303 REQUIRE(VALID_REF(TargetAuxDataItemRef
));
304 REQUIRE(VALID_REF(SourceAuxDataItemRef
));
305 REQUIRE(VALID_REF(*SourceAuxDataItemRef
) || *SourceAuxDataItemRef
== NULL
);
306 REQUIRE(VALID_BOOLEAN((Boolean_t
)ClientData
));
308 ConsiderRetain
= (Boolean_t
)ClientData
;
310 /* duplicate the item */
311 if (*SourceAuxDataItemRef
!= NULL
&&
312 (!ConsiderRetain
|| (*SourceAuxDataItemRef
)->Retain
))
314 *TargetAuxDataItemRef
= AuxDataItemAlloc((*SourceAuxDataItemRef
)->Name
,
315 (*SourceAuxDataItemRef
)->Value
,
316 (*SourceAuxDataItemRef
)->Type
,
317 (*SourceAuxDataItemRef
)->Retain
);
318 IsOk
= (*TargetAuxDataItemRef
!= NULL
);
321 *TargetAuxDataItemRef
= NULL
;
323 ENSURE(VALID_REF(*TargetAuxDataItemRef
) || *TargetAuxDataItemRef
== NULL
);
324 ENSURE(VALID_BOOLEAN(IsOk
));
329 * Deallocates an auxiliary data handle and sets the handle to NULL.
332 * Reference to an auxiliary data handle or reference to NULL.
334 void AuxDataDealloc(AuxData_pa
*AuxData
)
336 REQUIRE(VALID_REF(AuxData
));
337 REQUIRE(VALID_REF(*AuxData
) || *AuxData
== NULL
);
339 if (*AuxData
!= NULL
)
341 ArrayListDealloc(&(*AuxData
)->ItemList
, AuxDataItemListItemDestructor
, 0);
342 FREE_ITEM(*AuxData
, "auxiliary data container");
346 ENSURE(*AuxData
== NULL
);
350 * Allocates an auxiliary data handle.
353 * Auxiliary data handle or NULL if sufficient memory was not available.
355 AuxData_pa
AuxDataAlloc(void)
357 AuxData_pa Result
= ALLOC_ITEM(AuxData_s
, "auxiliary data container");
360 Result
->ItemList
= ArrayListAlloc(0, ArrayListType_VoidPtr
, NULL
, 0);
361 if (Result
->ItemList
== NULL
)
362 AuxDataDealloc(&Result
);
365 ENSURE(VALID_REF(Result
) || Result
== NULL
);
370 * Copies the auxiliary data and all its members who's Retain flag is TRUE
371 * if the ConsiderRetain flag is TRUE otherwise it copies everything.
373 AuxData_pa
AuxDataCopy(AuxData_pa AuxData
,
374 Boolean_t ConsiderRetain
)
378 REQUIRE(VALID_REF(AuxData
));
379 REQUIRE(VALID_BOOLEAN(ConsiderRetain
));
381 Result
= ALLOC_ITEM(AuxData_s
, "auxiliary data container");
384 Result
->ItemList
= ArrayListCopy(AuxData
->ItemList
,
385 AuxDataItemDuplicator
,
387 if (Result
->ItemList
!= NULL
)
392 * Now pass through the array cleaning up the holes left by those
393 * auxiliary data item member who's Retain flag was FALSE and
394 * therefore left a VOID pointer because it was not copied.
396 LgIndex_t ItemOffset
= 0;
397 LgIndex_t ItemCount
= ArrayListGetCount(Result
->ItemList
);
398 while (ItemOffset
< ItemCount
)
400 /* if there is more than one in a row remove them all at once */
401 if (ArrayListGetVoidPtr(Result
->ItemList
, ItemOffset
) == NULL
)
403 LgIndex_t BaseOffsetToRemove
= ItemOffset
;
404 LgIndex_t NumItemsToRemove
= 1;
405 while (BaseOffsetToRemove
+ NumItemsToRemove
< ItemCount
&&
406 ArrayListGetVoidPtr(Result
->ItemList
,
407 BaseOffsetToRemove
+ NumItemsToRemove
) == NULL
)
410 /* delete the NULL items */
411 ArrayListDeleteItems(Result
->ItemList
,
417 * Update ItemCount but leave ItemOffset alone as it is now
418 * indexing the next item to examine.
420 ItemCount
= ArrayListGetCount(Result
->ItemList
);
428 AuxDataDealloc(&Result
);
431 ENSURE(VALID_REF(Result
) || Result
== NULL
);
436 * Gets the current number of auxiliary data items maintained by the auxiliary.
439 * Handle to auxiliary data.
442 * Number of items maintained by the auxiliary data.
444 LgIndex_t
AuxDataGetNumItems(AuxData_pa AuxData
)
448 REQUIRE(VALID_REF(AuxData
));
450 NumItems
= ArrayListGetCount(AuxData
->ItemList
);
452 ENSURE(NumItems
>= 0);
457 * Gets the item index of the name if found or if not found the index where an
458 * auxiliary data item could be inserted.
461 * Handle to auxiliary data.
463 * Name used for the search (case insensitive).
465 * Address to hold the index of the found item or the index where an
466 * auxiliary data item could be inserted.
469 * TRUE if the named item was found,
472 Boolean_t
AuxDataGetItemIndex(AuxData_pa AuxData
,
474 LgIndex_t
*ItemIndex
)
476 Boolean_t FoundItem
= FALSE
;
480 REQUIRE(VALID_REF(AuxData
));
481 INVARIANT("AuxData->ItemList is case-insensitive sorted by AuxDataItem->Name");
482 REQUIRE(VALID_REF(Name
) && AuxDataIsValidName(Name
));
483 REQUIRE(VALID_REF(ItemIndex
));
486 * Note that the current implementation just does a linear search
487 * though the array looking for the index of the item or if not
488 * found the index of the insertion point. This should be replaced
489 * with a binary search.
491 NumItems
= AuxDataGetNumItems(AuxData
);
493 # if defined DO_LINEAR_SEARCH
495 for (Index
= 0; Index
< NumItems
; Index
++)
497 AuxDataItem_s
*AuxDataItem
=
498 (AuxDataItem_s
*)ArrayListGetVoidPtr(AuxData
->ItemList
, Index
);
499 int CompareResult
= ustrcmp(AuxDataItem
->Name
, Name
);
500 if (CompareResult
>= 0)
502 FoundItem
= (CompareResult
== 0);
515 AuxDataItem_s
*AuxDataItem
;
517 Index
= (low
+ high
) / 2;
518 AuxDataItem
= (AuxDataItem_s
*)ArrayListGetVoidPtr(AuxData
->ItemList
, Index
);
519 CompareResult
= ustrcmp(Name
, AuxDataItem
->Name
);
520 if (CompareResult
< 0)
521 high
= Index
- 1; /* If the new name is "less" than the one we're comparing to,
522 don't change Index since Index is already in the right spot */
523 else if (CompareResult
> 0)
524 low
= ++Index
; /* If the new name it "greater" than the one we're comparing
525 against, we want to make sure its Index is greater than
526 the current name's index as well, that's why we increment Index here. */
538 ENSURE(VALID_BOOLEAN(FoundItem
));
539 ENSURE(0 <= *ItemIndex
&&
540 ((FoundItem
&& *ItemIndex
< NumItems
) ||
541 (!FoundItem
&& *ItemIndex
<= NumItems
)));
546 * Gets the auxiliary data item at the specified index.
548 * NOTE: The name and value are a references, NOT copies.
551 * Handle to auxiliary data.
553 * Index of the auxiliary data item of interest.
555 * Address to hold the auxiliary data item name.
557 * Address to hold the auxiliary data item value.
559 * Address to hold the auxiliary data item type.
561 * Address to hold the auxiliary data item retain flag.
563 void AuxDataGetItemByIndex(AuxData_pa AuxData
,
570 AuxDataItem_s
*AuxDataItem
;
572 REQUIRE(VALID_REF(AuxData
));
573 INVARIANT("AuxData->ItemList is case-insensitive sorted by AuxDataItem->Name");
574 REQUIRE(0 <= Index
&& Index
< ArrayListGetCount(AuxData
->ItemList
));
575 REQUIRE(VALID_REF(Name
));
576 REQUIRE(VALID_REF(Value
));
577 REQUIRE(VALID_REF(Type
));
578 REQUIRE(VALID_REF(Retain
));
580 AuxDataItem
= (AuxDataItem_s
*)ArrayListGetVoidPtr(AuxData
->ItemList
, Index
);
581 *Name
= AuxDataItem
->Name
;
582 *Value
= AuxDataItem
->Value
;
583 *Type
= AuxDataItem
->Type
;
584 *Retain
= AuxDataItem
->Retain
;
586 ENSURE(VALID_REF(*Name
) && AuxDataIsValidName(*Name
));
587 ENSURE(IMPLICATION(*Type
== AuxDataType_String
,
588 (VALID_REF((char *)(*Value
)) ||
589 (char *)(*Value
) == NULL
)));
590 ENSURE(VALID_ENUM(*Type
, AuxDataType_e
));
591 ENSURE(VALID_BOOLEAN(*Retain
));
595 * Gets the auxiliary data item by the specified name if it exists.
597 * NOTE: The name and value are a references, NOT copies.
600 * Handle to auxiliary data.
602 * Name used for the search (case insensitive).
604 * Address to hold the auxiliary data item value.
606 * Address to hold the auxiliary data item type.
608 * Address to hold the auxiliary data item retain flag.
611 * TRUE if the an auxilary data item by the specified name was found,
614 Boolean_t
AuxDataGetItemByName(AuxData_pa AuxData
,
623 REQUIRE(VALID_REF(AuxData
));
624 INVARIANT("AuxData->ItemList is case-insensitive sorted by AuxDataItem->Name");
625 REQUIRE(VALID_REF(Name
) && AuxDataIsValidName(Name
));
626 REQUIRE(VALID_REF(Value
));
627 REQUIRE(VALID_REF(Type
));
628 REQUIRE(VALID_REF(Retain
));
630 FoundItem
= AuxDataGetItemIndex(AuxData
, Name
, &ItemIndex
);
633 const char *SameName
;
634 AuxDataGetItemByIndex(AuxData
, ItemIndex
, &SameName
,
635 Value
, Type
, Retain
);
636 CHECK(ustrcmp(Name
, SameName
) == 0);
639 ENSURE(VALID_BOOLEAN(FoundItem
));
640 ENSURE(IMPLICATION(FoundItem
,
641 IMPLICATION(*Type
== AuxDataType_String
,
642 (VALID_REF((char *)(*Value
)) ||
643 (char *)(*Value
) == NULL
))));
644 ENSURE(IMPLICATION(FoundItem
,
645 VALID_ENUM(*Type
, AuxDataType_e
)));
646 ENSURE(IMPLICATION(FoundItem
,
647 VALID_BOOLEAN(*Retain
)));
653 * Get a string value from AuxData and convert it to a boolean.
655 Boolean_t
AuxDataGetBooleanItemByName(AuxData_pa AuxData
, /* IN */
656 const char *Name
, /* IN */
657 Boolean_t
*Value
, /* OUT */
658 AuxDataType_e
*Type
, /* OUT */
659 Boolean_t
*Retain
) /* OUT */
663 REQUIRE(VALID_REF(AuxData
));
664 INVARIANT("AuxData->ItemList is case-insensitive sorted by AuxDataItem->Name");
665 REQUIRE(VALID_REF(Name
) && AuxDataIsValidName(Name
));
666 REQUIRE(VALID_REF(Value
));
667 REQUIRE(VALID_REF(Type
));
668 REQUIRE(VALID_REF(Retain
));
671 FoundItem
= AuxDataGetItemByName(AuxData
,
678 (ustrcmp((char *)strValue
, "YES") == 0 ||
679 ustrcmp((char *)strValue
, "YEP") == 0 ||
680 ustrcmp((char *)strValue
, "Y") == 0 ||
681 ustrcmp((char *)strValue
, "TRUE") == 0 ||
682 ustrcmp((char *)strValue
, "T") == 0 ||
683 ustrcmp((char *)strValue
, "ON") == 0 ||
684 ustrcmp((char *)strValue
, "1") == 0))
693 ENSURE(VALID_BOOLEAN(FoundItem
));
694 ENSURE(VALID_BOOLEAN(*Value
));
700 * Adds the auxiliary data item to the auxiliary data or replaces it if one
701 * already exists by the same name.
703 * NOTE: The auxiliary data makes copies of the name and value.
706 * Auxiliary data handle.
708 * Auxiliary data item's name (case insenstive).
710 * Auxiliary data item's value.
712 * Auxiliary data item's value type.
714 * Indicates if the auxiliary data item should persist.
717 * TRUE if the item was added to the auxiliary data.
719 Boolean_t
AuxDataSetItem(AuxData_pa AuxData
,
726 AuxDataItem_s
*AuxDataItem
;
728 REQUIRE(VALID_REF(AuxData
));
729 INVARIANT("AuxData->ItemList is case-insensitive sorted by AuxDataItem->Name");
730 REQUIRE(VALID_REF(Name
) && AuxDataIsValidName(Name
));
731 REQUIRE(IMPLICATION(Type
== AuxDataType_String
,
732 (VALID_REF((char *)Value
) ||
733 (char *)Value
== NULL
)));
734 REQUIRE(VALID_ENUM(Type
, AuxDataType_e
));
735 REQUIRE(VALID_BOOLEAN(Retain
));
737 AuxDataItem
= AuxDataItemAlloc(Name
, Value
, Type
, Retain
);
738 IsOk
= (AuxDataItem
!= NULL
);
742 ArrayListItem_u ListItem
;
744 /* add or replace the item to the list */
745 ListItem
.VoidPtr
= (void *)AuxDataItem
;
746 if (!AuxDataGetItemIndex(AuxData
, Name
, &ItemIndex
))
747 IsOk
= ArrayListInsertItem(AuxData
->ItemList
, ItemIndex
, ListItem
);
749 IsOk
= ArrayListSetItem(AuxData
->ItemList
, ItemIndex
, ListItem
,
750 AuxDataItemListItemDestructor
, 0);
753 AuxDataItemDealloc(&AuxDataItem
);
756 ENSURE(VALID_BOOLEAN(IsOk
));
757 INVARIANT("AuxData->ItemList is case-insensitive sorted by AuxDataItem->Name");
762 * Deletes the auxiliary data item at the specified index.
765 * Auxiliary data handle.
767 * Index of the auxiliary data item of interest.
769 void AuxDataDeleteItemByIndex(AuxData_pa AuxData
,
772 REQUIRE(VALID_REF(AuxData
));
773 REQUIRE(0 <= Index
&& Index
< ArrayListGetCount(AuxData
->ItemList
));
775 ArrayListDeleteItem(AuxData
->ItemList
, Index
, AuxDataItemListItemDestructor
, 0);
779 * Deletes the auxiliary data item by the specified name if it exists.
782 * Auxiliary data handle.
784 * Name used for the search (case insensitive).
787 * TRUE if the an auxilary data item by the specified name was found,
790 Boolean_t
AuxDataDeleteItemByName(AuxData_pa AuxData
,
796 REQUIRE(VALID_REF(AuxData
));
797 REQUIRE(VALID_REF(Name
) && AuxDataIsValidName(Name
));
799 FoundItem
= AuxDataGetItemIndex(AuxData
, Name
, &ItemIndex
);
801 AuxDataDeleteItemByIndex(AuxData
, ItemIndex
);
803 ENSURE(VALID_BOOLEAN(FoundItem
));
807 #if defined TECPLOTKERNEL
808 /* CORE SOURCE CODE REMOVED */
809 #endif /* TECPLOTKERNEL */