1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-06 18:26:22 +03:00
occt/src/StepData/StepData_StepReaderData.cxx
abv d5f74e42d6 0024624: Lost word in license statement in source files
License statement text corrected; compiler warnings caused by Bison 2.41 disabled for MSVC; a few other compiler warnings on 54-bit Windows eliminated by appropriate type cast
Wrong license statements corrected in several files.
Copyright and license statements added in XSD and GLSL files.
Copyright year updated in some files.
Obsolete documentation files removed from DrawResources.
2014-02-20 16:15:17 +04:00

1922 lines
74 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 <StepData_StepReaderData.ixx>
#include <StepData_StepModel.hxx>
#include <Interface_FileParameter.hxx>
#include <Interface_ParamList.hxx>
#include <Message_Messenger.hxx>
#include <Message.hxx>
#include <Interface_Static.hxx>
#include <Interface_Macros.hxx>
#include <TColStd_SequenceOfInteger.hxx>
#include <TColStd_HArray1OfInteger.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_IndexedMapOfInteger.hxx>
#include <TCollection_HAsciiString.hxx>
#include <TColStd_HArray1OfTransient.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <Interface_HArray1OfHAsciiString.hxx>
#include <StepData_SelectMember.hxx>
#include <StepData_SelectNamed.hxx>
#include <StepData_SelectReal.hxx>
#include <StepData_SelectInt.hxx>
#include <TColStd_HSequenceOfReal.hxx>
#include <StepData_SelectArrReal.hxx>
#include <stdio.h>
// 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;
typedef Handle(TCollection_HAsciiString) Handle(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 ----------
//=======================================================================
//function : CleanText
//purpose :
//=======================================================================
static void CleanText (const Handle(TCollection_HAsciiString)& val)
{
Standard_Integer n = val->Length(); // avant reduction
val->Remove(n);
val->Remove(1);
// Ne pas oublier de traiter les caracteres speciaux
for (Standard_Integer i = n-2; i > 0; i --) {
char uncar = val->Value(i);
if (uncar == '\n')
{ val->Remove(i); if (i < n-2) uncar = val->Value(i); }
if (uncar == '\'' && i < n-2) {
if (val->Value(i+1) == '\'') { val->Remove(i+1); continue; }
}
if (uncar == '\\' && i < n-2) {
if (val->Value(i+1) == '\\') { val->Remove(i+1); continue; }
}
else if (uncar == '\\' && i < n-3) {
if (val->Value(i+2) == '\\') {
if (val->Value(i+1) == 'N')
{ val->SetValue(i,'\n'); val->Remove(i+1,2); continue; }
if (val->Value(i+1) == 'T')
{ val->SetValue(i,'\t'); val->Remove(i+1,2); continue; }
}
}
}
}
// ------------- METHODES -------------
//=======================================================================
//function : StepData_StepReaderData
//purpose :
//=======================================================================
StepData_StepReaderData::StepData_StepReaderData
(const Standard_Integer nbheader, const Standard_Integer nbtotal,
const Standard_Integer nbpar)
: Interface_FileReaderData (nbtotal,nbpar), theidents (1,nbtotal),
thetypes (1,nbtotal) //, themults (1,nbtotal)
{
// char textnum[10];
thenbscop = 0; thenbents = 0; thelastn = 0; thenbhead = nbheader;
//themults.Init(0);
thecheck = new Interface_Check;
//:S4136 acceptvoid = Interface_Static::IVal("step.readaccept.void");
if (initstr) return;
//for (Standard_Integer i = 0; i < Maxlst; i ++) {
// sprintf(textnum,"$%d",i+1);
// subl[i].AssignCat(textnum);
//}
initstr = Standard_True;
}
//=======================================================================
//function : SetRecord
//purpose :
//=======================================================================
void StepData_StepReaderData::SetRecord (const Standard_Integer num,
const Standard_CString ident,
const Standard_CString type,
const Standard_Integer /* nbpar */)
{
Standard_Integer numlst;
/*
if (strcmp(type,"/ * (SUB) * /") == 0) { // defini dans recfile.pc
thetypes.SetValue (num,sublist);
} else {
thenbents ++; // total de termes propres du fichier
thetypes.SetValue(num,TCollection_AsciiString(type));
// if (strcmp(ident,"SCOPE") != 0) thenbscop ++; // ?? a verifier
}
*/
if (type[0] != '(') thenbents ++; // total de termes propres du fichier
//thetypes.ChangeValue(num).SetValue(1,type); gka memory
//============================================
Standard_Integer index = 0;
TCollection_AsciiString strtype(type);
if(thenametypes.Contains(type))
index = thenametypes.FindIndex(strtype);
else index = thenametypes.Add(strtype);
thetypes.ChangeValue(num) = index;
//===========================================
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)))) {
//if (thetypes.Value(num).IsLess(thetypes.Value(prev)))
// ERREUR : Type complexe pas en ordre alphabetique. On enregistre.
TCollection_AsciiString errm("Complex Type incorrect : ");
errm.AssignCat(thenametypes.FindKey(thetypes.Value(prev)));
errm.AssignCat(" / ");
errm.AssignCat(thenametypes.FindKey(thetypes.Value(num)));
errm.AssignCat(" ... ");
thecheck->AddFail(errm.ToCString(),"Complex Type incorrect : ");
// On Affiche a l ecran, le plus de donnees possibles
while (theidents(prev) <= 0) {
prev --; if (prev <= 0) break;
}
Handle(Message_Messenger) sout = Message::DefaultMessenger();
sout << " *** Error on Record " << num << " (on " << NbRecords()
<< " -> " << num*100/NbRecords() << " % in File) ***";
if (prev > 0) sout << " Ident #" << theidents(prev);
sout << "\n" << errm << endl;
}
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);
}
//=======================================================================
//function : AddStepParam
//purpose :
//=======================================================================
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);
}
//=======================================================================
//function : RecordType
//purpose :
//=======================================================================
const TCollection_AsciiString& StepData_StepReaderData::RecordType
(const Standard_Integer num) const
{
return thenametypes.FindKey(thetypes.Value(num));
}
//=======================================================================
//function : CType
//purpose :
//=======================================================================
Standard_CString StepData_StepReaderData::CType(const Standard_Integer num) const
{
return thenametypes.FindKey(thetypes.Value(num)).ToCString();
}
//=======================================================================
//function : RecordIdent
//purpose :
//=======================================================================
Standard_Integer StepData_StepReaderData::RecordIdent (const Standard_Integer num) const
{
return theidents(num);
}
// ########################################################################
// .... Aides a la lecture des parametres, adaptees a STEP ....
//=======================================================================
//function : SubListNumber
//purpose :
//=======================================================================
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();
}
//=======================================================================
//function : IsComplex
//purpose :
//=======================================================================
Standard_Boolean StepData_StepReaderData::IsComplex(const Standard_Integer num) const
{
//return (themults(num) != 0);
return themults.IsBound(num);
}
//=======================================================================
//function : ComplexType
//purpose :
//=======================================================================
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));
}
}
//=======================================================================
//function : NextForComplex
//purpose :
//=======================================================================
Standard_Integer StepData_StepReaderData::NextForComplex
(const Standard_Integer num) const
{
Standard_Integer next =0;
if(themults.IsBound(num))
next = themults.Find(num);
return next;
}
//=======================================================================
//function : stepstrcmp
//purpose :
//=======================================================================
static Standard_Boolean stepstrcmp(const Standard_CString type,
const Standard_CString name)
{
// name peut etre d un tenant ou de deux : auquel cas il a une partie LONGUE
// et une partie COURTE separees par un blanc
// Attention : False pour dire OK, True sinon (car remplace strcmp)
Standard_Integer i,j = 0; Standard_Boolean res = Standard_False;
for (i = 0; name[i] != '\0' && type[i] != '\0' && !res ; i ++) {
if (name[i] == ' ' && type[i] == '\0') { j = i; break; }
if (type[i] != name[i]) res = Standard_True;
}
if (!res || (j == 0)) return res;
// Pas trouve et un blanc suit : on continue
for (i = j+1; name[i] != '\0'; i ++) {
if (type[i-j-1] != name[i]) return Standard_True;
}
return Standard_False;
}
//=======================================================================
//function : NamedForComplex
//purpose :
//=======================================================================
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) && (!stepstrcmp (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 (!stepstrcmp (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;
}
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
//=======================================================================
//function : CheckNbParams
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : ReadSubList
//purpose :
//=======================================================================
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 Standard_True;
// 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
//=======================================================================
//function : ReadSub
//purpose :
//=======================================================================
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());
if (ReadAny (numsub,1,mess,ach,descr,sn)) 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
}
//=======================================================================
//function : ReadMember
//purpose :
//=======================================================================
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,val);
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;
}
//=======================================================================
//function : ReadField
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : ReadList
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : ReadAny
//purpose :
//=======================================================================
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->SetInteger(atoi(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(StepData_SelectReal) sm1 = new StepData_SelectReal;
if( !ReadAny(numsub2,i,mess,ach,descr,sm1) ) continue;
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;
}
// ....
//=======================================================================
//function : ReadXY
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : ReadXYZ
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : ReadReal
//purpose :
//=======================================================================
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) 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;
}
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
//=======================================================================
//function : ReadEntity
//purpose :
//=======================================================================
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");
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;
}
//=======================================================================
//function : ReadEntity
//purpose :
//=======================================================================
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");
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;
}
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
//=======================================================================
//function : ReadInteger
//purpose :
//=======================================================================
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
if (nump > 0 && nump <= NbParams(num)) {
const Interface_FileParameter& FP = Param(num,nump);
if (FP.ParamType() == Interface_ParamInteger) val = atoi(FP.CValue());
else 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);
ach->AddFail(txtmes,errmess->ToCString());
return Standard_False;
}
//=======================================================================
//function : ReadBoolean
//purpose :
//=======================================================================
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
{
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");
}
else errmess = new String("Parameter n0.%d (%s) not a Boolean");
}
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;
}
//=======================================================================
//function : ReadLogical
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : ReadString
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : ReadEnumParam
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : FailEnumValue
//purpose :
//=======================================================================
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());
}
//=======================================================================
//function : ReadEnum
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : ReadTypedParam
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : CheckDerived
//purpose :
//=======================================================================
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) .... //
//=======================================================================
//function : NbEntities
//purpose :
//=======================================================================
Standard_Integer StepData_StepReaderData::NbEntities () const // redefined
{
return thenbents;
}
//=======================================================================
//function : FindNextRecord
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : FindEntityNumber
//purpose :
//=======================================================================
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
//=======================================================================
//function : SetEntityNumbers
//purpose :
//=======================================================================
void StepData_StepReaderData::SetEntityNumbers(const Standard_Boolean withmap)
{
Handle(Message_Messenger) sout = Message::DefaultMessenger();
// 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() ;
TColStd_Array1OfInteger subn(0, thelastn);
Standard_Boolean pbmap = Standard_False; // au moins un conflit
Standard_Integer nbmap = 0;
TColStd_IndexedMapOfInteger imap(thenbents);
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) {
sout<<"Bad Sub.N0, Record "<<num<<" Param "<<na<<":$"<<numsub<<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
FP.SetEntityNumber(-id);
if (pbmap) 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 *** Pour Entite #"<< ident
<< "\n Type:" << RecordType(num)
<< " Param.n0 " << na << ": #" << id << " Non trouve" << 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();
Standard_Boolean iamap = withmap; // (par defaut True)
nbmap = 0;
TColStd_SequenceOfInteger scopile; // 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 << 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 *** Pour Entite "<<nument
<<", a "<< (nr*100)/nbseq<<"% de DATA : #"<< ident
<< "\n Type:" << RecordType(num)
<< " Param.n0 " << na << ": #" << id << " Non trouve" << 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 ....
//=======================================================================
//function : FindNextHeaderRecord
//purpose :
//=======================================================================
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;
}
//=======================================================================
//function : PrepareHeader
//purpose :
//=======================================================================
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 ++;
}
}
*/
}
//=======================================================================
//function : GlobalCheck
//purpose :
//=======================================================================
const Handle(Interface_Check) StepData_StepReaderData::GlobalCheck () const
{
return thecheck;
}