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