mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
Refactor SetEntityNumbers to use reusable memory pool. Update SetRecord to avoid extra map searches.
2521 lines
89 KiB
C++
2521 lines
89 KiB
C++
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
// abv 09.04.99 S4136: eliminate parameter step.readaccept.void
|
|
// sln 04,10.2001. BUC61003. Prevent exception which may occur during reading of complex entity
|
|
// (if entity's items are not in alphabetical order)
|
|
|
|
#include <Interface_Check.hxx>
|
|
#include <Interface_HArray1OfHAsciiString.hxx>
|
|
#include <Interface_Macros.hxx>
|
|
#include <Interface_ParamList.hxx>
|
|
#include <Message.hxx>
|
|
#include <Message_Messenger.hxx>
|
|
#include <Standard_Transient.hxx>
|
|
#include <Standard_Type.hxx>
|
|
#include <StepData_ESDescr.hxx>
|
|
#include <StepData_FieldList.hxx>
|
|
#include <StepData_PDescr.hxx>
|
|
#include <StepData_SelectArrReal.hxx>
|
|
#include <StepData_SelectInt.hxx>
|
|
#include <StepData_SelectMember.hxx>
|
|
#include <StepData_SelectNamed.hxx>
|
|
#include <StepData_SelectReal.hxx>
|
|
#include <StepData_SelectType.hxx>
|
|
#include <StepData_StepReaderData.hxx>
|
|
#include <NCollection_IncAllocator.hxx>
|
|
#include <TCollection_AsciiString.hxx>
|
|
#include <TCollection_ExtendedString.hxx>
|
|
#include <NCollection_UtfIterator.hxx>
|
|
#include <TCollection_HAsciiString.hxx>
|
|
#include <TColStd_Array1OfInteger.hxx>
|
|
#include <TColStd_HArray1OfInteger.hxx>
|
|
#include <TColStd_HArray1OfReal.hxx>
|
|
#include <TColStd_HArray1OfTransient.hxx>
|
|
#include <TColStd_HSequenceOfReal.hxx>
|
|
#include <TColStd_IndexedMapOfInteger.hxx>
|
|
#include <TColStd_SequenceOfInteger.hxx>
|
|
#include <StepData_UndefinedEntity.hxx>
|
|
#include <Resource_Unicode.hxx>
|
|
|
|
#include <stdio.h>
|
|
IMPLEMENT_STANDARD_RTTIEXT(StepData_StepReaderData, Interface_FileReaderData)
|
|
|
|
// Le Header est constitue d entites analogues dans leur principe a celles
|
|
// du Data, a ceci pres qu elles sont sans identifieur, et ne peuvent ni
|
|
// referencer, ni etre referencees (que ce soit avec Header ou avec Data)
|
|
// Ainsi, dans StepReaderData, le Header est constitue des "thenbhead" 1res Entites
|
|
// #########################################################################
|
|
// .... Creation et Acces de base aux donnees atomiques du fichier ....
|
|
typedef TCollection_HAsciiString String;
|
|
static char txtmes[200]; // plus commode que redeclarer partout
|
|
|
|
static Standard_Boolean initstr = Standard_False;
|
|
#define Maxlst 64
|
|
// static TCollection_AsciiString subl[Maxlst]; // Maxlst : minimum 10
|
|
|
|
static Standard_Integer acceptvoid = 0;
|
|
|
|
// ---------- Fonctions Utilitaires ----------
|
|
|
|
//! Convert unsigned character to hexadecimal system,
|
|
//! if character hasn't representation in this system, returns 0.
|
|
static Standard_Integer convertCharacterTo16bit(const Standard_ExtCharacter theCharacter)
|
|
{
|
|
switch (theCharacter)
|
|
{
|
|
case '0':
|
|
return 0;
|
|
case '1':
|
|
return 1;
|
|
case '2':
|
|
return 2;
|
|
case '3':
|
|
return 3;
|
|
case '4':
|
|
return 4;
|
|
case '5':
|
|
return 5;
|
|
case '6':
|
|
return 6;
|
|
case '7':
|
|
return 7;
|
|
case '8':
|
|
return 8;
|
|
case '9':
|
|
return 9;
|
|
case 'A':
|
|
case 'a':
|
|
return 10;
|
|
case 'B':
|
|
case 'b':
|
|
return 11;
|
|
case 'C':
|
|
case 'c':
|
|
return 12;
|
|
case 'D':
|
|
case 'd':
|
|
return 13;
|
|
case 'E':
|
|
case 'e':
|
|
return 14;
|
|
case 'F':
|
|
case 'f':
|
|
return 15;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void StepData_StepReaderData::cleanText(const Handle(TCollection_HAsciiString)& theVal) const
|
|
{
|
|
if (theVal->Length() == 2)
|
|
{
|
|
theVal->Clear();
|
|
return;
|
|
}
|
|
TCollection_ExtendedString aResString;
|
|
const Standard_Boolean toConversion = mySourceCodePage != Resource_FormatType_NoConversion;
|
|
Resource_Unicode::ConvertFormatToUnicode(mySourceCodePage, theVal->ToCString() + 1, aResString);
|
|
Standard_Integer aResStringSize = aResString.Length() - 1; // skip the last apostrophe
|
|
TCollection_ExtendedString aTempExtString; // string for characters within control directives
|
|
Standard_Integer aSetCharInd = 1; // index to set value to result string
|
|
// clang-format off
|
|
Resource_FormatType aLocalFormatType = Resource_FormatType_iso8859_1; // a code page for a "\S\" control directive
|
|
// clang-format on
|
|
for (Standard_Integer aStringInd = 1; aStringInd <= aResStringSize; ++aStringInd)
|
|
{
|
|
const Standard_ExtCharacter aChar = aResString.Value(aStringInd);
|
|
aSetCharInd = aStringInd;
|
|
if (aChar == '\\' && aStringInd <= aResStringSize - 3) // can contains the control directive
|
|
{
|
|
Standard_Boolean isConverted = Standard_False;
|
|
const Standard_ExtCharacter aDirChar = aResString.Value(aStringInd + 1);
|
|
const Standard_Boolean isSecSlash = aResString.Value(aStringInd + 2) == '\\';
|
|
const Standard_Boolean isThirdSlash = aResString.Value(aStringInd + 3) == '\\';
|
|
// Encoding ISO 8859 characters within a string;
|
|
// ("\P{N}\") control directive;
|
|
// indicates code page for ("\S\") control directive;
|
|
// {N}: "A", "B", "C", "D", "E", "F", "G", "H", "I";
|
|
// "A" identifies ISO 8859-1; "B" identifies ISO 8859-2, etc.
|
|
if (aDirChar == 'P' && isThirdSlash)
|
|
{
|
|
const Standard_Character aPageId =
|
|
UpperCase(static_cast<Standard_Character>(aResString.Value(aStringInd + 2) & 255));
|
|
if (aPageId >= 'A' && aPageId <= 'I')
|
|
{
|
|
aLocalFormatType = (Resource_FormatType)(Resource_FormatType_iso8859_1 + (aPageId - 'A'));
|
|
}
|
|
else
|
|
{
|
|
thecheck->AddWarning(
|
|
"String control directive \\P*\\ with an unsupported symbol in place of *");
|
|
}
|
|
isConverted = Standard_True;
|
|
aStringInd += 3;
|
|
}
|
|
// Encoding ISO 8859 characters within a string;
|
|
// ("\S\") control directive;
|
|
// converts followed a LATIN CODEPOINT character.
|
|
else if (aDirChar == 'S' && isSecSlash)
|
|
{
|
|
Standard_Character aResChar =
|
|
static_cast<Standard_Character>(aResString.Value(aStringInd + 3) | 0x80);
|
|
const char aStrForCovert[2] = {aResChar, '\0'};
|
|
Resource_Unicode::ConvertFormatToUnicode(aLocalFormatType, aStrForCovert, aTempExtString);
|
|
isConverted = Standard_True;
|
|
aStringInd += 3;
|
|
}
|
|
// Encoding U+0000 to U+00FF in a string
|
|
// ("\X\") control directive;
|
|
// converts followed two hexadecimal character.
|
|
else if (aDirChar == 'X' && aStringInd <= aResStringSize - 4 && isSecSlash)
|
|
{
|
|
Standard_Character aResChar =
|
|
(char)convertCharacterTo16bit(aResString.Value(aStringInd + 3));
|
|
aResChar =
|
|
(aResChar << 4) | (char)convertCharacterTo16bit(aResString.Value(aStringInd + 4));
|
|
const char aStrForConvert[2] = {aResChar, '\0'};
|
|
// clang-format off
|
|
aTempExtString = TCollection_ExtendedString(aStrForConvert, Standard_False); // pass through without conversion
|
|
// clang-format on
|
|
isConverted = Standard_True;
|
|
aStringInd += 4;
|
|
}
|
|
// Encoding ISO 10646 characters within a string
|
|
// ("\X{N}\") control directive;
|
|
// {N}: "0", "2", "4";
|
|
// "\X2\" or "\X4\" converts followed a hexadecimal character sequence;
|
|
// "\X0\" indicate the end of the "\X2\" or "\X4\".
|
|
else if (aDirChar == 'X' && isThirdSlash)
|
|
{
|
|
Standard_Integer aFirstInd = aStringInd + 3;
|
|
Standard_Integer aLastInd = aStringInd;
|
|
Standard_Boolean isClosed = Standard_False;
|
|
// find the end of the "\X2\" or "\X4\" by an external "aStringInd"
|
|
for (; aStringInd <= aResStringSize && !isClosed; ++aStringInd)
|
|
{
|
|
if (aResStringSize - aStringInd > 2 && aResString.Value(aStringInd) == '\\'
|
|
&& aResString.Value(aStringInd + 1) == 'X' && aResString.Value(aStringInd + 2) == '0'
|
|
&& aResString.Value(aStringInd + 3) == '\\')
|
|
{
|
|
aLastInd = aStringInd - 1;
|
|
aStringInd = aStringInd + 2;
|
|
isClosed = Standard_True;
|
|
}
|
|
}
|
|
if (!isClosed) // "\X0\" not exists
|
|
{
|
|
aLastInd = aStringInd = aResStringSize;
|
|
}
|
|
const Standard_Integer aStrLen = aLastInd - aFirstInd;
|
|
// "\X2\" control directive;
|
|
// followed by multiples of four or three hexadecimal characters.
|
|
// Encoding in UTF-16
|
|
if (aResString.Value(aFirstInd - 1) == '2' && aResStringSize - aFirstInd > 3)
|
|
{
|
|
Standard_Integer anIterStep = (aStrLen % 4 == 0) ? 4 : 3;
|
|
if (aStrLen % anIterStep)
|
|
{
|
|
aTempExtString.AssignCat('?');
|
|
thecheck->AddWarning(
|
|
"String control directive \\X2\\ is followed by number of digits not multiple of 4");
|
|
}
|
|
else
|
|
{
|
|
Standard_Utf16Char aUtfCharacter = '\0';
|
|
for (Standard_Integer aCharInd = 1; aCharInd <= aStrLen; ++aCharInd)
|
|
{
|
|
aUtfCharacter |= convertCharacterTo16bit(aResString.Value(aCharInd + aFirstInd));
|
|
if (aCharInd % anIterStep == 0)
|
|
{
|
|
aTempExtString.AssignCat(aUtfCharacter);
|
|
aUtfCharacter = '\0';
|
|
}
|
|
aUtfCharacter = aUtfCharacter << 4;
|
|
}
|
|
}
|
|
}
|
|
// "\X4\" control directive;
|
|
// followed by multiples of eight hexadecimal characters.
|
|
// Encoding in UTF-32
|
|
else if (aResString.Value(aFirstInd - 1) == '4' && aResStringSize - aFirstInd > 7)
|
|
{
|
|
if (aStrLen % 8)
|
|
{
|
|
aTempExtString.AssignCat('?');
|
|
thecheck->AddWarning(
|
|
"String control directive \\X4\\ is followed by number of digits not multiple of 8");
|
|
}
|
|
else
|
|
{
|
|
Standard_Utf32Char aUtfCharacter[2] = {'\0', '\0'};
|
|
for (Standard_Integer aCharInd = 1; aCharInd <= aStrLen; ++aCharInd)
|
|
{
|
|
aUtfCharacter[0] |= convertCharacterTo16bit(aResString.Value(aCharInd + aFirstInd));
|
|
if (aCharInd % 8 == 0)
|
|
{
|
|
NCollection_Utf32Iter aUtfIter(aUtfCharacter);
|
|
Standard_Utf16Char aStringBuffer[3];
|
|
Standard_Utf16Char* aUtfPntr = aUtfIter.GetUtf16(aStringBuffer);
|
|
*aUtfPntr++ = '\0';
|
|
TCollection_ExtendedString aUtfString(aStringBuffer);
|
|
aTempExtString.AssignCat(aUtfString);
|
|
aUtfCharacter[0] = '\0';
|
|
}
|
|
aUtfCharacter[0] = aUtfCharacter[0] << 4;
|
|
}
|
|
}
|
|
}
|
|
isConverted = Standard_True;
|
|
}
|
|
if (isConverted) // find the control directive
|
|
{
|
|
if (toConversion) // else skip moving
|
|
{
|
|
// clang-format off
|
|
aResStringSize -= aStringInd - aSetCharInd - aTempExtString.Length() + 1; // change the string size to remove unused symbols
|
|
// clang-format on
|
|
aResString.SetValue(aSetCharInd, aTempExtString);
|
|
aSetCharInd += aTempExtString.Length(); // move to the new position
|
|
aResString.SetValue(aSetCharInd, aResString.ToExtString() + aStringInd);
|
|
aStringInd = aSetCharInd - 1;
|
|
aResString.Trunc(aResStringSize);
|
|
;
|
|
}
|
|
aTempExtString.Clear();
|
|
continue;
|
|
}
|
|
}
|
|
if (aStringInd <= aResStringSize - 1)
|
|
{
|
|
const Standard_ExtCharacter aCharNext = aResString.Value(aStringInd + 1);
|
|
if (aCharNext == aChar && (aChar == '\'' || aChar == '\\'))
|
|
{
|
|
// clang-format off
|
|
aResString.SetValue(aSetCharInd, aResString.ToExtString() + aStringInd); // move the string,removing one symbol
|
|
// clang-format on
|
|
aResStringSize--; // change the string size to remove unused symbol
|
|
aResString.Trunc(aResStringSize);
|
|
}
|
|
else if (aChar == '\\')
|
|
{
|
|
const Standard_Boolean isDirective =
|
|
aStringInd <= aResStringSize - 2 && aResString.Value(aStringInd + 2) == '\\';
|
|
if (isDirective)
|
|
{
|
|
if (aCharNext == 'N')
|
|
{
|
|
aResString.SetValue(aSetCharInd++, '\n');
|
|
// clang-format off
|
|
aResString.SetValue(aSetCharInd, aResString.ToExtString() + aStringInd + 2); // move the string,removing two symbols
|
|
aResStringSize-=2; // change the string size to remove unused symbols
|
|
aResString.Trunc(aResStringSize);
|
|
continue;
|
|
}
|
|
else if (aCharNext == 'T')
|
|
{
|
|
aResString.SetValue(aSetCharInd++, '\t');
|
|
aResString.SetValue(aSetCharInd, aResString.ToExtString() + aStringInd + 2); // move the string,removing two symbols
|
|
// clang-format on
|
|
aResStringSize -= 2; // change the string size to remove unused symbols
|
|
aResString.Trunc(aResStringSize);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (aChar == '\n' || aChar == '\r')
|
|
{
|
|
aResString.SetValue(aSetCharInd, aResString.ToExtString() + aStringInd);
|
|
aResStringSize--;
|
|
aResString.Trunc(aResStringSize);
|
|
aStringInd--;
|
|
}
|
|
}
|
|
theVal->Clear();
|
|
aResString.Trunc(aResStringSize); // trunc the last apostrophe
|
|
TCollection_AsciiString aTmpString(aResString, 0);
|
|
theVal->AssignCat(aTmpString.ToCString());
|
|
}
|
|
|
|
// ------------- METHODES -------------
|
|
|
|
//=================================================================================================
|
|
|
|
StepData_StepReaderData::StepData_StepReaderData(const Standard_Integer nbheader,
|
|
const Standard_Integer nbtotal,
|
|
const Standard_Integer nbpar,
|
|
const Resource_FormatType theSourceCodePage)
|
|
: Interface_FileReaderData(nbtotal, nbpar),
|
|
theidents(1, nbtotal),
|
|
thetypes(1, nbtotal),
|
|
mySourceCodePage(theSourceCodePage) //, themults (1,nbtotal)
|
|
{
|
|
// char textnum[10];
|
|
thenbscop = 0;
|
|
thenbents = 0;
|
|
thelastn = 0;
|
|
thenbhead = nbheader;
|
|
// themults.Init(0);
|
|
thecheck = new Interface_Check;
|
|
if (initstr)
|
|
return;
|
|
// for (Standard_Integer i = 0; i < Maxlst; i ++) {
|
|
// sprintf(textnum,"$%d",i+1);
|
|
// subl[i].AssignCat(textnum);
|
|
// }
|
|
initstr = Standard_True;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void StepData_StepReaderData::SetRecord(const Standard_Integer num,
|
|
const Standard_CString ident,
|
|
const Standard_CString type,
|
|
const Standard_Integer /* nbpar */)
|
|
{
|
|
Standard_Integer numlst;
|
|
|
|
if (type[0] != '(')
|
|
thenbents++; // total de termes propres du fichier
|
|
|
|
thetypes.ChangeValue(num) = thenametypes.Add(TCollection_AsciiString(type));
|
|
|
|
if (ident[0] == '$')
|
|
{
|
|
if (strlen(ident) > 2)
|
|
numlst = atoi(&ident[1]);
|
|
else
|
|
numlst = ident[1] - 48;
|
|
if (thelastn < numlst)
|
|
thelastn = numlst; // plus fort n0 de sous-liste
|
|
theidents.SetValue(num, -2 - numlst);
|
|
}
|
|
else if (ident[0] == '#')
|
|
{
|
|
numlst = atoi(&ident[1]);
|
|
theidents.SetValue(num, numlst);
|
|
if (numlst == 0 && num > thenbhead)
|
|
{
|
|
// Header, ou bien Type Complexe ...
|
|
// Si Type Complexe, retrouver Type Precedent (on considere que c est rare)
|
|
// On chaine le type precedent sur le suivant
|
|
// VERIFICATION que les types sont en ordre alphabetique
|
|
for (Standard_Integer prev = num - 1; prev > thenbhead; prev--)
|
|
{
|
|
if (theidents(prev) >= 0)
|
|
{
|
|
|
|
// themults.SetValue(prev,num);
|
|
themults.Bind(prev, num);
|
|
if (thenametypes.FindKey(thetypes.Value(num))
|
|
.IsLess(thenametypes.FindKey(thetypes.Value(prev))))
|
|
{
|
|
// Warning: components in complex entity are not in alphabetical order.
|
|
TCollection_AsciiString errm("Complex Type incorrect : ");
|
|
errm.AssignCat(thenametypes.FindKey(thetypes.Value(prev)));
|
|
errm.AssignCat(" / ");
|
|
errm.AssignCat(thenametypes.FindKey(thetypes.Value(num)));
|
|
errm.AssignCat(" ... ");
|
|
while (theidents(prev) <= 0)
|
|
{
|
|
prev--;
|
|
if (prev <= 0)
|
|
break;
|
|
}
|
|
|
|
Message_Messenger::StreamBuffer sout = Message::SendTrace();
|
|
sout << " *** Incorrect record " << num << " (on " << NbRecords() << " -> "
|
|
<< num * 100 / NbRecords() << " % in File) ***";
|
|
if (prev > 0)
|
|
sout << " Ident #" << theidents(prev);
|
|
sout << "\n" << errm << std::endl;
|
|
thecheck->AddWarning(errm.ToCString(), "Complex Type incorrect : ");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (!strcmp(ident, "SCOPE"))
|
|
{
|
|
theidents.SetValue(num, -1); // SCOPE
|
|
thenbscop++;
|
|
}
|
|
else if (!strcmp(ident, "ENDSCOPE"))
|
|
theidents.SetValue(num, -2); // ENDSCOPE
|
|
// Reste 0
|
|
|
|
// InitParams(num);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void StepData_StepReaderData::AddStepParam(const Standard_Integer num,
|
|
const Standard_CString aval,
|
|
const Interface_ParamType atype,
|
|
const Standard_Integer nument)
|
|
{
|
|
if (atype == Interface_ParamSub)
|
|
{
|
|
Standard_Integer numid = 0;
|
|
if (aval[2] != '\0')
|
|
{
|
|
numid = atoi(&aval[1]);
|
|
// if (numid <= Maxlst) Interface_FileReaderData::AddParam
|
|
// (num,subl[numid-1].ToCString(),atype,numid);
|
|
Interface_FileReaderData::AddParam(num, aval, atype, numid);
|
|
}
|
|
else
|
|
{
|
|
char* numlstchar = (char*)(aval + 1);
|
|
numid = (*numlstchar) - 48; // -48 ('0') -1 (adresse [] depuis 0)
|
|
// Interface_FileReaderData::AddParam (num,subl[numid].ToCString(),atype,numid);
|
|
Interface_FileReaderData::AddParam(num, aval, atype, numid);
|
|
}
|
|
}
|
|
else if (atype == Interface_ParamIdent)
|
|
{
|
|
Standard_Integer numid = atoi(&aval[1]);
|
|
Interface_FileReaderData::AddParam(num, aval, atype, numid);
|
|
}
|
|
else
|
|
{
|
|
Interface_FileReaderData::AddParam(num, aval, atype, nument);
|
|
}
|
|
|
|
// Interface_FileReaderData::AddParam (num,parval,atype,numid);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
const TCollection_AsciiString& StepData_StepReaderData::RecordType(const Standard_Integer num) const
|
|
{
|
|
return thenametypes.FindKey(thetypes.Value(num));
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_CString StepData_StepReaderData::CType(const Standard_Integer num) const
|
|
{
|
|
return thenametypes.FindKey(thetypes.Value(num)).ToCString();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer StepData_StepReaderData::RecordIdent(const Standard_Integer num) const
|
|
{
|
|
return theidents(num);
|
|
}
|
|
|
|
// ########################################################################
|
|
// .... Aides a la lecture des parametres, adaptees a STEP ....
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer StepData_StepReaderData::SubListNumber(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_Boolean aslast) const
|
|
{
|
|
if (nump == 0 || nump > NbParams(num))
|
|
return 0;
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() != Interface_ParamSub)
|
|
return 0;
|
|
if (aslast)
|
|
{
|
|
if (nump != NbParams(num))
|
|
return 0;
|
|
}
|
|
return FP.EntityNumber();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::IsComplex(const Standard_Integer num) const
|
|
{
|
|
// return (themults(num) != 0);
|
|
return themults.IsBound(num);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void StepData_StepReaderData::ComplexType(const Standard_Integer num,
|
|
TColStd_SequenceOfAsciiString& types) const
|
|
{
|
|
if (theidents(num) < 0)
|
|
return;
|
|
for (Standard_Integer i = num; i > 0; i = NextForComplex(i))
|
|
{
|
|
types.Append(RecordType(i));
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer StepData_StepReaderData::NextForComplex(const Standard_Integer num) const
|
|
{
|
|
Standard_Integer next = 0;
|
|
if (themults.IsBound(num))
|
|
next = themults.Find(num);
|
|
return next;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::NamedForComplex(const Standard_CString name,
|
|
const Standard_Integer num0,
|
|
Standard_Integer& num,
|
|
Handle(Interface_Check)& ach) const
|
|
{
|
|
// Standard_Boolean stat = Standard_True;
|
|
Standard_Integer n = (num <= 0 ? num0 : NextForComplex(num));
|
|
// sln 04,10.2001. BUC61003. if(n==0) the next function is not called in order to avoid exception
|
|
if ((n != 0) && (!strcmp(RecordType(n).ToCString(), name)))
|
|
{
|
|
num = n;
|
|
return Standard_True;
|
|
}
|
|
|
|
if (n == 0) /*stat =*/
|
|
NamedForComplex(name, num0, n, ach); // on a rembobine
|
|
// Pas dans l ordre alphabetique : boucler
|
|
Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST");
|
|
sprintf(txtmes, errmess->ToCString(), num0, name);
|
|
for (n = num0; n > 0; n = NextForComplex(n))
|
|
{
|
|
if (!strcmp(RecordType(n).ToCString(), name))
|
|
{
|
|
num = n;
|
|
errmess = new String("Complex Record n0.%d, member type %s not in alphabetic order");
|
|
sprintf(txtmes, errmess->ToCString(), num0, name);
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
}
|
|
num = 0;
|
|
errmess = new String("Complex Record n0.%d, member type %s not found");
|
|
sprintf(txtmes, errmess->ToCString(), num0, name);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::NamedForComplex(const Standard_CString theName,
|
|
const Standard_CString theShortName,
|
|
const Standard_Integer num0,
|
|
Standard_Integer& num,
|
|
Handle(Interface_Check)& ach) const
|
|
{
|
|
Standard_Integer n = (num <= 0 ? num0 : NextForComplex(num));
|
|
|
|
if ((n != 0)
|
|
&& (!strcmp(RecordType(n).ToCString(), theName)
|
|
|| !strcmp(RecordType(n).ToCString(), theShortName)))
|
|
{
|
|
num = n;
|
|
return Standard_True;
|
|
}
|
|
|
|
// entities are not in alphabetical order
|
|
Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST");
|
|
sprintf(txtmes, errmess->ToCString(), num0, theName);
|
|
for (n = num0; n > 0; n = NextForComplex(n))
|
|
{
|
|
if (!strcmp(RecordType(n).ToCString(), theName)
|
|
|| !strcmp(RecordType(n).ToCString(), theShortName))
|
|
{
|
|
num = n;
|
|
errmess = new String("Complex Record n0.%d, member type %s not in alphabetic order");
|
|
sprintf(txtmes, errmess->ToCString(), num0, theName);
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
}
|
|
num = 0;
|
|
errmess = new String("Complex Record n0.%d, member type %s not found");
|
|
sprintf(txtmes, errmess->ToCString(), num0, theName);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::CheckNbParams(const Standard_Integer num,
|
|
const Standard_Integer nbreq,
|
|
Handle(Interface_Check)& ach,
|
|
const Standard_CString mess) const
|
|
{
|
|
if (NbParams(num) == nbreq)
|
|
return Standard_True;
|
|
Handle(String) errmess;
|
|
if (mess[0] == '\0')
|
|
errmess = new String("Count of Parameters is not %d");
|
|
else
|
|
errmess = new String("Count of Parameters is not %d for %s");
|
|
sprintf(txtmes, errmess->ToCString(), nbreq, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadSubList(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Standard_Integer& numsub,
|
|
const Standard_Boolean optional,
|
|
const Standard_Integer /* lenmin */,
|
|
const Standard_Integer /* lenmax */) const
|
|
{
|
|
numsub = SubListNumber(num, nump, Standard_False);
|
|
if (numsub > 0)
|
|
{
|
|
return (NbParams(numsub) > 0);
|
|
}
|
|
// Si optionel indefini, on passe l eponge
|
|
numsub = 0;
|
|
Standard_Boolean isvoid = (Param(num, nump).ParamType() == Interface_ParamVoid);
|
|
if (isvoid && optional)
|
|
return Standard_False;
|
|
|
|
Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST");
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
if (acceptvoid && isvoid)
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
else
|
|
{
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
// ... Facilites pour LateBinding
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer StepData_StepReaderData::ReadSub(const Standard_Integer numsub,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
const Handle(StepData_PDescr)& descr,
|
|
Handle(Standard_Transient)& val) const
|
|
{
|
|
Standard_Integer nbp = NbParams(numsub);
|
|
if (nbp == 0)
|
|
return 0; // liste vide = Handle Null
|
|
const TCollection_AsciiString& rectyp = RecordType(numsub);
|
|
if (nbp == 1 && rectyp.ToCString()[0] != '(')
|
|
{
|
|
// c est un type avec un parametre -> SelectNamed
|
|
// cf ReadSelect mais ici, on est deja sur le contenu du parametre
|
|
Handle(StepData_SelectNamed) sn = new StepData_SelectNamed;
|
|
val = sn;
|
|
sn->SetName(rectyp.ToCString());
|
|
Handle(Standard_Transient) aSN = sn;
|
|
if (ReadAny(numsub, 1, mess, ach, descr, aSN))
|
|
return sn->Kind();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
// cas courant : faire un HArray1 de ... de ... de quoi au fait
|
|
const Interface_FileParameter& FP0 = Param(numsub, 1);
|
|
Interface_ParamType FT, FT0 = FP0.ParamType();
|
|
Standard_CString str = FP0.CValue();
|
|
Handle(TColStd_HArray1OfTransient) htr;
|
|
Handle(TColStd_HArray1OfInteger) hin;
|
|
Handle(TColStd_HArray1OfReal) hre;
|
|
Handle(Interface_HArray1OfHAsciiString) hst;
|
|
Standard_Integer kod = 0;
|
|
switch (FT0)
|
|
{
|
|
case Interface_ParamMisc:
|
|
return -1;
|
|
case Interface_ParamInteger:
|
|
kod = 1;
|
|
break;
|
|
case Interface_ParamReal:
|
|
kod = 5;
|
|
break;
|
|
case Interface_ParamIdent:
|
|
kod = 7;
|
|
break;
|
|
case Interface_ParamVoid:
|
|
kod = 0;
|
|
break;
|
|
case Interface_ParamText:
|
|
kod = 6;
|
|
break;
|
|
case Interface_ParamEnum:
|
|
kod = 4;
|
|
break; // a confirmer(logical)
|
|
/* kod = 4;
|
|
if ( str[0] == '.' && str[2] == '.' && str[3] == '\0' &&
|
|
(str[1] == 'T' || str[1] == 'F' || str[1] == 'U') ) kod = 3;
|
|
break; */ // svv #2
|
|
case Interface_ParamLogical:
|
|
return -1;
|
|
case Interface_ParamSub:
|
|
kod = 0;
|
|
break;
|
|
case Interface_ParamHexa:
|
|
return -1;
|
|
case Interface_ParamBinary:
|
|
return -1;
|
|
default:
|
|
return -1;
|
|
}
|
|
if (kod == 1 || kod == 3)
|
|
{
|
|
hin = new TColStd_HArray1OfInteger(1, nbp);
|
|
val = hin;
|
|
}
|
|
else if (kod == 5)
|
|
{
|
|
hre = new TColStd_HArray1OfReal(1, nbp);
|
|
val = hre;
|
|
}
|
|
else if (kod == 6)
|
|
{
|
|
hst = new Interface_HArray1OfHAsciiString(1, nbp);
|
|
val = hst;
|
|
}
|
|
else
|
|
{
|
|
htr = new TColStd_HArray1OfTransient(1, nbp);
|
|
val = htr;
|
|
}
|
|
// Attention : si type variable, faudra changer son fusil d epaule -> htr
|
|
|
|
for (Standard_Integer ip = 1; ip <= nbp; ip++)
|
|
{
|
|
const Interface_FileParameter& FP = Param(numsub, ip);
|
|
str = FP.CValue();
|
|
FT = FP.ParamType();
|
|
switch (kod)
|
|
{
|
|
case 1: {
|
|
if (FT != Interface_ParamInteger)
|
|
{
|
|
kod = 0;
|
|
break;
|
|
}
|
|
hin->SetValue(ip, atoi(str));
|
|
break;
|
|
}
|
|
case 2:
|
|
case 3: {
|
|
if (FT != Interface_ParamEnum)
|
|
{
|
|
kod = 0;
|
|
break;
|
|
}
|
|
if (!strcmp(str, ".F."))
|
|
hin->SetValue(ip, 0);
|
|
else if (!strcmp(str, ".T."))
|
|
hin->SetValue(ip, 1);
|
|
else if (!strcmp(str, ".U."))
|
|
hin->SetValue(ip, 2);
|
|
else
|
|
kod = 0;
|
|
break;
|
|
}
|
|
case 4: {
|
|
if (FT != Interface_ParamEnum)
|
|
{
|
|
kod = 0;
|
|
break;
|
|
}
|
|
Handle(StepData_SelectNamed) sn = new StepData_SelectNamed;
|
|
sn->SetEnum(-1, str);
|
|
htr->SetValue(ip, sn);
|
|
break;
|
|
}
|
|
case 5: {
|
|
if (FT != Interface_ParamReal)
|
|
{
|
|
kod = 0;
|
|
break;
|
|
}
|
|
hre->SetValue(ip, Interface_FileReaderData::Fastof(str));
|
|
break;
|
|
}
|
|
case 6: {
|
|
if (FT != Interface_ParamText)
|
|
{
|
|
kod = 0;
|
|
break;
|
|
}
|
|
Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
|
|
cleanText(txt);
|
|
hst->SetValue(ip, txt);
|
|
break;
|
|
}
|
|
case 7: {
|
|
Handle(Standard_Transient) ent = BoundEntity(FP.EntityNumber());
|
|
htr->SetValue(ip, ent);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
// Restent les autres cas ... tout est possible. cf le type du Param
|
|
if (kod > 0)
|
|
continue;
|
|
// Il faut passer au transient ...
|
|
if (htr.IsNull())
|
|
{
|
|
htr = new TColStd_HArray1OfTransient(1, nbp);
|
|
val = htr;
|
|
Standard_Integer jp;
|
|
if (!hin.IsNull())
|
|
{
|
|
for (jp = 1; jp < ip; jp++)
|
|
{
|
|
Handle(StepData_SelectInt) sin = new StepData_SelectInt;
|
|
sin->SetInt(hin->Value(jp));
|
|
htr->SetValue(jp, sin);
|
|
}
|
|
}
|
|
if (!hre.IsNull())
|
|
{
|
|
for (jp = 1; jp < ip; jp++)
|
|
{
|
|
Handle(StepData_SelectReal) sre = new StepData_SelectReal;
|
|
sre->SetReal(hre->Value(jp));
|
|
htr->SetValue(jp, sre);
|
|
}
|
|
}
|
|
if (!hst.IsNull())
|
|
{
|
|
for (jp = 1; jp < ip; jp++)
|
|
{
|
|
htr->SetValue(jp, hst->Value(jp));
|
|
}
|
|
}
|
|
}
|
|
// A present, faut y aller : lire le champ et le mettre en place
|
|
// Ce qui suit ressemble fortement a ReadAny ...
|
|
|
|
switch (FT)
|
|
{
|
|
case Interface_ParamMisc:
|
|
break;
|
|
case Interface_ParamInteger: {
|
|
Handle(StepData_SelectInt) sin = new StepData_SelectInt;
|
|
sin->SetInteger(atoi(str));
|
|
htr->SetValue(ip, sin);
|
|
break;
|
|
}
|
|
case Interface_ParamReal: {
|
|
Handle(StepData_SelectReal) sre = new StepData_SelectReal;
|
|
sre->SetReal(Interface_FileReaderData::Fastof(str));
|
|
break;
|
|
// htr->SetValue (ip,sre); break; svv #2: unreachable
|
|
}
|
|
case Interface_ParamIdent:
|
|
htr->SetValue(ip, BoundEntity(FP.EntityNumber()));
|
|
break;
|
|
case Interface_ParamVoid:
|
|
break;
|
|
case Interface_ParamEnum: {
|
|
Handle(StepData_SelectInt) sin;
|
|
Handle(StepData_SelectNamed) sna;
|
|
Standard_Integer logic = -1;
|
|
// PTV 16.09.2000
|
|
// set the default value of StepData_Logical
|
|
StepData_Logical slog = StepData_LUnknown;
|
|
if (str[0] == '.' && str[2] == '.' && str[3] == '\0')
|
|
{
|
|
if (str[1] == 'F')
|
|
{
|
|
slog = StepData_LFalse;
|
|
logic = 0;
|
|
}
|
|
else if (str[1] == 'T')
|
|
{
|
|
slog = StepData_LTrue;
|
|
logic = 1;
|
|
}
|
|
else if (str[1] == 'U')
|
|
{
|
|
slog = StepData_LUnknown;
|
|
logic = 2;
|
|
}
|
|
}
|
|
if (logic >= 0)
|
|
{
|
|
sin = new StepData_SelectInt;
|
|
sin->SetLogical(slog);
|
|
htr->SetValue(ip, sin);
|
|
}
|
|
else
|
|
{
|
|
sna = new StepData_SelectNamed;
|
|
sna->SetEnum(logic, str);
|
|
htr->SetValue(ip, sna);
|
|
}
|
|
break;
|
|
}
|
|
case Interface_ParamLogical:
|
|
break;
|
|
case Interface_ParamText: {
|
|
Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
|
|
cleanText(txt);
|
|
htr->SetValue(ip, txt);
|
|
break;
|
|
}
|
|
case Interface_ParamSub: {
|
|
Handle(Standard_Transient) sub;
|
|
Standard_Integer nent = FP.EntityNumber();
|
|
Standard_Integer kind = ReadSub(nent, mess, ach, descr, sub);
|
|
if (kind < 0)
|
|
break;
|
|
htr->SetValue(ip, sub);
|
|
break;
|
|
}
|
|
case Interface_ParamHexa:
|
|
break;
|
|
case Interface_ParamBinary:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return -1;
|
|
}
|
|
return 8; // pour Any
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadMember(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Handle(StepData_SelectMember)& val) const
|
|
{
|
|
Handle(Standard_Transient) v = val;
|
|
Handle(StepData_PDescr) nuldescr;
|
|
if (v.IsNull())
|
|
{
|
|
return ReadAny(num, nump, mess, ach, nuldescr, v)
|
|
&& !(val = Handle(StepData_SelectMember)::DownCast(v)).IsNull();
|
|
}
|
|
Standard_Boolean res = ReadAny(num, nump, mess, ach, nuldescr, v);
|
|
if (v == val)
|
|
return res;
|
|
// changement -> refus
|
|
Handle(String) errmess = new String("Parameter n0.%d (%s) : does not match SELECT clause");
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadField(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
const Handle(StepData_PDescr)& descr,
|
|
StepData_Field& fild) const
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
Standard_CString str = FP.CValue();
|
|
Standard_Boolean OK = Standard_True;
|
|
Standard_Integer nent, kind;
|
|
Handle(TCollection_HAsciiString) txt;
|
|
Handle(Standard_Transient) sub;
|
|
Interface_ParamType FT = FP.ParamType();
|
|
switch (FT)
|
|
{
|
|
case Interface_ParamMisc:
|
|
OK = Standard_False;
|
|
break;
|
|
case Interface_ParamInteger:
|
|
fild.SetInteger(atoi(str));
|
|
break;
|
|
case Interface_ParamReal:
|
|
fild.SetReal(Interface_FileReaderData::Fastof(str));
|
|
break;
|
|
case Interface_ParamIdent:
|
|
nent = FP.EntityNumber();
|
|
if (nent > 0)
|
|
fild.SetEntity(BoundEntity(nent));
|
|
break;
|
|
case Interface_ParamVoid:
|
|
break;
|
|
case Interface_ParamText:
|
|
txt = new TCollection_HAsciiString(str);
|
|
cleanText(txt);
|
|
fild.Set(txt);
|
|
break;
|
|
case Interface_ParamEnum:
|
|
if (!strcmp(str, ".T."))
|
|
fild.SetLogical(StepData_LTrue);
|
|
else if (!strcmp(str, ".F."))
|
|
fild.SetLogical(StepData_LFalse);
|
|
else if (!strcmp(str, ".U."))
|
|
fild.SetLogical(StepData_LUnknown);
|
|
else
|
|
fild.SetEnum(-1, str);
|
|
break;
|
|
case Interface_ParamLogical:
|
|
OK = Standard_False;
|
|
break;
|
|
case Interface_ParamSub:
|
|
nent = FP.EntityNumber();
|
|
kind = ReadSub(nent, mess, ach, descr, sub);
|
|
if (kind < 0)
|
|
break;
|
|
fild.Clear(kind);
|
|
fild.Set(sub);
|
|
break;
|
|
case Interface_ParamHexa:
|
|
OK = Standard_False;
|
|
break;
|
|
case Interface_ParamBinary:
|
|
OK = Standard_False;
|
|
break;
|
|
default:
|
|
OK = Standard_False;
|
|
break;
|
|
}
|
|
|
|
if (!OK)
|
|
{
|
|
if (!strcmp(str, "*"))
|
|
fild.SetDerived();
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadList(const Standard_Integer num,
|
|
Handle(Interface_Check)& ach,
|
|
const Handle(StepData_ESDescr)& descr,
|
|
StepData_FieldList& list) const
|
|
{
|
|
// controler nbs egaux
|
|
Standard_Integer i, nb = list.NbFields();
|
|
if (!CheckNbParams(num, nb, ach, descr->TypeName()))
|
|
return Standard_False;
|
|
for (i = 1; i <= nb; i++)
|
|
{
|
|
Handle(StepData_PDescr) pde = descr->Field(i);
|
|
StepData_Field& fild = list.CField(i);
|
|
ReadField(num, i, pde->Name(), ach, pde, fild);
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadAny(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
const Handle(StepData_PDescr)& descr,
|
|
Handle(Standard_Transient)& val) const
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
Standard_CString str = FP.CValue();
|
|
Interface_ParamType FT = FP.ParamType();
|
|
|
|
// A present, faut y aller : lire le champ et le mettre en place
|
|
switch (FT)
|
|
{
|
|
case Interface_ParamMisc:
|
|
break;
|
|
case Interface_ParamInteger: {
|
|
if (!val.IsNull())
|
|
{
|
|
DeclareAndCast(StepData_SelectMember, sm, val);
|
|
sm->SetReal(Interface_FileReaderData::Fastof(str));
|
|
return Standard_True;
|
|
}
|
|
Handle(StepData_SelectInt) sin = new StepData_SelectInt;
|
|
sin->SetInteger(atoi(str));
|
|
val = sin;
|
|
return Standard_True;
|
|
}
|
|
case Interface_ParamReal: {
|
|
if (!val.IsNull())
|
|
{
|
|
DeclareAndCast(StepData_SelectMember, sm, val);
|
|
sm->SetReal(Interface_FileReaderData::Fastof(str));
|
|
return Standard_True;
|
|
}
|
|
Handle(StepData_SelectReal) sre = new StepData_SelectReal;
|
|
sre->SetReal(Interface_FileReaderData::Fastof(str));
|
|
val = sre;
|
|
return Standard_True;
|
|
}
|
|
case Interface_ParamIdent: {
|
|
Standard_Integer nent = FP.EntityNumber();
|
|
if (nent > 0)
|
|
val = BoundEntity(nent);
|
|
return (!val.IsNull());
|
|
}
|
|
case Interface_ParamVoid:
|
|
break;
|
|
case Interface_ParamEnum: {
|
|
Handle(StepData_SelectMember) sm;
|
|
if (!val.IsNull())
|
|
sm = GetCasted(StepData_SelectMember, val);
|
|
Handle(StepData_SelectInt) sin;
|
|
Handle(StepData_SelectNamed) sna;
|
|
Standard_Integer logic = -1;
|
|
|
|
// PTV 16.09.2000
|
|
// set the default value of StepData_Logical
|
|
StepData_Logical slog = StepData_LUnknown;
|
|
if (str[0] == '.' && str[2] == '.' && str[3] == '\0')
|
|
{
|
|
if (str[1] == 'F')
|
|
{
|
|
slog = StepData_LFalse;
|
|
logic = 0;
|
|
}
|
|
else if (str[1] == 'T')
|
|
{
|
|
slog = StepData_LTrue;
|
|
logic = 1;
|
|
}
|
|
else if (str[1] == 'U')
|
|
{
|
|
slog = StepData_LUnknown;
|
|
logic = 2;
|
|
}
|
|
}
|
|
if (logic >= 0)
|
|
{
|
|
if (!sm.IsNull())
|
|
sm->SetLogical(slog);
|
|
else
|
|
{
|
|
sin = new StepData_SelectInt;
|
|
val = sin;
|
|
sin->SetLogical(slog);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!sm.IsNull())
|
|
sm->SetEnum(logic, str);
|
|
else
|
|
{
|
|
sna = new StepData_SelectNamed;
|
|
val = sna; // Named sans nom...
|
|
sna->SetEnum(logic, str);
|
|
}
|
|
} // -> Select general
|
|
return Standard_True;
|
|
}
|
|
case Interface_ParamLogical:
|
|
break;
|
|
case Interface_ParamText: {
|
|
Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
|
|
cleanText(txt);
|
|
|
|
// PDN May 2000: for reading SOURCE_ITEM (external references)
|
|
if (!val.IsNull())
|
|
{
|
|
DeclareAndCast(StepData_SelectMember, sm, val);
|
|
sm->SetString(txt->ToCString());
|
|
return Standard_True;
|
|
}
|
|
|
|
val = txt;
|
|
return Standard_True;
|
|
}
|
|
case Interface_ParamSub: {
|
|
Standard_Integer numsub = SubListNumber(num, nump, Standard_False);
|
|
Standard_Integer nbp = NbParams(numsub);
|
|
if (nbp == 0)
|
|
return Standard_False; // liste vide = Handle Null
|
|
const TCollection_AsciiString& rectyp = RecordType(numsub);
|
|
if (nbp == 1 && rectyp.ToCString()[0] != '(')
|
|
{
|
|
// SelectNamed because Field !!!
|
|
// skl 15.01.2003 (for members with array of real)
|
|
DeclareAndCast(StepData_SelectArrReal, sma, val);
|
|
if (!sma.IsNull())
|
|
{
|
|
Standard_Integer numsub2 = SubListNumber(numsub, 1, Standard_False);
|
|
Standard_Integer nbp2 = NbParams(numsub2);
|
|
if (nbp2 > 1)
|
|
{
|
|
if (Param(numsub2, 1).ParamType() == Interface_ParamReal)
|
|
{
|
|
if (!sma->SetName(rectyp.ToCString()))
|
|
return Standard_False;
|
|
Handle(TColStd_HSequenceOfReal) aSeq = new TColStd_HSequenceOfReal;
|
|
for (Standard_Integer i = 1; i <= nbp2; i++)
|
|
{
|
|
if (Param(numsub2, i).ParamType() != Interface_ParamReal)
|
|
continue;
|
|
Handle(Standard_Transient) asr = new StepData_SelectReal;
|
|
if (!ReadAny(numsub2, i, mess, ach, descr, asr))
|
|
continue;
|
|
Handle(StepData_SelectReal) sm1 = Handle(StepData_SelectReal)::DownCast(asr);
|
|
if (!sm1.IsNull())
|
|
aSeq->Append(sm1->Real());
|
|
}
|
|
Handle(TColStd_HArray1OfReal) anArr = new TColStd_HArray1OfReal(1, aSeq->Length());
|
|
for (Standard_Integer nr = 1; nr <= aSeq->Length(); nr++)
|
|
{
|
|
anArr->SetValue(nr, aSeq->Value(nr));
|
|
}
|
|
sma->SetArrReal(anArr);
|
|
return Standard_True;
|
|
}
|
|
}
|
|
}
|
|
DeclareAndCast(StepData_SelectMember, sm, val);
|
|
if (sm.IsNull())
|
|
{
|
|
sm = new StepData_SelectNamed;
|
|
val = sm;
|
|
}
|
|
if (!sm->SetName(rectyp.ToCString()))
|
|
return Standard_False; // loupe
|
|
return ReadAny(numsub, 1, mess, ach, descr, val);
|
|
}
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return Standard_False;
|
|
}
|
|
|
|
// ....
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadXY(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Standard_Real& X,
|
|
Standard_Real& Y) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Integer numsub = SubListNumber(num, nump, Standard_False);
|
|
if (numsub != 0)
|
|
{
|
|
if (NbParams(numsub) == 2)
|
|
{
|
|
const Interface_FileParameter& FPX = Param(numsub, 1);
|
|
if (FPX.ParamType() == Interface_ParamReal)
|
|
X = Interface_FileReaderData::Fastof(FPX.CValue());
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y) X not a Real");
|
|
|
|
const Interface_FileParameter& FPY = Param(numsub, 2);
|
|
if (FPY.ParamType() == Interface_ParamReal)
|
|
Y = Interface_FileReaderData::Fastof(FPY.CValue());
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y) Y not a Real");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y) has not 2 params");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y) not a SubList");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadXYZ(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Standard_Real& X,
|
|
Standard_Real& Y,
|
|
Standard_Real& Z) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Integer numsub = SubListNumber(num, nump, Standard_False);
|
|
if (numsub != 0)
|
|
{
|
|
if (NbParams(numsub) == 3)
|
|
{
|
|
const Interface_FileParameter& FPX = Param(numsub, 1);
|
|
if (FPX.ParamType() == Interface_ParamReal)
|
|
X = Interface_FileReaderData::Fastof(FPX.CValue());
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) X not a Real");
|
|
|
|
const Interface_FileParameter& FPY = Param(numsub, 2);
|
|
if (FPY.ParamType() == Interface_ParamReal)
|
|
Y = Interface_FileReaderData::Fastof(FPY.CValue());
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) Y not a Real");
|
|
|
|
const Interface_FileParameter& FPZ = Param(numsub, 3);
|
|
if (FPZ.ParamType() == Interface_ParamReal)
|
|
Z = Interface_FileReaderData::Fastof(FPZ.CValue());
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) Z not a Real");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) has not 3 params");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) not a SubList");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadReal(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Standard_Real& val) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() == Interface_ParamReal || FP.ParamType() == Interface_ParamInteger)
|
|
val = Interface_FileReaderData::Fastof(FP.CValue());
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) not a Real");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadEntity(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
const Handle(Standard_Type)& atype,
|
|
Handle(Standard_Transient)& ent) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Boolean warn = Standard_False;
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
Standard_Integer nent = FP.EntityNumber();
|
|
if (FP.ParamType() == Interface_ParamIdent)
|
|
{
|
|
warn = (acceptvoid > 0);
|
|
if (nent > 0)
|
|
{
|
|
Handle(Standard_Transient) entent = BoundEntity(nent);
|
|
if (entent.IsNull() || !entent->IsKind(atype))
|
|
{
|
|
errmess = new String("Parameter n0.%d (%s) : Entity has illegal type");
|
|
if (!entent.IsNull() && entent->IsKind(STANDARD_TYPE(StepData_UndefinedEntity)))
|
|
ent = entent;
|
|
}
|
|
else
|
|
ent = entent;
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : Unresolved reference");
|
|
}
|
|
else
|
|
{
|
|
if (acceptvoid && FP.ParamType() == Interface_ParamVoid)
|
|
warn = Standard_True;
|
|
errmess = new String("Parameter n0.%d (%s) not an Entity");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
warn = (acceptvoid > 0);
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
}
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
if (warn)
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
else
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadEntity(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
StepData_SelectType& sel) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Boolean warn = Standard_False;
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
Standard_Integer nent = FP.EntityNumber();
|
|
if (FP.ParamType() == Interface_ParamIdent)
|
|
{
|
|
warn = (acceptvoid > 0);
|
|
if (nent > 0)
|
|
{
|
|
Handle(Standard_Transient) entent = BoundEntity(nent);
|
|
if (!sel.Matches(entent))
|
|
{
|
|
errmess = new String("Parameter n0.%d (%s) : Entity has illegal type");
|
|
// fot not supported STEP entity
|
|
if (!entent.IsNull() && entent->IsKind(STANDARD_TYPE(StepData_UndefinedEntity)))
|
|
sel.SetValue(entent);
|
|
}
|
|
else
|
|
sel.SetValue(entent);
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : Unresolved reference");
|
|
}
|
|
else if (FP.ParamType() == Interface_ParamVoid)
|
|
{
|
|
if (acceptvoid)
|
|
warn = Standard_True;
|
|
errmess = new String("Parameter n0.%d (%s) not an Entity");
|
|
}
|
|
else
|
|
{
|
|
// Cas restant : on s interesse en fait au SelectMember ...
|
|
Handle(Standard_Transient) sm = sel.NewMember();
|
|
// SelectMember qui assure ce role. Peut etre specialise
|
|
if (!ReadAny(num, nump, mess, ach, sel.Description(), sm))
|
|
errmess = new String("Parameter n0.%d (%s) : could not be read");
|
|
if (!sel.Matches(sm))
|
|
errmess = new String("Parameter n0.%d (%s) : illegal parameter type");
|
|
else
|
|
sel.SetValue(sm);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
warn = (acceptvoid > 0);
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
}
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
if (warn)
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
else
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadInteger(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Standard_Integer& val) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Boolean warn = Standard_False;
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() == Interface_ParamInteger)
|
|
val = atoi(FP.CValue());
|
|
else if (FP.ParamType() == Interface_ParamReal)
|
|
{
|
|
val =
|
|
static_cast<Standard_Integer>(std::round(Interface_FileReaderData::Fastof(FP.CValue())));
|
|
if (acceptvoid)
|
|
warn = Standard_True;
|
|
errmess = new String("Parameter n0.%d (%s) was rounded");
|
|
}
|
|
if (FP.ParamType() != Interface_ParamInteger && FP.ParamType() != Interface_ParamReal)
|
|
errmess = new String("Parameter n0.%d (%s) not an Integer");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
if (warn)
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
else
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadBoolean(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Standard_Boolean& flag) const
|
|
{
|
|
flag = Standard_True;
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() == Interface_ParamEnum)
|
|
{
|
|
Standard_CString txt = FP.CValue();
|
|
if (!strcmp(txt, ".T."))
|
|
flag = Standard_True;
|
|
else if (!strcmp(txt, ".F."))
|
|
flag = Standard_False;
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : Incorrect Boolean Value. It was set to true");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) not a Boolean. It was set to true");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent.It was set to true");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadLogical(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
StepData_Logical& flag) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() == Interface_ParamEnum)
|
|
{
|
|
Standard_CString txt = FP.CValue();
|
|
if (!strcmp(txt, ".T."))
|
|
flag = StepData_LTrue;
|
|
else if (!strcmp(txt, ".F."))
|
|
flag = StepData_LFalse;
|
|
else if (!strcmp(txt, ".U."))
|
|
flag = StepData_LUnknown;
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : Incorrect Logical Value");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) not a Logical");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadString(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Handle(TCollection_HAsciiString)& val) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Boolean warn = Standard_False;
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() == Interface_ParamText)
|
|
{
|
|
/*Standard_CString anStr = FP.CValue();
|
|
if(strlen(anStr) < 3)
|
|
val = new TCollection_HAsciiString("");
|
|
else {
|
|
val = new TCollection_HAsciiString(FP.CValue());
|
|
CleanText (val);
|
|
}*/
|
|
val = new TCollection_HAsciiString(FP.CValue());
|
|
cleanText(val);
|
|
}
|
|
else
|
|
{
|
|
if (acceptvoid && FP.ParamType() == Interface_ParamVoid)
|
|
warn = Standard_True;
|
|
errmess = new String("Parameter n0.%d (%s) not a quoted String");
|
|
}
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
if (warn)
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
else
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadEnumParam(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Standard_CString& text) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Boolean warn = Standard_False;
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() == Interface_ParamEnum)
|
|
{
|
|
text = FP.CValue();
|
|
warn = (acceptvoid > 0);
|
|
}
|
|
else if (FP.ParamType() == Interface_ParamVoid)
|
|
{
|
|
errmess = new String("Parameter n0.%d (%s) : Undefined Enumeration not allowed");
|
|
warn = (acceptvoid > 0);
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) not an Enumeration");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
if (warn)
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
else
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void StepData_StepReaderData::FailEnumValue(const Standard_Integer /* num */,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach) const
|
|
{
|
|
Handle(String) errmess = new String("Parameter n0.%d (%s) : Incorrect Enumeration Value");
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadEnum(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
const StepData_EnumTool& enumtool,
|
|
Standard_Integer& val) const
|
|
{
|
|
// reprendre avec ReadEnumParam ?
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Boolean warn = Standard_False;
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() == Interface_ParamEnum)
|
|
{
|
|
val = enumtool.Value(FP.CValue());
|
|
if (val >= 0)
|
|
return Standard_True;
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) : Incorrect Enumeration Value");
|
|
warn = (acceptvoid > 0);
|
|
}
|
|
else if (FP.ParamType() == Interface_ParamVoid)
|
|
{
|
|
val = enumtool.NullValue();
|
|
if (val < 0)
|
|
errmess = new String("Parameter n0.%d (%s) : Undefined Enumeration not allowed");
|
|
warn = (acceptvoid > 0);
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) not an Enumeration");
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
if (warn)
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
else
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::ReadTypedParam(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_Boolean mustbetyped,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
Standard_Integer& numr,
|
|
Standard_Integer& numrp,
|
|
TCollection_AsciiString& typ) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, nump);
|
|
if (FP.ParamType() != Interface_ParamSub)
|
|
{
|
|
// Pas une sous-liste : OK si admis
|
|
numr = num;
|
|
numrp = nump;
|
|
typ.Clear();
|
|
if (mustbetyped)
|
|
{
|
|
errmess = new String("Parameter n0.%d (%s) : single, not typed");
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
return Standard_True;
|
|
}
|
|
numr = FP.EntityNumber();
|
|
numrp = 1;
|
|
if (NbParams(numr) != 1)
|
|
errmess = new String("Parameter n0.%d (%s) : SubList, not typed");
|
|
typ = RecordType(numr);
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean StepData_StepReaderData::CheckDerived(const Standard_Integer num,
|
|
const Standard_Integer nump,
|
|
const Standard_CString mess,
|
|
Handle(Interface_Check)& ach,
|
|
const Standard_Boolean errstat) const
|
|
{
|
|
Handle(String) errmess; // Null si pas d erreur
|
|
Standard_Boolean warn = !errstat;
|
|
if (nump > 0 && nump <= NbParams(num))
|
|
{
|
|
if (!strcmp(Param(num, nump).CValue(), "*"))
|
|
return Standard_True;
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) not Derived");
|
|
if (acceptvoid)
|
|
warn = Standard_True;
|
|
}
|
|
else
|
|
errmess = new String("Parameter n0.%d (%s) absent");
|
|
|
|
if (errmess.IsNull())
|
|
return Standard_True;
|
|
sprintf(txtmes, errmess->ToCString(), nump, mess);
|
|
if (warn)
|
|
ach->AddWarning(txtmes, errmess->ToCString());
|
|
else
|
|
ach->AddFail(txtmes, errmess->ToCString());
|
|
return Standard_False;
|
|
}
|
|
|
|
// #########################################################################
|
|
// .... Methodes specifiques (demandees par FileReaderData) .... //
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer StepData_StepReaderData::NbEntities() const // redefined
|
|
{
|
|
return thenbents;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer StepData_StepReaderData::FindNextRecord(const Standard_Integer num) const
|
|
{
|
|
// retourne, sur un numero d enregistrement donne (par num), le suivant qui
|
|
// definit une entite, ou 0 si c est fini :
|
|
// passe le Header (nbhend premiers records) et
|
|
// saute les enregistrements SCOPE et ENDSCOPE et les SOUS-LISTES
|
|
|
|
if (num < 0)
|
|
return 0;
|
|
Standard_Integer num1 = num + 1;
|
|
if (num == 0)
|
|
num1 = thenbhead + 1;
|
|
Standard_Integer max = NbRecords();
|
|
|
|
while (num1 <= max)
|
|
{
|
|
if (theidents(num1) > 0)
|
|
return num1;
|
|
|
|
// SCOPE,ENDSCOPE et Sous-Liste ont un identifieur fictif: -1,-2 respectivement
|
|
// et SUBLIST ont un negatif. Seule une vraie entite a un Ident positif
|
|
num1++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer StepData_StepReaderData::FindEntityNumber(const Standard_Integer num,
|
|
const Standard_Integer id) const
|
|
{
|
|
// Soit un "Id" : recherche dans les Parametres de type Ident de <num>,
|
|
// si un d eux designe #Id justement. Si oui, retourne son EntityNumber
|
|
if (num == 0)
|
|
return 0;
|
|
Standard_Integer nb = NbParams(num);
|
|
for (Standard_Integer i = 1; i <= nb; i++)
|
|
{
|
|
const Interface_FileParameter& FP = Param(num, i);
|
|
if (FP.ParamType() != Interface_ParamIdent)
|
|
continue;
|
|
Standard_Integer ixp = atoi(&FP.CValue()[1]);
|
|
if (ixp == id)
|
|
return FP.EntityNumber();
|
|
}
|
|
return 0; // ici, pas trouve
|
|
}
|
|
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// .... La fonction qui suit merite une attention speciale ....
|
|
|
|
// Cette methode precharge les EntityNumbers dans les Params : ils designent
|
|
// les Entites proprement dites dans la liste lue par BoundEntity
|
|
// Interet : adresse de meme les sous-listes (Num->no record dans le Direc)
|
|
// resultat exploite par ParamEntity et ParamNumber
|
|
|
|
// En l absence de SCOPE, ou si les "ident" sont strictement ordonnes, a coup
|
|
// sur ils ne sont pas dupliques, on peut utiliser une IndexedMap en toute
|
|
// confiance. Sinon, il faut balayer dans le fichier, mais avec les SCOPES
|
|
// cela va beaucoup plus vite (s ils sont assez gros) : on s y retrouve.
|
|
|
|
// Pour la recherche par balayage, On opere en plusieurs etapes
|
|
// Avant toute chose, le chargement a deja fait une preparation : les idents
|
|
// (Entity, SubList) sont deja en entiers (rapidite de lecture), en particulier
|
|
// dans les EntityNumber : ainsi, on lit cet ident, on le traite, et on remet
|
|
// a la place un vrai numero de Record
|
|
//
|
|
// D abord, on passe le directory en table d entiers, sous-listes expurgees
|
|
// en // , table inverse vers cette table, car les sous-listes peuvent par
|
|
// contre designer des objets ...
|
|
|
|
// Pour les sous-listes, on exploite leur mode de construction : elles sont
|
|
// enregistrees AVANT d etre referencees. Un tableau "subn" note donc pour
|
|
// chaque numero de sous-liste (relatif a une entite qui suit, et reference
|
|
// par elle ou une autre sous-liste qui suit egalement), son n0 de record
|
|
// REMARQUE : ceci marche aussi pour le Header, traite par l occasion
|
|
|
|
//=================================================================================================
|
|
|
|
void StepData_StepReaderData::SetEntityNumbers(const Standard_Boolean withmap)
|
|
{
|
|
Message_Messenger::StreamBuffer sout = Message::SendTrace();
|
|
// Passe initiale : Resolution directe par Map
|
|
// si tout passe (pas de collision), OK. Sinon, autres passes a prevoir
|
|
// On resoud du meme coup les sous-listes
|
|
Standard_Integer nbdirec = NbRecords();
|
|
Handle(NCollection_IncAllocator) anAlloc =
|
|
new NCollection_IncAllocator(NCollection_IncAllocator::THE_MINIMUM_BLOCK_SIZE);
|
|
TColStd_Array1OfInteger subn(0, thelastn);
|
|
|
|
Standard_Boolean pbmap = Standard_False; // au moins un conflit
|
|
Standard_Integer nbmap = 0;
|
|
TColStd_IndexedMapOfInteger imap(thenbents, anAlloc);
|
|
TColStd_Array1OfInteger indm(0, nbdirec); // Index Map -> Record Number (seulement si map)
|
|
|
|
Standard_Integer num; // svv Jan11 2000 : porting on DEC
|
|
for (num = 1; num <= nbdirec; num++)
|
|
{
|
|
Standard_Integer ident = theidents(num);
|
|
if (ident > 0)
|
|
{ // Ident normal -> Map ?
|
|
// Map : si Recouvrement, l inhiber. Sinon, noter index
|
|
Standard_Integer indmap = imap.Add(ident);
|
|
if (indmap <= nbmap)
|
|
{
|
|
indmap = imap.FindIndex(ident); // plus sur
|
|
indm(indmap) = -1; // Map -> pb
|
|
pbmap = Standard_True;
|
|
// pbmap signifie qu une autre passe sera necessaire ...
|
|
}
|
|
else
|
|
{
|
|
nbmap = indmap;
|
|
indm(indmap) = num; // Map ->ident
|
|
}
|
|
}
|
|
}
|
|
|
|
for (num = 1; num <= nbdirec; num++)
|
|
{
|
|
Standard_Integer ident = theidents(num);
|
|
if (ident < -2)
|
|
subn(-(ident + 2)) = num; // toujours a jour ...
|
|
|
|
Standard_Integer nba = NbParams(num);
|
|
Standard_Integer nda = (num == 1 ? 0 : ParamFirstRank(num - 1));
|
|
|
|
for (Standard_Integer na = nba; na > 0; na--)
|
|
{
|
|
// On traite : les sous-listes (sf subn), les idents (si Map dit OK ...)
|
|
Interface_FileParameter& FP = ChangeParameter(nda + na);
|
|
// Interface_FileParameter& FP = ChangeParam (num,na);
|
|
Interface_ParamType letype = FP.ParamType();
|
|
if (letype == Interface_ParamSub)
|
|
{
|
|
Standard_Integer numsub = FP.EntityNumber();
|
|
if (numsub > thelastn)
|
|
{
|
|
Message::SendInfo() << "Bad Sub.N0, Record " << num << " Param " << na << ":$" << numsub
|
|
<< std::endl;
|
|
continue;
|
|
}
|
|
FP.SetEntityNumber(subn(numsub));
|
|
}
|
|
else if (letype == Interface_ParamIdent)
|
|
{
|
|
Standard_Integer id = FP.EntityNumber();
|
|
Standard_Integer indmap = imap.FindIndex(id);
|
|
if (indmap > 0)
|
|
{ // la map a trouve
|
|
Standard_Integer num0 = indm(indmap);
|
|
if (num0 > 0)
|
|
FP.SetEntityNumber(num0); // ET VOILA, on a resolu
|
|
else
|
|
FP.SetEntityNumber(-id); // CONFLIT -> faudra resoudre ...
|
|
}
|
|
else
|
|
{ // NON RESOLU, si pas pbmap, le dire
|
|
if (pbmap)
|
|
{
|
|
FP.SetEntityNumber(-id);
|
|
continue; // pbmap : on se retrouvera
|
|
}
|
|
char failmess[100];
|
|
// ... Construire le Check ...
|
|
sprintf(failmess, "Unresolved Reference, Ent.Id.#%d Param.n0 %d (Id.#%d)", ident, na, id);
|
|
thecheck->AddFail(failmess, "Unresolved Reference");
|
|
// ... Et sortir message un peu plus complet
|
|
sout << "*** ERR StepReaderData *** Entite #" << ident << "\n Type:" << RecordType(num)
|
|
<< " Param.n0 " << na << ": #" << id << " Not found" << std::endl;
|
|
} // FIN Mapping
|
|
} // FIN Traitement Reference
|
|
} // FIN Boucle Parametres
|
|
} // FIN Boucle Repertoires
|
|
|
|
if (!pbmap)
|
|
{
|
|
return;
|
|
}
|
|
sout << " -- 2nd pass required --";
|
|
|
|
Standard_Integer nbseq = thenbents + 2 * thenbscop;
|
|
TColStd_Array1OfInteger inds(0, nbseq); // n0 Record/Entite
|
|
TColStd_Array1OfInteger indi(0, nbseq); // Idents/scopes
|
|
TColStd_Array1OfInteger indr(0, nbdirec); // inverse de nds
|
|
Handle(TColStd_HArray1OfInteger) indx; // pour EXPORT (silya)
|
|
|
|
imap.Clear();
|
|
anAlloc->Reset();
|
|
Standard_Boolean iamap = withmap; // (par defaut True)
|
|
nbmap = 0;
|
|
|
|
TColStd_SequenceOfInteger scopile(anAlloc); // chainage des scopes note par pile
|
|
Standard_Integer nr = 0;
|
|
for (num = 1; num <= nbdirec; num++)
|
|
{
|
|
Standard_Integer ident = theidents(num);
|
|
if (ident < -2)
|
|
{ // SOUS-LISTE (cas le plus courant)
|
|
indr(num) = nr + 1; // recherche basee sur nr (objet qui suit)
|
|
}
|
|
else if (ident >= 0)
|
|
{ // Ident normal
|
|
nr++;
|
|
inds(nr) = num;
|
|
indi(nr) = ident;
|
|
indr(num) = nr;
|
|
if (ident > 0)
|
|
{ // et non (iamap && ident > 0)
|
|
// Map : si Recouvrement, l inhiber. Sinon, noter index
|
|
Standard_Integer indmap = imap.Add(ident);
|
|
if (indmap <= nbmap)
|
|
{
|
|
Standard_Boolean errorscope = Standard_False;
|
|
indmap = imap.FindIndex(ident); // plus sur
|
|
pbmap = Standard_True;
|
|
if (thenbscop == 0)
|
|
errorscope = Standard_True;
|
|
// Numeros identiques alors quilnya pas de SCOPE ? ERREUR !
|
|
// (Bien sur, silya des SCOPES, on passe au travers, mais bon...)
|
|
else
|
|
{
|
|
// Silya des SCOPES, tachons d y voir de plus pres pour signaler un probleme
|
|
// Erreur si MEME groupe SCOPE
|
|
// ATTENTION, on recherche, non dans tous les records, mais dans les records
|
|
// CHAINES, cf nr et non num (pas de sous-liste, chainage scope-endscope)
|
|
Standard_Integer fromscope = nr;
|
|
Standard_Integer toscope = indm(indmap);
|
|
if (toscope < 0)
|
|
toscope = -toscope;
|
|
for (;;)
|
|
{
|
|
fromscope--; // iteration de base
|
|
if (fromscope <= toscope)
|
|
{
|
|
errorscope = Standard_True; // BANG, on est dessus
|
|
break;
|
|
}
|
|
Standard_Integer idtest = indi(fromscope);
|
|
if (idtest >= 0)
|
|
continue; // le suivant (enfin, le precedent)
|
|
if (idtest == -1)
|
|
break; // pas meme niveau, donc c est OK
|
|
if (idtest == -3)
|
|
{
|
|
fromscope = inds(fromscope);
|
|
if (fromscope < toscope)
|
|
break; // on sort, pas en meme niveau
|
|
}
|
|
}
|
|
}
|
|
if (errorscope)
|
|
{
|
|
// On est dedans : le signaler
|
|
char ligne[80];
|
|
sprintf(ligne, "Ident defined SEVERAL TIMES : #%d", ident);
|
|
thecheck->AddFail(ligne, "Ident defined SEVERAL TIMES : #%d");
|
|
sout << "StepReaderData : SetEntityNumbers, " << ligne << std::endl;
|
|
}
|
|
if (indm(indmap) > 0)
|
|
indm(indmap) = -indm(indmap); // Pas pour Map
|
|
// Cas Normal pour la Map
|
|
}
|
|
else
|
|
{
|
|
nbmap = indmap;
|
|
indm(indmap) = nr; // Map ->(indm)->inds
|
|
}
|
|
}
|
|
}
|
|
else if (ident == -1)
|
|
{ // SCOPE
|
|
nr++;
|
|
inds(nr) = num;
|
|
indi(nr) = -1;
|
|
indr(num) = 0;
|
|
scopile.Append(nr);
|
|
}
|
|
else if (ident == -2)
|
|
{ // ENDSCOPE
|
|
Standard_Integer nscop = scopile.Last(); // chainage SCOPE-ENDSCOPE
|
|
scopile.Remove(scopile.Length());
|
|
nr++;
|
|
inds(nr) = nscop;
|
|
indi(nr) = -3;
|
|
indr(num) = 0;
|
|
inds(nscop) = nr;
|
|
if (NbParams(num) > 0)
|
|
{
|
|
// EXPORT : traitement special greffe sur celui de SCOPE (sans le perturber)
|
|
if (indx.IsNull())
|
|
{
|
|
indx = new TColStd_HArray1OfInteger(0, nbseq);
|
|
for (Standard_Integer ixp = 0; ixp <= nbseq; ixp++)
|
|
indx->ChangeValue(ixp) = 0;
|
|
}
|
|
indx->ChangeValue(nr) = num;
|
|
indx->ChangeValue(nscop) = num;
|
|
}
|
|
}
|
|
else if (ident == 0)
|
|
{ // HEADER
|
|
indr(num) = 0;
|
|
}
|
|
}
|
|
|
|
// .. Resolution des EXPORT, silyena et silya besoin ..
|
|
// Pour chaque valeur de EXPORT qui n a pas ete resolue par la MAP,
|
|
// determiner sa position locale par recherche en arriere depuis ENDSCOPE
|
|
if ((!iamap || pbmap) && !indx.IsNull())
|
|
{
|
|
for (nr = 0; nr <= nbseq; nr++)
|
|
{
|
|
if (indx->Value(nr) == 0 && indi(nr) != -3)
|
|
continue; // ENDSCOPE + EXPORT
|
|
num = indx->Value(nr);
|
|
Standard_Integer nba = NbParams(num);
|
|
for (Standard_Integer na = 1; na <= nba; na++)
|
|
{
|
|
Interface_FileParameter& FP = ChangeParam(num, na);
|
|
if (FP.ParamType() != Interface_ParamIdent)
|
|
continue;
|
|
Standard_Integer id = -FP.EntityNumber();
|
|
if (id < 0)
|
|
continue; // deja resolu en tete
|
|
/* if (imap.Contains(id)) { et voila
|
|
FP.SetEntityNumber(indm(imap.FindIndex(id)));
|
|
continue;
|
|
} */
|
|
|
|
// Recherche du Id demande : si EXPORT imbrique, deja resolu mais il faut
|
|
// regarder ! (inutile par contre d aller y voir : c est deja fait, car
|
|
// un EXPORT imbrique a ete traite AVANT celui qui imbrique)
|
|
Standard_Integer n0 = nr - 1;
|
|
if (indi(n0) == -3)
|
|
n0--; // si on suit juste un ENDSCOPE
|
|
while (n0 > 0)
|
|
{
|
|
Standard_Integer irec = indi(n0);
|
|
if (irec == id)
|
|
{ // trouve
|
|
FP.SetEntityNumber(inds(n0));
|
|
break;
|
|
}
|
|
if (irec == -1)
|
|
break; // SCOPE : fin de ce SCOPE/ENDSCOPE
|
|
if (irec == -3)
|
|
{
|
|
// gare a EXPORT : si un EXPORT detient Id, noter son Numero deja calcule
|
|
// Attention : Id a lire depuis CValue car EntityNumber deja resolu
|
|
Standard_Integer nok = FindEntityNumber(indx->Value(n0), id);
|
|
if (nok > 0)
|
|
{
|
|
FP.SetEntityNumber(nok);
|
|
break;
|
|
}
|
|
n0 = inds(n0); // ENDSCOPE ou EXPORT infructueux : le sauter
|
|
} // fin traitement sur un ENDSCOPE ou EXPORT
|
|
n0--;
|
|
} // fin resolution d un Parametre EXPORT
|
|
} // fin resolution de la liste d un EXPORT
|
|
} // fin bouclage sur les EXPORT
|
|
}
|
|
|
|
// Exploitation de la table : bouclage porte sur la table
|
|
|
|
// Traitement des sous-listes : se fait dans la foulee, par gestion d une pile
|
|
// basee sur la constitution des sous-listes
|
|
Standard_Integer maxsubpil = 30; // pile simulee avec un Array : tres fort
|
|
Handle(TColStd_HArray1OfInteger) subpile = // ... gagne de la memoire ...
|
|
new TColStd_HArray1OfInteger(1, maxsubpil);
|
|
Standard_Integer nbsubpil = 0; // ... et tellement plus rapide !
|
|
|
|
for (num = 1; num <= nbdirec; num++)
|
|
{
|
|
nr = indr(num);
|
|
if (nr == 0)
|
|
continue; // pas un objet ou une sous-liste
|
|
Standard_Integer nba = NbParams(num);
|
|
for (Standard_Integer na = nba; na > 0; na--)
|
|
{
|
|
// On lit depuis la fin : cela permet de traiter les sous-listes dans la foulee
|
|
// Sinon, on devrait noter qu il y a eu des sous-listes et reprendre ensuite
|
|
|
|
Interface_FileParameter& FP = ChangeParam(num, na);
|
|
Interface_ParamType letype = FP.ParamType();
|
|
if (letype == Interface_ParamSub)
|
|
{
|
|
// parametre type sous-liste : numero de la sous-liste lu par depilement
|
|
FP.SetEntityNumber(subpile->Value(nbsubpil));
|
|
nbsubpil--; // subpile->Remove(nbsubpil);
|
|
}
|
|
else if (letype == Interface_ParamIdent)
|
|
{
|
|
// parametre type ident (reference une entite) : chercher ident demande
|
|
Standard_Integer id = -FP.EntityNumber();
|
|
if (id < 0)
|
|
continue; // deja resolu en tete
|
|
|
|
// Voila : on va chercher id dans ndi; algorithme de balayage
|
|
Standard_Integer pass, sens, nok, n0, irec;
|
|
pass = sens = nok = 0;
|
|
if (!iamap)
|
|
pass = 1; // si map non disponible
|
|
while (pass < 3)
|
|
{
|
|
pass++;
|
|
// MAP disponible
|
|
if (pass == 1)
|
|
{ // MAP DISPONIBLE
|
|
Standard_Integer indmap = imap.FindIndex(id);
|
|
if (indmap > 0)
|
|
{ // la map a trouve
|
|
nok = indm(indmap);
|
|
if (nok < 0)
|
|
continue; // CONFLIT -> faut resoudre ...
|
|
break;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
// 1re Passe : REMONTEE -> Debut fichier
|
|
if (sens == 0 && nr > 1)
|
|
{
|
|
n0 = nr - 1;
|
|
if (indi(n0) == -3)
|
|
n0--; // si on suit juste un ENDSCOPE
|
|
while (n0 > 0)
|
|
{
|
|
irec = indi(n0);
|
|
if (irec == id)
|
|
{ // trouve
|
|
nok = n0;
|
|
break;
|
|
}
|
|
// ENDSCOPE : Attention a EXPORT sinon sauter
|
|
if (irec == -3)
|
|
{
|
|
if (indx.IsNull())
|
|
n0 = inds(n0);
|
|
else
|
|
{
|
|
// EXPORT, il faut regarder
|
|
nok = FindEntityNumber(indx->Value(n0), id);
|
|
if (nok > 0)
|
|
break;
|
|
n0 = inds(n0); // ENDSCOPE : le sauter
|
|
}
|
|
}
|
|
n0--;
|
|
}
|
|
// 2me Passe : DESCENTE -> Fin fichier
|
|
}
|
|
else if (nr < nbseq)
|
|
{ // descente -> fin fichier
|
|
n0 = nr + 1;
|
|
while (n0 <= nbseq)
|
|
{
|
|
irec = indi(n0);
|
|
if (irec == id)
|
|
{ // trouve
|
|
nok = n0;
|
|
break;
|
|
}
|
|
// SCOPE : Attention a EXPORT sinon sauter
|
|
if (irec == -1)
|
|
{
|
|
if (indx.IsNull())
|
|
n0 = inds(n0);
|
|
else
|
|
{
|
|
// EXPORT, il faut regarder
|
|
nok = FindEntityNumber(indx->Value(n0), id);
|
|
if (nok > 0)
|
|
break;
|
|
n0 = inds(n0); // SCOPE : le sauter
|
|
}
|
|
}
|
|
n0++;
|
|
}
|
|
}
|
|
if (nok > 0)
|
|
break;
|
|
sens = 1 - sens; // passe suivante
|
|
}
|
|
// ici on a nok, numero trouve
|
|
if (nok > 0)
|
|
{
|
|
Standard_Integer num0 = inds(nok);
|
|
FP.SetEntityNumber(num0); // ET VOILA, on a resolu
|
|
|
|
// pas trouve : le signaler
|
|
}
|
|
else
|
|
{
|
|
// Alimenter le Check ... Pour cela, determiner n0 Entite et Ident
|
|
char failmess[100];
|
|
Standard_Integer nument = 0;
|
|
Standard_Integer n0ent; // svv Jan11 2000 : porting on DEC
|
|
for (n0ent = 1; n0ent <= nr; n0ent++)
|
|
{
|
|
if (indi(n0ent) > 0)
|
|
nument++;
|
|
}
|
|
Standard_Integer ident = RecordIdent(num);
|
|
if (ident < 0)
|
|
{
|
|
for (n0ent = num + 1; n0ent <= nbdirec; n0ent++)
|
|
{
|
|
ident = RecordIdent(n0ent);
|
|
if (ident > 0)
|
|
break;
|
|
}
|
|
}
|
|
// ... Construire le Check ...
|
|
sprintf(failmess,
|
|
"Unresolved Reference, Ent.n0 %d (Id.#%d) Param.n0 %d (Id.#%d)",
|
|
nument,
|
|
ident,
|
|
na,
|
|
id);
|
|
thecheck->AddFail(failmess, "Unresolved Reference");
|
|
|
|
// ... Et sortir message un peu plus complet
|
|
sout << "*** ERR StepReaderData *** Entite " << nument << ", a " << (nr * 100) / nbseq
|
|
<< "% de DATA : #" << ident << "\n Type:" << RecordType(num) << " Param.n0 "
|
|
<< na << ": #" << id << " Not found" << std::endl;
|
|
|
|
FP.SetEntityNumber(0); // -> Reference non resolue
|
|
}
|
|
}
|
|
}
|
|
// Si ce record est lui-meme une sous-liste, empiler !
|
|
if (inds(nr) != num)
|
|
{
|
|
if (nbsubpil >= maxsubpil)
|
|
{
|
|
maxsubpil = maxsubpil + 30;
|
|
Handle(TColStd_HArray1OfInteger) newsubpil = new TColStd_HArray1OfInteger(1, maxsubpil);
|
|
for (Standard_Integer bidpil = 1; bidpil <= maxsubpil - 30; bidpil++)
|
|
newsubpil->SetValue(bidpil, subpile->Value(bidpil));
|
|
subpile = newsubpil;
|
|
}
|
|
nbsubpil++;
|
|
subpile->SetValue(nbsubpil, num); // Append(num);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// .... Gestion du Header : Preparation, lecture ....
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer StepData_StepReaderData::FindNextHeaderRecord(const Standard_Integer num) const
|
|
{
|
|
// retourne, sur un numero d enregistrement donne (par num), le suivant qui
|
|
// definit une entite, ou 0 si c est fini :
|
|
// Opere comme FindNextRecord mais ne balaie que le Header
|
|
|
|
if (num < 0)
|
|
return 0;
|
|
Standard_Integer num1 = num + 1;
|
|
Standard_Integer max = thenbhead;
|
|
|
|
while (num1 <= max)
|
|
{
|
|
// SCOPE,ENDSCOPE et Sous-Liste ont un identifieur negatif
|
|
// Ne retenir que les Idents positifs ou nuls (nul : pas d Ident dans Header)
|
|
if (RecordIdent(num1) >= 0)
|
|
return num1;
|
|
num1++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void StepData_StepReaderData::PrepareHeader()
|
|
{
|
|
// Resolution des references : ne concerne que les sous-listes
|
|
// deja faite par SetEntityNumbers donc pas de souci a se faire
|
|
|
|
/*
|
|
// Algorithme repris et adapte de SetEntityNumbers
|
|
// Traitement des sous-listes : se fait dans la foulee, par gestion d une pile
|
|
// basee sur la constitution des sous-listes
|
|
TColStd_SequenceOfInteger subpile;
|
|
Standard_Integer nbsubpil = 0; // profondeur de pile mais plus rapide ...
|
|
|
|
for (Standard_Integer num = 1 ; num <= thenbhead ; num ++) {
|
|
Standard_Integer nba = NbParams(num) ;
|
|
for (Standard_Integer na = nba ; na > 0 ; na --) {
|
|
.. On lit depuis la fin : cela permet de traiter les sous-listes dans la foulee
|
|
.. Sinon, on devrait noter qu il y a eu des sous-listes et reprendre ensuite
|
|
|
|
Interface_FileParameter& FP = ChangeParam(num,na);
|
|
Interface_ParamType letype = FP.ParamType();
|
|
if (letype == Interface_ParamSub) {
|
|
.. parametre type sous-liste : numero de la sous-liste lu par depilement
|
|
FP.SetEntityNumber(subpile.Last());
|
|
.. .. SetParam(num,na,FP);
|
|
subpile.Remove(nbsubpil);
|
|
nbsubpil --;
|
|
}
|
|
}
|
|
.. Si c est une sous-liste, empiler
|
|
if (RecordIdent(num) < -2) {
|
|
subpile.Append(num);
|
|
nbsubpil ++;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
const Handle(Interface_Check) StepData_StepReaderData::GlobalCheck() const
|
|
{
|
|
return thecheck;
|
|
}
|