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