This repository has been archived on 2023-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
foam-extend4.1-coherent-io/applications/utilities/postProcessing/dataConversion/foamToTecplot360/tecio/tecsrc/dataio4.cpp
2010-08-25 22:42:57 +01:00

3357 lines
115 KiB
C++

/*
* NOTICE and LICENSE for Tecplot Input/Output Library (TecIO) - OpenFOAM
*
* Copyright (C) 1988-2009 Tecplot, Inc. All rights reserved worldwide.
*
* Tecplot hereby grants OpenCFD limited authority to distribute without
* alteration the source code to the Tecplot Input/Output library, known
* as TecIO, as part of its distribution of OpenFOAM and the
* OpenFOAM_to_Tecplot converter. Users of this converter are also hereby
* granted access to the TecIO source code, and may redistribute it for the
* purpose of maintaining the converter. However, no authority is granted
* to alter the TecIO source code in any form or manner.
*
* This limited grant of distribution does not supersede Tecplot, Inc.'s
* copyright in TecIO. Contact Tecplot, Inc. for further information.
*
* Tecplot, Inc.
* 3535 Factoria Blvd, Ste. 550
* Bellevue, WA 98006, USA
* Phone: +1 425 653 1200
* http://www.tecplot.com/
*
*/
#include "stdafx.h"
#include "MASTER.h"
#define TECPLOTENGINEMODULE
/*
******************************************************************
******************************************************************
******* ********
****** (C) 1988-2008 Tecplot, Inc. *******
******* ********
******************************************************************
******************************************************************
*/
#define DATAIO4MODULE
#include "GLOBAL.h"
#include "TASSERT.h"
#include "Q_UNICODE.h"
#include "ALLOC.h"
#include "AUXDATA.h"
#include "DATASET.h"
#include "FILESTREAM.h"
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
#include "GEOM2.h"
#include "GEOM.h"
#include "INPUT.h"
#include "SET.h"
#include "TEXT.h"
#include "DATAIO4.h"
#include "DATASET0.h"
#include "STRUTIL.h"
#include "ARRLIST.h"
#include "STRLIST.h"
#include "Q_MSG.h"
#if defined IRIS
#include <ieeefp.h>
#endif
using namespace tecplot::strutil;
#if !defined(TECPLOTKERNEL) && defined(MSWIN)
# pragma warning(disable : 4244)
#endif
/*END HEADER*/
/*
* This module contains mostly low level i/o functions.
*/
#if defined DECALPHA || defined COMPAQALPHA
#define _IEEE_FP_INEXACT
#define _IEEE_FP
#endif
#if defined SUN41
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
/**********************************************************************
**********************************************************************
********************** INPUT **************************
**********************************************************************
**********************************************************************/
static char FilterFloatChar(float X)
{
char C;
if (((X >= 32.0) && (X <= 127.0)) ||
((X >= 160.0) && (X <= 255.0)) ||
(X == 0.0))
C = (char)X;
else
C = '?';
return (C);
}
double GetNextValue(FileStream_s *FileStream,
FieldDataType_e FieldDataType,
double VMin,
double VMax,
Boolean_t *IsOk)
{
double X = 0.0;
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
REQUIRE(!(*IsOk) || VALID_FIELD_DATA_TYPE(FieldDataType));
REQUIRE(!(*IsOk) || VALID_REF(FileStream));
if (*IsOk)
{
switch (FieldDataType)
{
case FieldDataType_Float :
{
float XX;
*IsOk = (TP_FREAD(&XX, 4, 1, FileStream->File) == 1);
if (!FileStream->IsByteOrderNative)
REVERSE_4_BYTES(&XX);
if (*IsOk)
X = XX;
else
X = 0.0;
} break;
case FieldDataType_Double :
{
double XX;
*IsOk = (TP_FREAD(&XX, sizeof(double), 1, FileStream->File) == 1);
if (!FileStream->IsByteOrderNative)
REVERSE_8_BYTES(&XX);
if (*IsOk)
X = XX;
else
X = 0.0;
} break;
case FieldDataType_Int32 :
{
Int32_t L;
*IsOk = (TP_FREAD(&L, sizeof(Int32_t), 1, FileStream->File) == 1);
if (!FileStream->IsByteOrderNative)
REVERSE_4_BYTES(&L);
if (*IsOk)
X = (double)L;
} break;
case FieldDataType_Int16 :
{
Int16_t S;
*IsOk = (TP_FREAD(&S, sizeof(Int16_t), 1, FileStream->File) == 1);
if (!FileStream->IsByteOrderNative)
REVERSE_2_BYTES(&S);
if (*IsOk)
X = (double)S;
} break;
case FieldDataType_Byte :
{
Byte_t B;
*IsOk = (TP_FREAD(&B, sizeof(Byte_t), 1, FileStream->File) == 1);
if (*IsOk)
X = (double)B;
} break;
case FieldDataType_Bit :
{
/*
* Important note:
* Reading bit data a value at a time is only valid for a
* single bit value. If the file contains a block of more than
* one bit value and you attempt to read it a bit at a time it
* will not work as Tecplot does not buffer the read. In order
* to read a block of bits you must perform a block read.
*/
Byte_t B;
*IsOk = (TP_FREAD(&B, sizeof(Byte_t), 1, FileStream->File) == 1);
if (*IsOk)
X = (double)(B & (Byte_t)01);
} break;
default: CHECK(FALSE); break;
}
if (*IsOk)
{
if ((X < VMin) || (X > VMax))
{
*IsOk = FALSE;
}
}
}
return X;
}
LgIndex_t GetNextI(FileStream_s *FileStream,
Boolean_t *IsOk)
{
LgIndex_t I = 0;
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
REQUIRE(!(*IsOk) || (VALID_REF(FileStream) && VALID_REF(FileStream->File)));
if (*IsOk)
{
Int32_t Int32Val;
*IsOk = (TP_FREAD((void *) & Int32Val, 4, 1, FileStream->File) == 1);
if (!FileStream->IsByteOrderNative)
REVERSE_4_BYTES(&Int32Val);
I = Int32Val;
}
return I;
}
LgIndex_t GetIoFileInt(FileStream_s *FileStream,
short Version,
LgIndex_t IMin,
LgIndex_t IMax,
Boolean_t *IsOk)
{
LgIndex_t I = 0;
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
REQUIRE(!(*IsOk) || (0 < Version && Version <= TecplotBinaryFileVersion));
REQUIRE(!(*IsOk) || (VALID_REF(FileStream) && VALID_REF(FileStream->File)));
REQUIRE(!(*IsOk) || IMin <= IMax);
if (!(*IsOk))
return (0);
if (Version <= 63)
{
float X;
if (*IsOk)
{
X = (float)GetNextValue(FileStream, FieldDataType_Float,
(double)IMin - 1.0e-10,
(double)IMax + 1.0e-10, IsOk);
if (*IsOk)
{
if (ABS(X) < (float)MAXINDEX)
I = (LgIndex_t)X;
else
*IsOk = FALSE;
}
else
*IsOk = FALSE;
}
}
else
{
I = GetNextI(FileStream, IsOk);
}
if ((I < IMin) || (I > IMax))
*IsOk = FALSE;
return (I);
}
/**
* Basically this is "realloc" but apparently "realloc" doesn't behave reliably
* on all platforms.
*/
static Boolean_t ReallocString(char **String,
LgIndex_t NewLength)
{
Boolean_t IsOk;
char *NewString;
REQUIRE(VALID_REF(String));
REQUIRE(*String == NULL || VALID_REF(*String));
REQUIRE((*String != NULL && NewLength >= (LgIndex_t)strlen(*String)) ||
(*String == NULL && NewLength >= 0));
NewString = ALLOC_ARRAY(NewLength + 1, char, "reallocated string");
IsOk = (NewString != NULL);
if (IsOk)
{
if (*String == NULL)
{
NewString[0] = '\0';
}
else
{
strcpy(NewString, *String);
FREE_ARRAY(*String, "old string");
}
*String = NewString;
}
ENSURE(VALID_BOOLEAN(IsOk));
ENSURE(IMPLICATION(IsOk, VALID_REF(*String)));
return IsOk;
}
/**
* Reads a string from all versions of a binary plt file.
*
* param FileStream
* Open file stream positioned at the string to read.
* param IVersion
* Binary file version number.
* param MaxCharacters
* IVersion < 63
* This value is exactly the number of characters (actually floats, each
* one representing a character's ordinal value) to read from the file.
* IVersion >= 63 and ProcessData == TRUE
* If non-zero, this value represents the largest string to be returned.
* In other words, larger strings are read from the file but an allocated
* string of up to MaxCharacters is returned. A zero value indicates that
* the string size is unlimited and determined only by the actual length
* of the string in the file.
* param TargetStr
* Pointer to hold the allocated string if ProcessData == TRUE.
* param ProcessData
* Indicates if the read string should be retrieved.
*
* return
* TRUE if the read was successful with an allocated string *TargetStr
* containing the string read (no larger than requested or necessary),
* FALSE otherwise.
*/
Boolean_t ReadInString(FileStream_s *FileStream,
short IVersion,
int MaxCharacters,
char **TargetStr,
Boolean_t ProcessData)
{
Boolean_t IsOk = TRUE;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
REQUIRE(IMPLICATION(IVersion < 63 || ProcessData, MaxCharacters >= 0));
REQUIRE(IMPLICATION(ProcessData, VALID_REF(TargetStr)));
REQUIRE(VALID_BOOLEAN(ProcessData));
if (IVersion < 63)
{
/*
* One word per character. Read Exactly "MaxCharacters" number of words.
*/
float X;
if (ProcessData)
{
*TargetStr = ALLOC_ARRAY(MaxCharacters + 1, char, "target string");
IsOk = (*TargetStr != NULL);
}
if (IsOk)
{
LgIndex_t I;
for (I = 0; IsOk && I < MaxCharacters; I++)
{
X = (float)GetNextValue(FileStream, FieldDataType_Float, 0.0, 127.0, &IsOk);
if (!IsOk)
break;
if (ProcessData)
(*TargetStr)[I] = FilterFloatChar(X);
}
if (ProcessData)
(*TargetStr)[I] = '\0';
}
else
{
ErrMsg(translate("Cannot allocate memory for string during read",
"'string' meaning the computer science data type"));
}
}
else
{
#define MAX_STRBUFFER_LEN 4095
static char StrBuffer[MAX_STRBUFFER_LEN+1];
LgIndex_t StrBufferLen = 0;
LgIndex_t TargetStrLen = 0;
LgIndex_t I = 0;
LgIndex_t CharValue = 0;
if (ProcessData)
*TargetStr = NULL;
do
{
CharValue = GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
if (IsOk && ProcessData)
{
/* massage the character if necessary */
if ((CharValue < 32 && CharValue != '\0' && CharValue != '\n') ||
(CharValue >= 128 && CharValue < 160))
CharValue = ' ';
/*
* if the limit is not exceded, stuff the
* character into the buffer
*/
if (CharValue != '\0' &&
(I < MaxCharacters || MaxCharacters == 0))
{
StrBuffer[StrBufferLen] = (char)CharValue;
StrBufferLen++;
}
if (CharValue == '\0' ||
StrBufferLen == MAX_STRBUFFER_LEN)
{
if (StrBufferLen != 0 || *TargetStr == NULL)
{
StrBuffer[StrBufferLen] = '\0';
TargetStrLen += StrBufferLen;
IsOk = ReallocString(TargetStr, TargetStrLen);
if (IsOk)
strcat(*TargetStr, StrBuffer);
StrBufferLen = 0; /* reset the string buffer */
}
}
}
I++;
}
while (IsOk && (char)CharValue != '\0');
/* if we failed cleanup if necessary */
if (!IsOk &&
ProcessData &&
*TargetStr != NULL)
{
FREE_ARRAY(*TargetStr, "failed read string");
*TargetStr = NULL;
}
}
ENSURE(IMPLICATION(ProcessData,
(VALID_REF(*TargetStr) || *TargetStr == NULL)));
ENSURE(VALID_BOOLEAN(IsOk));
return (IsOk);
}
/**
*/
static void ReadDoubleBlock(FileStream_s *FileStream,
Boolean_t DoRead,
double *Buffer,
LgIndex_t StartIndex,
LgIndex_t NumValues,
Boolean_t *IsOk)
{
if (DoRead)
{
double *DPtr = Buffer + StartIndex;
*IsOk = (TP_FREAD(DPtr, sizeof(double), NumValues, FileStream->File) == (size_t)NumValues);
if (!FileStream->IsByteOrderNative && *IsOk)
{
LgIndex_t N;
for (N = 0; N < NumValues; N++)
REVERSE_8_BYTES(&DPtr[N]);
}
}
else
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(double), SEEK_CUR) == 0);
}
/**
*/
static void ReadFloatBlock(FileStream_s *FileStream,
Boolean_t DoRead,
float *Buffer,
LgIndex_t StartIndex,
LgIndex_t NumValues,
Boolean_t *IsOk)
{
if (DoRead)
{
float *FPtr = Buffer + StartIndex;
*IsOk = (TP_FREAD(FPtr, sizeof(float), NumValues, FileStream->File) == (size_t)NumValues);
if (!FileStream->IsByteOrderNative && *IsOk)
{
LgIndex_t N;
for (N = 0; N < NumValues; N++)
REVERSE_4_BYTES(&FPtr[N]);
}
}
else
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(float), SEEK_CUR) == 0);
}
/**
*/
static void ReadBitBlock(FileStream_s *FileStream,
Boolean_t DoRead,
Byte_t *Buffer,
LgIndex_t NumValues,
Boolean_t *IsOk)
{
/*
* Do not allow reading of bit values if startindex is not 0.
* (This means geometries cannot use bit data.
*/
LgIndex_t NumBytes = (NumValues + 7) / 8;
if (DoRead)
{
*IsOk = (TP_FREAD(Buffer,
sizeof(Byte_t),
NumBytes,
FileStream->File) == (size_t)NumBytes);
}
else
*IsOk = (TP_FSEEK(FileStream->File, NumBytes * sizeof(Byte_t), SEEK_CUR) == 0);
}
/**
*/
void ReadByteBlock(FileStream_s *FileStream,
Boolean_t DoRead,
Byte_t *Buffer,
HgIndex_t StartIndex,
HgIndex_t NumValues,
Boolean_t *IsOk)
{
if (DoRead)
{
*IsOk = (TP_FREAD(Buffer + StartIndex,
sizeof(Byte_t),
NumValues,
FileStream->File) == (size_t)NumValues);
}
else
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Byte_t), SEEK_CUR) == 0);
}
/**
*/
void ReadInt16Block(FileStream_s *FileStream,
Boolean_t DoRead,
Int16_t *Buffer,
HgIndex_t StartIndex,
HgIndex_t NumValues,
Boolean_t *IsOk)
{
if (DoRead)
{
Int16_t *IntPtr = Buffer + StartIndex;
*IsOk = (TP_FREAD(IntPtr,
sizeof(Int16_t),
NumValues,
FileStream->File) == (size_t)NumValues);
if (!FileStream->IsByteOrderNative && *IsOk)
{
LgIndex_t N;
for (N = 0; N < NumValues; N++)
REVERSE_2_BYTES(&IntPtr[N]);
}
}
else
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int16_t), SEEK_CUR) == 0);
}
/**
*/
void ReadInt16BlockToInt32(FileStream_s *FileStream,
Boolean_t DoRead,
Int32_t *Buffer,
HgIndex_t StartIndex,
HgIndex_t NumValues,
Boolean_t *IsOk)
{
REQUIRE(VALID_REF(FileStream));
REQUIRE(VALID_BOOLEAN(DoRead));
REQUIRE(VALID_REF(Buffer));
REQUIRE(StartIndex >= 0);
REQUIRE(NumValues >= 0);
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
if (DoRead)
{
HgIndex_t EndIndex = StartIndex + NumValues;
for (HgIndex_t ValueIndex = StartIndex; *IsOk && ValueIndex < EndIndex; ValueIndex++)
{
Int16_t Value;
*IsOk = (TP_FREAD(&Value, sizeof(Int16_t), 1, FileStream->File) == 1);
if (!FileStream->IsByteOrderNative && *IsOk)
REVERSE_2_BYTES(&Value);
Buffer[ValueIndex] = (Int32_t)Value;
}
}
else
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int16_t), SEEK_CUR) == 0);
}
/**
*/
void ReadInt32Block(FileStream_s *FileStream,
Boolean_t DoRead,
Int32_t *Buffer,
HgIndex_t StartIndex,
HgIndex_t NumValues,
Boolean_t *IsOk)
{
if (DoRead)
{
Int32_t *IntPtr = Buffer + StartIndex;
*IsOk = (TP_FREAD(IntPtr,
sizeof(Int32_t),
NumValues,
FileStream->File) == (size_t)NumValues);
if (!FileStream->IsByteOrderNative && *IsOk)
{
LgIndex_t N;
for (N = 0; N < NumValues; N++)
REVERSE_4_BYTES(&IntPtr[N]);
}
}
else
*IsOk = (TP_FSEEK(FileStream->File, NumValues * sizeof(Int32_t), SEEK_CUR) == 0);
}
/**
*/
void ReadPureBlock(FileStream_s *FileStream,
Boolean_t DoRead,
void *Buffer,
FieldDataType_e FieldDataType,
HgIndex_t StartIndex,
HgIndex_t NumValues,
Boolean_t *IsOk)
{
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_BOOLEAN(DoRead));
REQUIRE(!DoRead || VALID_REF(Buffer));
REQUIRE(VALID_FIELD_DATA_TYPE(FieldDataType));
REQUIRE(StartIndex >= 0);
REQUIRE(NumValues >= 0);
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
switch (FieldDataType)
{
case FieldDataType_Float :
{
ReadFloatBlock(FileStream,
DoRead,
(float *)Buffer,
StartIndex,
NumValues,
IsOk);
} break;
case FieldDataType_Double :
{
ReadDoubleBlock(FileStream,
DoRead,
(double *)Buffer,
StartIndex,
NumValues,
IsOk);
} break;
case FieldDataType_Bit :
{
if (StartIndex != 0)
{
ErrMsg(translate("Internal Error: Attempt to read bit data at non-zero offset",
"see Tecplot User's manual for a definition of 'bit' data"));
*IsOk = FALSE;
}
else
ReadBitBlock(FileStream,
DoRead,
(Byte_t *)Buffer,
NumValues,
IsOk);
} break;
case FieldDataType_Byte :
{
ReadByteBlock(FileStream,
DoRead,
(Byte_t *)Buffer,
StartIndex,
NumValues,
IsOk);
} break;
case FieldDataType_Int16 :
{
ReadInt16Block(FileStream,
DoRead,
(Int16_t *)Buffer,
StartIndex,
NumValues,
IsOk);
} break;
case FieldDataType_Int32 :
{
ReadInt32Block(FileStream,
DoRead,
(Int32_t *)Buffer,
StartIndex,
NumValues,
IsOk);
} break;
case FieldDataType_IJKFunction : /* Not used yet */
case FieldDataType_Int64 : /* Not used yet */
default: CHECK(FALSE); break;
}
ENSURE(VALID_BOOLEAN(*IsOk));
}
/**
*/
void ReadBlock(FileStream_s *FileStream,
FieldData_pa FieldData,
Boolean_t DoRead,
FieldDataType_e FieldDataTypeInFile,
HgIndex_t StartIndex,
HgIndex_t EndIndex,
Boolean_t *IsOk)
{
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
REQUIRE(IMPLICATION(IsOk, VALID_REF(FileStream)));
REQUIRE(IMPLICATION(IsOk, VALID_FIELD_DATA_TYPE(FieldDataTypeInFile)));
REQUIRE(VALID_BOOLEAN(DoRead));
REQUIRE(IMPLICATION(DoRead, VALID_REF(FieldData)));
/*
* Bit data is packed into bytes. Since Tecplot doesn't buffer reads it can
* not perform bit by bit value reads and therefore must only perform block
* reads of bit data.
*/
Boolean_t ReadByBlock = IMPLICATION(DoRead, GetFieldDataType(FieldData) == FieldDataTypeInFile);
REQUIRE(ReadByBlock || (FieldDataTypeInFile != FieldDataType_Bit));
if (*IsOk)
{
LgIndex_t NumValues = EndIndex - StartIndex + 1;
if (ReadByBlock)
{
void *data_array;
if (DoRead)
data_array = GetFieldDataVoidPtr(FieldData);
else
data_array = NULL;
ReadPureBlock(FileStream,
DoRead,
data_array,
FieldDataTypeInFile,
StartIndex,
NumValues,
IsOk);
}
else
{
LgIndex_t N;
for (N = 0; *IsOk && (N < NumValues); N++)
{
double D = GetNextValue(FileStream, FieldDataTypeInFile, -LARGEDOUBLE, LARGEDOUBLE, IsOk);
if (DoRead)
SetFieldValue(FieldData, N + StartIndex, D);
}
}
}
}
/**
*/
void ReadClassicOrderedCCBlock(FileStream_s *DataFileStream,
FieldData_pa FieldData,
FieldDataType_e FieldDataTypeInFile,
LgIndex_t NumIPtsInFile,
LgIndex_t NumJPtsInFile,
LgIndex_t NumKPtsInFile,
Boolean_t *IsOk)
{
REQUIRE(IMPLICATION(*IsOk, VALID_REF(DataFileStream)));
REQUIRE(IMPLICATION(*IsOk, VALID_FIELD_DATA_TYPE(FieldDataTypeInFile)));
REQUIRE(VALID_REF(FieldData));
REQUIRE(NumIPtsInFile >= 0);
REQUIRE(NumJPtsInFile >= 0);
REQUIRE(NumKPtsInFile >= 0);
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
if (*IsOk)
{
LgIndex_t J, K;
LgIndex_t NumIJPts = NumIPtsInFile * NumJPtsInFile;
LgIndex_t IEnd = MAX(NumIPtsInFile - 1, 1);
LgIndex_t JEnd = MAX(NumJPtsInFile - 1, 1);
LgIndex_t KEnd = MAX(NumKPtsInFile - 1, 1);
LgIndex_t NumValues = (IEnd * JEnd * KEnd);
Boolean_t IsLinear = ((NumJPtsInFile == 1 && NumKPtsInFile == 1) ||
(NumIPtsInFile == 1 && NumKPtsInFile == 1) ||
(NumIPtsInFile == 1 && NumJPtsInFile == 1));
if (IsLinear)
ReadBlock(DataFileStream, FieldData, TRUE, FieldDataTypeInFile,
0, NumValues - 1, IsOk);
else
for (K = 0; K < KEnd && IsOk; K++)
for (J = 0; J < JEnd && IsOk; J++)
{
LgIndex_t CellIndex = 0 + (J * NumIPtsInFile) + (K * NumIJPts);
ReadBlock(DataFileStream, FieldData, TRUE, FieldDataTypeInFile,
CellIndex, CellIndex + IEnd - 1, IsOk);
}
}
ENSURE(VALID_BOOLEAN(*IsOk));
}
/**
*/
static void AdjustCustomColor(short IVersion,
ColorIndex_t *BColor)
{
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
REQUIRE(VALID_REF(BColor));
if ((IVersion < 70) && (*BColor >= 15) && (*BColor <= 22))
*BColor -= 7;
}
/*
* ReadInDataFileTypeTitleAndVarNames replaces ReadInDataFileTitleAndVarNames
* and reads in the filetype as well in files with version >= 109.
*/
Boolean_t ReadInDataFileTypeTitleAndVarNames(FileStream_s *FileStream,
short IVersion,
char **DataSetTitle,
DataFileType_e *FileType,
int *NumVars,
StringList_pa *VarNames)
{
EntIndex_t CurVar;
Boolean_t IsOk = TRUE;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
REQUIRE(VALID_REF(DataSetTitle) || (DataSetTitle == NULL));
REQUIRE(VALID_REF(FileType) || (FileType == NULL));
REQUIRE(VALID_REF(NumVars));
REQUIRE(VALID_REF(VarNames) || (VarNames == NULL));
*NumVars = 0;
if (DataSetTitle)
*DataSetTitle = NULL;
if (IVersion >= 109)
{
if (FileType)
*FileType = (DataFileType_e)GetIoFileInt(FileStream,
IVersion,
0,
DataFileType_Solution,
&IsOk);
else
GetIoFileInt(FileStream,
IVersion,
0,
DataFileType_Solution,
&IsOk);
}
if (ReadInString(FileStream,
IVersion,
((IVersion < 63) ? 80 : MaxChrsDatasetTitle),
DataSetTitle,
(Boolean_t)(DataSetTitle != NULL)))
{
if (DataSetTitle)
TrimLeadAndTrailSpaces(*DataSetTitle);
*NumVars = GetIoFileInt(FileStream, IVersion, 0, MAXZONEMAP, &IsOk);
}
else
IsOk = FALSE;
if (IsOk && (*NumVars > MaxNumZonesOrVars))
{
ErrMsg(translate("Too many variables"));
IsOk = FALSE;
}
if (IsOk && VarNames)
{
if (*NumVars > 0)
{
/* allocate a string list filled with NULL's */
*VarNames = StringListAlloc();
IsOk = (*VarNames != NULL);
if (IsOk)
IsOk = StringListSetString(*VarNames, *NumVars - 1, NULL);
if (!IsOk)
{
if (*VarNames != NULL)
StringListDealloc(VarNames);
ErrMsg(translate("Out of space while allocating var names"));
}
}
}
for (CurVar = 0; IsOk && (CurVar < *NumVars); CurVar++)
{
char *VName = NULL;
IsOk = ReadInString(FileStream,
IVersion,
((IVersion < 63) ? 5 : MaxChrsVarName),
VarNames ? &VName : NULL,
(Boolean_t)(VarNames != NULL));
if (IsOk && VarNames)
{
if (VName == NULL)
{
/* NULL variable names are converted to empty names */
VName = ALLOC_ARRAY(1, char, "empty variable name");
strcpy(VName, "");
}
TrimLeadAndTrailSpaces(VName);
/*
* variables are not allowed to have litteral new line characters
* within them but they can sneek in from ASCII data files so
* convert any to their appropriate two character representation
*/
IsOk = ReplaceNewlineWithBackslashN(&VName);
IsOk = IsOk && StringListSetString(*VarNames, CurVar, VName);
if (VName != NULL)
FREE_ARRAY(VName, "variable name");
}
if (!IsOk)
{
if (VarNames && *VarNames)
StringListDealloc(VarNames);
ErrMsg(translate("Out of space while allocating variable names"));
}
}
ENSURE(VALID_BOOLEAN(IsOk));
return (IsOk);
}
/**
*/
static Boolean_t ReadInPresetZoneColor(FileStream_s *FileStream,
short IVersion,
ZoneSpec_s *ZoneSpec)
{
Boolean_t IsOk = TRUE;
LgIndex_t ZoneColor;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
REQUIRE(VALID_REF(ZoneSpec));
ZoneColor = GetIoFileInt(FileStream, IVersion, -1, LastBasicColor, &IsOk);
if (IsOk)
{
if (VALID_BASIC_COLOR(ZoneColor))
{
ZoneSpec->ZoneLoadInfo.PresetZoneColor = (EntIndex_t)ZoneColor;
AdjustCustomColor(IVersion, &ZoneSpec->ZoneLoadInfo.PresetZoneColor);
}
else if (ZoneColor != -1)
IsOk = FALSE;
}
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
*/
static void ConvertCommonTimeToSolutionTime(ZoneSpec_s *ZoneSpec)
{
REQUIRE(VALID_REF(ZoneSpec));
REQUIRE(ZoneSpec->AuxData == NULL || VALID_REF(ZoneSpec->AuxData));
LgIndex_t ItemIndex;
if (ZoneSpec->AuxData != NULL &&
AuxDataGetItemIndex(ZoneSpec->AuxData, AuxData_Common_Time, &ItemIndex))
{
const char *SameName;
ArbParam_t Value;
AuxDataType_e Type;
Boolean_t Retain;
AuxDataGetItemByIndex(ZoneSpec->AuxData, ItemIndex,
&SameName, &Value, &Type, &Retain);
CHECK(ustrcmp(AuxData_Common_Time, SameName) == 0);
CHECK(Type == AuxDataType_String);
char *EndPtr = NULL;
double SolutionTime = strtod((const char *)Value, &EndPtr);
if (EndPtr != (char *)Value)
{
/* we only allow white space to trail a value */
while (isspace(*EndPtr))
EndPtr++;
}
if (EndPtr != (char *)Value && *EndPtr == '\0')
{
ZoneSpec->SolutionTime = SolutionTime;
ZoneSpec->StrandID = STRAND_ID_PENDING;
AuxDataDeleteItemByIndex(ZoneSpec->AuxData, ItemIndex);
}
}
}
/*
* Pass1 for a zone reads in and initializes the zone structures.
* These structures are released later if the user elects to not read them
* in.
*/
Boolean_t ReadInZoneHeader(FileStream_s *FileStream,
short IVersion,
ZoneSpec_s *ZoneSpec,
Set_pa IsVarCellCentered,
EntIndex_t NumVars,
Boolean_t *IsRawFNAvailable,
LgIndex_t *FNNumBndryConns)
{
EntIndex_t Var;
Boolean_t IsOk = TRUE;
LgIndex_t I1;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
REQUIRE(VALID_REF(ZoneSpec));
REQUIRE(IsVarCellCentered == NULL || VALID_REF(IsVarCellCentered));
REQUIRE(NumVars >= 0);
REQUIRE(VALID_REF(IsRawFNAvailable));
REQUIRE(VALID_REF(FNNumBndryConns));
SetZoneSpecDefaults(ZoneSpec);
if (IsVarCellCentered != NULL)
{
/* assign default variable value location: nodal */
ClearSet(IsVarCellCentered);
IsOk = ExpandSet(IsVarCellCentered, NumVars, FALSE);
}
if (IsOk)
IsOk = ReadInString(FileStream, IVersion,
((IVersion < 63) ? 10 : MaxChrsZnTitle),
&ZoneSpec->Name,
TRUE);
if (IsOk && ZoneSpec->Name == NULL)
{
/* NULL zone names are converted to empty names */
ZoneSpec->Name = ALLOC_ARRAY(1, char, "empty zone name");
IsOk = (ZoneSpec->Name != NULL);
if (IsOk)
strcpy(ZoneSpec->Name, "");
}
if (IsOk)
TrimLeadAndTrailSpaces(ZoneSpec->Name);
if (IVersion < 101)
{
Boolean_t IsZoneFinite;
DataFormat_e ZoneDataFormat;
I1 = GetIoFileInt(FileStream, IVersion, 0, 3, &IsOk);
if ((I1 < 0) || (I1 > 3))
{
return (FALSE);
}
ZoneDataFormat = (DataFormat_e)I1;
IsZoneFinite = (ZoneDataFormat == DataFormat_FEPoint ||
ZoneDataFormat == DataFormat_FEBlock);
ZoneSpec->ZoneLoadInfo.IsInBlockFormat = (ZoneDataFormat == DataFormat_IJKBlock ||
ZoneDataFormat == DataFormat_FEBlock);
if (IVersion > 62)
IsOk = ReadInPresetZoneColor(FileStream, IVersion, ZoneSpec);
if (IVersion < 60)
GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk); /* Old ZPlane Value */
if (IsOk)
{
ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
if (IVersion >= 60)
ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
else
ZoneSpec->NumPtsK = 1;
}
if (IsOk)
{
/* If IMax,JMax, & KMax are all zero then this zone was "zombied" by
a partial read to make layout files align. */
if (!((ZoneSpec->NumPtsI == 0) &&
(ZoneSpec->NumPtsJ == 0) &&
(ZoneSpec->NumPtsK == 0)) &&
((ZoneSpec->NumPtsI <= 0) ||
(ZoneSpec->NumPtsJ <= 0) ||
(ZoneSpec->NumPtsK < 0) ||
((!IsZoneFinite && (ZoneSpec->NumPtsK == 0)))))
{
ErrMsg(translate("Datafile is corrupted"));
IsOk = FALSE;
}
if (IsZoneFinite)
{
if (IVersion >= 61)
{
ZoneSpec->Type = (ZoneType_e)(ZoneSpec->NumPtsK + 1);
switch (ZoneSpec->Type)
{
case ZoneType_FETriangle: ZoneSpec->NumPtsK = 3; break;
case ZoneType_FEQuad: ZoneSpec->NumPtsK = 4; break;
case ZoneType_FETetra: ZoneSpec->NumPtsK = 4; break;
case ZoneType_FEBrick: ZoneSpec->NumPtsK = 8; break;
case ZoneType_FELineSeg: ZoneSpec->NumPtsK = 2; break;
default:
{
ErrMsg(translate("Datafile corrupted: Invalid element type for FE DataSet"));
IsOk = FALSE;
}
}
}
else
{
ZoneSpec->Type = ZoneType_FEQuad;
ZoneSpec->NumPtsK = 4;
}
}
else
{
ZoneSpec->Type = ZoneType_Ordered;
ZoneSpec->ICellDim = ZoneSpec->NumPtsI - 1;
ZoneSpec->JCellDim = ZoneSpec->NumPtsJ - 1;
ZoneSpec->KCellDim = ZoneSpec->NumPtsK - 1;
}
}
/*
* Raw and user defined boundary face neighbors connections were not in
* this or previous versions of the binary data files.
*/
*IsRawFNAvailable = FALSE;
*FNNumBndryConns = 0;
}
else
{
if (IsOk && (IVersion >= 107))
{
ZoneSpec->ParentZone = GetIoFileInt(FileStream, IVersion, -1, MAXZONEMAP - 1, &IsOk);
if (!IsOk)
ErrMsg(translate("Invalid datafile: parent zone assignment must be to an existing zone within the same datafile."));
}
if (IsOk && (IVersion >= 106))
{
/* Strand ID and solution time. Strand ID's of STRAND_ID_PENDING, -2, instruct Tecplot to generate strand ID's */
ZoneSpec->StrandID = GetIoFileInt(FileStream, IVersion, -2, MAXZONEMAP - 1, &IsOk);
ZoneSpec->SolutionTime = GetNextValue(FileStream, FieldDataType_Double, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
if (!IsOk)
ErrMsg(translate("Invalid datafile: bad StrandID or SolutionTime"));
}
/* preset zone color */
IsOk = IsOk && ReadInPresetZoneColor(FileStream, IVersion, ZoneSpec);
/* ZoneType */
I1 = (ZoneType_e)GetIoFileInt(FileStream, IVersion, 0, 7, &IsOk);
switch (I1)
{
case 0: ZoneSpec->Type = ZoneType_Ordered; break;
case 1: ZoneSpec->Type = ZoneType_FELineSeg; break;
case 2: ZoneSpec->Type = ZoneType_FETriangle; break;
case 3: ZoneSpec->Type = ZoneType_FEQuad; break;
case 4: ZoneSpec->Type = ZoneType_FETetra; break;
case 5: ZoneSpec->Type = ZoneType_FEBrick; break;
case 6: ZoneSpec->Type = ZoneType_FEPolygon; break;
case 7: ZoneSpec->Type = ZoneType_FEPolyhedron; break;
default:
{
ErrMsg(translate("Invalid datafile: unknown zone type."));
IsOk = FALSE;
} break;
}
/* DataPacking (Always BLOCK starting with file version 112 so removed from binary format) */
if (IVersion < 112)
ZoneSpec->ZoneLoadInfo.IsInBlockFormat =
((DataPacking_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) == DataPacking_Block);
else
ZoneSpec->ZoneLoadInfo.IsInBlockFormat = TRUE;
/* is the variable value location specified? */
if ((Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) && IsOk)
{
/* Variable Value Location foreach Var */
for (Var = 0; Var < NumVars && IsOk; Var++)
{
if ((Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk) && IsOk &&
IsVarCellCentered != NULL)
{
IsOk = (ZoneSpec->ZoneLoadInfo.IsInBlockFormat);
if (IsOk)
IsOk = AddToSet(IsVarCellCentered, Var, FALSE);
else
ErrMsg(translate("Invalid datafile: cell centered "
"variable must be in block format.",
"See the Tecplot User's Manual for a definition of 'block format'"));
}
}
}
/* are raw face neighbors supplied in the data section? */
if (IVersion >= 108 && IsOk)
{
*IsRawFNAvailable = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
if (*IsRawFNAvailable &&
(ZoneSpec->Type == ZoneType_Ordered ||
ZoneSpec->Type == ZoneType_FELineSeg))
{
IsOk = FALSE;
ErrMsg(translate("Invalid datafile: raw face neighbors may not be "
"supplied for ordered or FE line segment zones."));
}
}
else
*IsRawFNAvailable = FALSE;
/*
* If raw face neighbors are available in the datafile then Tecplot
* should not auto-assign the neighbors after the load.
*/
ZoneSpec->FNAreCellFaceNbrsSupplied = *IsRawFNAvailable;
/* miscellaneous face neighbor info */
*FNNumBndryConns = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
if (*FNNumBndryConns != 0)
ZoneSpec->FNMode = (FaceNeighborMode_e)GetIoFileInt(FileStream, IVersion, 0, 3, &IsOk);
if (IVersion >= 108 && IsOk)
{
Boolean_t FaceNeighborsComplete = FALSE;
if (*FNNumBndryConns != 0 &&
ZoneSpec->Type != ZoneType_Ordered)
FaceNeighborsComplete = (Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
/*
* If the user defined face neighbors completely specify all the
* face neighbors then we don't want to auto-assign the cell face
* neighbors after loading. If they are not complete then leave the
* setting (as set above) dependent on the availability of the raw
* face neighbors.
*
* NOTE:
* This is a rather inefficient way to specify face neighbors.
*/
if (FaceNeighborsComplete)
ZoneSpec->FNAreCellFaceNbrsSupplied = TRUE;
}
if (ZoneSpec->Type == ZoneType_Ordered)
{
/* IMax, JMax, KMax */
ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
/*
* if not a zombie zone (zombie zone: points in all dimensions are
* zero) then points in each direction must be specified
*/
if (IsOk &&
!(ZoneSpec->NumPtsI == 0 &&
ZoneSpec->NumPtsJ == 0 &&
ZoneSpec->NumPtsK == 0) &&
(ZoneSpec->NumPtsI == 0 ||
ZoneSpec->NumPtsJ == 0 ||
ZoneSpec->NumPtsK == 0))
{
ErrMsg(translate("Invalid data file: incorrect specification of "
"I, J, or K points for ordered data set."));
IsOk = FALSE;
}
}
else
{
ZoneSpec->NumPtsI = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
if (ZoneSpec->Type == ZoneType_FEPolygon || ZoneSpec->Type == ZoneType_FEPolyhedron)
{
ZoneSpec->NumPtsK = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk); // ...NumFaces
if (IVersion >= 111)
{
ZoneSpec->NumFaceNodes = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
ZoneSpec->NumFaceBndryFaces = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
ZoneSpec->NumFaceBndryItems = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
}
}
else
{
switch (ZoneSpec->Type)
{
case ZoneType_FETriangle: ZoneSpec->NumPtsK = 3; break;
case ZoneType_FEQuad: ZoneSpec->NumPtsK = 4; break;
case ZoneType_FETetra: ZoneSpec->NumPtsK = 4; break;
case ZoneType_FEBrick: ZoneSpec->NumPtsK = 8; break;
case ZoneType_FELineSeg: ZoneSpec->NumPtsK = 2; break;
default :
{
ErrMsg(translate("Invalid data file: invalid element type for FE data set."));
IsOk = FALSE;
}
}
}
ZoneSpec->NumPtsJ = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
ZoneSpec->ICellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
ZoneSpec->JCellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
ZoneSpec->KCellDim = GetIoFileInt(FileStream, IVersion, 0, MAXINDEX, &IsOk);
}
/* Zone Auxiliary Data indicator followed by Zone Auxiliary Data */
for (I1 = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
IsOk && I1 != 0;
I1 = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk))
{
if (ZoneSpec->AuxData == NULL)
ZoneSpec->AuxData = AuxDataAlloc();
IsOk = (ZoneSpec->AuxData != NULL);
if (IsOk)
IsOk = ReadInAuxData(FileStream, IVersion, ZoneSpec->AuxData);
}
}
/*
* Convert AuxZone's Common.Time from non-time aware data files to zone
* solution time if it exists.
*/
if (IVersion < 106 && IsOk)
ConvertCommonTimeToSolutionTime(ZoneSpec);
ENSURE(VALID_BOOLEAN(IsOk));
return (IsOk);
}
/*
* Pass1 for Custom labels simply acknowledges that a custom label was
* parsed and skips over the labels.
*/
Boolean_t ReadInCustomLabels(FileStream_s *FileStream,
short IVersion,
Boolean_t OkToLoad,
StringList_pa *CustomLabelBase)
{
LgIndex_t NumLabels;
short I;
Boolean_t IsOk = TRUE;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(IVersion > 0);
REQUIRE(VALID_BOOLEAN(OkToLoad));
REQUIRE(!(OkToLoad) || VALID_REF(CustomLabelBase));
NumLabels = (short)GetIoFileInt(FileStream, IVersion, 1, MAXINDEX, &IsOk);
if (IsOk && NumLabels != 0 && OkToLoad)
{
*CustomLabelBase = StringListAlloc();
IsOk = (*CustomLabelBase != NULL);
if (!IsOk)
ErrMsg(translate("Cannot allocate memory for Custom Labels."));
}
for (I = 0; IsOk && (I < NumLabels); I++)
{
char *TLabel = NULL;
IsOk = ReadInString(FileStream, IVersion,
1024,
&TLabel,
OkToLoad);
TrimLeadAndTrailSpaces(TLabel);
if (IsOk && OkToLoad)
{
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
IsOk = StringListAppendString(*CustomLabelBase, TLabel);
if (TLabel != NULL)
FREE_ARRAY(TLabel, "custom label");
if (!IsOk)
ErrMsg(translate("Cannot allocate memory for Custom Label."));
}
}
if (!IsOk)
ErrMsg(translate("Invalid custom axis label record in binary datafile"));
ENSURE(VALID_BOOLEAN(IsOk));
ENSURE(!(IsOk && NumLabels != 0 && OkToLoad) ||
StringListValid(*CustomLabelBase));
return IsOk;
}
Boolean_t ReadInUserRec(FileStream_s *FileStream,
short IVersion,
int MaxCharactersAllowed,
char **UserRec) /* NULL if to ignore */
{
if (!ReadInString(FileStream, IVersion,
MaxCharactersAllowed,
UserRec,
(Boolean_t)(UserRec != NULL)))
{
ErrMsg(translate("Invalid USERREC record in binary datafile"));
return (FALSE);
}
return (TRUE);
}
/**
*/
Boolean_t ReadInAuxData(FileStream_s *FileStream,
short IVersion,
AuxData_pa AuxData)
{
Boolean_t IsOk;
Boolean_t DoCollectData;
char *AuxName = NULL;
LgIndex_t AuxValueType;
char *AuxValue = NULL;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(0 < IVersion && IVersion <= TecplotBinaryFileVersion);
REQUIRE(AuxData == NULL || VALID_REF(AuxData));
DoCollectData = (AuxData != NULL);
IsOk = ReadInString(FileStream,
IVersion,
MaxChrsVarName, /* ... seems reasonable */
&AuxName,
DoCollectData);
if (IsOk && DoCollectData && !AuxDataIsValidName(AuxName))
{
ErrMsg(translate("Invalid auxiliary data name."));
IsOk = FALSE;
}
/*
* currently only one value type is supported
* 0: AuxiliaryValueFormat_String
*/
if (IsOk)
{
AuxValueType = GetIoFileInt(FileStream, IVersion, 0, 0, &IsOk);
if (IsOk && (AuxValueType != (LgIndex_t)AuxDataType_String))
{
ErrMsg(translate("Unsupported auxiliary data type"));
IsOk = FALSE;
}
}
if (IsOk)
IsOk = ReadInString(FileStream,
IVersion,
MaxChrsAuxValueString,
&AuxValue,
DoCollectData);
if (IsOk && DoCollectData)
IsOk = AuxDataSetItem(AuxData,
AuxName, (ArbParam_t)AuxValue,
AuxDataType_String,
TRUE); /* Retain */
/* cleanup: auxiliary data made a copy of the name and value */
if (AuxName != NULL)
FREE_ARRAY(AuxName, "data set auxiliary data item name");
if (AuxValue != NULL)
FREE_ARRAY(AuxValue, "data set auxiliary data item value");
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
static void GetZoneAttachment(FileStream_s *FileStream,
short IVersion,
EntIndex_t *Z,
Boolean_t *IsAttached,
Boolean_t *IsOk)
{
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_REF(Z));
REQUIRE(VALID_REF(IsAttached));
REQUIRE(VALID_REF(IsOk) && VALID_BOOLEAN(*IsOk));
if (IVersion >= 47)
*Z = (EntIndex_t)GetIoFileInt(FileStream, IVersion, -1, MAXZONEMAP, IsOk);
else
*Z = 0;
if (IVersion < 70)
(*Z)--;
if (*Z == -1)
{
*Z = 0;
*IsAttached = FALSE;
}
else
*IsAttached = TRUE;
ENSURE(VALID_BOOLEAN(*IsAttached));
ENSURE(VALID_BOOLEAN(*IsOk));
ENSURE(*Z >= 0);
}
static Boolean_t ReadMacroFunctionCommand(FileStream_s *FileStream,
short IVersion,
Boolean_t OkToLoad,
char **MacroFunctionCommand)
{
Boolean_t Result = FALSE;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(IVersion > 0);
REQUIRE(VALID_BOOLEAN(OkToLoad));
REQUIRE(VALID_REF(MacroFunctionCommand));
Result = ReadInString(FileStream, IVersion, 0, MacroFunctionCommand, OkToLoad);
ENSURE(VALID_BOOLEAN(Result));
return (Result);
}
/*
* Pass1 for Geometries simply acknowledges that a geometry was
* parsed and skips over the geometry.
*/
Boolean_t ReadInGeometry(FileStream_s *FileStream,
short IVersion,
Boolean_t OkToLoad,
Geom_s *Geom,
LgIndex_t MaxDataPts)
{
LgIndex_t I;
LgIndex_t S;
FieldDataType_e FFT;
Boolean_t IsOk = TRUE;
TranslatedString ErrMsgString = translate("Invalid geometry record");
REQUIRE(VALID_REF(Geom));
if (IVersion < 70)
FFT = FieldDataType_Float;
else
FFT = FieldDataType_Double;
if (IVersion < 101)
I = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
else
I = GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
if (I == 0)
Geom->PositionCoordSys = CoordSys_Grid;
else if (I == 1)
Geom->PositionCoordSys = CoordSys_Frame;
/*
* I == 2 is for CoordSys_FrameOffset and is not used currently
*
* I == 3 is for the old window coordinate system
*/
else if (I == 4)
Geom->PositionCoordSys = CoordSys_Grid3D;
else
{
ErrMsgString = translate("Invalid geometry coordinate system");
IsOk = FALSE;
}
Geom->Scope = (Scope_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
if (IVersion >= 102)
Geom->DrawOrder = (DrawOrder_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
Geom->AnchorPos.Generic.V1 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
Geom->AnchorPos.Generic.V2 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
if (IVersion >= 45)
Geom->AnchorPos.Generic.V3 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
else
Geom->AnchorPos.Generic.V3 = 0.0;
GetZoneAttachment(FileStream, IVersion, &Geom->Zone, &Geom->AttachToZone, &IsOk);
Geom->BColor = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
AdjustCustomColor(IVersion, &Geom->BColor);
if (IVersion > 47)
{
Geom->FillBColor = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
Geom->IsFilled = (Boolean_t)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
AdjustCustomColor(IVersion, &Geom->FillBColor);
}
else
{
Geom->FillBColor = Geom->BColor;
Geom->IsFilled = FALSE;
}
if (IVersion < 101)
{
Geom->GeomType = (GeomType_e)GetIoFileInt(FileStream, IVersion, 0, 5, &IsOk);
if (Geom->GeomType == GeomType_LineSegs3D)
{
/*
* GeomType_LineSegs3D is deprecated, converter to GeomType_LineSegs
* with CoordSys_Grid3D instead
*/
Geom->GeomType = GeomType_LineSegs;
Geom->PositionCoordSys = CoordSys_Grid3D; /*...should have been anyway */
}
}
else
{
Geom->GeomType = (GeomType_e)GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
}
/*
* Check geom coord sys versus geom type
*/
if (Geom->PositionCoordSys == CoordSys_Grid3D &&
Geom->GeomType != GeomType_LineSegs)
{
ErrMsgString = translate("Mismatch between geometry coordinate system and geometry type");
IsOk = FALSE;
}
if (IVersion > 41)
{
Geom->LinePattern = (LinePattern_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)LinePattern_DashDotDot, &IsOk);
}
else
{
Geom->LinePattern = (LinePattern_e)((int)Geom->GeomType % 2);
Geom->GeomType = (GeomType_e)((int)Geom->GeomType / 10);
}
if ((IVersion < 49) && ((short)(Geom->GeomType) == 2))
{
Geom->GeomType = GeomType_Rectangle;
Geom->IsFilled = TRUE;
}
if ((IVersion < 70) && ((short)(Geom->GeomType) > 1))
Geom->GeomType = (GeomType_e)((short)Geom->GeomType + 1);
ResetString(&Geom->MacroFunctionCommand, NULL, TRUE);
Geom->ImageResizeFilter = ImageResizeFilter_Texture;
if (IVersion >= 70)
{
Geom->PatternLength = GetNextValue(FileStream, FFT,
PatternLengthInputSpec.Min,
PatternLengthInputSpec.Max,
&IsOk);
Geom->LineThickness = GetNextValue(FileStream, FFT,
LineThicknessInputSpec.Min,
LineThicknessInputSpec.Max,
&IsOk);
Geom->NumEllipsePts = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 2, MaxPtsCircleOrEllipse, &IsOk);
Geom->ArrowheadStyle = (ArrowheadStyle_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)ArrowheadStyle_Hollow, &IsOk);
Geom->ArrowheadAttachment = (ArrowheadAttachment_e)GetIoFileInt(FileStream, IVersion,
0,
(LgIndex_t)ArrowheadAttachment_AtBothEnds,
&IsOk);
Geom->ArrowheadSize = GetNextValue(FileStream, FFT,
ArrowheadSizeInputSpec.Min,
ArrowheadSizeInputSpec.Max,
&IsOk);
Geom->ArrowheadAngle = GetNextValue(FileStream, FFT,
ArrowheadAngleInputSpec.Min,
ArrowheadAngleInputSpec.Max,
&IsOk);
if (IVersion >= 75)
{
IsOk = ReadMacroFunctionCommand(FileStream,
IVersion,
OkToLoad,
&Geom->MacroFunctionCommand);
} /* version >= 75 */
} /* version >= 70 */
else
{
Geom->LineThickness = 0.001;
Geom->PatternLength = 0.02;
Geom->ArrowheadStyle = ArrowheadStyle_Plain;
Geom->ArrowheadAttachment = ArrowheadAttachment_None;
Geom->ArrowheadSize = 0.05;
Geom->ArrowheadAngle = 12.0 / DEGPERRADIANS;
}
if (IVersion < 41)
{
GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
GetNextValue(FileStream, FieldDataType_Float, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
}
if (IVersion < 70)
Geom->DataType = FieldDataType_Float;
else
Geom->DataType = (FieldDataType_e)GetIoFileInt(FileStream, IVersion, 1, 2, &IsOk);
CHECK(VALID_GEOM_FIELD_DATA_TYPE(Geom->DataType));
Geom->Clipping = Clipping_ClipToViewport; /* default value for pre 101 versions */
if (IVersion >= 101)
{
Geom->Clipping = (Clipping_e)GetIoFileInt(FileStream, IVersion, 0, 2, &IsOk);
/*
* The second clipping value was deprecated during v10 development and thus removed.
* This moved Clipping_ClipToFrame to the 2nd position from the 3rd, so we convert
* value 2 to ClipToFrame to support files made during v10 developement.
*/
if (Geom->Clipping == (Clipping_e)2)
Geom->Clipping = Clipping_ClipToFrame;
}
if (IVersion < 50 ||
Geom->GeomType == GeomType_LineSegs)
{
Geom->NumSegments = (SmInteger_t)GetIoFileInt(FileStream, IVersion, 1, MaxGeoSegments, &IsOk);
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
S = -1;
I = 0;
while ((S + 1 < Geom->NumSegments) &&
!feof(FileStream->File) && IsOk)
{
S++;
Geom->NumSegPts[S] = GetIoFileInt(FileStream, IVersion, 1, MAXINDEX, &IsOk);
if ((I + Geom->NumSegPts[S] > MaxDataPts) && OkToLoad)
{
ErrMsgString = translate("Geometry is too big");
IsOk = FALSE;
}
else
{
ReadBlock(FileStream, Geom->GeomData.Generic.V1Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
ReadBlock(FileStream, Geom->GeomData.Generic.V2Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
if (Geom->PositionCoordSys == CoordSys_Grid3D)
ReadBlock(FileStream, Geom->GeomData.Generic.V3Base, OkToLoad, Geom->DataType, I, I + Geom->NumSegPts[S] - 1, &IsOk);
I += Geom->NumSegPts[S];
}
}
if (IsOk && (Geom->GeomType == GeomType_Rectangle)) /* IVersion < 50 */
{
if (OkToLoad)
{
CopyFieldValue(Geom->GeomData.Generic.V1Base, 0, Geom->GeomData.Generic.V1Base, 2);
CopyFieldValue(Geom->GeomData.Generic.V2Base, 0, Geom->GeomData.Generic.V2Base, 2);
}
}
}
else if (Geom->GeomType == GeomType_Rectangle ||
Geom->GeomType == GeomType_Ellipse)
{
double XX, YY;
XX = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
YY = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
if (OkToLoad)
{
SetFieldValue(Geom->GeomData.XYZ.XBase, 0, XX);
SetFieldValue(Geom->GeomData.XYZ.YBase, 0, YY);
}
Geom->NumSegments = 1;
Geom->NumSegPts[0] = 1;
}
else
{
double XX;
CHECK((Geom->GeomType == GeomType_Square) ||
(Geom->GeomType == GeomType_Circle));
XX = GetNextValue(FileStream, Geom->DataType, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
if (OkToLoad)
{
SetFieldValue(Geom->GeomData.XYZ.XBase, 0, XX);
}
Geom->NumSegments = 1;
Geom->NumSegPts[0] = 1;
}
if (!IsOk)
ErrMsg(ErrMsgString);
return (IsOk);
}
/*
* Pass1 for text simply acknowledges that a text was
* parsed and skips over the text.
*/
Boolean_t ReadInText(FileStream_s *FileStream,
short IVersion,
Boolean_t OkToLoad,
Text_s *Text,
LgIndex_t MaxTextLen)
{
LgIndex_t I;
FieldDataType_e FFT;
SmInteger_t TextLength = 0;
Boolean_t IsOk = TRUE;
TranslatedString ErrMsgString = translate("Invalid text record");
REQUIRE(VALID_REF(Text));
if (IVersion < 70)
FFT = FieldDataType_Float;
else
FFT = FieldDataType_Double;
if (IVersion < 101)
I = GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
else
I = GetIoFileInt(FileStream, IVersion, 0, 4, &IsOk);
if (I == 0)
Text->PositionCoordSys = CoordSys_Grid;
else if (I == 1)
Text->PositionCoordSys = CoordSys_Frame;
/*
* I == 2 is for CoordSys_FrameOffset and is not used currently
*
* I == 3 is for the old window coordinate system
*/
else if (I == 4)
Text->PositionCoordSys = CoordSys_Grid3D;
else
{
ErrMsgString = translate("Invalid text coordinate system.");
IsOk = FALSE;
}
Text->Scope = (Scope_e)GetIoFileInt(FileStream, IVersion, 0, 1, &IsOk);
Text->AnchorPos.Generic.V1 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
Text->AnchorPos.Generic.V2 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
if (IVersion >= 101)
Text->AnchorPos.Generic.V3 = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
else
Text->AnchorPos.Generic.V3 = 0.0; /* default value for pre 101 versions */
if (IVersion > 40)
Text->TextShape.Font = (Font_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)Font_CourierBold, &IsOk);
else
Text->TextShape.Font = Font_Helvetica;
if (IVersion < 43)
GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
if (IVersion < 70)
{
if (Text->PositionCoordSys == CoordSys_Grid)
Text->TextShape.SizeUnits = Units_Grid;
else
Text->TextShape.SizeUnits = Units_Frame;
}
else
Text->TextShape.SizeUnits = (Units_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)Units_Point, &IsOk);
Text->TextShape.Height = GetNextValue(FileStream, FFT, -LARGEDOUBLE, LARGEDOUBLE, &IsOk);
if (IVersion > 47)
{
Text->Box.BoxType = (TextBox_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)TextBox_Hollow, &IsOk);
if (IVersion < 70)
{
if (Text->Box.BoxType == TextBox_Hollow)
Text->Box.BoxType = TextBox_Filled;
else if (Text->Box.BoxType == TextBox_Filled)
Text->Box.BoxType = TextBox_Hollow;
}
Text->Box.Margin = GetNextValue(FileStream, FFT,
TextBoxMarginInputSpec.Min,
TextBoxMarginInputSpec.Max,
&IsOk);
if (IVersion >= 70)
Text->Box.LineThickness = GetNextValue(FileStream, FFT,
LineThicknessInputSpec.Min,
LineThicknessInputSpec.Max,
&IsOk);
else
Text->Box.LineThickness = 0.01;
Text->Box.BColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
Text->Box.FillBColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
AdjustCustomColor(IVersion, &Text->Box.BColor);
AdjustCustomColor(IVersion, &Text->Box.FillBColor);
}
else
{
Text->Box.BoxType = TextBox_None;
Text->Box.Margin = 0.0;
Text->Box.BColor = White_C;
Text->Box.FillBColor = Black_C;
}
if (IVersion < 70)
{
Text->Angle = GetIoFileInt(FileStream, IVersion, -720, 720, &IsOk) / DEGPERRADIANS;
Text->LineSpacing = 1;
Text->Anchor = TextAnchor_Left;
}
else
{
Text->Angle = GetNextValue(FileStream, FFT,
TextAngleInputSpec.Min,
TextAngleInputSpec.Max,
&IsOk);
Text->LineSpacing = GetNextValue(FileStream, FFT,
TextLineSpacingInputSpec.Min,
TextLineSpacingInputSpec.Max,
&IsOk);
Text->Anchor = (TextAnchor_e)GetIoFileInt(FileStream, IVersion, 0, (LgIndex_t)TextAnchor_HeadRight, &IsOk);
}
GetZoneAttachment(FileStream, IVersion, &Text->Zone, &Text->AttachToZone, &IsOk);
Text->BColor = (ColorIndex_t)GetIoFileInt(FileStream, IVersion, 0, 255, &IsOk);
AdjustCustomColor(IVersion, &Text->BColor);
if (IVersion < 70)
TextLength = (short)GetIoFileInt(FileStream, IVersion, 0, 5000, &IsOk);
ResetString(&Text->MacroFunctionCommand, NULL, TRUE);
Text->Clipping = Clipping_ClipToViewport; /* default value for pre 101 versions */
if (IVersion < 70)
{
short I, S;
for (I = 0; I < TextLength; I++)
{
S = (short)GetIoFileInt(FileStream, IVersion, 0, 1000, &IsOk);
if (OkToLoad && (I <= MaxTextLen))
Text->Text[I] = (char)S;
}
if (OkToLoad)
Text->Text[MIN(TextLength, MaxTextLen)] = '\0';
}
else
{
char *S = NULL;
if (IVersion >= 75)
{
IsOk = ReadMacroFunctionCommand(FileStream,
IVersion,
OkToLoad,
&Text->MacroFunctionCommand);
} /* IVersion >= 75 */
if (IVersion >= 101)
{
/*
* The second clipping value was deprecated during v10 development and thus removed.
* This moved Clipping_ClipToFrame to the 2nd position from the 3rd, so we convert
* value 2 to ClipToFrame to support files made during v10 developement.
*/
Text->Clipping = (Clipping_e)GetIoFileInt(FileStream, IVersion, 0, 2, &IsOk);
if (Text->Clipping == (Clipping_e)2)
Text->Clipping = Clipping_ClipToFrame;
}
if (ReadInString(FileStream,
IVersion,
MaxTextLen,
&S,
OkToLoad))
{
REQUIRE(!(S || OkToLoad) || VALID_REF(Text->Text));
if (S)
{
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif /* TECPLOTKERNEL */
if (IsOk)
{
strcpy(Text->Text, S);
}
FREE_ARRAY(S, "Release temp string for new text label");
}
else if (OkToLoad)
Text->Text[0] = '\0';
}
else
IsOk = FALSE;
}
if (!IsOk)
ErrMsg(ErrMsgString);
return (IsOk);
}
static Boolean_t CompareVersion(float Version,
char *VersionString,
Boolean_t IsByteOrderNative)
{
char *VersionBuf = (char *) & Version;
REQUIRE(VALID_REF(VersionString));
if (IsByteOrderNative)
return ((VersionString[0] == VersionBuf[0]) &&
(VersionString[1] == VersionBuf[1]) &&
(VersionString[2] == VersionBuf[2]) &&
(VersionString[3] == VersionBuf[3]));
else
return ((VersionString[3] == VersionBuf[0]) &&
(VersionString[2] == VersionBuf[1]) &&
(VersionString[1] == VersionBuf[2]) &&
(VersionString[0] == VersionBuf[3]));
}
static float ValidVersions[] = {7.0F,
6.3F, 6.2F, 6.1F, 6.0F,
5.0F,
4.7F, 4.6F, 4.5F, 4.4F, 4.3F, 4.2F, 4.1F, 4.0F
};
#define NUMVALIDVERSIONS ((int)(sizeof(ValidVersions)/sizeof(ValidVersions[0])))
/*
* Extra caution taken here in case value read is invalid float
*/
static Boolean_t GetDoubleVersion(char *VersionString,
float *FInputVersion,
Boolean_t IsByteOrderNative)
{
int I;
REQUIRE(VALID_REF(FInputVersion));
for (I = 0; I < NUMVALIDVERSIONS; I++)
if (CompareVersion(ValidVersions[I], VersionString, IsByteOrderNative))
{
*FInputVersion = ValidVersions[I];
return (TRUE);
}
return (FALSE);
}
static short GetNewInputVersion(FileStream_s *FileStream)
{
/*
*
*/
char Buf[4];
short IVersion = 0;
short I;
LgIndex_t OneValue;
Boolean_t IsOk = TRUE;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(FileStream->IsByteOrderNative);
if (TP_FREAD(Buf, 4, 1, FileStream->File) != 1)
return (0);
if (strncmp(Buf, "#!TD", 4))
return (0);
if (TP_FREAD(Buf, 4, 1, FileStream->File) != 1)
return (0);
if (Buf[0] != 'V')
return (0);
I = 1;
while ((I < 4) && isdigit(Buf[I]))
IVersion = IVersion * 10 + Buf[I++] - '0';
if (IVersion < 70)
return (0);
else if (IVersion > TecplotBinaryFileVersion)
{
ErrMsg(translate("Binary file version newer than Tecplot version. "
"Upgrade Tecplot or use an older Preplot to produce "
"the datafile."));
return (IVersion);
}
/*
* Determine Byte Order.
*/
OneValue = GetIoFileInt(FileStream,
IVersion,
-MAXINDEX,
MAXINDEX,
&IsOk);
if (!IsOk)
return (0);
FileStream->IsByteOrderNative = (OneValue == 1);
return (IVersion);
}
/**
* Return value of zero is to be considered as an invalid
* tecplot binary datafile header. Actually binary files
* older than version 4.0 (return value of 40) are not supported
* (See notes in preplot.c).
*/
short GetInputVersion(FileStream_s *FileStream)
{
Boolean_t IsOk = TRUE;
float FInputVersion;
short IVersion;
char VersionString[4];
FileOffset_t StartOffset = 0;
/*
* First check to see if file uses new
* input version format.
*/
/* keep track of our start offset */
StartOffset = TP_FTELL(FileStream->File);
IVersion = GetNewInputVersion(FileStream);
if (IVersion > TecplotBinaryFileVersion)
return IVersion; /* unsupported version */
else if (IVersion == 0)
{
/* rewind to clear any errors and seek to the start offset */
rewind(FileStream->File);
IsOk = (TP_FSEEK(FileStream->File, StartOffset, SEEK_SET) == 0);
if (IsOk && TP_FREAD(VersionString, 4, 1, FileStream->File) == 1)
{
/* try both native and foreign versions numbers */
if (!GetDoubleVersion(VersionString, &FInputVersion, FileStream->IsByteOrderNative))
{
FileStream->IsByteOrderNative = !FileStream->IsByteOrderNative; /* ...reverse the byte order */
IsOk = GetDoubleVersion(VersionString, &FInputVersion, FileStream->IsByteOrderNative);
}
if (IsOk)
IVersion = ROUNDS(FInputVersion * 10);
}
}
if (IsOk)
return (IVersion);
else
return ((short)0);
}
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#if !defined ENGINE /* TODO(RMS)-H 12/12/2005: ENGINE: refactor to use just the Interrupted flag as-is */
#else
#endif
#endif
/**********************************************************************
**********************************************************************
********************** OUTPUT **************************
**********************************************************************
**********************************************************************/
/**
* Byte blocks cannot be unaligned or reversed in bytes
*/
Boolean_t WriteBinaryByteBlock(FileStream_s *FileStream,
const Byte_t *ByteValues,
const HgIndex_t NumValues)
{
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_REF(ByteValues));
REQUIRE(NumValues >= 0);
Boolean_t IsOk = TP_FWRITE(ByteValues,
sizeof(Byte_t),
(size_t)NumValues,
FileStream->File) == (size_t)NumValues;
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
* Type Byte_t cannot be unaligned or reversed in byte order
*/
static inline Boolean_t WriteBinaryByte(FileStream_s *FileStream,
Byte_t ByteValue)
{
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
Boolean_t IsOk = WriteBinaryByteBlock(FileStream, &ByteValue, 1);
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
*/
template <typename T>
void CopyAndReverseUnalignedBytes(T *DstBuffer,
const Byte_t *SrcBuffer)
{
REQUIRE(VALID_REF(DstBuffer));
REQUIRE(VALID_REF(SrcBuffer));
size_t typeSize = sizeof(T);
for (size_t ii = 0; ii < typeSize; ii++)
((Byte_t *)(DstBuffer))[ii] = ((Byte_t *)(SrcBuffer))[typeSize-1-ii];
}
/**
*/
template <typename T>
void CopyUnalignedBytes(T *DstBuffer,
const Byte_t *SrcBuffer)
{
REQUIRE(VALID_REF(DstBuffer));
REQUIRE(VALID_REF(SrcBuffer));
for (size_t ii = 0; ii < sizeof(T); ii++)
((Byte_t *)(DstBuffer))[ii] = ((Byte_t *)(SrcBuffer))[ii];
}
/**
*/
template <typename T>
Boolean_t WriteBinaryDataUnaligned(FileStream_s *FileStream,
const Byte_t *ValueBuffer,
const Boolean_t ValueInNativeOrder)
{
REQUIRE(VALID_REF(FileStream) && VALID_FILE_HANDLE(FileStream->File));
REQUIRE(VALID_REF(ValueBuffer));
REQUIRE(VALID_BOOLEAN(ValueInNativeOrder));
T DataValue;
if (ValueInNativeOrder != FileStream->IsByteOrderNative)
CopyAndReverseUnalignedBytes<T>(&DataValue, ValueBuffer);
else
CopyUnalignedBytes<T>(&DataValue, ValueBuffer);
Boolean_t IsOk = TP_FWRITE(&DataValue, sizeof(T), 1, FileStream->File) == 1;
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
* This is used in many places and requires the value be in proper order.
*/
Boolean_t WriteBinaryInt16(FileStream_s *FileStream,
Int16_t Value)
{
Boolean_t IsOk;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE("Value can be any Int16_t");
IsOk = WriteBinaryDataUnaligned<Int16_t>(FileStream, (Byte_t *) & Value, TRUE/*ValueInNativeOrder*/);
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
* This is used in many places and requires the value be in proper order.
*/
Boolean_t WriteBinaryInt32(FileStream_s *FileStream,
Int32_t Value)
{
Boolean_t IsOk;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE("Value can be any Int32_t");
IsOk = WriteBinaryDataUnaligned<Int32_t>(FileStream, (Byte_t *) & Value, TRUE/*ValueInNativeOrder*/);
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
*/
template <typename T>
Boolean_t WriteBinaryBlockUnaligned(FileStream_s *FileStream,
const Byte_t *Values,
const HgIndex_t NumValues,
const Boolean_t ValuesInNativeOrdering)
{
Boolean_t IsOk = TRUE;
Boolean_t WriteEachValueSeparately;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_REF(Values));
REQUIRE(NumValues >= 0);
REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
WriteEachValueSeparately = (ValuesInNativeOrdering != FileStream->IsByteOrderNative);
if (WriteEachValueSeparately)
{
for (HgIndex_t NIndex = 0; IsOk && NIndex < NumValues; NIndex++)
{
IsOk = WriteBinaryDataUnaligned<T>(FileStream, Values + NIndex * sizeof(T), ValuesInNativeOrdering);
}
}
else
{
#if 1
size_t NumBytesToWrite = NumValues * sizeof(T);
size_t NumBytesWritten = TP_FWRITE(Values, sizeof(Byte_t), NumBytesToWrite, FileStream->File);
IsOk = NumBytesToWrite == NumBytesWritten;
#else
IsOk = WriteBinaryByteBlock(FileStream, Values, NumValues * sizeof(T));
#endif
}
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
* Use Byte_t instead of Int16_t to support unaligned values
*/
Boolean_t WriteBinaryInt16BlockUnaligned(FileStream_s *FileStream,
Byte_t *Int16Values,
HgIndex_t NumValues,
Boolean_t ValuesInNativeOrdering)
{
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_REF(Int16Values));
REQUIRE(NumValues >= 0);
REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
Boolean_t IsOk = WriteBinaryBlockUnaligned<Int16_t>(FileStream,
Int16Values,
NumValues,
ValuesInNativeOrdering);
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
* Use Byte_t instead of Int32_t to support unaligned values
*/
Boolean_t WriteBinaryInt32BlockUnaligned(FileStream_s *FileStream,
Byte_t *Int32Values,
HgIndex_t NumValues,
Boolean_t ValuesInNativeOrdering)
{
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_REF(Int32Values));
REQUIRE(NumValues >= 0);
REQUIRE(VALID_BOOLEAN(ValuesInNativeOrdering));
Boolean_t IsOk = WriteBinaryBlockUnaligned<Int32_t>(FileStream,
Int32Values,
NumValues,
ValuesInNativeOrdering);
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
*/
Boolean_t WriteBinaryReal(FileStream_s *FileStream,
double RR,
FieldDataType_e FieldDataType)
{
Boolean_t IsOk = FALSE; /* ...quite compiler */
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE((FieldDataType == FieldDataType_Float) ||
(FieldDataType == FieldDataType_Double) ||
(FieldDataType == FieldDataType_Byte));
switch (FieldDataType)
{
case FieldDataType_Float :
{
float FloatVal = CONVERT_DOUBLE_TO_FLOAT(RR);
IsOk = WriteBinaryDataUnaligned<float>(FileStream, (Byte_t *) & FloatVal, TRUE/*NativeOrdering*/);
} break;
case FieldDataType_Double :
{
double DoubleVal = CLAMP_DOUBLE(RR);
IsOk = WriteBinaryDataUnaligned<double>(FileStream, (Byte_t *) & DoubleVal, TRUE/*NativeOrdering*/);
} break;
case FieldDataType_Byte :
{
/* Note: type Byte cannot be unaligned or reversed in bytes */
Byte_t B;
if (RR > 255)
B = 255;
else if (RR < 0)
B = 0;
else
B = (Byte_t)RR;
IsOk = WriteBinaryByte(FileStream, B);
} break;
default: CHECK(FALSE); break;
}
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
Boolean_t WriteFieldDataType(FileStream_s *FileStream,
FieldDataType_e FDT,
Boolean_t WriteBinary)
{
if (WriteBinary)
return (WriteBinaryInt32(FileStream, (LgIndex_t)FDT));
else
{
short S = 0;
switch (FDT)
{
case FieldDataType_Float : S = fprintf(FileStream->File, "SINGLE "); break;
case FieldDataType_Double : S = fprintf(FileStream->File, "DOUBLE "); break;
case FieldDataType_Int32 : S = fprintf(FileStream->File, "LONGINT "); break;
case FieldDataType_Int16 : S = fprintf(FileStream->File, "SHORTINT "); break;
case FieldDataType_Byte : S = fprintf(FileStream->File, "BYTE "); break;
case FieldDataType_Bit : S = fprintf(FileStream->File, "BIT "); break;
default: CHECK(FALSE);
}
return (FPRINTFOK(S));
}
}
/**
*/
template <typename T>
Boolean_t WriteBinaryChecksumByteValues(FileStream_s *FileStream,
const Byte_t *ByteValues,
const HgIndex_t NumValues)
{
REQUIRE(VALID_REF(FileStream) && VALID_FILE_HANDLE(FileStream->File));
REQUIRE(VALID_REF(ByteValues));
REQUIRE(NumValues >= 1);
Boolean_t IsOk;
if (NumValues == 1)
IsOk = WriteBinaryDataUnaligned<T>(FileStream, ByteValues, TRUE);
else
IsOk = WriteBinaryBlockUnaligned<T>(FileStream, ByteValues, NumValues, TRUE);
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
* For FieldData of Type Bit, use WriteBinaryFieldDataBlockOfTypeBit instead.
*/
template <typename T>
Boolean_t WriteBinaryFieldDataBlockOfType(FileStream_s *FileStream,
const FieldData_pa FieldData,
const LgIndex_t StartOffset,
const LgIndex_t NumValues)
{
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
Boolean_t IsOk = FALSE;
if (IsFieldDataDirectAccessAllowed(FieldData))
{
Byte_t *ByteArray = GetFieldDataBytePtr(FieldData) + StartOffset * sizeof(T);
IsOk = WriteBinaryChecksumByteValues<T>(FileStream, ByteArray, (HgIndex_t)NumValues);
}
else
{
for (LgIndex_t Offset = StartOffset; Offset < NumValues; Offset++)
{
T ValueBuffer = (T)GetFieldValue(FieldData, Offset);
Byte_t *ByteValue = (Byte_t *) & ValueBuffer;
IsOk = WriteBinaryChecksumByteValues<T>(FileStream, ByteValue, 1);
}
}
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
static Boolean_t WriteBinaryFieldDataBlockOfTypeBit(FileStream_s *FileStream,
const FieldData_pa FieldData,
const LgIndex_t StartOffset, /* Not used */
const LgIndex_t NumValues)
{
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
Boolean_t IsOk = FALSE;
size_t NumBytes = 1 + (NumValues - 1) / 8;
if (IsFieldDataDirectAccessAllowed(FieldData))
{
Byte_t *ByteArray = GetFieldDataBytePtr(FieldData);
IsOk = WriteBinaryChecksumByteValues<Byte_t>(FileStream, ByteArray, (HgIndex_t)NumBytes);
}
else
{
// Bits are written out a Byte at a time and since we only come in here every 8th
// bit, make sure to assemble a Byte value from the next 8 bits.
for (LgIndex_t Offset = 0; Offset < NumValues; Offset += 8)
{
Byte_t ValueBuffer = 0;
for (int ii = 0; ii < 8; ii++)
{
Byte_t CurBit = (Byte_t)GetFieldValue(FieldData, Offset + ii);
ValueBuffer |= (CurBit << ii);
}
IsOk = WriteBinaryChecksumByteValues<Byte_t>(FileStream, &ValueBuffer, 1);
}
}
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/*
*/
Boolean_t WriteBinaryFieldDataBlock(FileStream_s *FileStream,
FieldData_pa FieldData,
LgIndex_t StartOffset,
LgIndex_t NumValues)
{
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
Boolean_t IsOk = FALSE;
switch (GetFieldDataType(FieldData))
{
case FieldDataType_Float : IsOk = WriteBinaryFieldDataBlockOfType<float>(FileStream, FieldData, StartOffset, NumValues); break;
case FieldDataType_Double : IsOk = WriteBinaryFieldDataBlockOfType<double>(FileStream, FieldData, StartOffset, NumValues); break;
case FieldDataType_Int32 : IsOk = WriteBinaryFieldDataBlockOfType<Int32_t>(FileStream, FieldData, StartOffset, NumValues); break;
case FieldDataType_Int16 : IsOk = WriteBinaryFieldDataBlockOfType<Int16_t>(FileStream, FieldData, StartOffset, NumValues); break;
case FieldDataType_Byte : IsOk = WriteBinaryFieldDataBlockOfType<Byte_t>(FileStream, FieldData, StartOffset, NumValues); break;
case FieldDataType_Bit : IsOk = WriteBinaryFieldDataBlockOfTypeBit(FileStream, FieldData, StartOffset, NumValues); break;
default: CHECK(FALSE); break;
}
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
static Boolean_t WriteASCIIFieldDataValue(FileStream_s *FileStream,
FieldData_pa FieldData,
LgIndex_t Offset,
SmInteger_t AsciiPrecision)
{
Boolean_t IsOk = FALSE; /* ...quiet compiler */
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
double V = 0.0;
char buffer[100*MAX_SIZEOFUTF8CHAR];
char *AsciiValue = buffer;
#ifdef TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
V = GetFieldValue(FieldData, Offset);
switch (GetFieldDataType(FieldData))
{
case FieldDataType_Float :
case FieldDataType_Double :
/*IsOk = FPRINTFOK(fprintf(FileStream->File," %.*E",(int)AsciiPrecision,V)); */
sprintf(buffer, " %.*E", (int)AsciiPrecision, V);
break;
case FieldDataType_Int32 :
/* IsOk = FPRINTFOK(fprintf(FileStream->File," %*d",(int)AsciiPrecision,ROUNDL(V))); */
sprintf(buffer, " %*d", (int)AsciiPrecision, ROUNDL(V));
break;
case FieldDataType_Int16 :
/* IsOk = FPRINTFOK(fprintf(FileStream->File," %6d",ROUND2(V))); */
sprintf(buffer, " %6d", ROUND2(V));
break;
case FieldDataType_Byte :
/* IsOk = FPRINTFOK(fprintf(FileStream->File," %3d",ROUNDS(V))); */
sprintf(buffer, " %3d", ROUNDS(V));
break;
case FieldDataType_Bit :
/* IsOk = FPRINTFOK(fprintf(FileStream->File," %c",((V == 0) ? '0' : '1'))); */
sprintf(buffer, " %c", ((V == 0) ? '0' : '1'));
break;
default: CHECK(FALSE); break;
}
IsOk = FPRINTFOK(fprintf(FileStream->File, buffer));
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#endif
ENSURE(VALID_BOOLEAN(IsOk));
return (IsOk);
}
/**
*/
Boolean_t WriteCCFieldDataBlock(FileStream_s *FileStream,
FieldData_pa FieldData,
Boolean_t IsOrderedData,
LgIndex_t NumIPts,
LgIndex_t NumJPts,
LgIndex_t NumKPts,
Boolean_t WriteBinary,
SmInteger_t AsciiPrecision)
{
Boolean_t IsOk = TRUE;
LgIndex_t NumValues;
LgIndex_t I, J, K;
LgIndex_t NumIJPts = -1;
LgIndex_t IEnd = -1;
LgIndex_t JEnd = -1;
LgIndex_t KEnd = -1;
Boolean_t IsLinear = -1;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_REF(FieldData));
REQUIRE(VALID_BOOLEAN(IsOrderedData));
REQUIRE(NumIPts >= 0);
REQUIRE(NumJPts >= 0);
REQUIRE(NumKPts >= 0);
REQUIRE(VALID_BOOLEAN(WriteBinary));
REQUIRE(IMPLICATION(!WriteBinary, AsciiPrecision >= 0));
/*
* As of version 103 Tecplot writes binary data files so that ordered cell
* centered field data includes the ghost cells. This makes it much easier
* for Tecplot to map the data when reading by simply writing out
* FieldData->NumValues. As of version 104 the ghost cells of the slowest
* moving index are not included but that does effect the output as it is
* still FieldData->NumValues.
*/
if (IsOrderedData && !WriteBinary)
{
/*
* Ordered ASCII output is always layed out using
* DataValueStructure_Classic format.
*/
NumIJPts = NumIPts * NumJPts;
IEnd = MAX(NumIPts - 1, 1);
JEnd = MAX(NumJPts - 1, 1);
KEnd = MAX(NumKPts - 1, 1);
NumValues = (IEnd * JEnd * KEnd);
IsLinear = ((NumJPts == 1 && NumKPts == 1) ||
(NumIPts == 1 && NumKPts == 1) ||
(NumIPts == 1 && NumJPts == 1));
}
else
{
NumValues = GetFieldDataNumValues(FieldData);
}
if (WriteBinary)
{
IsOk = WriteBinaryFieldDataBlock(FileStream, FieldData, 0, NumValues);
}
else
{
LgIndex_t NumValuesPerLine = 80 / (AsciiPrecision + 5);
if (IsOrderedData && !IsLinear)
{
LgIndex_t ValueIndex = 0;
for (K = 0; K < KEnd && IsOk; K++)
for (J = 0; J < JEnd && IsOk; J++)
for (I = 0; I < IEnd && IsOk; I++)
{
LgIndex_t CellIndex = I + (J * NumIPts) + (K * NumIJPts);
IsOk = WriteASCIIFieldDataValue(FileStream,
FieldData,
CellIndex,
AsciiPrecision);
if ((ValueIndex + 1) % NumValuesPerLine == 0 || ValueIndex == NumValues - 1)
IsOk = (fputc('\n', FileStream->File) != EOF);
ValueIndex++;
}
}
else
{
for (I = 0; I < NumValues && IsOk; I++)
{
IsOk = WriteASCIIFieldDataValue(FileStream,
FieldData,
I,
AsciiPrecision);
if ((I + 1) % NumValuesPerLine == 0 || I == NumValues - 1)
IsOk = (fputc('\n', FileStream->File) != EOF);
}
}
}
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
Boolean_t DumpDatafileString(FileStream_s *FileStream,
const char *S,
Boolean_t WriteBinary)
{
Boolean_t IsOk = TRUE;
const char *CPtr = S;
if (WriteBinary)
{
const char *CPtr = S;
while (IsOk && CPtr && *CPtr)
IsOk = WriteBinaryInt32(FileStream, (LgIndex_t)(unsigned char) * CPtr++);
if (IsOk)
IsOk = WriteBinaryInt32(FileStream, 0);
}
else
{
fputc('"', FileStream->File);
while (CPtr && *CPtr)
{
if (*CPtr == '\n')
{
CPtr++;
fputc('\\', FileStream->File);
fputc('\\', FileStream->File);
fputc('n', FileStream->File);
}
else
{
if ((*CPtr == '"') || (*CPtr == '\\'))
fputc('\\', FileStream->File);
fputc(*CPtr++, FileStream->File);
}
}
fputc('"', FileStream->File);
IsOk = (fputc('\n', FileStream->File) != EOF);
}
return (IsOk);
}
static void WriteAsciiColor(FILE *File,
ColorIndex_t Color)
{
if (Color >= FirstCustomColor && Color <= LastCustomColor)
fprintf(File, "CUST%1d ", Color - FirstCustomColor + 1);
else
{
switch (Color)
{
case Black_C : fprintf(File, "BLACK "); break;
case Red_C : fprintf(File, "RED "); break;
case Green_C : fprintf(File, "GREEN "); break;
case Blue_C : fprintf(File, "BLUE "); break;
case Cyan_C : fprintf(File, "CYAN "); break;
case Yellow_C : fprintf(File, "YELLOW "); break;
case Purple_C : fprintf(File, "PURPLE "); break;
case White_C : fprintf(File, "WHITE "); break;
}
}
}
static void WriteAsciiTextGeomBasics(FILE* File,
CoordSys_e CoordSys,
Boolean_t AttachToZone,
EntIndex_t Zone,
ColorIndex_t Color,
Scope_e Scope,
Boolean_t IncludeZ,
Boolean_t WriteGridDataAsPolar,
AnchorPos_u const* AnchorPos,
double ScaleFact)
{
REQUIRE(VALID_REF(File));
REQUIRE(VALID_TEXT_COORDSYS(CoordSys) || VALID_GEOM_COORDSYS(CoordSys));
REQUIRE(VALID_BOOLEAN(AttachToZone));
REQUIRE(IMPLICATION(AttachToZone, Zone >= 0));
REQUIRE(VALID_ENUM(Scope, Scope_e));
REQUIRE(VALID_BOOLEAN(IncludeZ));
REQUIRE(VALID_BOOLEAN(WriteGridDataAsPolar));
REQUIRE(VALID_REF(AnchorPos));
fprintf(File, "CS=");
if (CoordSys == CoordSys_Frame)
fprintf(File, "FRAME");
else if (CoordSys == CoordSys_Grid)
fprintf(File, "GRID");
/*
* Not currently used
*
else if (CoordSys == CoordSys_FrameOffset)
fprintf(File,"FRAMEOFFSET");
*/
else if (CoordSys == CoordSys_Grid3D)
fprintf(File, "GRID3D");
else
CHECK(FALSE);
if (CoordSys == CoordSys_Grid && !IncludeZ && WriteGridDataAsPolar)
{
fprintf(File, "\nTHETA=%.12G,R=%.12G",
ScaleFact*AnchorPos->ThetaR.Theta,
ScaleFact*AnchorPos->ThetaR.R);
CHECK(!IncludeZ);
}
else
{
fprintf(File, "\nX=%.12G,Y=%.12G",
ScaleFact*AnchorPos->XYZ.X,
ScaleFact*AnchorPos->XYZ.Y);
if (IncludeZ)
fprintf(File, ",Z=%.12G", ScaleFact*AnchorPos->XYZ.Z);
}
if (AttachToZone)
fprintf(File, "\nZN=%d", Zone + 1);
fprintf(File, "\nC=");
WriteAsciiColor(File, Color);
fprintf(File, "\nS=");
if (Scope == Scope_Global)
fprintf(File, "GLOBAL");
else if (Scope == Scope_Local)
fprintf(File, "LOCAL");
else
CHECK(FALSE);
fputc('\n', File);
}
bool DumpGeometry(FileStream_s* FileStream,
Geom_s const* Geom,
Boolean_t WriteBinary,
Boolean_t WriteGridDataAsPolar)
{
LgIndex_t I, Index;
LgIndex_t SegIndex;
bool IsOk = TRUE;
FieldDataType_e FDT;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_REF(Geom));
REQUIRE(Geom->GeomType != GeomType_Image);
if (WriteBinary)
{
WriteBinaryReal(FileStream, GeomMarker, FieldDataType_Float);
if (Geom->PositionCoordSys == CoordSys_Grid)
WriteBinaryInt32(FileStream, 0);
else if (Geom->PositionCoordSys == CoordSys_Frame)
WriteBinaryInt32(FileStream, 1);
#if 0 /*
* Not currently used
*/
else if (Geom->PositionCoordSys == CoordSys_FrameOffset)
WriteBinaryInt32(FileStream, 2);
#endif
/*
* PositionCoordSys == 3 is for old window coordinate system
*/
else if (Geom->PositionCoordSys == CoordSys_Grid3D)
WriteBinaryInt32(FileStream, 4);
else
CHECK(FALSE);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Scope);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->DrawOrder);
WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V1, FieldDataType_Double);
WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V2, FieldDataType_Double);
WriteBinaryReal(FileStream, Geom->AnchorPos.Generic.V3, FieldDataType_Double);
if (Geom->AttachToZone)
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Zone);
else
WriteBinaryInt32(FileStream, (LgIndex_t) - 1);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->BColor);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->FillBColor);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->IsFilled);
CHECK(Geom->GeomType != GeomType_LineSegs3D); /* deprecated */
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->GeomType);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->LinePattern);
WriteBinaryReal(FileStream, Geom->PatternLength, FieldDataType_Double);
WriteBinaryReal(FileStream, Geom->LineThickness, FieldDataType_Double);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->NumEllipsePts);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->ArrowheadStyle);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->ArrowheadAttachment);
WriteBinaryReal(FileStream, Geom->ArrowheadSize, FieldDataType_Double);
WriteBinaryReal(FileStream, Geom->ArrowheadAngle, FieldDataType_Double);
/* MACRO FUNCTION COMMAND */
DumpDatafileString(FileStream, Geom->MacroFunctionCommand, TRUE);
/*
* Assume geometry has X,Y (and Z) all using same field
* data type.
*/
FDT = GetGeomFieldDataType(Geom);
WriteFieldDataType(FileStream, FDT, TRUE);
WriteBinaryInt32(FileStream, (LgIndex_t)Geom->Clipping);
if (Geom->GeomType == GeomType_LineSegs)
{
short S;
WriteBinaryInt32(FileStream, Geom->NumSegments);
I = 0;
for (S = 0; IsOk && (S < Geom->NumSegments); S++)
{
WriteBinaryInt32(FileStream, Geom->NumSegPts[S]);
WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V1Base, I, Geom->NumSegPts[S]);
IsOk = WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V2Base, I, Geom->NumSegPts[S]) == TRUE;
if (Geom->PositionCoordSys == CoordSys_Grid3D)
IsOk = WriteBinaryFieldDataBlock(FileStream, Geom->GeomData.Generic.V3Base, I, Geom->NumSegPts[S]) == TRUE;
I += Geom->NumSegPts[S];
}
}
else if (Geom->GeomType == GeomType_Rectangle ||
Geom->GeomType == GeomType_Ellipse)
{
WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.XBase, 0), FDT);
IsOk = WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.YBase, 0), FDT) == TRUE;
}
else
{
CHECK((Geom->GeomType == GeomType_Square) ||
(Geom->GeomType == GeomType_Circle));
IsOk = WriteBinaryReal(FileStream, GetFieldValue(Geom->GeomData.XYZ.XBase, 0), FDT) == TRUE;
}
}
else
{
double ScaleFact;
if (Geom->PositionCoordSys == CoordSys_Frame)
ScaleFact = 100.0;
else
ScaleFact = 1.0;
fprintf(FileStream->File, "GEOMETRY\nF=POINT\n");
WriteAsciiTextGeomBasics(FileStream->File,
Geom->PositionCoordSys,
Geom->AttachToZone,
Geom->Zone,
Geom->BColor,
Geom->Scope,
TRUE,
WriteGridDataAsPolar,
&Geom->AnchorPos,
ScaleFact);
switch (Geom->LinePattern)
{
case LinePattern_Solid : fprintf(FileStream->File, "L=SOLID\n"); break;
case LinePattern_Dashed : fprintf(FileStream->File, "L=DASHED\n"); break;
case LinePattern_DashDot : fprintf(FileStream->File, "L=DASHDOT\n"); break;
case LinePattern_Dotted : fprintf(FileStream->File, "L=DOTTED\n"); break;
case LinePattern_LongDash : fprintf(FileStream->File, "L=LONGDASH\n"); break;
case LinePattern_DashDotDot : fprintf(FileStream->File, "L=DASHDOTDOT\n"); break;
default: CHECK(FALSE); break;
}
fprintf(FileStream->File, "PL=%.12G\n",
Geom->PatternLength*PatternLengthInputSpec.InterfaceAdjust.ScaleFact);
fprintf(FileStream->File, "LT=%.12G\n",
Geom->LineThickness*LineThicknessInputSpec.InterfaceAdjust.ScaleFact);
if (Geom->IsFilled)
{
fprintf(FileStream->File, "FC=");
WriteAsciiColor(FileStream->File, Geom->FillBColor);
}
if (Geom->Clipping == Clipping_ClipToViewport)
fprintf(FileStream->File, "CLIPPING=CLIPTOVIEWPORT\n");
else if (Geom->Clipping == Clipping_ClipToFrame)
fprintf(FileStream->File, "CLIPPING=CLIPTOFRAME\n");
else
CHECK(FALSE);
if (Geom->DrawOrder == DrawOrder_AfterData)
fprintf(FileStream->File, "DRAWORDER=AFTERDATA\n");
else if (Geom->DrawOrder == DrawOrder_BeforeData)
fprintf(FileStream->File, "DRAWORDER=BEFOREDATA\n");
else
CHECK(FALSE);
/* Macro function command */
fprintf(FileStream->File, "MFC=");
DumpDatafileString(FileStream, Geom->MacroFunctionCommand, FALSE);
if ((Geom->GeomType == GeomType_Circle) || (Geom->GeomType == GeomType_Ellipse))
fprintf(FileStream->File, "EP=%ld\n", (long)Geom->NumEllipsePts);
if (Geom->GeomType == GeomType_LineSegs && Geom->PositionCoordSys != CoordSys_Grid3D)
{
switch (Geom->ArrowheadStyle)
{
case ArrowheadStyle_Plain : fprintf(FileStream->File, "AST=PLAIN\n"); break;
case ArrowheadStyle_Filled : fprintf(FileStream->File, "AST=FILLED\n"); break;
case ArrowheadStyle_Hollow : fprintf(FileStream->File, "AST=HOLLOW\n"); break;
default: CHECK(FALSE); break;
}
switch (Geom->ArrowheadAttachment)
{
case ArrowheadAttachment_None : break;
case ArrowheadAttachment_AtBeginning : fprintf(FileStream->File, "AAT=BEGINNING\n"); break;
case ArrowheadAttachment_AtEnd : fprintf(FileStream->File, "AAT=END\n"); break;
case ArrowheadAttachment_AtBothEnds : fprintf(FileStream->File, "AAT=BOTH\n"); break;
default: CHECK(FALSE); break;
}
if (Geom->ArrowheadAttachment != ArrowheadAttachment_None)
{
fprintf(FileStream->File, "ASZ=%.12G\n",
Geom->ArrowheadSize*ArrowheadSizeInputSpec.InterfaceAdjust.ScaleFact);
fprintf(FileStream->File, "AAN=%.12G\n",
Geom->ArrowheadAngle*ArrowheadAngleInputSpec.InterfaceAdjust.ScaleFact);
}
}
switch (Geom->GeomType)
{
case GeomType_LineSegs :
{
fprintf(FileStream->File, "T=LINE\n");
fprintf(FileStream->File, "DT=");
WriteFieldDataType(FileStream, GetFieldDataType(Geom->GeomData.Generic.V1Base), FALSE);
fputc('\n', FileStream->File);
fprintf(FileStream->File, "%d\n", (int)Geom->NumSegments);
SegIndex = 0;
for (I = 0; IsOk && (I < Geom->NumSegments); I++)
{
fprintf(FileStream->File, "%ld\n", (long)Geom->NumSegPts[I]);
for (Index = 0; Index < Geom->NumSegPts[I]; Index++)
{
fprintf(FileStream->File, "%.12G ", GetFieldValue(Geom->GeomData.Generic.V1Base, SegIndex + Index)*ScaleFact);
fprintf(FileStream->File, "%.12G", GetFieldValue(Geom->GeomData.Generic.V2Base, SegIndex + Index)*ScaleFact);
if (Geom->PositionCoordSys == CoordSys_Grid3D)
IsOk = FPRINTFOK(fprintf(FileStream->File, " %.12G\n", GetFieldValue(Geom->GeomData.Generic.V3Base, SegIndex + Index)));
else
IsOk = (Boolean_t)(fputc('\n', FileStream->File) != EOF);
}
SegIndex += Geom->NumSegPts[I];
}
} break;
case GeomType_Rectangle :
{
fprintf(FileStream->File, "T=RECTANGLE %.12G %.12G\n",
GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact,
GetFieldValue(Geom->GeomData.XYZ.YBase, 0)*ScaleFact);
} break;
case GeomType_Square :
{
fprintf(FileStream->File, "T=SQUARE %.12G\n",
GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact);
} break;
case GeomType_Circle :
{
fprintf(FileStream->File, "T=CIRCLE %.12G\n",
GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact);
} break;
case GeomType_Ellipse :
{
fprintf(FileStream->File, "T=ELLIPSE %.12G %.12G\n",
GetFieldValue(Geom->GeomData.XYZ.XBase, 0)*ScaleFact,
GetFieldValue(Geom->GeomData.XYZ.YBase, 0)*ScaleFact);
} break;
default: CHECK(FALSE);
}
}
return IsOk;
}
/**
*/
bool DumpText(FileStream_s* FileStream,
Text_s const* Text,
Boolean_t WriteBinary,
Boolean_t WriteGridDataAsPolar)
{
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_REF(Text));
REQUIRE(VALID_BOOLEAN(WriteBinary));
REQUIRE(VALID_BOOLEAN(WriteGridDataAsPolar));
if (WriteBinary)
{
WriteBinaryReal(FileStream, TextMarker, FieldDataType_Float);
if (Text->PositionCoordSys == CoordSys_Grid)
WriteBinaryInt32(FileStream, 0);
else if (Text->PositionCoordSys == CoordSys_Frame)
WriteBinaryInt32(FileStream, 1);
#if 0 /*
* Not currently used
*/
else if (Geom->PositionCoordSys == CoordSys_FrameOffset)
WriteBinaryInt32(FileStream, 2);
#endif
/*
* 3 is used for old window coordinate system
*/
else if (Text->PositionCoordSys == CoordSys_Grid3D)
WriteBinaryInt32(FileStream, 4);
else
CHECK(FALSE);
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Scope);
WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V1, FieldDataType_Double);
WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V2, FieldDataType_Double);
WriteBinaryReal(FileStream, Text->AnchorPos.Generic.V3, FieldDataType_Double);
WriteBinaryInt32(FileStream, (LgIndex_t)Text->TextShape.Font);
WriteBinaryInt32(FileStream, (LgIndex_t)Text->TextShape.SizeUnits);
WriteBinaryReal(FileStream, Text->TextShape.Height, FieldDataType_Double);
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.BoxType);
WriteBinaryReal(FileStream, Text->Box.Margin, FieldDataType_Double);
WriteBinaryReal(FileStream, Text->Box.LineThickness, FieldDataType_Double);
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.BColor);
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Box.FillBColor);
WriteBinaryReal(FileStream, Text->Angle, FieldDataType_Double);
WriteBinaryReal(FileStream, Text->LineSpacing, FieldDataType_Double);
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Anchor);
if (Text->AttachToZone)
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Zone);
else
WriteBinaryInt32(FileStream, (LgIndex_t) - 1);
WriteBinaryInt32(FileStream, (LgIndex_t)Text->BColor);
}
else
{
double ScaleFact;
Boolean_t IncludeZ = Text->PositionCoordSys == CoordSys_Grid3D;
if (Text->PositionCoordSys == CoordSys_Frame)
ScaleFact = 100.0;
else
ScaleFact = 1.0;
fprintf(FileStream->File, "TEXT\n");
WriteAsciiTextGeomBasics(FileStream->File,
Text->PositionCoordSys,
Text->AttachToZone,
Text->Zone,
Text->BColor,
Text->Scope,
IncludeZ,
WriteGridDataAsPolar,
&Text->AnchorPos,
ScaleFact);
fprintf(FileStream->File, "HU=");
switch (Text->TextShape.SizeUnits)
{
case Units_Grid : fprintf(FileStream->File, "GRID\n"); break;
case Units_Frame : fprintf(FileStream->File, "FRAME\n"); break;
case Units_Point : fprintf(FileStream->File, "POINT\n"); break;
case Units_AxisPercentage : /* Not allowed */
default: CHECK(FALSE); break;
}
fprintf(FileStream->File, "LS=%.4G ", Text->LineSpacing);
fprintf(FileStream->File, "AN=");
switch (Text->Anchor)
{
case TextAnchor_Left : fprintf(FileStream->File, "LEFT\n"); break;
case TextAnchor_Center : fprintf(FileStream->File, "CENTER\n"); break;
case TextAnchor_Right : fprintf(FileStream->File, "RIGHT\n"); break;
case TextAnchor_MidLeft : fprintf(FileStream->File, "MIDLEFT\n"); break;
case TextAnchor_MidCenter : fprintf(FileStream->File, "MIDCENTER\n"); break;
case TextAnchor_MidRight : fprintf(FileStream->File, "MIDRIGHT\n"); break;
case TextAnchor_HeadLeft : fprintf(FileStream->File, "HEADLEFT\n"); break;
case TextAnchor_HeadCenter : fprintf(FileStream->File, "HEADCENTER\n"); break;
case TextAnchor_HeadRight : fprintf(FileStream->File, "HEADRIGHT\n"); break;
default: CHECK(FALSE); break;
}
switch (Text->Box.BoxType)
{
case TextBox_Hollow : fprintf(FileStream->File, "BX=Hollow "); break;
case TextBox_Filled : fprintf(FileStream->File, "BX=Filled "); break;
default :;
}
fprintf(FileStream->File, "BXM=%.4G ", Text->Box.Margin*100);
fprintf(FileStream->File, "LT=%.4G ", Text->Box.LineThickness*100.0);
fprintf(FileStream->File, "BXO="); WriteAsciiColor(FileStream->File, Text->Box.BColor);
fprintf(FileStream->File, "BXF="); WriteAsciiColor(FileStream->File, Text->Box.FillBColor);
fprintf(FileStream->File, "\nF=");
switch (Text->TextShape.Font)
{
case Font_Helvetica : fprintf(FileStream->File, "HELV"); break;
case Font_HelveticaBold : fprintf(FileStream->File, "HELV-BOLD"); break;
case Font_Times : fprintf(FileStream->File, "TIMES"); break;
case Font_TimesBold: fprintf(FileStream->File, "TIMES-BOLD"); break;
case Font_TimesItalic : fprintf(FileStream->File, "TIMES-ITALIC"); break;
case Font_TimesItalicBold : fprintf(FileStream->File, "TIMES-ITALIC-BOLD"); break;
case Font_Courier : fprintf(FileStream->File, "COURIER"); break;
case Font_CourierBold : fprintf(FileStream->File, "COURIER-BOLD"); break;
case Font_Greek : fprintf(FileStream->File, "GREEK"); break;
case Font_Math : fprintf(FileStream->File, "MATH"); break;
case Font_UserDefined : fprintf(FileStream->File, "USER-DEF"); break;
default: CHECK(FALSE); break;
}
if (Text->TextShape.SizeUnits == Units_Frame)
ScaleFact = 100.0;
else
ScaleFact = 1.0;
fprintf(FileStream->File, "\nH=%.12G A=%.12G",
Text->TextShape.Height*ScaleFact,
Text->Angle*DEGPERRADIANS);
}
if (!WriteBinary)
fprintf(FileStream->File, "\nMFC=");
DumpDatafileString(FileStream, Text->MacroFunctionCommand, WriteBinary);
if (!WriteBinary)
{
if (Text->Clipping == Clipping_ClipToViewport)
fprintf(FileStream->File, "CLIPPING=CLIPTOVIEWPORT\n");
else if (Text->Clipping == Clipping_ClipToFrame)
fprintf(FileStream->File, "CLIPPING=CLIPTOFRAME\n");
else
CHECK(FALSE);
}
else
{
WriteBinaryInt32(FileStream, (LgIndex_t)Text->Clipping);
}
if (!WriteBinary)
fprintf(FileStream->File, "T=");
return DumpDatafileString(FileStream, Text->Text, WriteBinary) == TRUE;
}
Boolean_t DumpCustomAxisLabels(FileStream_s *FileStream,
Boolean_t WriteBinary,
StringList_pa LabelBase)
{
Boolean_t IsOk = TRUE;
LgIndex_t Index = 0;
LgIndex_t Count = 0;
REQUIRE(VALID_REF(FileStream) && VALID_REF(FileStream->File));
REQUIRE(VALID_BOOLEAN(WriteBinary));
REQUIRE(StringListValid(LabelBase));
Count = StringListCount(LabelBase);
if (WriteBinary)
{
WriteBinaryReal(FileStream, CustomLabelMarker, FieldDataType_Float);
WriteBinaryInt32(FileStream, Count);
}
else
{
fprintf(FileStream->File, " CUSTOMLABELS = \n");
}
for (Index = 0, IsOk = TRUE; Index < Count && IsOk; Index++)
{
const char *CurLabel = StringListGetStringRef(LabelBase, Index);
IsOk = DumpDatafileString(FileStream, CurLabel, WriteBinary);
}
ENSURE(VALID_BOOLEAN(IsOk));
return IsOk;
}
/**
*/
Boolean_t WriteBinaryMagic(FileStream_s *FileStream)
{
/*
* Write an integer value of 1 to the file. This is used
* by the reader to determine byte order of the file.
*/
return (WriteBinaryInt32(FileStream, 1));
}
/**
*/
bool writeBinaryVersionNumber(FileStream_s& fileStream,
int versionNumber)
{
char buffer[5];
sprintf(buffer,
"V%-3d",
versionNumber);
CHECK(strlen(buffer) == 4);
return fprintf(fileStream.File,
"#!TD%s",
buffer) > 0;
}
#if defined TECPLOTKERNEL
/* CORE SOURCE CODE REMOVED */
#if !defined SUN
#else
#endif
#if !defined NO_ASSERTS
#endif
#if defined ALLOW_USERDEF_NO_NEIGHBORING_ELEMENT
#else
#endif
#if 0 /* not used yet */
#endif
#if defined TECPLOTKERNEL
#endif
#if defined TECPLOTKERNEL
#endif
#endif