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 // List of changes:
15 //skl 29.01.2003 - deleted one space symbol at the beginning
16 //                 of strings from Header Section
17 
18 #include <Interface_Check.hxx>
19 #include <Interface_CheckIterator.hxx>
20 #include <Interface_EntityIterator.hxx>
21 #include <Interface_FloatWriter.hxx>
22 #include <Interface_InterfaceMismatch.hxx>
23 #include <Interface_Macros.hxx>
24 #include <Interface_ReportEntity.hxx>
25 #include <Standard_NoSuchObject.hxx>
26 #include <Standard_Transient.hxx>
27 #include <StepData_ESDescr.hxx>
28 #include <StepData_Field.hxx>
29 #include <StepData_FieldList.hxx>
30 #include <StepData_PDescr.hxx>
31 #include <StepData_Protocol.hxx>
32 #include <StepData_ReadWriteModule.hxx>
33 #include <StepData_SelectArrReal.hxx>
34 #include <StepData_SelectMember.hxx>
35 #include <StepData_StepModel.hxx>
36 #include <StepData_StepWriter.hxx>
37 #include <StepData_UndefinedEntity.hxx>
38 #include <StepData_WriterLib.hxx>
39 #include <TCollection_AsciiString.hxx>
40 #include <TCollection_HAsciiString.hxx>
41 
42 #include <stdio.h>
43 #define StepLong 72
44 // StepLong : longueur maxi d une ligne de fichier Step
45 
46 
47 //  Constantes litterales (interessantes, pour les performances ET LA MEMOIRE)
48 
49 static TCollection_AsciiString  textscope    (" &SCOPE");
50 static TCollection_AsciiString  textendscope ("        ENDSCOPE");
51 static TCollection_AsciiString  textcomm     ("  /*  ");
52 static TCollection_AsciiString  textendcomm  ("  */");
53 static TCollection_AsciiString  textlist     ("(");
54 static TCollection_AsciiString  textendlist  (")");
55 static TCollection_AsciiString  textendent   (");");
56 static TCollection_AsciiString  textparam    (",");
57 static TCollection_AsciiString  textundef    ("$");
58 static TCollection_AsciiString  textderived  ("*");
59 static TCollection_AsciiString  texttrue     (".T.");
60 static TCollection_AsciiString  textfalse    (".F.");
61 static TCollection_AsciiString  textunknown  (".U.");
62 
63 
64 
65 //=======================================================================
66 //function : StepData_StepWriter
67 //purpose  :
68 //=======================================================================
69 
StepData_StepWriter(const Handle (StepData_StepModel)& amodel)70 StepData_StepWriter::StepData_StepWriter(const Handle(StepData_StepModel)& amodel)
71     : thecurr (StepLong) , thefloatw (12)
72 {
73   themodel = amodel;  thelabmode = thetypmode = 0;
74   thefile  = new TColStd_HSequenceOfHAsciiString();
75   thesect  = Standard_False;  thefirst = Standard_True;
76   themult  = Standard_False;  thecomm  = Standard_False;
77   thelevel = theindval = 0;   theindent = Standard_False;
78 //  Format flottant : reporte dans le FloatWriter
79 }
80 
81 //  ....                Controle d Envoi des Flottants                ....
82 
83 //=======================================================================
84 //function : FloatWriter
85 //purpose  :
86 //=======================================================================
87 
FloatWriter()88 Interface_FloatWriter& StepData_StepWriter::FloatWriter ()
89 {  return thefloatw;  }    // s y reporter
90 
91 
92 //=======================================================================
93 //function : LabelMode
94 //purpose  :
95 //=======================================================================
96 
LabelMode()97 Standard_Integer&  StepData_StepWriter::LabelMode ()
98 {  return thelabmode;  }
99 
100 
101 //=======================================================================
102 //function : TypeMode
103 //purpose  :
104 //=======================================================================
105 
TypeMode()106 Standard_Integer&  StepData_StepWriter::TypeMode  ()
107 {  return thetypmode;  }
108 
109 //  ....                Description des Scopes (AVANT Envoi)               ....
110 
111 
112 //=======================================================================
113 //function : SetScope
114 //purpose  :
115 //=======================================================================
116 
SetScope(const Standard_Integer numscope,const Standard_Integer numin)117 void StepData_StepWriter::SetScope (const Standard_Integer numscope,
118                                     const Standard_Integer numin)
119 {
120   Standard_Integer nb = themodel->NbEntities();
121   if (numscope <= 0 || numscope > nb || numin <= 0 || numin > nb)
122     throw Interface_InterfaceMismatch("StepWriter : SetScope, out of range");
123   if (thescopenext.IsNull()) {
124     thescopebeg  = new TColStd_HArray1OfInteger (1,nb); thescopebeg->Init(0);
125     thescopeend  = new TColStd_HArray1OfInteger (1,nb); thescopeend->Init(0);
126     thescopenext = new TColStd_HArray1OfInteger (1,nb); thescopenext->Init(0);
127   }
128   else if (thescopenext->Value(numin) != 0) {
129 #ifdef OCCT_DEBUG
130     std::cout << "StepWriter : SetScope (scope : " << numscope << " entity : "
131       << numin << "), Entity already in a Scope"<<std::endl;
132 #endif
133     throw Interface_InterfaceMismatch("StepWriter : SetScope, already set");
134   }
135   thescopenext->SetValue(numin,-1);  // nouvelle fin de scope
136   if (thescopebeg->Value(numscope) == 0) thescopebeg->SetValue(numscope,numin);
137   Standard_Integer lastin = thescopeend->Value(numscope);
138   if (lastin > 0) thescopenext->SetValue(lastin,numin);
139   thescopeend->SetValue(numscope,numin);
140 }
141 
142 
143 //=======================================================================
144 //function : IsInScope
145 //purpose  :
146 //=======================================================================
147 
IsInScope(const Standard_Integer num) const148 Standard_Boolean StepData_StepWriter::IsInScope(const Standard_Integer num) const
149 {
150   if (thescopenext.IsNull()) return Standard_False;
151   return (thescopenext->Value(num) != 0);
152 }
153 
154 //  ###########################################################################
155 //  ##    ##    ##    ##        ENVOI DES  SECTIONS        ##    ##    ##    ##
156 
157 //  ....                      Envoi du Modele Complet                      ....
158 
159 
160 //=======================================================================
161 //function : SendModel
162 //purpose  :
163 //=======================================================================
164 
SendModel(const Handle (StepData_Protocol)& protocol,const Standard_Boolean headeronly)165 void StepData_StepWriter::SendModel(const Handle(StepData_Protocol)& protocol,
166                                     const Standard_Boolean headeronly)
167 {
168   StepData_WriterLib lib(protocol);
169 
170   if (!headeronly)
171     thefile->Append (new TCollection_HAsciiString("ISO-10303-21;"));
172   SendHeader();
173 
174 //  ....                Header : suite d entites sans Ident                ....
175 
176   Interface_EntityIterator header = themodel->Header();
177   thenum = 0;
178   for (header.Start(); header.More(); header.Next()) {
179     Handle(Standard_Transient) anent = header.Value();
180 
181 //   Write Entity via Lib  (similaire a SendEntity)
182     Handle(StepData_ReadWriteModule) module;  Standard_Integer CN;
183     if (lib.Select(anent,module,CN)) {
184       if (module->IsComplex(CN))   StartComplex();
185       else {
186 	TCollection_AsciiString styp;
187 	if (thetypmode > 0) styp = module->ShortType(CN);
188 	if (styp.Length() == 0) styp = module->StepType(CN);
189 	StartEntity (styp);
190       }
191       module->WriteStep(CN,*this,anent);
192       if (module->IsComplex(CN))   EndComplex();
193     } else {
194 //    Pas trouve ci-dessus ... tenter UndefinedEntity
195       DeclareAndCast(StepData_UndefinedEntity,und,anent);
196       if (und.IsNull()) continue;
197       if (und->IsComplex())   StartComplex();
198       und->WriteParams(*this);
199       if (und->IsComplex())   EndComplex();
200    }
201     EndEntity ();
202   }
203   EndSec();
204   if (headeronly) return;
205 
206 //  Data : Comme Header mais avec des Idents ... sinon le code est le meme
207   SendData();
208 
209 // ....                    Erreurs Globales (silya)                    ....
210 
211   Handle(Interface_Check) achglob = themodel->GlobalCheck();
212   Standard_Integer nbfails = achglob->NbFails();
213   if (nbfails > 0) {
214     Comment(Standard_True);
215     SendComment("GLOBAL FAIL MESSAGES,  recorded at Read time :");
216     for (Standard_Integer ifail = 1; ifail <= nbfails; ifail ++) {
217       SendComment (achglob->Fail(ifail));
218     }
219     Comment(Standard_False);
220     NewLine(Standard_False);
221   }
222 
223 //  ....                Sortie des Entites une par une                ....
224 
225   Standard_Integer nb = themodel->NbEntities();
226   for (Standard_Integer i = 1 ; i <= nb; i ++) {
227 //    Liste principale : on n envoie pas les Entites dans un Scope
228 //    Elles le seront par l intermediaire du Scope qui les contient
229     if (!thescopebeg.IsNull()) {  if (thescopenext->Value(i) != 0) continue;  }
230     SendEntity (i,lib);
231   }
232 
233   EndSec();
234   EndFile();
235 }
236 
237 
238 //  ....                DECOUPAGE DU FICHIER EN SECTIONS                ....
239 
240 
241 //=======================================================================
242 //function : SendHeader
243 //purpose  :
244 //=======================================================================
245 
SendHeader()246 void StepData_StepWriter::SendHeader ()
247 {
248   NewLine(Standard_False);
249   thefile->Append (new TCollection_HAsciiString("HEADER;"));
250   thesect = Standard_True;
251 }
252 
253 
254 //=======================================================================
255 //function : SendData
256 //purpose  :
257 //=======================================================================
258 
SendData()259 void StepData_StepWriter::SendData ()
260 {
261   if (thesect) throw Interface_InterfaceMismatch("StepWriter : Data section");
262   NewLine(Standard_False);
263   thefile->Append (new TCollection_HAsciiString("DATA;"));
264   thesect = Standard_True;
265 }
266 
267 
268 //=======================================================================
269 //function : EndSec
270 //purpose  :
271 //=======================================================================
272 
EndSec()273 void StepData_StepWriter::EndSec ()
274 {
275   thefile->Append (new TCollection_HAsciiString("ENDSEC;"));
276   thesect = Standard_False;
277 }
278 
279 
280 //=======================================================================
281 //function : EndFile
282 //purpose  :
283 //=======================================================================
284 
EndFile()285 void StepData_StepWriter::EndFile ()
286 {
287   if (thesect) throw Interface_InterfaceMismatch("StepWriter : EndFile");
288   NewLine(Standard_False);
289   thefile->Append (new TCollection_HAsciiString("END-ISO-10303-21;"));
290   thesect = Standard_False;
291 }
292 
293 //  ....                        ENVOI D UNE ENTITE                        ....
294 
295 
296 //=======================================================================
297 //function : SendEntity
298 
299 //purpose  :
300 //=======================================================================
301 
SendEntity(const Standard_Integer num,const StepData_WriterLib & lib)302 void StepData_StepWriter::SendEntity(const Standard_Integer num,
303                                      const StepData_WriterLib& lib)
304 {
305   char lident[20];
306   Handle(Standard_Transient) anent = themodel->Entity(num);
307   Standard_Integer idnum = num , idtrue = 0;
308 
309     //   themodel->Number(anent) et-ou IdentLabel(anent)
310   if (thelabmode > 0) idtrue = themodel->IdentLabel(anent);
311   if (thelabmode == 1) idnum = idtrue;
312   if (idnum == 0) idnum = num;
313   if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d = ",idnum); //skl 29.01.2003
314   else sprintf(lident,"%d:#%d = ",idnum,idtrue); //skl 29.01.2003
315 
316 //  SendIdent repris , lident vient d etre calcule
317   thecurr.Clear();
318   thecurr.Add (lident);
319   themult = Standard_False;
320 
321 //  ....        Traitement du Scope Eventuel
322   if (!thescopebeg.IsNull()) {
323     Standard_Integer numin = thescopebeg->Value(num);
324     if (numin != 0) {
325       SendScope();
326       for (Standard_Integer nument = numin; numin > 0; nument = numin) {
327 	SendEntity(nument,lib);
328 	numin = thescopenext->Value(nument);
329       }
330       SendEndscope();
331     }
332   }
333 
334 //  ....        Envoi de l Entite proprement dite
335 
336 //   Write Entity via Lib
337   thenum = num;
338   Handle(StepData_ReadWriteModule) module;  Standard_Integer CN;
339   if (themodel->IsRedefinedContent(num)) {
340 //    Entite Erreur : Ecrire le Contenu + les Erreurs en Commentaires
341     Handle(Interface_ReportEntity) rep = themodel->ReportEntity(num);
342     DeclareAndCast(StepData_UndefinedEntity,und,rep->Content());
343     if (und.IsNull()) {
344       thechecks.CCheck(num)->AddFail("Erroneous Entity, Content lost");
345       StartEntity(TCollection_AsciiString("!?LOST_DATA"));
346     } else {
347       thechecks.CCheck(num)->AddWarning("Erroneous Entity, equivalent content");
348       if (und->IsComplex())   AddString(" (",2);
349       und->WriteParams(*this);
350       if (und->IsComplex()) { AddString(") ",2); }  //thelevel --; }
351     }
352     EndEntity ();        // AVANT les Commentaires
353     NewLine(Standard_False);
354     Comment(Standard_True);
355     if (und.IsNull()) SendComment("   ERRONEOUS ENTITY, DATA LOST");
356     SendComment("On Entity above, Fail Messages recorded at Read time :");
357     Handle(Interface_Check) ach = rep->Check();
358     Standard_Integer nbfails = ach->NbFails();
359     for (Standard_Integer ifail = 1; ifail <= nbfails; ifail ++) {
360       SendComment (ach->Fail(ifail));
361     }
362     Comment(Standard_False);
363     NewLine(Standard_False);
364 
365 //    Cas normal
366   }
367   else if (lib.Select(anent,module,CN)) {
368     if (module->IsComplex(CN))   StartComplex();
369     else {
370       TCollection_AsciiString styp;
371       if (thetypmode > 0) styp = module->ShortType(CN);
372       if (styp.Length() == 0) styp = module->StepType(CN);
373       StartEntity (styp);
374     }
375     module->WriteStep(CN,*this,anent);
376     if (module->IsComplex(CN))   EndComplex();
377     EndEntity ();
378   }
379   else {
380     //    Pas trouve ci-dessus ... tenter UndefinedEntity
381     DeclareAndCast(StepData_UndefinedEntity,und,anent);
382     if (und.IsNull()) return;
383     if (und->IsComplex())   StartComplex();
384     und->WriteParams(*this);
385     if (und->IsComplex())   EndComplex();
386     EndEntity ();
387   }
388 }
389 
390 //  ###########################################################################
391 //  ##    ##    ##        CONSTITUTION DU TEXTE A ENVOYER        ##    ##    ##
392 
393 //  Passer a la ligne. Ligne vide pas comptee sauf si evenempty == Standard_True
394 
395 
396 //=======================================================================
397 //function : NewLine
398 //purpose  :
399 //=======================================================================
400 
NewLine(const Standard_Boolean evenempty)401 void StepData_StepWriter::NewLine (const Standard_Boolean evenempty)
402 {
403   if (evenempty || thecurr.Length() > 0) {
404     thefile->Append(thecurr.Moved());
405   }
406   Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
407   thecurr.SetInitial(indst);  thecurr.Clear();
408 }
409 
410 
411 //  Regrouper ligne en cours avec precedente; reste en cours sauf si newline
412 //  == Standard_True, auquel cas on commence une nouvelle ligne
413 //  Ne fait rien si : total correspondant > StepLong ou debut ou fin d`entite
414 
415 
416 //=======================================================================
417 //function : JoinLast
418 //purpose  :
419 //=======================================================================
420 
JoinLast(const Standard_Boolean)421 void StepData_StepWriter::JoinLast (const Standard_Boolean)
422 {
423   thecurr.SetKeep();
424 }
425 
426 
427 //=======================================================================
428 //function : Indent
429 //purpose  :
430 //=======================================================================
431 
Indent(const Standard_Boolean onent)432 void StepData_StepWriter::Indent (const Standard_Boolean onent)
433 {  theindent = onent;  }
434 
435 
436 //=======================================================================
437 //function : SendIdent
438 //purpose  :
439 //=======================================================================
440 
SendIdent(const Standard_Integer ident)441 void StepData_StepWriter::SendIdent(const Standard_Integer ident)
442 {
443   char lident[12];
444   sprintf(lident,"#%d =",ident);
445   thecurr.Clear();
446   thecurr.Add (lident);
447   themult = Standard_False;
448 }
449 
450 
451 //=======================================================================
452 //function : SendScope
453 //purpose  :
454 //=======================================================================
455 
SendScope()456 void StepData_StepWriter::SendScope ()
457 {  AddString(textscope);  }
458 
459 
460 //=======================================================================
461 //function : SendEndscope
462 //purpose  :
463 //=======================================================================
464 
SendEndscope()465 void StepData_StepWriter::SendEndscope ()
466 {
467   NewLine(Standard_False);
468   thefile->Append(new TCollection_HAsciiString(textendscope));
469 }
470 
471 
472 //=======================================================================
473 //function : Comment
474 //purpose  :
475 //=======================================================================
476 
Comment(const Standard_Boolean mode)477 void StepData_StepWriter::Comment (const Standard_Boolean mode)
478 {
479   if (mode && !thecomm) AddString(textcomm,20);
480   if (!mode && thecomm) AddString(textendcomm);
481   thecomm = mode;
482 }
483 
484 
485 //=======================================================================
486 //function : SendComment
487 //purpose  :
488 //=======================================================================
489 
SendComment(const Handle (TCollection_HAsciiString)& text)490 void StepData_StepWriter::SendComment(const Handle(TCollection_HAsciiString)& text)
491 {
492   if (!thecomm) throw Interface_InterfaceMismatch("StepWriter : Comment");
493   AddString(text->ToCString(),text->Length());
494 }
495 
496 
497 //=======================================================================
498 //function : SendComment
499 //purpose  :
500 //=======================================================================
501 
SendComment(const Standard_CString text)502 void StepData_StepWriter::SendComment (const Standard_CString text)
503 {
504   if (!thecomm) throw Interface_InterfaceMismatch("StepWriter : Comment");
505   AddString(text,(Standard_Integer) strlen(text));
506 }
507 
508 
509 //=======================================================================
510 //function : StartEntity
511 //purpose  :
512 //=======================================================================
513 
StartEntity(const TCollection_AsciiString & atype)514 void StepData_StepWriter::StartEntity(const TCollection_AsciiString& atype)
515 {
516   if (atype.Length() == 0) return;
517   if (themult) {
518     if (thelevel != 1) throw Interface_InterfaceMismatch("StepWriter : StartEntity");   // decompte de parentheses mauvais ...
519     AddString(textendlist);
520     AddString(" ",1); //skl 29.01.2003
521   }
522   themult = Standard_True;
523   //AddString(" ",1);  //skl 29.01.2003
524   AddString(atype);
525   thelevel  = 0;
526   theindval = thecurr.Length();
527   thecurr.SetInitial(0);
528   thefirst  = Standard_True;
529   OpenSub();
530 }
531 
532 
533 //=======================================================================
534 //function : StartComplex
535 //purpose  :
536 //=======================================================================
537 
StartComplex()538 void  StepData_StepWriter::StartComplex ()
539 {
540   AddString("( ",2); //skl 29.01.2003
541 }    // thelevel unchanged
542 
543 
544 //=======================================================================
545 //function : EndComplex
546 //purpose  :
547 //=======================================================================
548 
EndComplex()549 void  StepData_StepWriter::EndComplex ()
550 {  AddString(") ",2);  }    // thelevel unchanged
551 
552 
553 //  ....                SendField et ce qui va avec
554 
555 
556 //=======================================================================
557 //function : SendField
558 //purpose  :
559 //=======================================================================
560 
SendField(const StepData_Field & fild,const Handle (StepData_PDescr)& descr)561 void StepData_StepWriter::SendField(const StepData_Field& fild,
562                                     const Handle(StepData_PDescr)& descr)
563 {
564   Standard_Boolean done = Standard_True;
565   Standard_Integer kind = fild.Kind (Standard_False);  // valeur interne
566 
567   if (kind == 16) {
568     DeclareAndCast(StepData_SelectMember,sm,fild.Transient());
569     SendSelect (sm,descr);
570     return;
571   }
572   switch (kind) {
573 //   ici les cas simples; ensuite on caste et on voit
574     case 0 : SendUndef(); break;
575     case 1 : Send        (fild.Integer  ()); break;
576     case 2 : SendBoolean (fild.Boolean  ()); break;
577     case 3 : SendLogical (fild.Logical  ()); break;
578     case 4 : SendEnum    (fild.EnumText ()); break; // enum : descr ?
579     case 5 : Send        (fild.Real     ()); break;
580     case 6 : Send        (fild.String   ()); break;
581     case 7 : Send        (fild.Entity   ()); break;
582     case 8 : done = Standard_False; break;
583     case 9 : SendDerived (); break;
584     default: done = Standard_False; break;
585   }
586   if (done) return;
587 
588 //  Que reste-t-il : les tableaux ...
589   Standard_Integer arity = fild.Arity();
590   if (arity == 0) {  SendUndef();  return;  }    // PAS NORMAL
591   if (arity == 1) {
592     OpenSub();
593     Standard_Integer i,low = fild.Lower(), up = low + fild.Length() - 1;
594     for (i = low; i <= up; i ++) {
595       kind = fild.ItemKind(i);
596       done = Standard_True;
597       switch (kind) {
598         case 0 : SendUndef();  break;
599 	case 1 : Send        (fild.Integer  (i)); break;
600 	case 2 : SendBoolean (fild.Boolean  (i)); break;
601 	case 3 : SendLogical (fild.Logical  (i)); break;
602 	case 4 : SendEnum    (fild.EnumText (i)); break;
603 	case 5 : Send        (fild.Real     (i)); break;
604 	case 6 : Send        (fild.String   (i)); break;
605 	case 7 : Send        (fild.Entity   (i)); break;
606 	default: SendUndef();  done = Standard_False; break;  // ANORMAL
607       }
608     }
609     CloseSub();
610     return;
611   }
612   if (arity == 2) {
613     OpenSub();
614     Standard_Integer   j,low1 = fild.Lower(1), up1 = low1 + fild.Length(1) - 1;
615     for (j = low1; j <= up1; j ++) {
616       Standard_Integer i=0,low2 = fild.Lower(2), up2 = low2 + fild.Length(2) - 1;
617       OpenSub();
618       for (i = low2; i <= up2; i ++) {
619 	kind = fild.ItemKind(i,j);
620 	done = Standard_True;
621 	switch (kind) {
622         case 0 : SendUndef();  break;
623 	case 1 : Send        (fild.Integer  (i,j)); break;
624 	case 2 : SendBoolean (fild.Boolean  (i,j)); break;
625 	case 3 : SendLogical (fild.Logical  (i,j)); break;
626 	case 4 : SendEnum    (fild.EnumText (i,j)); break;
627 	case 5 : Send        (fild.Real     (i,j)); break;
628 	case 6 : Send        (fild.String   (i,j)); break;
629 	case 7 : Send        (fild.Entity   (i,j)); break;
630 	default: SendUndef();  done = Standard_False; break;  // ANORMAL
631         }
632       }
633       CloseSub();
634     }
635     CloseSub();
636     return;
637   }
638 }
639 
640 
641 //=======================================================================
642 //function : SendSelect
643 //purpose  :
644 //=======================================================================
645 
SendSelect(const Handle (StepData_SelectMember)& sm,const Handle (StepData_PDescr)&)646 void StepData_StepWriter::SendSelect(const Handle(StepData_SelectMember)& sm,
647                                      const Handle(StepData_PDescr)& /*descr*/)
648 {
649   //    Cas du SelectMember. Traiter le Select puis la valeur
650   //    NB : traitement actuel non recursif (pas de SELNAME(SELNAME(..)) )
651   Standard_Boolean selname = Standard_False;
652   if (sm.IsNull()) return;  // ??
653   if (sm->HasName()) {
654     selname = Standard_True;
655     //    SendString (sm->Name());
656     //    AddString(textlist);     // SANS AJOUT DE PARAMETRE !!
657     OpenTypedSub (sm->Name());
658   }
659   Standard_Integer kind = sm->Kind();
660   switch (kind) {
661     case 0 : SendUndef(); break;
662     case 1 : Send        (sm->Integer  ()); break;
663     case 2 : SendBoolean (sm->Boolean  ()); break;
664     case 3 : SendLogical (sm->Logical  ()); break;
665     case 4 : SendEnum    (sm->EnumText ()); break; // enum : descr ?
666     case 5 : Send        (sm->Real     ()); break;
667     case 6 : Send        (sm->String   ()); break;
668     case 8 : SendArrReal (Handle(StepData_SelectArrReal)::DownCast(sm)->ArrReal()); break;
669     default: break;    // ??
670   }
671   if (selname) CloseSub();
672 }
673 
674 
675 //=======================================================================
676 //function : SendList
677 //purpose  :
678 //=======================================================================
679 
SendList(const StepData_FieldList & list,const Handle (StepData_ESDescr)& descr)680 void  StepData_StepWriter::SendList(const StepData_FieldList& list,
681                                     const Handle(StepData_ESDescr)& descr)
682 {
683 // start entity  ?
684   Standard_Integer i, nb = list.NbFields();
685   for (i = 1; i <= nb; i ++) {
686     Handle(StepData_PDescr) pde;
687     if (!descr.IsNull()) pde  = descr->Field(i);
688     const StepData_Field fild = list.Field(i);
689     SendField (fild,pde);
690   }
691 // end entity  ?
692 }
693 
694 //  ....                Send* de base
695 
696 
697 //=======================================================================
698 //function : OpenSub
699 //purpose  :
700 //=======================================================================
701 
OpenSub()702 void StepData_StepWriter::OpenSub ()
703 {
704   AddParam();
705   AddString(textlist);
706   thefirst = Standard_True;
707   thelevel ++;
708 }
709 
710 
711 //=======================================================================
712 //function : OpenTypedSub
713 //purpose  :
714 //=======================================================================
715 
OpenTypedSub(const Standard_CString subtype)716 void StepData_StepWriter::OpenTypedSub (const Standard_CString subtype)
717 {
718   AddParam();
719   if (subtype[0] != '\0') AddString (subtype,(Standard_Integer) strlen(subtype));
720   AddString(textlist);
721   thefirst = Standard_True;
722   thelevel ++;
723 }
724 
725 
726 //=======================================================================
727 //function : CloseSub
728 //purpose  :
729 //=======================================================================
730 
CloseSub()731 void StepData_StepWriter::CloseSub ()
732 {
733   AddString(textendlist);
734   thefirst = Standard_False;  // le parametre suivant une sous-liste n est donc pas 1er
735   thelevel --;
736 }
737 
738 
739 //=======================================================================
740 //function : AddParam
741 //purpose  :
742 //=======================================================================
743 
AddParam()744 void StepData_StepWriter::AddParam ()
745 {
746   if (!thefirst) AddString(textparam);
747   thefirst = Standard_False;
748 }
749 
750 
751 //=======================================================================
752 //function : Send
753 //purpose  :
754 //=======================================================================
755 
Send(const Standard_Integer val)756 void StepData_StepWriter::Send (const Standard_Integer val)
757 {
758   char lval[12];
759   AddParam();
760   sprintf(lval,"%d",val);
761   AddString(lval,(Standard_Integer) strlen(lval));
762 }
763 
764 
765 //=======================================================================
766 //function : Send
767 //purpose  :
768 //=======================================================================
769 
Send(const Standard_Real val)770 void StepData_StepWriter::Send (const Standard_Real val)
771 {
772 //    Valeur flottante, expurgee de "0000" qui trainent et de "E+00"
773   char lval[24] = {};
774   Standard_Integer lng = thefloatw.Write(val,lval);
775   AddParam();
776   AddString(lval,lng);    // gere le format specifique : si besoin est
777 }
778 
779 //  Send(String) : attention, on envoie un Texte ... donc entre '  '
780 
781 //=======================================================================
782 //function : Send
783 //purpose  :
784 //=======================================================================
785 
Send(const TCollection_AsciiString & val)786 void StepData_StepWriter::Send (const TCollection_AsciiString& val)
787 {
788   AddParam();
789   TCollection_AsciiString aval(val);  // on duplique pour trafiquer si besoin
790   Standard_Integer nb = aval.Length();  Standard_Integer nn = nb;
791   aval.AssignCat('\'');    // comme cela, Insert(i+1) est OK
792 
793 //    Conversion des Caracteres speciaux
794   for (Standard_Integer i = nb; i > 0; i --) {
795     char uncar = aval.Value(i);
796     if (uncar == '\'') {  aval.Insert(i+1,'\'');  nn ++;    continue;  }
797     if (uncar == '\\') {  aval.Insert(i+1,'\\');  nn ++;    continue;  }
798     if (uncar == '\n') {  aval.SetValue(i,'\\');  aval.Insert(i+1,'\\');
799 			  aval.Insert(i+1,'N' );  nn += 2;  continue;  }
800     if (uncar == '\t') {  aval.SetValue(i,'\\');  aval.Insert(i+1,'\\');
801 			  aval.Insert(i+1,'T' );  nn += 2;  continue;  }
802   }
803   //:i2 abv 31 Aug 98: ProSTEP TR9: avoid wrapping text or do it at spaces
804   aval.Insert(1,'\'');
805   nn += 2;
806 
807 //:i2  AddString ("\'",1); nn ++;
808 
809 //    Attention au depassement des 72 caracteres
810   if (thecurr.CanGet(nn)) AddString(aval,0);
811   //:i2
812   else {
813     thefile->Append(thecurr.Moved());
814     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
815     if ( indst+nn <= StepLong ) thecurr.SetInitial(indst);
816     else thecurr.SetInitial(0);
817     if ( thecurr.CanGet(nn) ) AddString(aval,0);
818     else {
819       while ( nn >0 ) {
820 	if (nn <= StepLong) {
821 	  thecurr.Add (aval);  // Ca yet, on a tout epuise
822 	  thecurr.FreezeInitial();
823 	  break;
824 	}
825 	Standard_Integer stop = StepLong; // position of last separator
826 	for ( ; stop > 0 && aval.Value(stop) != ' '; stop-- );
827 	if ( ! stop ) {
828 	  stop = StepLong;
829 	  for ( ; stop > 0 && aval.Value(stop) != '\\'; stop-- );
830 	  if ( ! stop ) {
831 	    stop = StepLong;
832 	    for ( ; stop > 0 && aval.Value(stop) != '_'; stop-- );
833 	    if ( ! stop ) stop = StepLong;
834 	  }
835 	}
836 	TCollection_AsciiString bval = aval.Split(stop);
837 	thefile->Append(new TCollection_HAsciiString(aval));
838 	aval = bval;
839 	nn -= stop;
840       }
841     }
842   }
843 /* //:i2
844   else {
845     //    Il faut tronconner ...  lignes limitees a 72 caracteres (StepLong)
846     Standard_Integer ncurr = thecurr.Length();
847     Standard_Integer nbuff = StepLong - ncurr;
848     thecurr.Add (aval.ToCString(),nbuff);
849     thefile->Append(thecurr.Moved());
850     aval.Remove(1,nbuff);
851     nn -= nbuff;
852     while (nn > 0) {
853       if (nn <= StepLong) {
854 	thecurr.Add (aval);  // Ca yet, on a tout epuise
855 	thecurr.FreezeInitial();
856 	break;
857       }
858       TCollection_AsciiString bval = aval.Split(StepLong);
859       thefile->Append(new TCollection_HAsciiString(bval));
860       nn -= StepLong;
861     }
862   }
863 //:i2 */
864 //  thecurr.Add('\'');   deja mis dans aval au debut
865 }
866 
867 
868 //=======================================================================
869 //function : Send
870 //purpose  :
871 //=======================================================================
872 
Send(const Handle (Standard_Transient)& val)873 void StepData_StepWriter::Send (const Handle(Standard_Transient)& val)
874 {
875   char lident[20];
876 //  Undefined ?
877   if (val.IsNull()) {
878 //   throw Interface_InterfaceMismatch("StepWriter : Sending Null Reference");
879     thechecks.CCheck(thenum)->AddFail("Null Reference");
880     SendUndef();
881     Comment(Standard_True);
882     SendComment(" NUL REF ");
883     Comment(Standard_False);
884     return;
885   }
886   Standard_Integer num = themodel->Number(val);
887 //  String ? (si non repertoriee dans le Modele)
888   if (num == 0) {
889     if (val->IsKind(STANDARD_TYPE(TCollection_HAsciiString))) {
890       DeclareAndCast(TCollection_HAsciiString,strval,val);
891       Send (TCollection_AsciiString(strval->ToCString()));
892       return;
893     }
894 //  SelectMember ? (toujours, si non repertoriee)
895 //  mais attention, pas de description attachee
896     else if (val->IsKind(STANDARD_TYPE(StepData_SelectMember))) {
897       DeclareAndCast(StepData_SelectMember,sm,val);
898       Handle(StepData_PDescr) descr;  // null
899       SendSelect (sm,descr);
900     }
901 //  Sinon, PAS NORMAL !
902     else {
903       thechecks.CCheck(thenum)->AddFail("UnknownReference");
904       SendUndef();
905       Comment(Standard_True);
906       SendComment(" UNKNOWN REF ");
907       Comment(Standard_False);
908 //      throw Interface_InterfaceMismatch("StepWriter : Sending Unknown Reference");
909     }
910   }
911 //  Cas normal : une bonne Entite, on envoie son Ident.
912   else {
913     Standard_Integer idnum = num, idtrue = 0;
914     if (thelabmode > 0) idtrue = themodel->IdentLabel(val);
915     if (thelabmode == 1) idnum = idtrue;
916     if (idnum == 0) idnum = num;
917     if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d",idnum);
918     else sprintf(lident,"%d:#%d",idnum,idtrue);
919     AddParam();
920     AddString(lident,(Standard_Integer) strlen(lident));
921   }
922 }
923 
924 
925 //=======================================================================
926 //function : SendBoolean
927 //purpose  :
928 //=======================================================================
929 
SendBoolean(const Standard_Boolean val)930 void StepData_StepWriter::SendBoolean (const Standard_Boolean val)
931 {
932   if (val) SendString(texttrue);
933   else     SendString(textfalse);
934 }
935 
936 
937 //=======================================================================
938 //function : SendLogical
939 //purpose  :
940 //=======================================================================
941 
SendLogical(const StepData_Logical val)942 void StepData_StepWriter::SendLogical (const StepData_Logical val)
943 {
944   if      (val == StepData_LTrue)   SendString(texttrue);
945   else if (val == StepData_LFalse)  SendString(textfalse);
946   else                              SendString(textunknown);
947 }
948 
949 
950 //  SendString : attention, on donne l'intitule exact
951 
952 //=======================================================================
953 //function : SendString
954 //purpose  :
955 //=======================================================================
956 
SendString(const TCollection_AsciiString & val)957 void StepData_StepWriter::SendString (const TCollection_AsciiString& val)
958 {
959   AddParam();
960   AddString(val);
961 }
962 
963 //  SendString : attention, on donne l'intitule exact
964 
965 //=======================================================================
966 //function : SendString
967 //purpose  :
968 //=======================================================================
969 
SendString(const Standard_CString val)970 void StepData_StepWriter::SendString (const Standard_CString val)
971 {
972   AddParam();
973   AddString(val,(Standard_Integer) strlen(val));
974 }
975 
976 //  SendEnum : attention, on envoie un intitule d'Enum ... donc entre .  .
977 
978 //=======================================================================
979 //function : SendEnum
980 //purpose  :
981 //=======================================================================
982 
SendEnum(const TCollection_AsciiString & val)983 void StepData_StepWriter::SendEnum (const TCollection_AsciiString& val)
984 {
985   if (val.Length() == 1 && val.Value(1) == '$')  {  SendUndef();  return;  }
986   AddParam();
987   TCollection_AsciiString aValue = val;
988   if (aValue.Value(1) != '.') aValue.Prepend('.');
989   if (aValue.Value(aValue.Length()) != '.') aValue+='.';
990   AddString(aValue,2);
991 
992 }
993 
994 //  SendEnum : attention, on envoie un intitule d'Enum ... donc entre .  .
995 
996 //=======================================================================
997 //function : SendEnum
998 //purpose  :
999 //=======================================================================
1000 
SendEnum(const Standard_CString val)1001 void StepData_StepWriter::SendEnum (const Standard_CString val)
1002 {
1003 
1004   if (val[0] == '$' && val[1] == '\0')  {  SendUndef();  return;  }
1005   TCollection_AsciiString aValue(val);
1006   SendEnum(aValue);
1007 }
1008 
1009 
1010 //=======================================================================
1011 //function : SendArrReal
1012 //purpose  :
1013 //=======================================================================
1014 
SendArrReal(const Handle (TColStd_HArray1OfReal)& anArr)1015 void StepData_StepWriter::SendArrReal (const Handle(TColStd_HArray1OfReal) &anArr)
1016 {
1017   AddString(textlist);
1018   if(anArr->Length()>0) {
1019     // add real
1020     Send(anArr->Value(1));
1021     for( Standard_Integer i=2; i<=anArr->Length(); i++) {
1022 //      AddString(textparam);
1023       //add real
1024       Send(anArr->Value(i));
1025     }
1026   }
1027   AddString(textendlist);
1028 }
1029 
1030 
1031 //=======================================================================
1032 //function : SendUndef
1033 //purpose  :
1034 //=======================================================================
1035 
SendUndef()1036 void StepData_StepWriter::SendUndef ()
1037 {
1038   AddParam();
1039   AddString(textundef);
1040 }
1041 
1042 
1043 //=======================================================================
1044 //function : SendDerived
1045 //purpose  :
1046 //=======================================================================
1047 
SendDerived()1048 void StepData_StepWriter::SendDerived ()
1049 {
1050   AddParam();
1051   AddString(textderived);
1052 }
1053 
1054 
1055 // EndEntity : s'il faut mettre ; a la ligne, l'aligner sur debut d'entite ...
1056 
1057 //=======================================================================
1058 //function : EndEntity
1059 //purpose  :
1060 //=======================================================================
1061 
EndEntity()1062 void StepData_StepWriter::EndEntity ()
1063 {
1064   if (thelevel != 1) throw Interface_InterfaceMismatch("StepWriter : EndEntity");   // decompte de parentheses mauvais ...
1065   AddString(textendent);
1066   thelevel  = 0;        // on garde theindval : sera traite au prochain NewLine
1067   Standard_Boolean indent = theindent; theindent = Standard_False;
1068   NewLine(Standard_False); theindent = indent;
1069   themult = Standard_False;
1070 // pour forcer indentation si necessaire
1071 }
1072 
1073 
1074 //  gestion de la ligne courante (cf aussi NewLine/JoinLine)
1075 
1076 //=======================================================================
1077 //function : AddString
1078 //purpose  :
1079 //=======================================================================
1080 
AddString(const TCollection_AsciiString & astr,const Standard_Integer more)1081 void StepData_StepWriter::AddString(const TCollection_AsciiString& astr,
1082                                     const Standard_Integer more)
1083 {
1084   while (!thecurr.CanGet(astr.Length() + more)) {
1085     thefile->Append(thecurr.Moved());
1086     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1087     thecurr.SetInitial(indst);
1088   }
1089   thecurr.Add(astr);
1090 }
1091 
1092 
1093 //=======================================================================
1094 //function : AddString
1095 //purpose  :
1096 //=======================================================================
1097 
AddString(const Standard_CString astr,const Standard_Integer lnstr,const Standard_Integer more)1098 void StepData_StepWriter::AddString(const Standard_CString astr,
1099                                     const Standard_Integer lnstr,
1100                                     const Standard_Integer more)
1101 {
1102   while (!thecurr.CanGet(lnstr + more)) {
1103     thefile->Append(thecurr.Moved());
1104     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1105     thecurr.SetInitial(indst);
1106   }
1107   thecurr.Add(astr,lnstr);
1108 }
1109 
1110 
1111 //   ENVOI FINAL
1112 
1113 
1114 //=======================================================================
1115 //function : CheckList
1116 //purpose  :
1117 //=======================================================================
1118 
CheckList() const1119 Interface_CheckIterator  StepData_StepWriter::CheckList () const
1120 {
1121   return thechecks;
1122 }
1123 
1124 
1125 //=======================================================================
1126 //function : NbLines
1127 //purpose  :
1128 //=======================================================================
1129 
NbLines() const1130 Standard_Integer  StepData_StepWriter::NbLines () const
1131 {  return thefile->Length();  }
1132 
1133 
1134 //=======================================================================
1135 //function : Line
1136 //purpose  :
1137 //=======================================================================
1138 
Handle(TCollection_HAsciiString)1139 Handle(TCollection_HAsciiString) StepData_StepWriter::Line
1140        (const Standard_Integer num) const
1141 {  return thefile->Value(num);  }
1142 
1143 
1144 //=======================================================================
1145 //function : Printw
1146 //purpose  :
1147 //=======================================================================
1148 
Print(Standard_OStream & S)1149 Standard_Boolean StepData_StepWriter::Print (Standard_OStream& S)
1150 {
1151   Standard_Boolean isGood = (S.good());
1152   Standard_Integer nb = thefile->Length();
1153   for (Standard_Integer i = 1; i <= nb && isGood; i ++)
1154     S << thefile->Value(i)->ToCString() << "\n";
1155 
1156   S<< std::flush;
1157   isGood = (S && S.good());
1158 
1159   return  isGood;
1160 
1161 }
1162