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"
42 #include "TranslatedString.h"
44 #if defined TECPLOTKERNEL
45 /* CORE SOURCE CODE REMOVED */
48 /* Disable warning about conversion from long to short.
49 Even if we have disabled it in stdafx.h,
50 we still need to disable here also for
51 tecio, which includes this cpp file. */
53 #pragma warning (disable : 4244)
56 * Temp text and geom buffers.
58 static Geom_s TempGeom
;
59 static Text_s TempText
;
64 #include "FILESTREAM.h"
76 #if defined TECPLOTKERNEL
77 /* CORE SOURCE CODE REMOVED */
79 using namespace tecplot::strutil
;
81 #if defined TECPLOTKERNEL
82 /* CORE SOURCE CODE REMOVED */
85 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
87 #endif /* TECPLOTKERNEL */
91 * Multi-Purpose datafile header reader. This is designed so that
92 * not all parts of the header is loaded and so that the task of loading
93 * the header information is separated out from installing of that
94 * information into a dataset.
98 Boolean_t
ReadDataFileHeader(FileStream_s
*FileStream
,
100 Boolean_t ShowDataIOStatus
,
101 EntIndex_t
*NumZones
,
103 SmInteger_t
*NumCustomLabelSets
,
107 StringList_pa
**CustomLabelBase
,
108 StringList_pa
*UserRec
,
109 AuxData_pa
*DataSetAuxData
,
110 Set_pa
**IsVarCellCentered
, /* Create an Array dim by zones */
113 ArrayList_pa
*ZoneSpecList
,
114 StringList_pa
*VarNames
,
115 ArrayList_pa
*VarAuxDataList
, /*<AuxData_pa>[NumVars]*/
116 Set_pa
*IsRawFNAvailable
, /* classic data only */
117 LgIndex_t
**FNNumBndryConns
, /* classic data only */
118 DataFileType_e
*FileType
)
120 Boolean_t IsOk
= TRUE
;
121 Boolean_t SentError
= FALSE
;
124 FileOffset_t InitialFilePosition
;
126 REQUIRE(VALID_REF(FileStream
) && VALID_REF(FileStream
->File
));
127 REQUIRE(IVersion
> 0);
128 REQUIRE(VALID_BOOLEAN(ShowDataIOStatus
));
129 REQUIRE(VALID_REF(NumZones
));
130 REQUIRE(VALID_REF(NumVars
));
131 REQUIRE(VALID_REF(DataSetTitle
) || (DataSetTitle
== NULL
));
132 REQUIRE(VALID_REF(BaseText
) || (BaseText
== NULL
));
133 REQUIRE(VALID_REF(BaseGeom
) || (BaseGeom
== NULL
));
134 REQUIRE(VALID_REF(HasText
) || (HasText
== NULL
));
135 REQUIRE(VALID_REF(HasGeoms
) || (HasGeoms
== NULL
));
136 REQUIRE(VALID_REF(ZoneSpecList
) || (ZoneSpecList
== NULL
));
137 REQUIRE(VALID_REF(VarNames
) || (VarNames
== NULL
));
138 REQUIRE(VALID_REF(NumCustomLabelSets
) || (NumCustomLabelSets
== NULL
));
139 REQUIRE(VALID_REF(UserRec
) || (UserRec
== NULL
));
140 REQUIRE((VALID_REF(DataSetAuxData
) &&
141 (VALID_REF(*DataSetAuxData
) || *DataSetAuxData
== NULL
)) ||
142 DataSetAuxData
== NULL
);
143 REQUIRE((VALID_REF(VarAuxDataList
) &&
144 (VALID_REF(*VarAuxDataList
) || *VarAuxDataList
== NULL
)) ||
145 VarAuxDataList
== NULL
);
146 REQUIRE(VALID_REF(IsVarCellCentered
) || (IsVarCellCentered
== NULL
));
147 REQUIRE((VALID_REF(CustomLabelBase
) && VALID_REF(NumCustomLabelSets
)) || (CustomLabelBase
== NULL
));
148 REQUIRE(VALID_REF(IsRawFNAvailable
) || (IsRawFNAvailable
== NULL
));
149 REQUIRE(VALID_REF(FNNumBndryConns
) || (FNNumBndryConns
== NULL
));
150 REQUIRE(VALID_REF(FileType
) || (FileType
== NULL
));
153 *DataSetTitle
= NULL
;
163 *ZoneSpecList
= NULL
;
166 if (NumCustomLabelSets
)
167 *NumCustomLabelSets
= 0;
169 *CustomLabelBase
= NULL
;
170 if (DataSetAuxData
!= NULL
)
173 * Note unlike most of the other output only parameters that we nullify,
174 * DataSetAuxData is both an input and output parameter therefore we do
175 * not nullify it. The CHECK is here for clarity.
177 CHECK(VALID_REF(*DataSetAuxData
) || *DataSetAuxData
== NULL
);
179 if (VarAuxDataList
!= NULL
)
182 * Note unlike most of the other output only parameters that we nullify,
183 * VarAuxDataList is both an input and output parameter therefore we do
184 * not nullify it. The CHECK is here for clarity.
186 CHECK(VALID_REF(*VarAuxDataList
) || *VarAuxDataList
== NULL
);
190 if (IsVarCellCentered
)
191 *IsVarCellCentered
= NULL
;
193 if (IsRawFNAvailable
)
194 *IsRawFNAvailable
= NULL
;
197 *FNNumBndryConns
= NULL
;
200 *FileType
= DataFileType_Full
;
203 * Pass 1 is used only to count up the number of zones and custom label sets,
204 * Also determine if there are any preset zone colors.
207 InitialFilePosition
= TP_FTELL(FileStream
->File
);
209 for (Pass
= 1; IsOk
&& (Pass
<= 2); Pass
++)
213 if (TP_FSEEK(FileStream
->File
, InitialFilePosition
, SEEK_SET
) != 0)
216 if (IsOk
&& (*NumZones
> 0 && ZoneSpecList
!= NULL
&& *ZoneSpecList
== NULL
))
218 *ZoneSpecList
= ArrayListAlloc(*NumZones
, ArrayListType_VoidPtr
,
219 ZoneOrVarListAdjustCapacityRequest
, 0);
220 IsOk
= (*ZoneSpecList
!= NULL
);
222 if (IsOk
&& (CustomLabelBase
!= NULL
&&
223 *CustomLabelBase
== NULL
&&
224 *NumCustomLabelSets
> 0))
226 *CustomLabelBase
= ALLOC_ARRAY(*NumCustomLabelSets
, StringList_pa
, "CustomLabel Sets");
227 IsOk
= (*CustomLabelBase
!= NULL
);
231 for (N
= 0; N
< *NumCustomLabelSets
; N
++)
232 (*CustomLabelBase
)[N
] = NULL
;
235 if (IsOk
&& (UserRec
!= NULL
&& *UserRec
== NULL
))
237 *UserRec
= StringListAlloc();
238 IsOk
= (Boolean_t
)(*UserRec
!= NULL
);
240 if (IsOk
&& (DataSetAuxData
!= NULL
&& *DataSetAuxData
== NULL
))
242 *DataSetAuxData
= AuxDataAlloc();
243 IsOk
= (Boolean_t
)(*DataSetAuxData
!= NULL
);
245 if (IsOk
&& (VarAuxDataList
!= NULL
&& *VarAuxDataList
== NULL
) && *NumVars
> 0)
247 *VarAuxDataList
= ArrayListAlloc(0, ArrayListType_VoidPtr
,
248 ZoneOrVarListAdjustCapacityRequest
, 0);
249 IsOk
= (*VarAuxDataList
!= NULL
&&
250 ArrayListSetVoidPtr(*VarAuxDataList
, *NumVars
- 1, NULL
));
254 (IsVarCellCentered
!= NULL
) &&
255 (*IsVarCellCentered
== NULL
))
258 * First construct the array of sets...
260 *IsVarCellCentered
= ALLOC_ARRAY(*NumZones
, Set_pa
, "Array of IsVarCellCentered sets");
261 if (*IsVarCellCentered
)
264 for (Z
= 0; IsOk
&& (Z
< *NumZones
); Z
++)
267 * Now allocate a set for each zone
269 (*IsVarCellCentered
)[Z
] = AllocSet(FALSE
);
270 IsOk
= (Boolean_t
)((*IsVarCellCentered
)[Z
] != NULL
);
276 if (IsOk
&& *NumZones
> 0 && IsRawFNAvailable
!= NULL
)
278 *IsRawFNAvailable
= AllocSet(FALSE
);
279 IsOk
= (*IsRawFNAvailable
!= NULL
);
281 if (IsOk
&& *NumZones
> 0 && FNNumBndryConns
!= NULL
)
283 *FNNumBndryConns
= ALLOC_ARRAY(*NumZones
, LgIndex_t
, "Array of FNNumBndryConns");
284 IsOk
= (*FNNumBndryConns
!= NULL
);
286 for (LgIndex_t i
= 0; i
< *NumZones
; i
++)
287 (*FNNumBndryConns
)[i
] = 0;
291 if (NumCustomLabelSets
!= NULL
)
292 *NumCustomLabelSets
= 0;
294 EntIndex_t TotalNumZones
= *NumZones
; /* ...only meaningful for pass 2 */
304 IsOk
= ReadInDataFileTypeTitleAndVarNames(FileStream
,
306 ((Pass
== 2) ? &S
: (char **)NULL
),
307 ((Pass
== 2) ? FileType
: (DataFileType_e
*)NULL
),
309 ((Pass
== 2) ? VarNames
: (StringList_pa
*)NULL
));
312 *NumVars
= (EntIndex_t
)INumVars
;
314 if ((Pass
== 2) && S
&& IsOk
&& DataSetTitle
)
317 FREE_ARRAY(S
, "data set title");
322 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no dialog feedback */
323 LgIndex_t NumGeoms
= 0;
324 LgIndex_t NumTexts
= 0;
328 X1
= GetNextValue(FileStream
, FieldDataType_Float
, 0.0, 1000.0, &IsOk
);
330 while (IsOk
&& (X1
!= EndHeaderMarker
))
332 if (X1
== ZoneMarker
)
334 ZoneSpec_s
*ZoneSpec
= ZoneSpecAlloc();
335 Boolean_t OkToLoad
= (Pass
== 2 &&
336 IsVarCellCentered
!= NULL
);
337 IsOk
= (ZoneSpec
!= NULL
);
340 Boolean_t LocalIsRawFNAvailable
;
341 LgIndex_t LocalFNNumBndryConns
;
342 IsOk
= ReadInZoneHeader(FileStream
, IVersion
, ZoneSpec
,
343 OkToLoad
? (*IsVarCellCentered
)[*NumZones
] : NULL
,
344 *NumVars
, &LocalIsRawFNAvailable
,
345 &LocalFNNumBndryConns
);
346 if (IsOk
&& OkToLoad
&& IsRawFNAvailable
!= NULL
)
348 if (LocalIsRawFNAvailable
)
349 IsOk
= AddToSet(*IsRawFNAvailable
, *NumZones
, FALSE
);
351 if (IsOk
&& OkToLoad
&& FNNumBndryConns
!= NULL
)
352 (*FNNumBndryConns
)[*NumZones
] = LocalFNNumBndryConns
;
356 ZoneSpecList
!= NULL
&&
359 IsOk
= (ZoneSpec
->ParentZone
== BAD_SET_VALUE
||
360 (ZoneSpec
->ParentZone
!= *NumZones
&&
361 (0 <= ZoneSpec
->ParentZone
&& ZoneSpec
->ParentZone
< TotalNumZones
)));
364 ArrayListItem_u CurZoneSpecItem
;
365 CurZoneSpecItem
.VoidPtr
= (void *)ZoneSpec
;
366 ArrayListSetItem(*ZoneSpecList
, *NumZones
,
368 ZoneSpecItemDestructor
, 0);
372 if (ZoneSpec
->ParentZone
== *NumZones
)
373 ErrMsg(translate("Parent zone assignment for zone %d "
374 "may not be self referencing."),
377 ErrMsg(translate("Parent zone assignment for zone %d "
378 "must be to an existing zone within the datafile."),
380 ZoneSpecDealloc(&ZoneSpec
);
385 ZoneSpecDealloc(&ZoneSpec
);
389 if (*NumZones
> MaxNumZonesOrVars
)
391 ErrMsg(translate("Exceeding Tecplot's current zone limit of %d. "
392 "Reduce the number of zones being loaded."), MaxNumZonesOrVars
);
397 else if (X1
== GeomMarker
)
399 #if defined TECPLOTKERNEL
400 /* CORE SOURCE CODE REMOVED */
402 IsOk
= ReadInGeometry(FileStream
,
415 #if defined TECPLOTKERNEL
416 /* CORE SOURCE CODE REMOVED */
419 #if defined TECPLOTKERNEL
420 /* CORE SOURCE CODE REMOVED */
421 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
425 else if (X1
== TextMarker
)
427 #if defined TECPLOTKERNEL
428 /* CORE SOURCE CODE REMOVED */
430 IsOk
= ReadInText(FileStream
,
443 #if defined TECPLOTKERNEL
444 /* CORE SOURCE CODE REMOVED */
447 #if defined TECPLOTKERNEL
448 /* CORE SOURCE CODE REMOVED */
449 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
453 else if (X1
== CustomLabelMarker
)
457 OkToLoad
= (Pass
== 2) &&
458 NumCustomLabelSets
&&
459 (*NumCustomLabelSets
< MaxCustomLabelSets
) &&
462 IsOk
= ReadInCustomLabels(FileStream
,
465 (OkToLoad
? &(*CustomLabelBase
)[*NumCustomLabelSets
] : NULL
));
466 if (IsOk
&& NumCustomLabelSets
)
467 (*NumCustomLabelSets
)++;
469 else if (X1
== UserRecMarker
)
472 char *CurUserRec
= NULL
;
474 OkToLoad
= (Boolean_t
)((Pass
== 2) && UserRec
);
476 IsOk
= ReadInUserRec(FileStream
,
479 OkToLoad
? &CurUserRec
: (char **)NULL
);
480 if (IsOk
&& OkToLoad
)
481 IsOk
= StringListAppendString(*UserRec
, CurUserRec
);
483 FREE_ARRAY(CurUserRec
, "temp user rec");
486 else if (X1
== DataSetAuxMarker
)
489 CHECK(IVersion
>= 101);
490 OkToLoad
= (Pass
== 2 &&
491 DataSetAuxData
!= NULL
);
492 IsOk
= ReadInAuxData(FileStream
, IVersion
,
493 OkToLoad
? *DataSetAuxData
: NULL
);
496 ErrMsg(translate("Invalid DATASETAUXDATA record in binary datafile"));
500 else if (X1
== VarAuxMarker
)
504 CHECK(IVersion
>= 102);
505 OkToLoad
= (Pass
== 2 &&
506 VarAuxDataList
!= NULL
);
507 VarNum
= GetIoFileInt(FileStream
, IVersion
, 0, *NumVars
- 1, &IsOk
);
510 AuxData_pa VarAuxData
;
513 VarAuxData
= (AuxData_pa
)ArrayListGetVoidPtr(*VarAuxDataList
, VarNum
);
514 if (VarAuxData
== NULL
)
516 VarAuxData
= AuxDataAlloc();
517 IsOk
= (VarAuxData
!= NULL
&&
518 ArrayListSetVoidPtr(*VarAuxDataList
, VarNum
, VarAuxData
));
524 IsOk
= IsOk
&& ReadInAuxData(FileStream
, IVersion
, VarAuxData
);
527 ErrMsg(translate("Invalid VARAUXDATA record in binary datafile"));
533 ErrMsg(translate("Invalid VARAUXDATA variable number association"));
540 X1
= GetNextValue(FileStream
, FieldDataType_Float
, 0.0, 1000.0, &IsOk
);
546 * Old plt files that did not contain data still contained variable name
547 * definitions in the header. This is no longer necessary and in fact can
548 * cause confusion in the data read options dialog. If the number of zones
549 * in the datafile is zero set the number of variables to 0 and dealloc the
550 * variable name list.
553 if (IsOk
&& (*NumZones
== 0) && (*NumVars
> 0))
556 if (VarNames
&& *VarNames
)
558 StringListDealloc(VarNames
);
565 if (ZoneSpecList
&& *ZoneSpecList
)
566 ArrayListDealloc(ZoneSpecList
, ZoneSpecItemDestructor
, 0);
567 if (DataSetTitle
&& *DataSetTitle
)
569 FREE_ARRAY(*DataSetTitle
, "DataSetTitle");
570 *DataSetTitle
= NULL
;
572 #if defined TECPLOTKERNEL
573 /* CORE SOURCE CODE REMOVED */
575 if (VarNames
&& *VarNames
)
577 StringListDealloc(VarNames
);
579 #if defined TECPLOTKERNEL
580 /* CORE SOURCE CODE REMOVED */
582 if (UserRec
&& *UserRec
)
583 StringListDealloc(UserRec
);
586 /* If there was an error, get rid of the auxiliary data list. */
587 if ((DataSetAuxData
!= NULL
&& *DataSetAuxData
!= NULL
) &&
589 AuxDataDealloc(DataSetAuxData
);
591 if (!IsOk
&& !SentError
)
592 ErrMsg(translate("Invalid header in binary datafile"));
595 * NOTE: Do not close the file. Some calling functions will continue
596 * to read from this point on.
599 ENSURE((VarNames
== NULL
) || (*VarNames
== NULL
) || StringListValid(*VarNames
));
600 ENSURE(IMPLICATION(UserRec
!= NULL
,
602 StringListValid(*UserRec
))));
603 ENSURE(IMPLICATION(DataSetAuxData
!= NULL
,
604 (*DataSetAuxData
== NULL
||
605 VALID_REF(*DataSetAuxData
))));
611 #if defined TECPLOTKERNEL
612 /* CORE SOURCE CODE REMOVED */
613 #endif /* TECPLOTKERNEL */
616 Boolean_t
OpenBinaryFileAndCheckMagicNumber(FileStream_s
**FileStream
,
618 FileOffset_t StartOffset
,
621 Boolean_t Result
= TRUE
;
622 REQUIRE(VALID_REF(FileStream
));
623 REQUIRE(*FileStream
== NULL
);
624 REQUIRE(VALID_REF(FName
));
625 REQUIRE(StartOffset
>= 0);
626 REQUIRE(VALID_REF(IVersion
));
628 #if defined TECPLOTKERNEL
629 /* CORE SOURCE CODE REMOVED */
631 FILE *File
= TP_FOPEN(FName
, "rb");
637 *FileStream
= FileStreamAlloc(File
, TRUE
);
638 Result
= (*FileStream
!= NULL
);
640 Result
= Result
&& (TP_FSEEK((*FileStream
)->File
, StartOffset
, SEEK_SET
) == 0);
643 *IVersion
= GetInputVersion(*FileStream
);
645 * After version 71 we started listing individual valid
646 * versions. Before that time we just listed ranges. Also,
647 * note that versions 72, 73, and 74 were invalid.
649 Result
= (/* past valid plt file version ranges follow: */
650 (40 <= *IVersion
&& *IVersion
<= 71) ||
652 (100 <= *IVersion
&& *IVersion
<= TecplotBinaryFileVersion
));
655 * This check is put here to make sure that the above code gets visited
656 * when the TecplotBinaryFileVersion number changes. When the version
657 * changes the "past valid plt file version ranges" above and the number
658 * compared to the TecplotBinaryFileVersion below may need to be
659 * adjusted such as when we skip a consecutive number as we did between
660 * version 71 and 75, and between 75 and 100.
662 CHECK(TecplotBinaryFileVersion
== 112);
665 ENSURE(VALID_BOOLEAN(Result
));
672 #if defined TECPLOTKERNEL
673 /* CORE SOURCE CODE REMOVED */
674 #if !defined NO_ASSERTS
676 #if !defined NO_ASSERTS
678 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
680 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
682 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
684 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
686 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
688 #if !defined ENGINE /* TODO(RMS)-M 12/13/2005: ENGINE-P2 - no status feedback */
690 #if !defined ENGINE /* TODO(RMS)-H 12/12/2005: ENGINE: refactor to use just the Interrupted flag as-is */
693 #if 0 /* we changed this behavior... not sure when */
695 #endif /* TECPLOTKERNEL */