0026715: Problems in reading STEP short names in complex entities
[occt.git] / src / StepData / StepData_StepReaderData.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
7fd59977 14// abv 09.04.99 S4136: eliminate parameter step.readaccept.void
15// sln 04,10.2001. BUC61003. Prevent exception which may occur during reading of complex entity (if entity's items are not in alphabetical order)
42cf5bc1 16
17#include <Interface_Check.hxx>
7fd59977 18#include <Interface_FileParameter.hxx>
42cf5bc1 19#include <Interface_HArray1OfHAsciiString.hxx>
20#include <Interface_Macros.hxx>
7fd59977 21#include <Interface_ParamList.hxx>
7fd59977 22#include <Interface_Static.hxx>
42cf5bc1 23#include <Message.hxx>
24#include <Message_Messenger.hxx>
25#include <Standard_Transient.hxx>
26#include <Standard_Type.hxx>
27#include <StepData_EnumTool.hxx>
28#include <StepData_ESDescr.hxx>
29#include <StepData_Field.hxx>
30#include <StepData_FieldList.hxx>
31#include <StepData_PDescr.hxx>
32#include <StepData_SelectArrReal.hxx>
33#include <StepData_SelectInt.hxx>
7fd59977 34#include <StepData_SelectMember.hxx>
35#include <StepData_SelectNamed.hxx>
36#include <StepData_SelectReal.hxx>
42cf5bc1 37#include <StepData_SelectType.hxx>
38#include <StepData_StepModel.hxx>
39#include <StepData_StepReaderData.hxx>
40#include <TCollection_AsciiString.hxx>
41#include <TCollection_HAsciiString.hxx>
42#include <TColStd_Array1OfInteger.hxx>
43#include <TColStd_HArray1OfInteger.hxx>
44#include <TColStd_HArray1OfReal.hxx>
45#include <TColStd_HArray1OfTransient.hxx>
7fd59977 46#include <TColStd_HSequenceOfReal.hxx>
42cf5bc1 47#include <TColStd_IndexedMapOfInteger.hxx>
48#include <TColStd_SequenceOfInteger.hxx>
7fd59977 49
50#include <stdio.h>
7fd59977 51// Le Header est constitue d entites analogues dans leur principe a celles
52// du Data, a ceci pres qu elles sont sans identifieur, et ne peuvent ni
53// referencer, ni etre referencees (que ce soit avec Header ou avec Data)
54// Ainsi, dans StepReaderData, le Header est constitue des "thenbhead" 1res Entites
7fd59977 55// #########################################################################
56// .... Creation et Acces de base aux donnees atomiques du fichier ....
7fd59977 57typedef TCollection_HAsciiString String;
7fd59977 58static char txtmes[200]; // plus commode que redeclarer partout
59
60
61static Standard_Boolean initstr = Standard_False;
62
63#define Maxlst 64
64//static TCollection_AsciiString subl[Maxlst]; // Maxlst : minimum 10
65
66static Standard_Integer acceptvoid = 0;
67
68// ---------- Fonctions Utilitaires ----------
69
70//=======================================================================
71//function : CleanText
72//purpose :
73//=======================================================================
74static void CleanText (const Handle(TCollection_HAsciiString)& val)
75{
76 Standard_Integer n = val->Length(); // avant reduction
77 val->Remove(n);
78 val->Remove(1);
79// Ne pas oublier de traiter les caracteres speciaux
80 for (Standard_Integer i = n-2; i > 0; i --) {
81 char uncar = val->Value(i);
82 if (uncar == '\n')
83 { val->Remove(i); if (i < n-2) uncar = val->Value(i); }
84 if (uncar == '\'' && i < n-2) {
85 if (val->Value(i+1) == '\'') { val->Remove(i+1); continue; }
86 }
87 if (uncar == '\\' && i < n-2) {
88 if (val->Value(i+1) == '\\') { val->Remove(i+1); continue; }
89 }
90 else if (uncar == '\\' && i < n-3) {
91 if (val->Value(i+2) == '\\') {
92 if (val->Value(i+1) == 'N')
93 { val->SetValue(i,'\n'); val->Remove(i+1,2); continue; }
94 if (val->Value(i+1) == 'T')
95 { val->SetValue(i,'\t'); val->Remove(i+1,2); continue; }
96 }
97 }
98 }
99}
100
101// ------------- METHODES -------------
102
103//=======================================================================
104//function : StepData_StepReaderData
105//purpose :
106//=======================================================================
107
108StepData_StepReaderData::StepData_StepReaderData
109 (const Standard_Integer nbheader, const Standard_Integer nbtotal,
110 const Standard_Integer nbpar)
111: Interface_FileReaderData (nbtotal,nbpar), theidents (1,nbtotal),
112 thetypes (1,nbtotal) //, themults (1,nbtotal)
113{
114// char textnum[10];
115 thenbscop = 0; thenbents = 0; thelastn = 0; thenbhead = nbheader;
116 //themults.Init(0);
117 thecheck = new Interface_Check;
118//:S4136 acceptvoid = Interface_Static::IVal("step.readaccept.void");
119 if (initstr) return;
120 //for (Standard_Integer i = 0; i < Maxlst; i ++) {
121 // sprintf(textnum,"$%d",i+1);
122 // subl[i].AssignCat(textnum);
123 //}
124 initstr = Standard_True;
125}
126
127
128//=======================================================================
129//function : SetRecord
130//purpose :
131//=======================================================================
132
133void StepData_StepReaderData::SetRecord (const Standard_Integer num,
134 const Standard_CString ident,
135 const Standard_CString type,
136 const Standard_Integer /* nbpar */)
137{
138 Standard_Integer numlst;
139/*
140 if (strcmp(type,"/ * (SUB) * /") == 0) { // defini dans recfile.pc
141 thetypes.SetValue (num,sublist);
142 } else {
143 thenbents ++; // total de termes propres du fichier
144 thetypes.SetValue(num,TCollection_AsciiString(type));
145// if (strcmp(ident,"SCOPE") != 0) thenbscop ++; // ?? a verifier
146 }
147*/
148 if (type[0] != '(') thenbents ++; // total de termes propres du fichier
149
150 //thetypes.ChangeValue(num).SetValue(1,type); gka memory
151 //============================================
152 Standard_Integer index = 0;
153 TCollection_AsciiString strtype(type);
154 if(thenametypes.Contains(type))
155 index = thenametypes.FindIndex(strtype);
156 else index = thenametypes.Add(strtype);
157 thetypes.ChangeValue(num) = index;
158 //===========================================
159
160 if (ident[0] == '$') {
161 if (strlen(ident) > 2) numlst = atoi(&ident[1]);
162 else numlst = ident[1] - 48;
163 if (thelastn < numlst) thelastn = numlst; // plus fort n0 de sous-liste
164 theidents.SetValue(num,-2-numlst);
165 } else if (ident[0] == '#') {
166 numlst = atoi(&ident[1]);
167 theidents.SetValue(num,numlst);
168 if (numlst == 0 && num > thenbhead) {
169// Header, ou bien Type Complexe ...
170// Si Type Complexe, retrouver Type Precedent (on considere que c est rare)
171// On chaine le type precedent sur le suivant
172// VERIFICATION que les types sont en ordre alphabetique
173 for (Standard_Integer prev = num-1; prev > thenbhead; prev --) {
174 if (theidents(prev) >= 0) {
175
176 //themults.SetValue(prev,num);
177 themults.Bind(prev,num);
178 if(thenametypes.FindKey(thetypes.Value(num)).IsLess(thenametypes.FindKey(thetypes.Value(prev)))) {
179 //if (thetypes.Value(num).IsLess(thetypes.Value(prev)))
180
181// ERREUR : Type complexe pas en ordre alphabetique. On enregistre.
182 TCollection_AsciiString errm("Complex Type incorrect : ");
183 errm.AssignCat(thenametypes.FindKey(thetypes.Value(prev)));
184 errm.AssignCat(" / ");
185 errm.AssignCat(thenametypes.FindKey(thetypes.Value(num)));
186 errm.AssignCat(" ... ");
187 thecheck->AddFail(errm.ToCString(),"Complex Type incorrect : ");
188// On Affiche a l ecran, le plus de donnees possibles
189 while (theidents(prev) <= 0) {
190 prev --; if (prev <= 0) break;
191 }
192 Handle(Message_Messenger) sout = Message::DefaultMessenger();
193 sout << " *** Error on Record " << num << " (on " << NbRecords()
194 << " -> " << num*100/NbRecords() << " % in File) ***";
195 if (prev > 0) sout << " Ident #" << theidents(prev);
196 sout << "\n" << errm << endl;
197 }
198 break;
199 }
200 }
201 }
202 }
203 else if (!strcmp(ident,"SCOPE")) {
204 theidents.SetValue(num,-1); // SCOPE
205 thenbscop ++;
206 }
207 else if (!strcmp(ident,"ENDSCOPE")) theidents.SetValue(num,-2); // ENDSCOPE
208// Reste 0
209
210 // InitParams(num);
211}
212
213
214//=======================================================================
215//function : AddStepParam
216//purpose :
217//=======================================================================
218
219void StepData_StepReaderData::AddStepParam (const Standard_Integer num,
220 const Standard_CString aval,
221 const Interface_ParamType atype,
222 const Standard_Integer nument)
223{
224 if (atype == Interface_ParamSub) {
225 Standard_Integer numid = 0;
226 if (aval[2] != '\0') {
227 numid = atoi(&aval[1]);
228// if (numid <= Maxlst) Interface_FileReaderData::AddParam
229// (num,subl[numid-1].ToCString(),atype,numid);
230 Interface_FileReaderData::AddParam (num,aval,atype,numid);
231 } else {
232 char *numlstchar = (char *)(aval+1);
233 numid = (*numlstchar) - 48; // -48 ('0') -1 (adresse [] depuis 0)
234// Interface_FileReaderData::AddParam (num,subl[numid].ToCString(),atype,numid);
235 Interface_FileReaderData::AddParam (num,aval,atype,numid);
236 }
237 } else if (atype == Interface_ParamIdent) {
238 Standard_Integer numid = atoi(&aval[1]);
239 Interface_FileReaderData::AddParam (num,aval,atype,numid);
240 } else {
241 Interface_FileReaderData::AddParam (num,aval,atype,nument);
242 }
243
244// Interface_FileReaderData::AddParam (num,parval,atype,numid);
245}
246
247
248//=======================================================================
249//function : RecordType
250//purpose :
251//=======================================================================
252
253const TCollection_AsciiString& StepData_StepReaderData::RecordType
254 (const Standard_Integer num) const
255{
256 return thenametypes.FindKey(thetypes.Value(num));
257}
258
259
260//=======================================================================
261//function : CType
262//purpose :
263//=======================================================================
264
265Standard_CString StepData_StepReaderData::CType(const Standard_Integer num) const
266{
267 return thenametypes.FindKey(thetypes.Value(num)).ToCString();
268}
269
270
271//=======================================================================
272//function : RecordIdent
273//purpose :
274//=======================================================================
275
276Standard_Integer StepData_StepReaderData::RecordIdent (const Standard_Integer num) const
277{
278 return theidents(num);
279}
280
281
282// ########################################################################
283// .... Aides a la lecture des parametres, adaptees a STEP ....
284
285
286//=======================================================================
287//function : SubListNumber
288//purpose :
289//=======================================================================
290
291Standard_Integer StepData_StepReaderData::SubListNumber (const Standard_Integer num,
292 const Standard_Integer nump,
293 const Standard_Boolean aslast) const
294{
295 if (nump == 0 || nump > NbParams(num)) return 0;
296 const Interface_FileParameter& FP = Param(num,nump);
297 if (FP.ParamType() != Interface_ParamSub) return 0;
298 if (aslast) { if(nump != NbParams(num)) return 0; }
299 return FP.EntityNumber();
300}
301
302
303//=======================================================================
304//function : IsComplex
305//purpose :
306//=======================================================================
307
308Standard_Boolean StepData_StepReaderData::IsComplex(const Standard_Integer num) const
309{
310 //return (themults(num) != 0);
311 return themults.IsBound(num);
312}
313
314
315//=======================================================================
316//function : ComplexType
317//purpose :
318//=======================================================================
319
320void StepData_StepReaderData::ComplexType(const Standard_Integer num,
321 TColStd_SequenceOfAsciiString& types) const
322{
323 if (theidents(num) < 0) return;
324 for (Standard_Integer i = num; i > 0; i = NextForComplex(i)) {
325 types.Append(RecordType(i));
326 }
327}
328
329
330//=======================================================================
331//function : NextForComplex
332//purpose :
333//=======================================================================
334
335Standard_Integer StepData_StepReaderData::NextForComplex
336 (const Standard_Integer num) const
337{
338 Standard_Integer next =0;
339 if(themults.IsBound(num))
340 next = themults.Find(num);
341 return next;
342}
343
344
345//=======================================================================
346//function : stepstrcmp
347//purpose :
348//=======================================================================
349static Standard_Boolean stepstrcmp(const Standard_CString type,
350 const Standard_CString name)
351{
352// name peut etre d un tenant ou de deux : auquel cas il a une partie LONGUE
353// et une partie COURTE separees par un blanc
354// Attention : False pour dire OK, True sinon (car remplace strcmp)
355 Standard_Integer i,j = 0; Standard_Boolean res = Standard_False;
356 for (i = 0; name[i] != '\0' && type[i] != '\0' && !res ; i ++) {
d029c7ef 357 if (name[i] == ' ' && type[i] == '\0') { j = i; break; }
7fd59977 358 if (type[i] != name[i]) res = Standard_True;
359 }
360 if (!res || (j == 0)) return res;
361// Pas trouve et un blanc suit : on continue
362 for (i = j+1; name[i] != '\0'; i ++) {
363 if (type[i-j-1] != name[i]) return Standard_True;
364 }
365 return Standard_False;
366}
367
368
369//=======================================================================
370//function : NamedForComplex
371//purpose :
372//=======================================================================
373
374Standard_Boolean StepData_StepReaderData::NamedForComplex
375 (const Standard_CString name, const Standard_Integer num0,
376 Standard_Integer& num, Handle(Interface_Check)& ach) const
377{
378 //Standard_Boolean stat = Standard_True;
379 Standard_Integer n = (num <= 0 ? num0 : NextForComplex(num));
380 // sln 04,10.2001. BUC61003. if(n==0) the next function is not called in order to avoid exception
381 if ((n!=0) && (!stepstrcmp (RecordType(n).ToCString(),name)))
382 { num = n; return Standard_True; }
383
384 if (n == 0) /*stat =*/ NamedForComplex (name,num0,n,ach); // on a rembobine
385// Pas dans l ordre alphabetique : boucler
386 Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST");
387 sprintf (txtmes,errmess->ToCString(),num0,name);
388 for (n = num0; n > 0; n = NextForComplex(n)) {
389 if (!stepstrcmp (RecordType(n).ToCString(),name)) {
390 num = n;
391 errmess = new String("Complex Record n0.%d, member type %s not in alphabetic order");
392 sprintf (txtmes,errmess->ToCString(),num0,name);
393 ach->AddWarning(txtmes,errmess->ToCString());
394 return Standard_False;
395 }
396 }
397 num = 0;
398 errmess = new String("Complex Record n0.%d, member type %s not found");
399 sprintf (txtmes,errmess->ToCString(),num0,name);
400 ach->AddFail (txtmes,errmess->ToCString());
401 return Standard_False;
402}
403
a7197ef3 404//=======================================================================
405//function : NamedForComplex
406//purpose :
407//=======================================================================
408
409Standard_Boolean StepData_StepReaderData::NamedForComplex
410 (const Standard_CString theName, const Standard_CString theShortName,
411 const Standard_Integer num0, Standard_Integer& num,
412 Handle(Interface_Check)& ach) const
413{
414 Standard_Integer n = (num <= 0 ? num0 : NextForComplex(num));
415 if ((n!=0) && !(stepstrcmp(RecordType(n).ToCString(),theName) &&
416 stepstrcmp(RecordType(n).ToCString(), theShortName)))
417 { num = n; return Standard_True; }
418
419 if (n == 0)
420 NamedForComplex (theName, theShortName, num0, n, ach);
421 //entities are not in alphabetical order
422 Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST");
423 sprintf (txtmes,errmess->ToCString(), num0, theName);
424 for (n = num0; n > 0; n = NextForComplex(n)) {
425 if (!(stepstrcmp(RecordType(n).ToCString(),theName) &&
426 stepstrcmp(RecordType(n).ToCString(), theShortName))) {
427 num = n;
428 errmess = new String("Complex Record n0.%d, member type %s not in alphabetic order");
429 sprintf (txtmes,errmess->ToCString(), num0, theName);
430 ach->AddWarning(txtmes,errmess->ToCString());
431 return Standard_False;
432 }
433 }
434 num = 0;
435 errmess = new String("Complex Record n0.%d, member type %s not found");
436 sprintf (txtmes,errmess->ToCString(), num0, theName);
437 ach->AddFail (txtmes,errmess->ToCString());
438 return Standard_False;
439}
440
7fd59977 441// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
442
443
444//=======================================================================
445//function : CheckNbParams
446//purpose :
447//=======================================================================
448
449Standard_Boolean StepData_StepReaderData::CheckNbParams(const Standard_Integer num,
450 const Standard_Integer nbreq,
451 Handle(Interface_Check)& ach,
452 const Standard_CString mess) const
453{
454 if (NbParams(num) == nbreq) return Standard_True;
455 Handle(String) errmess;
456 if (mess[0] == '\0') errmess = new String("Count of Parameters is not %d");
457 else errmess = new String("Count of Parameters is not %d for %s");
458 sprintf (txtmes,errmess->ToCString(),nbreq,mess);
459 ach->AddFail (txtmes,errmess->ToCString());
460 return Standard_False;
461}
462
463
464//=======================================================================
465//function : ReadSubList
466//purpose :
467//=======================================================================
468
469Standard_Boolean StepData_StepReaderData::ReadSubList(const Standard_Integer num,
470 const Standard_Integer nump,
471 const Standard_CString mess,
472 Handle(Interface_Check)& ach,
473 Standard_Integer& numsub,
474 const Standard_Boolean optional,
475 const Standard_Integer /* lenmin */,
476 const Standard_Integer /* lenmax */) const
477{
478 numsub = SubListNumber (num,nump,Standard_False);
479 if (numsub > 0) return Standard_True;
480// Si optionel indefini, on passe l eponge
481 numsub = 0;
482 Standard_Boolean isvoid = (Param(num,nump).ParamType() == Interface_ParamVoid);
483 if (isvoid && optional) return Standard_False;
484
485 Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST");
486 sprintf (txtmes,errmess->ToCString(),nump,mess);
487 if (acceptvoid && isvoid) ach->AddWarning(txtmes,errmess->ToCString());
488 else { ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; }
489 return Standard_True;
490}
491
492
493// ... Facilites pour LateBinding
494
495
496//=======================================================================
497//function : ReadSub
498//purpose :
499//=======================================================================
500
501Standard_Integer StepData_StepReaderData::ReadSub(const Standard_Integer numsub,
502 const Standard_CString mess,
503 Handle(Interface_Check)& ach,
504 const Handle(StepData_PDescr)& descr,
505 Handle(Standard_Transient)& val) const
506{
507 Standard_Integer nbp = NbParams(numsub);
508 if (nbp == 0) return 0; // liste vide = Handle Null
509 const TCollection_AsciiString& rectyp = RecordType (numsub);
510 if (nbp == 1 && rectyp.ToCString()[0] != '(') {
511 // c est un type avec un parametre -> SelectNamed
512 // cf ReadSelect mais ici, on est deja sur le contenu du parametre
513 Handle(StepData_SelectNamed) sn = new StepData_SelectNamed;
514 val = sn;
515 sn->SetName (rectyp.ToCString());
516 if (ReadAny (numsub,1,mess,ach,descr,sn)) return sn->Kind();
517 else return 0;
518 }
519
520 // cas courant : faire un HArray1 de ... de ... de quoi au fait
521 const Interface_FileParameter& FP0 = Param(numsub,1);
522 Interface_ParamType FT, FT0 = FP0.ParamType();
523 Standard_CString str = FP0.CValue();
524 Handle(TColStd_HArray1OfTransient) htr;
525 Handle(TColStd_HArray1OfInteger) hin;
526 Handle(TColStd_HArray1OfReal) hre;
527 Handle(Interface_HArray1OfHAsciiString) hst;
528 Standard_Integer kod = 0;
529 switch (FT0) {
530 case Interface_ParamMisc : return -1;
531 case Interface_ParamInteger : kod = 1; break;
532 case Interface_ParamReal : kod = 5; break;
533 case Interface_ParamIdent : kod = 7; break;
534 case Interface_ParamVoid : kod = 0; break;
535 case Interface_ParamText : kod = 6; break;
536 case Interface_ParamEnum : kod = 4; break; // a confirmer(logical)
537 /* kod = 4;
538 if ( str[0] == '.' && str[2] == '.' && str[3] == '\0' &&
539 (str[1] == 'T' || str[1] == 'F' || str[1] == 'U') ) kod = 3;
540 break; */ // svv #2
541 case Interface_ParamLogical : return -1;
542 case Interface_ParamSub : kod = 0; break;
543 case Interface_ParamHexa : return -1;
544 case Interface_ParamBinary : return -1;
545 default : return -1;
546 }
547 if (kod == 1 || kod == 3) { hin = new TColStd_HArray1OfInteger (1,nbp); val = hin; }
548 else if (kod == 5) { hre = new TColStd_HArray1OfReal (1,nbp); val = hre; }
549 else if (kod == 6) { hst = new Interface_HArray1OfHAsciiString (1,nbp); val = hst; }
550 else { htr = new TColStd_HArray1OfTransient (1,nbp); val = htr; }
551// Attention : si type variable, faudra changer son fusil d epaule -> htr
552
553 for (Standard_Integer ip = 1; ip <= nbp; ip ++) {
554 const Interface_FileParameter& FP = Param(numsub,ip);
555 str = FP.CValue();
556 FT = FP.ParamType();
557 switch (kod) {
558 case 1 : {
559 if (FT != Interface_ParamInteger) { kod = 0; break; }
560 hin->SetValue (ip,atoi(str)); break;
561 }
562 case 2 :
563 case 3 : {
564 if (FT != Interface_ParamEnum) { kod = 0; break; }
565 if (!strcmp(str,".F.")) hin->SetValue (ip,0);
566 else if (!strcmp(str,".T.")) hin->SetValue (ip,1);
567 else if (!strcmp(str,".U.")) hin->SetValue (ip,2);
568 else kod = 0;
569 break;
570 }
571 case 4 : {
572 if (FT != Interface_ParamEnum) { kod = 0; break; }
573 Handle(StepData_SelectNamed) sn = new StepData_SelectNamed;
574 sn->SetEnum (-1,str);
575 htr->SetValue (ip,sn); break;
576 }
577 case 5 : {
578 if (FT != Interface_ParamReal) { kod = 0; break; }
579 hre->SetValue (ip,Interface_FileReaderData::Fastof(str)); break;
580 }
581 case 6 : {
582 if (FT != Interface_ParamText) { kod = 0; break; }
583 Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
584 CleanText (txt); hst->SetValue (ip,txt); break;
585 }
586 case 7 : {
587 Handle(Standard_Transient) ent = BoundEntity (FP.EntityNumber());
588 htr->SetValue (ip,ent); break;
589 }
590 default : break;
591 }
592// Restent les autres cas ... tout est possible. cf le type du Param
593 if (kod > 0) continue;
594// Il faut passer au transient ...
595 if (htr.IsNull()) {
596 htr = new TColStd_HArray1OfTransient (1,nbp); val = htr;
597 Standard_Integer jp;
598 if (!hin.IsNull()) {
599 for (jp = 1; jp < ip; jp ++) {
600 Handle(StepData_SelectInt) sin = new StepData_SelectInt;
601 sin->SetInt (hin->Value(jp));
602 htr->SetValue (jp,sin);
603 }
604 }
605 if (!hre.IsNull()) {
606 for (jp = 1; jp < ip; jp ++) {
607 Handle(StepData_SelectReal) sre = new StepData_SelectReal;
608 sre->SetReal (hre->Value(jp));
609 htr->SetValue (jp,sre);
610 }
611 }
612 if (!hst.IsNull()) {
613 for (jp = 1; jp < ip; jp ++) {
614 htr->SetValue (jp,hst->Value(jp));
615 }
616 }
617 }
618// A present, faut y aller : lire le champ et le mettre en place
619// Ce qui suit ressemble fortement a ReadAny ...
620
621 switch (FT) {
622 case Interface_ParamMisc : break;
623 case Interface_ParamInteger : {
624 Handle(StepData_SelectInt) sin = new StepData_SelectInt;
625 sin->SetInteger (atoi(str));
626 htr->SetValue (ip,sin); break;
627 }
628 case Interface_ParamReal : {
629 Handle(StepData_SelectReal) sre = new StepData_SelectReal;
630 sre->SetReal (Interface_FileReaderData::Fastof(str)); break;
631 //htr->SetValue (ip,sre); break; svv #2: unreachable
632 }
633 case Interface_ParamIdent : htr->SetValue (ip,BoundEntity (FP.EntityNumber())); break;
634 case Interface_ParamVoid : break;
635 case Interface_ParamEnum : {
636 Handle(StepData_SelectInt) sin;
637 Handle(StepData_SelectNamed) sna;
638 Standard_Integer logic = -1;
639// PTV 16.09.2000
640// set the default value of StepData_Logical
641 StepData_Logical slog = StepData_LUnknown;
642 if ( str[0] == '.' && str[2] == '.' && str[3] == '\0') {
643 if (str[1] == 'F') { slog = StepData_LFalse; logic = 0; }
644 else if (str[1] == 'T') { slog = StepData_LTrue; logic = 1; }
645 else if (str[1] == 'U') { slog = StepData_LUnknown; logic = 2; }
646 }
647 if (logic >= 0)
648 { sin = new StepData_SelectInt; sin->SetLogical(slog); htr->SetValue(ip,sin); }
649 else { sna = new StepData_SelectNamed;
650 sna->SetEnum (logic,str); htr->SetValue (ip,sna); }
651 break;
652 }
653 case Interface_ParamLogical : break;
654 case Interface_ParamText : {
655 Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
656 CleanText (txt); htr->SetValue (ip,txt); break;
657 }
658 case Interface_ParamSub : {
659 Handle(Standard_Transient) sub;
660 Standard_Integer nent = FP.EntityNumber();
661 Standard_Integer kind = ReadSub (nent,mess,ach,descr,sub); if (kind < 0) break;
662 htr->SetValue(ip,sub); break;
663 }
664 case Interface_ParamHexa : break;
665 case Interface_ParamBinary : break;
666 default : break;
667 }
668 return -1;
669 }
670 return 8; // pour Any
671}
672
673
674//=======================================================================
675//function : ReadMember
676//purpose :
677//=======================================================================
678
679Standard_Boolean StepData_StepReaderData::ReadMember(const Standard_Integer num,
680 const Standard_Integer nump,
681 const Standard_CString mess,
682 Handle(Interface_Check)& ach,
683 Handle(StepData_SelectMember)& val) const
684{
685 Handle(Standard_Transient) v = val;
686 Handle(StepData_PDescr) nuldescr;
687 if (v.IsNull()) return ReadAny (num,nump,mess,ach,nuldescr,val);
688 Standard_Boolean res = ReadAny (num,nump,mess,ach,nuldescr,v);
689 if (v == val) return res;
690 // changement -> refus
691 Handle(String) errmess =
692 new String("Parameter n0.%d (%s) : does not match SELECT clause");
693 sprintf (txtmes,errmess->ToCString(),nump,mess);
694 ach->AddFail(txtmes,errmess->ToCString());
695 return Standard_False;
696}
697
698
699//=======================================================================
700//function : ReadField
701//purpose :
702//=======================================================================
703
704Standard_Boolean StepData_StepReaderData::ReadField(const Standard_Integer num,
705 const Standard_Integer nump,
706 const Standard_CString mess,
707 Handle(Interface_Check)& ach,
708 const Handle(StepData_PDescr)& descr,
709 StepData_Field& fild) const
710{
711 const Interface_FileParameter& FP = Param(num,nump);
712 Standard_CString str = FP.CValue();
713 Standard_Boolean OK = Standard_True;
714 Standard_Integer nent, kind;
715 Handle(TCollection_HAsciiString) txt;
716 Handle(Standard_Transient) sub;
717 Interface_ParamType FT = FP.ParamType();
718 switch (FT) {
719 case Interface_ParamMisc : OK = Standard_False; break;
720 case Interface_ParamInteger : fild.SetInteger (atoi(str)); break;
721 case Interface_ParamReal :
722 fild.SetReal (Interface_FileReaderData::Fastof(str)); break;
723 case Interface_ParamIdent :
724 nent = FP.EntityNumber();
725 if (nent > 0) fild.SetEntity (BoundEntity(nent));
726 break;
727 case Interface_ParamVoid : break;
728 case Interface_ParamText :
729 txt = new TCollection_HAsciiString(str);
730 CleanText (txt); fild.Set (txt); break;
731 case Interface_ParamEnum :
732 if (!strcmp(str,".T.")) fild.SetLogical (StepData_LTrue);
733 else if (!strcmp(str,".F.")) fild.SetLogical (StepData_LFalse);
734 else if (!strcmp(str,".U.")) fild.SetLogical (StepData_LUnknown);
735 else fild.SetEnum (-1,str);
736 break;
737 case Interface_ParamLogical : OK = Standard_False; break;
738 case Interface_ParamSub :
739 nent = FP.EntityNumber();
740 kind = ReadSub (nent,mess,ach,descr,sub); if (kind < 0) break;
741 fild.Clear(kind); fild.Set (sub); break;
742 case Interface_ParamHexa : OK = Standard_False; break;
743 case Interface_ParamBinary : OK = Standard_False; break;
744 default : OK = Standard_False; break;
745 }
746
747 if (!OK) {
748 if (!strcmp(str,"*")) fild.SetDerived();
749 }
750 return Standard_True;
751}
752
753
754//=======================================================================
755//function : ReadList
756//purpose :
757//=======================================================================
758
759Standard_Boolean StepData_StepReaderData::ReadList(const Standard_Integer num,
760 Handle(Interface_Check)& ach,
761 const Handle(StepData_ESDescr)& descr,
762 StepData_FieldList& list) const
763{
764 // controler nbs egaux
765 Standard_Integer i,nb = list.NbFields();
766 if (!CheckNbParams (num,nb,ach,descr->TypeName())) return Standard_False;
767 for (i = 1; i <= nb; i ++) {
768 Handle(StepData_PDescr) pde = descr->Field(i);
769 StepData_Field& fild = list.CField(i);
770 ReadField (num,i,pde->Name(),ach,pde,fild);
771 }
772 return Standard_True;
773}
774
775
776//=======================================================================
777//function : ReadAny
778//purpose :
779//=======================================================================
780
781Standard_Boolean StepData_StepReaderData::ReadAny(const Standard_Integer num,
782 const Standard_Integer nump,
783 const Standard_CString mess,
784 Handle(Interface_Check)& ach,
785 const Handle(StepData_PDescr)& descr,
786 Handle(Standard_Transient)& val) const
787{
788 const Interface_FileParameter& FP = Param(num,nump);
789 Standard_CString str = FP.CValue();
790 Interface_ParamType FT = FP.ParamType();
791
792// A present, faut y aller : lire le champ et le mettre en place
793 switch (FT) {
794 case Interface_ParamMisc : break;
795 case Interface_ParamInteger : {
796 if (!val.IsNull()) {
797 DeclareAndCast(StepData_SelectMember,sm,val);
798 sm->SetInteger(atoi(str));
799 return Standard_True;
800 }
801 Handle(StepData_SelectInt) sin = new StepData_SelectInt;
802 sin->SetInteger (atoi(str));
803 val = sin;
804 return Standard_True;
805 }
806 case Interface_ParamReal : {
807 if (!val.IsNull()) {
808 DeclareAndCast(StepData_SelectMember,sm,val);
809 sm->SetReal (Interface_FileReaderData::Fastof(str));
810 return Standard_True;
811 }
812 Handle(StepData_SelectReal) sre = new StepData_SelectReal;
813 sre->SetReal (Interface_FileReaderData::Fastof(str));
814 val = sre;
815 return Standard_True;
816 }
817 case Interface_ParamIdent : {
818 Standard_Integer nent = FP.EntityNumber();
819 if (nent > 0) val = BoundEntity(nent);
820 return (!val.IsNull());
821 }
822 case Interface_ParamVoid : break;
823 case Interface_ParamEnum : {
824 Handle(StepData_SelectMember) sm;
825 if (!val.IsNull()) sm = GetCasted(StepData_SelectMember,val);
826 Handle(StepData_SelectInt) sin;
827 Handle(StepData_SelectNamed) sna;
828 Standard_Integer logic = -1;
829
830 // PTV 16.09.2000
831 // set the default value of StepData_Logical
832 StepData_Logical slog = StepData_LUnknown;
833 if ( str[0] == '.' && str[2] == '.' && str[3] == '\0') {
834 if (str[1] == 'F') { slog = StepData_LFalse; logic = 0; }
835 else if (str[1] == 'T') { slog = StepData_LTrue; logic = 1; }
836 else if (str[1] == 'U') { slog = StepData_LUnknown; logic = 2; }
837 }
838 if (logic >= 0) {
839 if (!sm.IsNull()) sm->SetLogical(slog);
840 else {
841 sin = new StepData_SelectInt; val = sin;
842 sin->SetLogical(slog);
843 }
844 }
845 else {
846 if (!sm.IsNull()) sm->SetEnum (logic,str);
847 else {
848 sna = new StepData_SelectNamed; val = sna; // Named sans nom...
849 sna->SetEnum (logic,str);
850 }
851 } // -> Select general
852 return Standard_True;
853 }
854 case Interface_ParamLogical : break;
855 case Interface_ParamText : {
856 Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str);
857 CleanText (txt);
858
859 // PDN May 2000: for reading SOURCE_ITEM (external references)
860 if (!val.IsNull()) {
861 DeclareAndCast(StepData_SelectMember,sm,val);
862 sm->SetString (txt->ToCString());
863 return Standard_True;
864 }
865
866 val = txt;
867 return Standard_True;
868 }
869 case Interface_ParamSub : {
870 Standard_Integer numsub = SubListNumber (num,nump,Standard_False);
871 Standard_Integer nbp = NbParams(numsub);
872 if (nbp == 0) return Standard_False; // liste vide = Handle Null
873 const TCollection_AsciiString& rectyp = RecordType (numsub);
874 if (nbp == 1 && rectyp.ToCString()[0] != '(') {
875 // SelectNamed because Field !!!
876 // skl 15.01.2003 (for members with array of real)
877 DeclareAndCast(StepData_SelectArrReal,sma,val);
878 if(!sma.IsNull()) {
879 Standard_Integer numsub2 = SubListNumber (numsub,1,Standard_False);
880 Standard_Integer nbp2 = NbParams(numsub2);
881 if(nbp2>1) {
882 if( Param(numsub2,1).ParamType() == Interface_ParamReal ) {
883 if (!sma->SetName (rectyp.ToCString())) return Standard_False;
884 Handle(TColStd_HSequenceOfReal) aSeq = new TColStd_HSequenceOfReal;
885 for(Standard_Integer i=1; i<=nbp2; i++) {
886 if( Param(numsub2,i).ParamType() != Interface_ParamReal ) continue;
887 Handle(StepData_SelectReal) sm1 = new StepData_SelectReal;
888 if( !ReadAny(numsub2,i,mess,ach,descr,sm1) ) continue;
889 aSeq->Append(sm1->Real());
890 }
891 Handle(TColStd_HArray1OfReal) anArr = new TColStd_HArray1OfReal(1,aSeq->Length());
892 for(Standard_Integer nr=1; nr<=aSeq->Length(); nr++) {
893 anArr->SetValue(nr,aSeq->Value(nr));
894 }
895 sma->SetArrReal(anArr);
896 return Standard_True;
897 }
898 }
899 }
900 DeclareAndCast(StepData_SelectMember,sm,val);
901 if (sm.IsNull()) {
902 sm = new StepData_SelectNamed;
903 val = sm;
904 }
905 if (!sm->SetName (rectyp.ToCString())) return Standard_False; // loupe
906 return ReadAny (numsub,1,mess,ach,descr,val);
907 }
908 }
909 default : break;
910 }
911 return Standard_False;
912}
913
914
915// ....
916
917
918//=======================================================================
919//function : ReadXY
920//purpose :
921//=======================================================================
922
923Standard_Boolean StepData_StepReaderData::ReadXY(const Standard_Integer num,
924 const Standard_Integer nump,
925 const Standard_CString mess,
926 Handle(Interface_Check)& ach,
927 Standard_Real& X, Standard_Real& Y) const
928{
929 Handle(String) errmess; // Null si pas d erreur
930 Standard_Integer numsub = SubListNumber(num,nump,Standard_False);
931 if (numsub != 0) {
932 if (NbParams(numsub) == 2) {
933 const Interface_FileParameter& FPX = Param(numsub,1);
934 if (FPX.ParamType() == Interface_ParamReal) X =
935 Interface_FileReaderData::Fastof(FPX.CValue());
936 else errmess = new String("Parameter n0.%d (%s) : (X,Y) X not a Real");
937
938 const Interface_FileParameter& FPY = Param(numsub,2);
939 if (FPY.ParamType() == Interface_ParamReal) Y =
940 Interface_FileReaderData::Fastof( FPY.CValue());
941 else errmess = new String("Parameter n0.%d (%s) : (X,Y) Y not a Real");
942
943 }
944 else errmess = new String("Parameter n0.%d (%s) : (X,Y) has not 2 params");
945 }
946 else errmess = new String("Parameter n0.%d (%s) : (X,Y) not a SubList");
947
948 if (errmess.IsNull()) return Standard_True;
949 sprintf (txtmes,errmess->ToCString(),nump,mess);
950 ach->AddFail(txtmes,errmess->ToCString());
951 return Standard_False;
952}
953
954
955//=======================================================================
956//function : ReadXYZ
957//purpose :
958//=======================================================================
959
960Standard_Boolean StepData_StepReaderData::ReadXYZ(const Standard_Integer num,
961 const Standard_Integer nump,
962 const Standard_CString mess,
963 Handle(Interface_Check)& ach,
964 Standard_Real& X, Standard_Real& Y,
965 Standard_Real& Z) const
966{
967 Handle(String) errmess; // Null si pas d erreur
968 Standard_Integer numsub = SubListNumber(num,nump,Standard_False);
969 if (numsub != 0) {
970 if (NbParams(numsub) == 3) {
971 const Interface_FileParameter& FPX = Param(numsub,1);
972 if (FPX.ParamType() == Interface_ParamReal) X =
973 Interface_FileReaderData::Fastof(FPX.CValue());
974 else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) X not a Real");
975
976 const Interface_FileParameter& FPY = Param(numsub,2);
977 if (FPY.ParamType() == Interface_ParamReal) Y =
978 Interface_FileReaderData::Fastof(FPY.CValue());
979 else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) Y not a Real");
980
981 const Interface_FileParameter& FPZ = Param(numsub,3);
982 if (FPZ.ParamType() == Interface_ParamReal) Z =
983 Interface_FileReaderData::Fastof(FPZ.CValue());
984 else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) Z not a Real");
985
986 }
987 else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) has not 3 params");
988 }
989 else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) not a SubList");
990
991 if (errmess.IsNull()) return Standard_True;
992 sprintf (txtmes,errmess->ToCString(),nump,mess);
993 ach->AddFail(txtmes,errmess->ToCString());
994 return Standard_False;
995}
996
997
998//=======================================================================
999//function : ReadReal
1000//purpose :
1001//=======================================================================
1002
1003Standard_Boolean StepData_StepReaderData::ReadReal(const Standard_Integer num,
1004 const Standard_Integer nump,
1005 const Standard_CString mess,
1006 Handle(Interface_Check)& ach,
1007 Standard_Real& val) const
1008{
1009 Handle(String) errmess; // Null si pas d erreur
1010 if (nump > 0 && nump <= NbParams(num)) {
1011 const Interface_FileParameter& FP = Param(num,nump);
1012 if (FP.ParamType() == Interface_ParamReal) val =
1013 Interface_FileReaderData::Fastof(FP.CValue());
1014 else errmess = new String("Parameter n0.%d (%s) not a Real");
1015 }
1016 else errmess = new String("Parameter n0.%d (%s) absent");
1017
1018 if (errmess.IsNull()) return Standard_True;
1019 sprintf (txtmes,errmess->ToCString(),nump,mess);
1020 ach->AddFail(txtmes,errmess->ToCString());
1021 return Standard_False;
1022}
1023
1024
1025// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
1026
1027
1028//=======================================================================
1029//function : ReadEntity
1030//purpose :
1031//=======================================================================
1032
1033Standard_Boolean StepData_StepReaderData::ReadEntity(const Standard_Integer num,
1034 const Standard_Integer nump,
1035 const Standard_CString mess,
1036 Handle(Interface_Check)& ach,
1037 const Handle(Standard_Type)& atype,
1038 Handle(Standard_Transient)& ent) const
1039{
1040 Handle(String) errmess; // Null si pas d erreur
1041 Standard_Boolean warn = Standard_False;
1042 if (nump > 0 && nump <= NbParams(num)) {
1043 const Interface_FileParameter& FP = Param(num,nump);
1044 Standard_Integer nent = FP.EntityNumber();
1045 if (FP.ParamType() == Interface_ParamIdent) {
1046 warn = (acceptvoid > 0);
1047 if (nent > 0) {
1048 Handle(Standard_Transient) entent = BoundEntity(nent);
1049 if (entent.IsNull() || !entent->IsKind(atype))
1050 errmess = new String("Parameter n0.%d (%s) : Entity has illegal type");
1051 else ent = entent;
1052 }
1053 else errmess = new String("Parameter n0.%d (%s) : Unresolved reference");
1054 }
1055 else {
1056 if (acceptvoid && FP.ParamType() == Interface_ParamVoid) warn = Standard_True;
1057 errmess = new String("Parameter n0.%d (%s) not an Entity");
1058 }
1059 }
1060 else {
1061 warn = (acceptvoid > 0);
1062 errmess = new String("Parameter n0.%d (%s) absent");
1063 }
1064
1065 if (errmess.IsNull()) return Standard_True;
1066 sprintf (txtmes,errmess->ToCString(),nump,mess);
1067 if (warn) ach->AddWarning(txtmes,errmess->ToCString());
1068 else ach->AddFail(txtmes,errmess->ToCString());
1069 return Standard_False;
1070}
1071
1072
1073//=======================================================================
1074//function : ReadEntity
1075//purpose :
1076//=======================================================================
1077
1078Standard_Boolean StepData_StepReaderData::ReadEntity(const Standard_Integer num,
1079 const Standard_Integer nump,
1080 const Standard_CString mess,
1081 Handle(Interface_Check)& ach,
1082 StepData_SelectType& sel) const
1083{
1084 Handle(String) errmess; // Null si pas d erreur
1085 Standard_Boolean warn = Standard_False;
1086 if (nump > 0 && nump <= NbParams(num)) {
1087 const Interface_FileParameter& FP = Param(num,nump);
1088 Standard_Integer nent = FP.EntityNumber();
1089 if (FP.ParamType() == Interface_ParamIdent) {
1090 warn = (acceptvoid > 0);
1091 if (nent > 0) {
1092 Handle(Standard_Transient) entent = BoundEntity(nent);
1093 if (!sel.Matches(entent))
1094 errmess = new String("Parameter n0.%d (%s) : Entity has illegal type");
1095 else
1096 sel.SetValue(entent);
1097 }
1098 else
1099 errmess = new String("Parameter n0.%d (%s) : Unresolved reference");
1100 }
1101 else if (FP.ParamType() == Interface_ParamVoid) {
1102 if (acceptvoid) warn = Standard_True;
1103 errmess = new String("Parameter n0.%d (%s) not an Entity");
1104 }
1105 else {
1106 // Cas restant : on s interesse en fait au SelectMember ...
1107 Handle(Standard_Transient) sm = sel.NewMember();
1108 // SelectMember qui assure ce role. Peut etre specialise
1109 if (!ReadAny (num,nump,mess,ach,sel.Description(),sm))
1110 errmess = new String("Parameter n0.%d (%s) : could not be read");
1111 if (!sel.Matches(sm))
1112 errmess = new String("Parameter n0.%d (%s) : illegal parameter type");
1113 else
1114 sel.SetValue(sm);
1115 }
1116 }
1117 else {
1118 warn = (acceptvoid > 0);
1119 errmess = new String("Parameter n0.%d (%s) absent");
1120 }
1121
1122 if (errmess.IsNull()) return Standard_True;
1123 sprintf (txtmes,errmess->ToCString(),nump,mess);
1124 if (warn) ach->AddWarning(txtmes,errmess->ToCString());
1125 else ach->AddFail(txtmes,errmess->ToCString());
1126 return Standard_False;
1127}
1128
1129
1130// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
1131
1132
1133//=======================================================================
1134//function : ReadInteger
1135//purpose :
1136//=======================================================================
1137
1138Standard_Boolean StepData_StepReaderData::ReadInteger(const Standard_Integer num,
1139 const Standard_Integer nump,
1140 const Standard_CString mess,
1141 Handle(Interface_Check)& ach,
1142 Standard_Integer& val) const
1143{
1144 Handle(String) errmess; // Null si pas d erreur
1145 if (nump > 0 && nump <= NbParams(num)) {
1146 const Interface_FileParameter& FP = Param(num,nump);
1147 if (FP.ParamType() == Interface_ParamInteger) val = atoi(FP.CValue());
1148 else errmess = new String("Parameter n0.%d (%s) not an Integer");
1149 }
1150 else errmess = new String("Parameter n0.%d (%s) absent");
1151
1152 if (errmess.IsNull()) return Standard_True;
1153 sprintf (txtmes,errmess->ToCString(),nump,mess);
1154 ach->AddFail(txtmes,errmess->ToCString());
1155 return Standard_False;
1156}
1157
1158
1159//=======================================================================
1160//function : ReadBoolean
1161//purpose :
1162//=======================================================================
1163
1164Standard_Boolean StepData_StepReaderData::ReadBoolean(const Standard_Integer num,
1165 const Standard_Integer nump,
1166 const Standard_CString mess,
1167 Handle(Interface_Check)& ach,
1168 Standard_Boolean& flag) const
1169{
1170 Handle(String) errmess; // Null si pas d erreur
1171 if (nump > 0 && nump <= NbParams(num)) {
1172 const Interface_FileParameter& FP = Param(num,nump);
1173 if (FP.ParamType() == Interface_ParamEnum) {
1174 Standard_CString txt = FP.CValue();
1175 if (!strcmp(txt,".T.")) flag = Standard_True;
1176 else if (!strcmp(txt,".F.")) flag = Standard_False;
1177 else errmess = new String("Parameter n0.%d (%s) : Incorrect Boolean Value");
1178 }
1179 else errmess = new String("Parameter n0.%d (%s) not a Boolean");
1180 }
1181 else errmess = new String("Parameter n0.%d (%s) absent");
1182
1183 if (errmess.IsNull()) return Standard_True;
1184 sprintf (txtmes,errmess->ToCString(),nump,mess);
1185 ach->AddFail(txtmes,errmess->ToCString());
1186 return Standard_False;
1187}
1188
1189
1190//=======================================================================
1191//function : ReadLogical
1192//purpose :
1193//=======================================================================
1194
1195Standard_Boolean StepData_StepReaderData::ReadLogical(const Standard_Integer num,
1196 const Standard_Integer nump,
1197 const Standard_CString mess,
1198 Handle(Interface_Check)& ach,
1199 StepData_Logical& flag) const
1200{
1201 Handle(String) errmess; // Null si pas d erreur
1202 if (nump > 0 && nump <= NbParams(num)) {
1203 const Interface_FileParameter& FP = Param(num,nump);
1204 if (FP.ParamType() == Interface_ParamEnum) {
1205 Standard_CString txt = FP.CValue();
1206 if (!strcmp(txt,".T.")) flag = StepData_LTrue;
1207 else if (!strcmp(txt,".F.")) flag = StepData_LFalse;
1208 else if (!strcmp(txt,".U.")) flag = StepData_LUnknown;
1209 else errmess = new String("Parameter n0.%d (%s) : Incorrect Logical Value");
1210 }
1211 else errmess = new String("Parameter n0.%d (%s) not a Logical");
1212 }
1213 else errmess = new String("Parameter n0.%d (%s) absent");
1214
1215 if (errmess.IsNull()) return Standard_True;
1216 sprintf (txtmes,errmess->ToCString(),nump,mess);
1217 ach->AddFail(txtmes,errmess->ToCString());
1218 return Standard_False;
1219}
1220
1221
1222//=======================================================================
1223//function : ReadString
1224//purpose :
1225//=======================================================================
1226
1227Standard_Boolean StepData_StepReaderData::ReadString(const Standard_Integer num,
1228 const Standard_Integer nump,
1229 const Standard_CString mess,
1230 Handle(Interface_Check)& ach,
1231 Handle(TCollection_HAsciiString)& val) const
1232{
1233 Handle(String) errmess; // Null si pas d erreur
1234 Standard_Boolean warn = Standard_False;
1235 if (nump > 0 && nump <= NbParams(num)) {
1236 const Interface_FileParameter& FP = Param(num,nump);
1237 if (FP.ParamType() == Interface_ParamText) {
1238 /*Standard_CString anStr = FP.CValue();
1239 if(strlen(anStr) < 3)
1240 val = new TCollection_HAsciiString("");
1241 else {
1242 val = new TCollection_HAsciiString(FP.CValue());
1243 CleanText (val);
1244 }*/
1245 val = new TCollection_HAsciiString(FP.CValue());
1246 CleanText (val);
1247 } else {
1248 if (acceptvoid && FP.ParamType() == Interface_ParamVoid) warn = Standard_True;
1249 errmess = new String("Parameter n0.%d (%s) not a quoted String");
1250 }
1251 }
1252 else errmess = new String("Parameter n0.%d (%s) absent");
1253
1254 if (errmess.IsNull()) return Standard_True;
1255 sprintf (txtmes,errmess->ToCString(),nump,mess);
1256 if (warn) ach->AddWarning(txtmes,errmess->ToCString());
1257 else ach->AddFail(txtmes,errmess->ToCString());
1258 return Standard_False;
1259}
1260
1261
1262//=======================================================================
1263//function : ReadEnumParam
1264//purpose :
1265//=======================================================================
1266
1267Standard_Boolean StepData_StepReaderData::ReadEnumParam(const Standard_Integer num,
1268 const Standard_Integer nump,
1269 const Standard_CString mess,
1270 Handle(Interface_Check)& ach,
1271 Standard_CString& text) const
1272{
1273 Handle(String) errmess; // Null si pas d erreur
1274 Standard_Boolean warn = Standard_False;
1275 if (nump > 0 && nump <= NbParams(num)) {
1276 const Interface_FileParameter& FP = Param(num,nump);
1277 if (FP.ParamType() == Interface_ParamEnum) {
1278 text = FP.CValue();
1279 warn = (acceptvoid > 0);
1280 } else if (FP.ParamType() == Interface_ParamVoid) {
1281 errmess =
1282 new String("Parameter n0.%d (%s) : Undefined Enumeration not allowed");
1283 warn = (acceptvoid > 0);
1284 }
1285 else errmess = new String("Parameter n0.%d (%s) not an Enumeration");
1286 }
1287 else errmess = new String("Parameter n0.%d (%s) absent");
1288
1289 if (errmess.IsNull()) return Standard_True;
1290 sprintf (txtmes,errmess->ToCString(),nump,mess);
1291 if (warn) ach->AddWarning(txtmes,errmess->ToCString());
1292 else ach->AddFail(txtmes,errmess->ToCString());
1293 return Standard_False;
1294}
1295
1296
1297//=======================================================================
1298//function : FailEnumValue
1299//purpose :
1300//=======================================================================
1301
1302void StepData_StepReaderData::FailEnumValue(const Standard_Integer /* num */,
1303 const Standard_Integer nump,
1304 const Standard_CString mess,
1305 Handle(Interface_Check)& ach) const
1306{
1307 Handle(String) errmess =
1308 new String("Parameter n0.%d (%s) : Incorrect Enumeration Value");
1309 sprintf (txtmes,errmess->ToCString(),nump,mess);
1310 ach->AddFail(txtmes,errmess->ToCString());
1311}
1312
1313
1314//=======================================================================
1315//function : ReadEnum
1316//purpose :
1317//=======================================================================
1318
1319Standard_Boolean StepData_StepReaderData::ReadEnum(const Standard_Integer num,
1320 const Standard_Integer nump,
1321 const Standard_CString mess,
1322 Handle(Interface_Check)& ach,
1323 const StepData_EnumTool& enumtool,
1324 Standard_Integer& val) const
1325{
1326// reprendre avec ReadEnumParam ?
1327 Handle(String) errmess; // Null si pas d erreur
1328 Standard_Boolean warn = Standard_False;
1329 if (nump > 0 && nump <= NbParams(num)) {
1330 const Interface_FileParameter& FP = Param(num,nump);
1331 if (FP.ParamType() == Interface_ParamEnum) {
1332 val = enumtool.Value (FP.CValue());
1333 if (val >= 0) return Standard_True;
1334 else errmess = new String("Parameter n0.%d (%s) : Incorrect Enumeration Value");
1335 warn = (acceptvoid > 0);
1336 }
1337 else if (FP.ParamType() == Interface_ParamVoid) {
1338 val = enumtool.NullValue();
1339 if (val < 0) errmess =
1340 new String("Parameter n0.%d (%s) : Undefined Enumeration not allowed");
1341 warn = (acceptvoid > 0);
1342 }
1343 else errmess = new String("Parameter n0.%d (%s) not an Enumeration");
1344 }
1345 else errmess = new String("Parameter n0.%d (%s) absent");
1346
1347 if (errmess.IsNull()) return Standard_True;
1348 sprintf (txtmes,errmess->ToCString(),nump,mess);
1349 if (warn)
1350 ach->AddWarning(txtmes,errmess->ToCString());
1351 else
1352 ach->AddFail(txtmes,errmess->ToCString());
1353 return Standard_False;
1354}
1355
1356
1357//=======================================================================
1358//function : ReadTypedParam
1359//purpose :
1360//=======================================================================
1361
1362Standard_Boolean StepData_StepReaderData::ReadTypedParam(const Standard_Integer num,
1363 const Standard_Integer nump,
1364 const Standard_Boolean mustbetyped,
1365 const Standard_CString mess,
1366 Handle(Interface_Check)& ach,
1367 Standard_Integer& numr,
1368 Standard_Integer& numrp,
1369 TCollection_AsciiString& typ) const
1370{
1371 Handle(String) errmess; // Null si pas d erreur
1372 if (nump > 0 && nump <= NbParams(num)) {
1373 const Interface_FileParameter& FP = Param(num,nump);
1374 if (FP.ParamType() != Interface_ParamSub) {
1375 // Pas une sous-liste : OK si admis
1376 numr = num; numrp = nump; typ.Clear();
1377 if (mustbetyped) {
1378 errmess = new String("Parameter n0.%d (%s) : single, not typed");
1379 sprintf (txtmes,errmess->ToCString(),nump,mess);
1380 ach->AddFail(txtmes,errmess->ToCString());
1381 return Standard_False;
1382 }
1383 return Standard_True;
1384 }
1385 numr = FP.EntityNumber(); numrp = 1;
1386 if (NbParams(numr) != 1) errmess =
1387 new String("Parameter n0.%d (%s) : SubList, not typed");
1388 typ = RecordType(numr);
1389 }
1390 else errmess = new String("Parameter n0.%d (%s) absent");
1391
1392 if (errmess.IsNull()) return Standard_True;
1393 sprintf (txtmes,errmess->ToCString(),nump,mess);
1394 ach->AddFail(txtmes,errmess->ToCString());
1395 return Standard_False;
1396}
1397
1398
1399//=======================================================================
1400//function : CheckDerived
1401//purpose :
1402//=======================================================================
1403
1404Standard_Boolean StepData_StepReaderData::CheckDerived(const Standard_Integer num,
1405 const Standard_Integer nump,
1406 const Standard_CString mess,
1407 Handle(Interface_Check)& ach,
1408 const Standard_Boolean errstat) const
1409{
1410 Handle(String) errmess; // Null si pas d erreur
1411 Standard_Boolean warn = !errstat;
1412 if (nump > 0 && nump <= NbParams(num)) {
1413 if (!strcmp(Param(num,nump).CValue(),"*")) return Standard_True;
1414 else errmess = new String("Parameter n0.%d (%s) not Derived");
1415 if (acceptvoid) warn = Standard_True;
1416 }
1417 else errmess = new String("Parameter n0.%d (%s) absent");
1418
1419 if (errmess.IsNull()) return Standard_True;
1420 sprintf (txtmes,errmess->ToCString(),nump,mess);
1421 if (warn) ach->AddWarning (txtmes,errmess->ToCString());
1422 else ach->AddFail (txtmes,errmess->ToCString());
1423 return Standard_False;
1424}
1425
1426
1427// #########################################################################
1428// .... Methodes specifiques (demandees par FileReaderData) .... //
1429
1430
1431//=======================================================================
1432//function : NbEntities
1433//purpose :
1434//=======================================================================
1435
1436Standard_Integer StepData_StepReaderData::NbEntities () const // redefined
1437{
1438 return thenbents;
1439}
1440
1441
1442//=======================================================================
1443//function : FindNextRecord
1444//purpose :
1445//=======================================================================
1446
1447Standard_Integer StepData_StepReaderData::FindNextRecord
1448 (const Standard_Integer num) const
1449{
1450 // retourne, sur un numero d enregistrement donne (par num), le suivant qui
1451 // definit une entite, ou 0 si c est fini :
1452 // passe le Header (nbhend premiers records) et
1453 // saute les enregistrements SCOPE et ENDSCOPE et les SOUS-LISTES
1454
1455 if (num < 0) return 0 ;
1456 Standard_Integer num1 = num + 1 ; if (num == 0) num1 = thenbhead + 1;
1457 Standard_Integer max = NbRecords() ;
1458
1459 while (num1 <= max ) {
1460 if (theidents(num1) > 0) return num1;
1461
1462 // SCOPE,ENDSCOPE et Sous-Liste ont un identifieur fictif: -1,-2 respectivement
1463 // et SUBLIST ont un negatif. Seule une vraie entite a un Ident positif
1464 num1 ++ ;
1465 }
1466 return 0;
1467}
1468
1469
1470//=======================================================================
1471//function : FindEntityNumber
1472//purpose :
1473//=======================================================================
1474
1475Standard_Integer StepData_StepReaderData::FindEntityNumber(const Standard_Integer num,
1476 const Standard_Integer id) const
1477{
1478 // Soit un "Id" : recherche dans les Parametres de type Ident de <num>,
1479 // si un d eux designe #Id justement. Si oui, retourne son EntityNumber
1480 if (num == 0) return 0;
1481 Standard_Integer nb = NbParams(num);
1482 for (Standard_Integer i = 1; i <= nb; i ++) {
1483 const Interface_FileParameter& FP = Param(num,i);
1484 if (FP.ParamType() != Interface_ParamIdent) continue;
1485 Standard_Integer ixp = atoi( &FP.CValue()[1] );
1486 if (ixp == id) return FP.EntityNumber();
1487 }
1488 return 0; // ici, pas trouve
1489}
1490
1491
1492// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
1493// .... La fonction qui suit merite une attention speciale ....
1494
1495
1496// Cette methode precharge les EntityNumbers dans les Params : ils designent
1497// les Entites proprement dites dans la liste lue par BoundEntity
1498// Interet : adresse de meme les sous-listes (Num->no record dans le Direc)
1499// resultat exploite par ParamEntity et ParamNumber
1500
1501// En l absence de SCOPE, ou si les "ident" sont strictement ordonnes, a coup
1502// sur ils ne sont pas dupliques, on peut utiliser une IndexedMap en toute
1503// confiance. Sinon, il faut balayer dans le fichier, mais avec les SCOPES
1504// cela va beaucoup plus vite (s ils sont assez gros) : on s y retrouve.
1505
1506// Pour la recherche par balayage, On opere en plusieurs etapes
1507// Avant toute chose, le chargement a deja fait une preparation : les idents
1508// (Entity, SubList) sont deja en entiers (rapidite de lecture), en particulier
1509// dans les EntityNumber : ainsi, on lit cet ident, on le traite, et on remet
1510// a la place un vrai numero de Record
1511//
1512// D abord, on passe le directory en table d entiers, sous-listes expurgees
1513// en // , table inverse vers cette table, car les sous-listes peuvent par
1514// contre designer des objets ...
1515
1516// Pour les sous-listes, on exploite leur mode de construction : elles sont
1517// enregistrees AVANT d etre referencees. Un tableau "subn" note donc pour
1518// chaque numero de sous-liste (relatif a une entite qui suit, et reference
1519// par elle ou une autre sous-liste qui suit egalement), son n0 de record
1520// REMARQUE : ceci marche aussi pour le Header, traite par l occasion
1521
1522
1523//=======================================================================
1524//function : SetEntityNumbers
1525//purpose :
1526//=======================================================================
1527
1528void StepData_StepReaderData::SetEntityNumbers(const Standard_Boolean withmap)
1529{
1530 Handle(Message_Messenger) sout = Message::DefaultMessenger();
1531// Passe initiale : Resolution directe par Map
1532// si tout passe (pas de collision), OK. Sinon, autres passes a prevoir
1533// On resoud du meme coup les sous-listes
1534 Standard_Integer nbdirec = NbRecords() ;
1d37eeb6 1535 TColStd_Array1OfInteger subn(0, thelastn);
7fd59977 1536
1537 Standard_Boolean pbmap = Standard_False; // au moins un conflit
1538 Standard_Integer nbmap = 0;
1539 TColStd_IndexedMapOfInteger imap(thenbents);
1d37eeb6 1540 TColStd_Array1OfInteger indm(0, nbdirec); // Index Map -> Record Number (seulement si map)
7fd59977 1541
1542 Standard_Integer num; // svv Jan11 2000 : porting on DEC
1543 for (num = 1 ; num <= nbdirec ; num ++) {
1544 Standard_Integer ident = theidents(num);
1545 if (ident > 0) { // Ident normal -> Map ?
1546// Map : si Recouvrement, l inhiber. Sinon, noter index
1547 Standard_Integer indmap = imap.Add(ident);
1548 if (indmap <= nbmap) {
1549 indmap = imap.FindIndex(ident); // plus sur
1d37eeb6 1550 indm(indmap) = -1; // Map -> pb
7fd59977 1551 pbmap = Standard_True;
1552// pbmap signifie qu une autre passe sera necessaire ...
1553 } else {
1554 nbmap = indmap;
1d37eeb6 1555 indm(indmap) = num; // Map ->ident
7fd59977 1556 }
1557 }
1558 }
1559
1560 for (num = 1 ; num <= nbdirec ; num ++) {
1561 Standard_Integer ident = theidents(num);
1d37eeb6 1562 if (ident < -2) subn(-(ident+2)) = num; // toujours a jour ...
7fd59977 1563
1564 Standard_Integer nba = NbParams(num) ;
1565 Standard_Integer nda = (num == 1 ? 0 : ParamFirstRank(num-1));
1566
1567 for (Standard_Integer na = nba ; na > 0 ; na --) {
1568// On traite : les sous-listes (sf subn), les idents (si Map dit OK ...)
1569 Interface_FileParameter& FP = ChangeParameter (nda+na);
1570// Interface_FileParameter& FP = ChangeParam (num,na);
1571 Interface_ParamType letype = FP.ParamType();
1572 if (letype == Interface_ParamSub) {
1573 Standard_Integer numsub = FP.EntityNumber();
1574 if (numsub > thelastn) {
1575 sout<<"Bad Sub.N0, Record "<<num<<" Param "<<na<<":$"<<numsub<<endl;
1576 continue;
1577 }
1d37eeb6 1578 FP.SetEntityNumber(subn(numsub));
7fd59977 1579 } else if (letype == Interface_ParamIdent) {
1580 Standard_Integer id = FP.EntityNumber();
1581 Standard_Integer indmap = imap.FindIndex(id);
1582 if (indmap > 0) { // la map a trouve
1d37eeb6 1583 Standard_Integer num0 = indm(indmap);
7fd59977 1584 if (num0 > 0) FP.SetEntityNumber(num0); // ET VOILA, on a resolu
1585 else FP.SetEntityNumber(-id); // CONFLIT -> faudra resoudre ...
1586 } else { // NON RESOLU, si pas pbmap, le dire
1587 FP.SetEntityNumber(-id);
1588 if (pbmap) continue; // pbmap : on se retrouvera
1589 char failmess[100];
1590// ... Construire le Check ...
1591 sprintf(failmess,
1592 "Unresolved Reference, Ent.Id.#%d Param.n0 %d (Id.#%d)",
1593 ident,na,id);
1594 thecheck->AddFail(failmess,"Unresolved Reference");
1595// ... Et sortir message un peu plus complet
1596 sout << "*** ERR StepReaderData *** Pour Entite #"<< ident
1597 << "\n Type:" << RecordType(num)
1598 << " Param.n0 " << na << ": #" << id << " Non trouve" << endl ;
1599 } // FIN Mapping
1600 } // FIN Traitement Reference
1601 } // FIN Boucle Parametres
1602 } // FIN Boucle Repertoires
1603
7fd59977 1604 if (!pbmap) {
1d37eeb6 1605 return;
7fd59977 1606 }
1607 sout << " -- 2nd pass required --";
1608
1609 Standard_Integer nbseq = thenbents+2*thenbscop;
1d37eeb6
D
1610 TColStd_Array1OfInteger inds(0, nbseq); // n0 Record/Entite
1611 TColStd_Array1OfInteger indi(0, nbseq); // Idents/scopes
1612 TColStd_Array1OfInteger indr(0, nbdirec); // inverse de nds
1613 Handle(TColStd_HArray1OfInteger) indx; // pour EXPORT (silya)
7fd59977 1614
1615 imap.Clear();
1616 Standard_Boolean iamap = withmap; // (par defaut True)
1617 nbmap = 0;
1618
1619 TColStd_SequenceOfInteger scopile; // chainage des scopes note par pile
1620 Standard_Integer nr = 0 ;
1621 for (num = 1 ; num <= nbdirec ; num ++) {
1622 Standard_Integer ident = theidents(num);
1623 if (ident < -2) { // SOUS-LISTE (cas le plus courant)
1d37eeb6 1624 indr(num) = nr + 1; // recherche basee sur nr (objet qui suit)
7fd59977 1625 } else if (ident >= 0) { // Ident normal
1d37eeb6 1626 nr ++; inds(nr) = num; indi(nr) = ident; indr(num) = nr;
7fd59977 1627 if (ident > 0) { // et non (iamap && ident > 0)
1628// Map : si Recouvrement, l inhiber. Sinon, noter index
1629 Standard_Integer indmap = imap.Add(ident);
1630 if (indmap <= nbmap) {
1631 Standard_Boolean errorscope = Standard_False;
1632 indmap = imap.FindIndex(ident); // plus sur
1633 pbmap = Standard_True;
1634 if (thenbscop == 0) errorscope = Standard_True;
1635// Numeros identiques alors quilnya pas de SCOPE ? ERREUR !
1636// (Bien sur, silya des SCOPES, on passe au travers, mais bon...)
1637 else {
1638// Silya des SCOPES, tachons d y voir de plus pres pour signaler un probleme
1639// Erreur si MEME groupe SCOPE
1640// ATTENTION, on recherche, non dans tous les records, mais dans les records
1641// CHAINES, cf nr et non num (pas de sous-liste, chainage scope-endscope)
1642 Standard_Integer fromscope = nr;
1d37eeb6 1643 Standard_Integer toscope = indm(indmap);
7fd59977 1644 if (toscope < 0) toscope = -toscope;
302f96fb 1645 for(;;) {
7fd59977 1646 fromscope --; // iteration de base
1647 if (fromscope <= toscope) {
1648 errorscope = Standard_True; // BANG, on est dessus
1649 break;
1650 }
1d37eeb6 1651 Standard_Integer idtest = indi(fromscope);
7fd59977 1652 if (idtest >= 0) continue; // le suivant (enfin, le precedent)
1653 if (idtest == -1) break; // pas meme niveau, donc c est OK
1654 if (idtest == -3) {
1d37eeb6 1655 fromscope = inds(fromscope);
7fd59977 1656 if (fromscope < toscope) break; // on sort, pas en meme niveau
1657 }
1658 }
1659 }
1660 if (errorscope) {
1661// On est dedans : le signaler
1662 char ligne[80];
1663 sprintf(ligne,"Ident defined SEVERAL TIMES : #%d",ident);
1664 thecheck->AddFail(ligne,"Ident defined SEVERAL TIMES : #%d");
1665 sout << "StepReaderData:SetEntityNumbers, " << ligne << endl;
1666 }
1d37eeb6 1667 if (indm(indmap) > 0) indm(indmap) = -indm(indmap); // Pas pour Map
7fd59977 1668// Cas Normal pour la Map
1669 } else {
1670 nbmap = indmap;
1d37eeb6 1671 indm(indmap) = nr; // Map ->(indm)->inds
7fd59977 1672 }
1673 }
1674 } else if (ident == -1) { // SCOPE
1d37eeb6 1675 nr ++; inds(nr) = num; indi(nr) = -1; indr(num) = 0;
7fd59977 1676 scopile.Append(nr) ;
1677 } else if (ident == -2) { // ENDSCOPE
1678 Standard_Integer nscop = scopile.Last() ; // chainage SCOPE-ENDSCOPE
1679 scopile.Remove(scopile.Length()) ;
1d37eeb6 1680 nr ++; inds(nr) = nscop; indi(nr) = -3; indr(num) = 0; inds(nscop) = nr;
7fd59977 1681 if (NbParams(num) > 0) {
1682// EXPORT : traitement special greffe sur celui de SCOPE (sans le perturber)
1d37eeb6
D
1683 if (indx.IsNull()) {
1684 indx = new TColStd_HArray1OfInteger(0, nbseq);
1685 for (Standard_Integer ixp = 0; ixp <= nbseq; ixp ++) indx->ChangeValue(ixp) = 0;
7fd59977 1686 }
1d37eeb6 1687 indx->ChangeValue(nr) = num; indx->ChangeValue(nscop) = num;
7fd59977 1688 }
1689 } else if (ident == 0) { // HEADER
1d37eeb6 1690 indr(num) = 0;
7fd59977 1691 }
1692 }
1693
1694// .. Resolution des EXPORT, silyena et silya besoin ..
1695// Pour chaque valeur de EXPORT qui n a pas ete resolue par la MAP,
1696// determiner sa position locale par recherche en arriere depuis ENDSCOPE
1d37eeb6 1697 if ((!iamap || pbmap) && !indx.IsNull()) {
7fd59977 1698 for (nr = 0; nr <= nbseq; nr ++) {
1d37eeb6
D
1699 if (indx->Value(nr) == 0 && indi(nr) != -3) continue; // ENDSCOPE + EXPORT
1700 num = indx->Value(nr);
7fd59977 1701 Standard_Integer nba = NbParams(num);
1702 for (Standard_Integer na = 1; na <= nba; na ++) {
1703 Interface_FileParameter& FP = ChangeParam (num,na);
1704 if (FP.ParamType() != Interface_ParamIdent) continue;
1705 Standard_Integer id = - FP.EntityNumber();
1706 if (id < 0) continue; // deja resolu en tete
1707/* if (imap.Contains(id)) { et voila
1d37eeb6 1708 FP.SetEntityNumber(indm(imap.FindIndex(id)));
7fd59977 1709 continue;
1710 } */
1711
1712// Recherche du Id demande : si EXPORT imbrique, deja resolu mais il faut
1713// regarder ! (inutile par contre d aller y voir : c est deja fait, car
1714// un EXPORT imbrique a ete traite AVANT celui qui imbrique)
1715 Standard_Integer n0 = nr-1 ;
1d37eeb6 1716 if (indi(n0) == -3) n0 --; // si on suit juste un ENDSCOPE
7fd59977 1717 while (n0 > 0) {
1d37eeb6 1718 Standard_Integer irec = indi(n0);
7fd59977 1719 if (irec == id) { // trouve
1d37eeb6 1720 FP.SetEntityNumber(inds(n0));
7fd59977 1721 break ;
1722 }
1723 if (irec == -1) break; // SCOPE : fin de ce SCOPE/ENDSCOPE
1724 if (irec == -3) {
1725// gare a EXPORT : si un EXPORT detient Id, noter son Numero deja calcule
1726// Attention : Id a lire depuis CValue car EntityNumber deja resolu
1d37eeb6 1727 Standard_Integer nok = FindEntityNumber (indx->Value(n0),id);
7fd59977 1728 if (nok > 0) {
1729 FP.SetEntityNumber(nok);
1730 break;
1731 }
1d37eeb6 1732 n0 = inds(n0); // ENDSCOPE ou EXPORT infructueux : le sauter
7fd59977 1733 } // fin traitement sur un ENDSCOPE ou EXPORT
1734 n0 -- ;
1735 } // fin resolution d un Parametre EXPORT
1736 } // fin resolution de la liste d un EXPORT
1737 } // fin bouclage sur les EXPORT
1738 }
1739
1740// Exploitation de la table : bouclage porte sur la table
1741
1742// Traitement des sous-listes : se fait dans la foulee, par gestion d une pile
1743// basee sur la constitution des sous-listes
1744 Standard_Integer maxsubpil = 30; // pile simulee avec un Array : tres fort
1745 Handle(TColStd_HArray1OfInteger) subpile = // ... gagne de la memoire ...
1746 new TColStd_HArray1OfInteger (1,maxsubpil);
1747 Standard_Integer nbsubpil = 0; // ... et tellement plus rapide !
1748
1749 for (num = 1 ; num <= nbdirec ; num ++) {
1d37eeb6 1750 nr = indr(num);
7fd59977 1751 if (nr == 0) continue; // pas un objet ou une sous-liste
1752 Standard_Integer nba = NbParams(num) ;
1753 for (Standard_Integer na = nba ; na > 0 ; na --) {
1754// On lit depuis la fin : cela permet de traiter les sous-listes dans la foulee
1755// Sinon, on devrait noter qu il y a eu des sous-listes et reprendre ensuite
1756
1757 Interface_FileParameter& FP = ChangeParam (num,na);
1758 Interface_ParamType letype = FP.ParamType();
1759 if (letype == Interface_ParamSub) {
1760// parametre type sous-liste : numero de la sous-liste lu par depilement
1761 FP.SetEntityNumber(subpile->Value(nbsubpil));
1762 nbsubpil --; // subpile->Remove(nbsubpil);
1763
1764 } else if (letype == Interface_ParamIdent) {
1765// parametre type ident (reference une entite) : chercher ident demande
1766 Standard_Integer id = - FP.EntityNumber();
1767 if (id < 0) continue; // deja resolu en tete
1768
1769// Voila : on va chercher id dans ndi; algorithme de balayage
1770 Standard_Integer pass, sens, nok, n0,irec; pass = sens = nok = 0;
1771 if (!iamap) pass = 1; // si map non disponible
1772 while (pass < 3) {
1773 pass ++ ;
1774// MAP disponible
1775 if (pass == 1) { // MAP DISPONIBLE
1776 Standard_Integer indmap = imap.FindIndex(id);
1777 if (indmap > 0) { // la map a trouve
1d37eeb6 1778 nok = indm(indmap);
7fd59977 1779 if (nok < 0) continue; // CONFLIT -> faut resoudre ...
1780 break;
1781 }
1782 else continue;
1783 }
1784// 1re Passe : REMONTEE -> Debut fichier
1785 if (sens == 0 && nr > 1) {
1786 n0 = nr-1 ;
1d37eeb6 1787 if (indi(n0) == -3) n0 --; // si on suit juste un ENDSCOPE
7fd59977 1788 while (n0 > 0) {
1d37eeb6 1789 irec = indi(n0);
7fd59977 1790 if (irec == id) { // trouve
1791 nok = n0 ; break ;
1792 }
1793// ENDSCOPE : Attention a EXPORT sinon sauter
1794 if (irec == -3) {
1d37eeb6 1795 if (indx.IsNull()) n0 = inds(n0);
7fd59977 1796 else {
1797// EXPORT, il faut regarder
1d37eeb6 1798 nok = FindEntityNumber (indx->Value(n0),id);
7fd59977 1799 if (nok > 0) break;
1d37eeb6 1800 n0 = inds(n0); // ENDSCOPE : le sauter
7fd59977 1801 }
1802 }
1803 n0 -- ;
1804 }
1805// 2me Passe : DESCENTE -> Fin fichier
1806 } else if (nr < nbseq) { // descente -> fin fichier
1807 n0 = nr+1 ;
1808 while (n0 <= nbseq) {
1d37eeb6 1809 irec = indi(n0);
7fd59977 1810 if (irec == id) { // trouve
1811 nok = n0 ; break ;
1812 }
1813// SCOPE : Attention a EXPORT sinon sauter
1814 if (irec == -1) {
1d37eeb6 1815 if (indx.IsNull()) n0 = inds(n0);
7fd59977 1816 else {
1817// EXPORT, il faut regarder
1d37eeb6 1818 nok = FindEntityNumber (indx->Value(n0),id);
7fd59977 1819 if (nok > 0) break;
1d37eeb6 1820 n0 = inds(n0); // SCOPE : le sauter
7fd59977 1821 }
1822 }
1823 n0 ++ ;
1824 }
1825 }
1826 if (nok > 0) break ;
1827 sens = 1 - sens ; // passe suivante
1828 }
1829 // ici on a nok, numero trouve
1830 if (nok > 0) {
1d37eeb6 1831 Standard_Integer num0 = inds(nok);
7fd59977 1832 FP.SetEntityNumber(num0); // ET VOILA, on a resolu
1833
1834 // pas trouve : le signaler
1835 } else {
1836// Alimenter le Check ... Pour cela, determiner n0 Entite et Ident
1837 char failmess[100];
1838 Standard_Integer nument = 0;
1839 Standard_Integer n0ent; // svv Jan11 2000 : porting on DEC
1840 for (n0ent = 1; n0ent <= nr; n0ent ++) {
1d37eeb6 1841 if (indi(n0ent) > 0) nument ++;
7fd59977 1842 }
1843 Standard_Integer ident = RecordIdent(num);
1844 if (ident < 0) {
1845 for (n0ent = num + 1; n0ent <= nbdirec; n0ent ++) {
1846 ident = RecordIdent(n0ent); if (ident > 0) break;
1847 }
1848 }
1849// ... Construire le Check ...
1850 sprintf(failmess,
1851 "Unresolved Reference, Ent.n0 %d (Id.#%d) Param.n0 %d (Id.#%d)",
1852 nument,ident,na,id);
1853 thecheck->AddFail(failmess,"Unresolved Reference");
1854// ... Et sortir message un peu plus complet
1855 sout << "*** ERR StepReaderData *** Pour Entite "<<nument
1856 <<", a "<< (nr*100)/nbseq<<"% de DATA : #"<< ident
1857 << "\n Type:" << RecordType(num)
1858 << " Param.n0 " << na << ": #" << id << " Non trouve" << endl ;
1859 FP.SetEntityNumber(0); // -> Reference non resolue
1860 }
1861 }
1862 }
1863// Si ce record est lui-meme une sous-liste, empiler !
1d37eeb6 1864 if (inds(nr) != num) {
7fd59977 1865 if (nbsubpil >= maxsubpil) {
1866 maxsubpil = maxsubpil+30;
1867 Handle(TColStd_HArray1OfInteger) newsubpil =
1868 new TColStd_HArray1OfInteger (1,maxsubpil);
1869 for (Standard_Integer bidpil = 1; bidpil <= maxsubpil - 30; bidpil ++)
1870 newsubpil->SetValue(bidpil,subpile->Value(bidpil));
1871 subpile = newsubpil;
1872 }
1873 nbsubpil ++;
1874 subpile->SetValue(nbsubpil,num); // Append(num);
1875 }
1876 }
7fd59977 1877}
1878
1879
1880// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
1881// .... Gestion du Header : Preparation, lecture ....
1882
1883
1884//=======================================================================
1885//function : FindNextHeaderRecord
1886//purpose :
1887//=======================================================================
1888
1889Standard_Integer StepData_StepReaderData::FindNextHeaderRecord
1890 (const Standard_Integer num) const
1891{
1892// retourne, sur un numero d enregistrement donne (par num), le suivant qui
1893// definit une entite, ou 0 si c est fini :
1894// Opere comme FindNextRecord mais ne balaie que le Header
1895
1896 if (num < 0) return 0 ;
1897 Standard_Integer num1 = num + 1 ;
1898 Standard_Integer max = thenbhead;
1899
1900 while (num1 <= max ) {
1901// SCOPE,ENDSCOPE et Sous-Liste ont un identifieur negatif
1902// Ne retenir que les Idents positifs ou nuls (nul : pas d Ident dans Header)
1903 if ( RecordIdent(num1) >= 0) return num1 ;
1904 num1 ++ ;
1905 }
1906 return 0;
1907}
1908
1909
1910//=======================================================================
1911//function : PrepareHeader
1912//purpose :
1913//=======================================================================
1914
1915void StepData_StepReaderData::PrepareHeader ()
1916{
1917// Resolution des references : ne concerne que les sous-listes
1918// deja faite par SetEntityNumbers donc pas de souci a se faire
1919
1920/*
1921// Algorithme repris et adapte de SetEntityNumbers
1922// Traitement des sous-listes : se fait dans la foulee, par gestion d une pile
1923// basee sur la constitution des sous-listes
1924 TColStd_SequenceOfInteger subpile;
1925 Standard_Integer nbsubpil = 0; // profondeur de pile mais plus rapide ...
1926
1927 for (Standard_Integer num = 1 ; num <= thenbhead ; num ++) {
1928 Standard_Integer nba = NbParams(num) ;
1929 for (Standard_Integer na = nba ; na > 0 ; na --) {
1930.. On lit depuis la fin : cela permet de traiter les sous-listes dans la foulee
1931.. Sinon, on devrait noter qu il y a eu des sous-listes et reprendre ensuite
1932
1933 Interface_FileParameter& FP = ChangeParam(num,na);
1934 Interface_ParamType letype = FP.ParamType();
1935 if (letype == Interface_ParamSub) {
1936.. parametre type sous-liste : numero de la sous-liste lu par depilement
1937 FP.SetEntityNumber(subpile.Last());
1938.. .. SetParam(num,na,FP);
1939 subpile.Remove(nbsubpil);
1940 nbsubpil --;
1941 }
1942 }
1943.. Si c est une sous-liste, empiler
1944 if (RecordIdent(num) < -2) {
1945 subpile.Append(num);
1946 nbsubpil ++;
1947 }
1948 }
1949*/
1950}
1951
1952
1953//=======================================================================
1954//function : GlobalCheck
1955//purpose :
1956//=======================================================================
1957
1958const Handle(Interface_Check) StepData_StepReaderData::GlobalCheck () const
1959{
1960 return thecheck;
1961}