1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
15 //skl 29.01.2003 - deleted one space symbol at the beginning
16 // of strings from Header Section
18 #include <Interface_Check.hxx>
19 #include <Interface_EntityIterator.hxx>
20 #include <Interface_InterfaceMismatch.hxx>
21 #include <Interface_Macros.hxx>
22 #include <Interface_ReportEntity.hxx>
23 #include <Standard_Transient.hxx>
24 #include <StepData_ESDescr.hxx>
25 #include <StepData_FieldList.hxx>
26 #include <StepData_PDescr.hxx>
27 #include <StepData_Protocol.hxx>
28 #include <StepData_ReadWriteModule.hxx>
29 #include <StepData_SelectArrReal.hxx>
30 #include <StepData_SelectMember.hxx>
31 #include <StepData_StepModel.hxx>
32 #include <StepData_StepWriter.hxx>
33 #include <StepData_UndefinedEntity.hxx>
34 #include <StepData_WriterLib.hxx>
35 #include <TCollection_AsciiString.hxx>
36 #include <TCollection_HAsciiString.hxx>
40 // StepLong : longueur maxi d une ligne de fichier Step
43 // Constantes litterales (interessantes, pour les performances ET LA MEMOIRE)
45 static TCollection_AsciiString textscope (" &SCOPE");
46 static TCollection_AsciiString textendscope (" ENDSCOPE");
47 static TCollection_AsciiString textcomm (" /* ");
48 static TCollection_AsciiString textendcomm (" */");
49 static TCollection_AsciiString textlist ("(");
50 static TCollection_AsciiString textendlist (")");
51 static TCollection_AsciiString textendent (");");
52 static TCollection_AsciiString textparam (",");
53 static TCollection_AsciiString textundef ("$");
54 static TCollection_AsciiString textderived ("*");
55 static TCollection_AsciiString texttrue (".T.");
56 static TCollection_AsciiString textfalse (".F.");
57 static TCollection_AsciiString textunknown (".U.");
61 //=======================================================================
62 //function : StepData_StepWriter
64 //=======================================================================
66 StepData_StepWriter::StepData_StepWriter(const Handle(StepData_StepModel)& amodel)
67 : thecurr (StepLong) , thefloatw (12)
69 themodel = amodel; thelabmode = thetypmode = 0;
70 thefile = new TColStd_HSequenceOfHAsciiString();
71 thesect = Standard_False; thefirst = Standard_True;
72 themult = Standard_False; thecomm = Standard_False;
73 thelevel = theindval = 0; theindent = Standard_False;
74 // Format flottant : reporte dans le FloatWriter
77 // .... Controle d Envoi des Flottants ....
79 //=======================================================================
80 //function : FloatWriter
82 //=======================================================================
84 Interface_FloatWriter& StepData_StepWriter::FloatWriter ()
85 { return thefloatw; } // s y reporter
88 //=======================================================================
89 //function : LabelMode
91 //=======================================================================
93 Standard_Integer& StepData_StepWriter::LabelMode ()
94 { return thelabmode; }
97 //=======================================================================
100 //=======================================================================
102 Standard_Integer& StepData_StepWriter::TypeMode ()
103 { return thetypmode; }
105 // .... Description des Scopes (AVANT Envoi) ....
108 //=======================================================================
109 //function : SetScope
111 //=======================================================================
113 void StepData_StepWriter::SetScope (const Standard_Integer numscope,
114 const Standard_Integer numin)
116 Standard_Integer nb = themodel->NbEntities();
117 if (numscope <= 0 || numscope > nb || numin <= 0 || numin > nb)
118 throw Interface_InterfaceMismatch("StepWriter : SetScope, out of range");
119 if (thescopenext.IsNull()) {
120 thescopebeg = new TColStd_HArray1OfInteger (1,nb); thescopebeg->Init(0);
121 thescopeend = new TColStd_HArray1OfInteger (1,nb); thescopeend->Init(0);
122 thescopenext = new TColStd_HArray1OfInteger (1,nb); thescopenext->Init(0);
124 else if (thescopenext->Value(numin) != 0) {
126 std::cout << "StepWriter : SetScope (scope : " << numscope << " entity : "
127 << numin << "), Entity already in a Scope"<<std::endl;
129 throw Interface_InterfaceMismatch("StepWriter : SetScope, already set");
131 thescopenext->SetValue(numin,-1); // nouvelle fin de scope
132 if (thescopebeg->Value(numscope) == 0) thescopebeg->SetValue(numscope,numin);
133 Standard_Integer lastin = thescopeend->Value(numscope);
134 if (lastin > 0) thescopenext->SetValue(lastin,numin);
135 thescopeend->SetValue(numscope,numin);
139 //=======================================================================
140 //function : IsInScope
142 //=======================================================================
144 Standard_Boolean StepData_StepWriter::IsInScope(const Standard_Integer num) const
146 if (thescopenext.IsNull()) return Standard_False;
147 return (thescopenext->Value(num) != 0);
150 // ###########################################################################
151 // ## ## ## ## ENVOI DES SECTIONS ## ## ## ##
153 // .... Envoi du Modele Complet ....
156 //=======================================================================
157 //function : SendModel
159 //=======================================================================
161 void StepData_StepWriter::SendModel(const Handle(StepData_Protocol)& protocol,
162 const Standard_Boolean headeronly)
164 StepData_WriterLib lib(protocol);
167 thefile->Append (new TCollection_HAsciiString("ISO-10303-21;"));
170 // .... Header : suite d entites sans Ident ....
172 Interface_EntityIterator header = themodel->Header();
174 for (header.Start(); header.More(); header.Next()) {
175 const Handle(Standard_Transient)& anent = header.Value();
177 // Write Entity via Lib (similaire a SendEntity)
178 Handle(StepData_ReadWriteModule) module; Standard_Integer CN;
179 if (lib.Select(anent,module,CN)) {
180 if (module->IsComplex(CN)) StartComplex();
182 TCollection_AsciiString styp;
183 if (thetypmode > 0) styp = module->ShortType(CN);
184 if (styp.Length() == 0) styp = module->StepType(CN);
187 module->WriteStep(CN,*this,anent);
188 if (module->IsComplex(CN)) EndComplex();
190 // Pas trouve ci-dessus ... tenter UndefinedEntity
191 DeclareAndCast(StepData_UndefinedEntity,und,anent);
192 if (und.IsNull()) continue;
193 if (und->IsComplex()) StartComplex();
194 und->WriteParams(*this);
195 if (und->IsComplex()) EndComplex();
200 if (headeronly) return;
202 // Data : Comme Header mais avec des Idents ... sinon le code est le meme
205 // .... Erreurs Globales (silya) ....
207 Handle(Interface_Check) achglob = themodel->GlobalCheck();
208 Standard_Integer nbfails = achglob->NbFails();
210 Comment(Standard_True);
211 SendComment("GLOBAL FAIL MESSAGES, recorded at Read time :");
212 for (Standard_Integer ifail = 1; ifail <= nbfails; ifail ++) {
213 SendComment (achglob->Fail(ifail));
215 Comment(Standard_False);
216 NewLine(Standard_False);
219 // .... Sortie des Entites une par une ....
221 Standard_Integer nb = themodel->NbEntities();
222 for (Standard_Integer i = 1 ; i <= nb; i ++) {
223 // Liste principale : on n envoie pas les Entites dans un Scope
224 // Elles le seront par l intermediaire du Scope qui les contient
225 if (!thescopebeg.IsNull()) { if (thescopenext->Value(i) != 0) continue; }
234 // .... DECOUPAGE DU FICHIER EN SECTIONS ....
237 //=======================================================================
238 //function : SendHeader
240 //=======================================================================
242 void StepData_StepWriter::SendHeader ()
244 NewLine(Standard_False);
245 thefile->Append (new TCollection_HAsciiString("HEADER;"));
246 thesect = Standard_True;
250 //=======================================================================
251 //function : SendData
253 //=======================================================================
255 void StepData_StepWriter::SendData ()
257 if (thesect) throw Interface_InterfaceMismatch("StepWriter : Data section");
258 NewLine(Standard_False);
259 thefile->Append (new TCollection_HAsciiString("DATA;"));
260 thesect = Standard_True;
264 //=======================================================================
267 //=======================================================================
269 void StepData_StepWriter::EndSec ()
271 thefile->Append (new TCollection_HAsciiString("ENDSEC;"));
272 thesect = Standard_False;
276 //=======================================================================
279 //=======================================================================
281 void StepData_StepWriter::EndFile ()
283 if (thesect) throw Interface_InterfaceMismatch("StepWriter : EndFile");
284 NewLine(Standard_False);
285 thefile->Append (new TCollection_HAsciiString("END-ISO-10303-21;"));
286 thesect = Standard_False;
289 // .... ENVOI D UNE ENTITE ....
292 //=======================================================================
293 //function : SendEntity
296 //=======================================================================
298 void StepData_StepWriter::SendEntity(const Standard_Integer num,
299 const StepData_WriterLib& lib)
302 Handle(Standard_Transient) anent = themodel->Entity(num);
303 Standard_Integer idnum = num , idtrue = 0;
305 // themodel->Number(anent) et-ou IdentLabel(anent)
306 if (thelabmode > 0) idtrue = themodel->IdentLabel(anent);
307 if (thelabmode == 1) idnum = idtrue;
308 if (idnum == 0) idnum = num;
309 if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d = ",idnum); //skl 29.01.2003
310 else sprintf(lident,"%d:#%d = ",idnum,idtrue); //skl 29.01.2003
312 // SendIdent repris , lident vient d etre calcule
314 thecurr.Add (lident);
315 themult = Standard_False;
317 // .... Traitement du Scope Eventuel
318 if (!thescopebeg.IsNull()) {
319 Standard_Integer numin = thescopebeg->Value(num);
322 for (Standard_Integer nument = numin; numin > 0; nument = numin) {
323 SendEntity(nument,lib);
324 numin = thescopenext->Value(nument);
330 // .... Envoi de l Entite proprement dite
332 // Write Entity via Lib
334 Handle(StepData_ReadWriteModule) module; Standard_Integer CN;
335 if (themodel->IsRedefinedContent(num)) {
336 // Entite Erreur : Ecrire le Contenu + les Erreurs en Commentaires
337 Handle(Interface_ReportEntity) rep = themodel->ReportEntity(num);
338 DeclareAndCast(StepData_UndefinedEntity,und,rep->Content());
340 thechecks.CCheck(num)->AddFail("Erroneous Entity, Content lost");
341 StartEntity(TCollection_AsciiString("!?LOST_DATA"));
343 thechecks.CCheck(num)->AddWarning("Erroneous Entity, equivalent content");
344 if (und->IsComplex()) AddString(" (",2);
345 und->WriteParams(*this);
346 if (und->IsComplex()) { AddString(") ",2); } //thelevel --; }
348 EndEntity (); // AVANT les Commentaires
349 NewLine(Standard_False);
350 Comment(Standard_True);
351 if (und.IsNull()) SendComment(" ERRONEOUS ENTITY, DATA LOST");
352 SendComment("On Entity above, Fail Messages recorded at Read time :");
353 Handle(Interface_Check) ach = rep->Check();
354 Standard_Integer nbfails = ach->NbFails();
355 for (Standard_Integer ifail = 1; ifail <= nbfails; ifail ++) {
356 SendComment (ach->Fail(ifail));
358 Comment(Standard_False);
359 NewLine(Standard_False);
363 else if (lib.Select(anent,module,CN)) {
364 if (module->IsComplex(CN)) StartComplex();
366 TCollection_AsciiString styp;
367 if (thetypmode > 0) styp = module->ShortType(CN);
368 if (styp.Length() == 0) styp = module->StepType(CN);
371 module->WriteStep(CN,*this,anent);
372 if (module->IsComplex(CN)) EndComplex();
376 // Pas trouve ci-dessus ... tenter UndefinedEntity
377 DeclareAndCast(StepData_UndefinedEntity,und,anent);
378 if (und.IsNull()) return;
379 if (und->IsComplex()) StartComplex();
380 und->WriteParams(*this);
381 if (und->IsComplex()) EndComplex();
386 // ###########################################################################
387 // ## ## ## CONSTITUTION DU TEXTE A ENVOYER ## ## ##
389 // Passer a la ligne. Ligne vide pas comptee sauf si evenempty == Standard_True
392 //=======================================================================
395 //=======================================================================
397 void StepData_StepWriter::NewLine (const Standard_Boolean evenempty)
399 if (evenempty || thecurr.Length() > 0) {
400 thefile->Append(thecurr.Moved());
402 Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
403 thecurr.SetInitial(indst); thecurr.Clear();
407 // Regrouper ligne en cours avec precedente; reste en cours sauf si newline
408 // == Standard_True, auquel cas on commence une nouvelle ligne
409 // Ne fait rien si : total correspondant > StepLong ou debut ou fin d`entite
412 //=======================================================================
413 //function : JoinLast
415 //=======================================================================
417 void StepData_StepWriter::JoinLast (const Standard_Boolean)
423 //=======================================================================
426 //=======================================================================
428 void StepData_StepWriter::Indent (const Standard_Boolean onent)
429 { theindent = onent; }
432 //=======================================================================
433 //function : SendIdent
435 //=======================================================================
437 void StepData_StepWriter::SendIdent(const Standard_Integer ident)
440 sprintf(lident,"#%d =",ident);
442 thecurr.Add (lident);
443 themult = Standard_False;
447 //=======================================================================
448 //function : SendScope
450 //=======================================================================
452 void StepData_StepWriter::SendScope ()
453 { AddString(textscope); }
456 //=======================================================================
457 //function : SendEndscope
459 //=======================================================================
461 void StepData_StepWriter::SendEndscope ()
463 NewLine(Standard_False);
464 thefile->Append(new TCollection_HAsciiString(textendscope));
468 //=======================================================================
471 //=======================================================================
473 void StepData_StepWriter::Comment (const Standard_Boolean mode)
475 if (mode && !thecomm) AddString(textcomm,20);
476 if (!mode && thecomm) AddString(textendcomm);
481 //=======================================================================
482 //function : SendComment
484 //=======================================================================
486 void StepData_StepWriter::SendComment(const Handle(TCollection_HAsciiString)& text)
488 if (!thecomm) throw Interface_InterfaceMismatch("StepWriter : Comment");
489 AddString(text->ToCString(),text->Length());
493 //=======================================================================
494 //function : SendComment
496 //=======================================================================
498 void StepData_StepWriter::SendComment (const Standard_CString text)
500 if (!thecomm) throw Interface_InterfaceMismatch("StepWriter : Comment");
501 AddString(text,(Standard_Integer) strlen(text));
505 //=======================================================================
506 //function : StartEntity
508 //=======================================================================
510 void StepData_StepWriter::StartEntity(const TCollection_AsciiString& atype)
512 if (atype.Length() == 0) return;
514 if (thelevel != 1) throw Interface_InterfaceMismatch("StepWriter : StartEntity"); // decompte de parentheses mauvais ...
515 AddString(textendlist);
516 AddString(" ",1); //skl 29.01.2003
518 themult = Standard_True;
519 //AddString(" ",1); //skl 29.01.2003
522 theindval = thecurr.Length();
523 thecurr.SetInitial(0);
524 thefirst = Standard_True;
529 //=======================================================================
530 //function : StartComplex
532 //=======================================================================
534 void StepData_StepWriter::StartComplex ()
536 AddString("( ",2); //skl 29.01.2003
537 } // thelevel unchanged
540 //=======================================================================
541 //function : EndComplex
543 //=======================================================================
545 void StepData_StepWriter::EndComplex ()
546 { AddString(") ",2); } // thelevel unchanged
549 // .... SendField et ce qui va avec
552 //=======================================================================
553 //function : SendField
555 //=======================================================================
557 void StepData_StepWriter::SendField(const StepData_Field& fild,
558 const Handle(StepData_PDescr)& descr)
560 Standard_Boolean done = Standard_True;
561 Standard_Integer kind = fild.Kind (Standard_False); // valeur interne
564 DeclareAndCast(StepData_SelectMember,sm,fild.Transient());
565 SendSelect (sm,descr);
569 // ici les cas simples; ensuite on caste et on voit
570 case 0 : SendUndef(); break;
571 case 1 : Send (fild.Integer ()); break;
572 case 2 : SendBoolean (fild.Boolean ()); break;
573 case 3 : SendLogical (fild.Logical ()); break;
574 case 4 : SendEnum (fild.EnumText ()); break; // enum : descr ?
575 case 5 : Send (fild.Real ()); break;
576 case 6 : Send (fild.String ()); break;
577 case 7 : Send (fild.Entity ()); break;
578 case 8 : done = Standard_False; break;
579 case 9 : SendDerived (); break;
580 default: done = Standard_False; break;
584 // Que reste-t-il : les tableaux ...
585 Standard_Integer arity = fild.Arity();
586 if (arity == 0) { SendUndef(); return; } // PAS NORMAL
589 Standard_Integer i,low = fild.Lower(), up = low + fild.Length() - 1;
590 for (i = low; i <= up; i ++) {
591 kind = fild.ItemKind(i);
592 done = Standard_True;
594 case 0 : SendUndef(); break;
595 case 1 : Send (fild.Integer (i)); break;
596 case 2 : SendBoolean (fild.Boolean (i)); break;
597 case 3 : SendLogical (fild.Logical (i)); break;
598 case 4 : SendEnum (fild.EnumText (i)); break;
599 case 5 : Send (fild.Real (i)); break;
600 case 6 : Send (fild.String (i)); break;
601 case 7 : Send (fild.Entity (i)); break;
602 default: SendUndef(); done = Standard_False; break; // ANORMAL
610 Standard_Integer j,low1 = fild.Lower(1), up1 = low1 + fild.Length(1) - 1;
611 for (j = low1; j <= up1; j ++) {
612 Standard_Integer i=0,low2 = fild.Lower(2), up2 = low2 + fild.Length(2) - 1;
614 for (i = low2; i <= up2; i ++) {
615 kind = fild.ItemKind(i,j);
616 done = Standard_True;
618 case 0 : SendUndef(); break;
619 case 1 : Send (fild.Integer (i,j)); break;
620 case 2 : SendBoolean (fild.Boolean (i,j)); break;
621 case 3 : SendLogical (fild.Logical (i,j)); break;
622 case 4 : SendEnum (fild.EnumText (i,j)); break;
623 case 5 : Send (fild.Real (i,j)); break;
624 case 6 : Send (fild.String (i,j)); break;
625 case 7 : Send (fild.Entity (i,j)); break;
626 default: SendUndef(); done = Standard_False; break; // ANORMAL
637 //=======================================================================
638 //function : SendSelect
640 //=======================================================================
642 void StepData_StepWriter::SendSelect(const Handle(StepData_SelectMember)& sm,
643 const Handle(StepData_PDescr)& /*descr*/)
645 // Cas du SelectMember. Traiter le Select puis la valeur
646 // NB : traitement actuel non recursif (pas de SELNAME(SELNAME(..)) )
647 Standard_Boolean selname = Standard_False;
648 if (sm.IsNull()) return; // ??
650 selname = Standard_True;
651 // SendString (sm->Name());
652 // AddString(textlist); // SANS AJOUT DE PARAMETRE !!
653 OpenTypedSub (sm->Name());
655 Standard_Integer kind = sm->Kind();
657 case 0 : SendUndef(); break;
658 case 1 : Send (sm->Integer ()); break;
659 case 2 : SendBoolean (sm->Boolean ()); break;
660 case 3 : SendLogical (sm->Logical ()); break;
661 case 4 : SendEnum (sm->EnumText ()); break; // enum : descr ?
662 case 5 : Send (sm->Real ()); break;
663 case 6 : Send (sm->String ()); break;
664 case 8 : SendArrReal (Handle(StepData_SelectArrReal)::DownCast(sm)->ArrReal()); break;
665 default: break; // ??
667 if (selname) CloseSub();
671 //=======================================================================
672 //function : SendList
674 //=======================================================================
676 void StepData_StepWriter::SendList(const StepData_FieldList& list,
677 const Handle(StepData_ESDescr)& descr)
680 Standard_Integer i, nb = list.NbFields();
681 for (i = 1; i <= nb; i ++) {
682 Handle(StepData_PDescr) pde;
683 if (!descr.IsNull()) pde = descr->Field(i);
684 const StepData_Field& fild = list.Field(i);
685 SendField (fild,pde);
690 // .... Send* de base
693 //=======================================================================
696 //=======================================================================
698 void StepData_StepWriter::OpenSub ()
702 thefirst = Standard_True;
707 //=======================================================================
708 //function : OpenTypedSub
710 //=======================================================================
712 void StepData_StepWriter::OpenTypedSub (const Standard_CString subtype)
715 if (subtype[0] != '\0') AddString (subtype,(Standard_Integer) strlen(subtype));
717 thefirst = Standard_True;
722 //=======================================================================
723 //function : CloseSub
725 //=======================================================================
727 void StepData_StepWriter::CloseSub ()
729 AddString(textendlist);
730 thefirst = Standard_False; // le parametre suivant une sous-liste n est donc pas 1er
735 //=======================================================================
736 //function : AddParam
738 //=======================================================================
740 void StepData_StepWriter::AddParam ()
742 if (!thefirst) AddString(textparam);
743 thefirst = Standard_False;
747 //=======================================================================
750 //=======================================================================
752 void StepData_StepWriter::Send (const Standard_Integer val)
756 sprintf(lval,"%d",val);
757 AddString(lval,(Standard_Integer) strlen(lval));
761 //=======================================================================
764 //=======================================================================
766 void StepData_StepWriter::Send (const Standard_Real val)
768 // Valeur flottante, expurgee de "0000" qui trainent et de "E+00"
770 Standard_Integer lng = thefloatw.Write(val,lval);
772 AddString(lval,lng); // gere le format specifique : si besoin est
775 // Send(String) : attention, on envoie un Texte ... donc entre ' '
777 //=======================================================================
780 //=======================================================================
782 void StepData_StepWriter::Send (const TCollection_AsciiString& val)
785 TCollection_AsciiString aval(val); // on duplique pour trafiquer si besoin
786 Standard_Integer nb = aval.Length(); Standard_Integer nn = nb;
787 aval.AssignCat('\''); // comme cela, Insert(i+1) est OK
789 // Conversion des Caracteres speciaux
790 for (Standard_Integer i = nb; i > 0; i --) {
791 char uncar = aval.Value(i);
792 if (uncar == '\'') { aval.Insert(i+1,'\''); nn ++; continue; }
793 if (uncar == '\\') { aval.Insert(i+1,'\\'); nn ++; continue; }
794 if (uncar == '\n') { aval.SetValue(i,'\\'); aval.Insert(i+1,'\\');
795 aval.Insert(i+1,'N' ); nn += 2; continue; }
796 if (uncar == '\t') { aval.SetValue(i,'\\'); aval.Insert(i+1,'\\');
797 aval.Insert(i+1,'T' ); nn += 2; continue; }
799 //:i2 abv 31 Aug 98: ProSTEP TR9: avoid wrapping text or do it at spaces
803 //:i2 AddString ("\'",1); nn ++;
805 // Attention au depassement des 72 caracteres
806 if (thecurr.CanGet(nn)) AddString(aval,0);
809 thefile->Append(thecurr.Moved());
810 Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
811 if ( indst+nn <= StepLong ) thecurr.SetInitial(indst);
812 else thecurr.SetInitial(0);
813 if ( thecurr.CanGet(nn) ) AddString(aval,0);
816 if (nn <= StepLong) {
817 thecurr.Add (aval); // Ca yet, on a tout epuise
818 thecurr.FreezeInitial();
821 Standard_Integer stop = StepLong; // position of last separator
822 for ( ; stop > 0 && aval.Value(stop) != ' '; stop-- );
825 for ( ; stop > 0 && aval.Value(stop) != '\\'; stop-- );
828 for ( ; stop > 0 && aval.Value(stop) != '_'; stop-- );
829 if ( ! stop ) stop = StepLong;
832 TCollection_AsciiString bval = aval.Split(stop);
833 thefile->Append(new TCollection_HAsciiString(aval));
841 // Il faut tronconner ... lignes limitees a 72 caracteres (StepLong)
842 Standard_Integer ncurr = thecurr.Length();
843 Standard_Integer nbuff = StepLong - ncurr;
844 thecurr.Add (aval.ToCString(),nbuff);
845 thefile->Append(thecurr.Moved());
846 aval.Remove(1,nbuff);
849 if (nn <= StepLong) {
850 thecurr.Add (aval); // Ca yet, on a tout epuise
851 thecurr.FreezeInitial();
854 TCollection_AsciiString bval = aval.Split(StepLong);
855 thefile->Append(new TCollection_HAsciiString(bval));
860 // thecurr.Add('\''); deja mis dans aval au debut
864 //=======================================================================
867 //=======================================================================
869 void StepData_StepWriter::Send (const Handle(Standard_Transient)& val)
874 // throw Interface_InterfaceMismatch("StepWriter : Sending Null Reference");
875 thechecks.CCheck(thenum)->AddFail("Null Reference");
877 Comment(Standard_True);
878 SendComment(" NUL REF ");
879 Comment(Standard_False);
882 Standard_Integer num = themodel->Number(val);
883 // String ? (si non repertoriee dans le Modele)
885 if (val->IsKind(STANDARD_TYPE(TCollection_HAsciiString))) {
886 DeclareAndCast(TCollection_HAsciiString,strval,val);
887 Send (TCollection_AsciiString(strval->ToCString()));
890 // SelectMember ? (toujours, si non repertoriee)
891 // mais attention, pas de description attachee
892 else if (val->IsKind(STANDARD_TYPE(StepData_SelectMember))) {
893 DeclareAndCast(StepData_SelectMember,sm,val);
894 Handle(StepData_PDescr) descr; // null
895 SendSelect (sm,descr);
897 // Sinon, PAS NORMAL !
899 thechecks.CCheck(thenum)->AddFail("UnknownReference");
901 Comment(Standard_True);
902 SendComment(" UNKNOWN REF ");
903 Comment(Standard_False);
904 // throw Interface_InterfaceMismatch("StepWriter : Sending Unknown Reference");
907 // Cas normal : une bonne Entite, on envoie son Ident.
909 Standard_Integer idnum = num, idtrue = 0;
910 if (thelabmode > 0) idtrue = themodel->IdentLabel(val);
911 if (thelabmode == 1) idnum = idtrue;
912 if (idnum == 0) idnum = num;
913 if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d",idnum);
914 else sprintf(lident,"%d:#%d",idnum,idtrue);
916 AddString(lident,(Standard_Integer) strlen(lident));
921 //=======================================================================
922 //function : SendBoolean
924 //=======================================================================
926 void StepData_StepWriter::SendBoolean (const Standard_Boolean val)
928 if (val) SendString(texttrue);
929 else SendString(textfalse);
933 //=======================================================================
934 //function : SendLogical
936 //=======================================================================
938 void StepData_StepWriter::SendLogical (const StepData_Logical val)
940 if (val == StepData_LTrue) SendString(texttrue);
941 else if (val == StepData_LFalse) SendString(textfalse);
942 else SendString(textunknown);
946 // SendString : attention, on donne l'intitule exact
948 //=======================================================================
949 //function : SendString
951 //=======================================================================
953 void StepData_StepWriter::SendString (const TCollection_AsciiString& val)
959 // SendString : attention, on donne l'intitule exact
961 //=======================================================================
962 //function : SendString
964 //=======================================================================
966 void StepData_StepWriter::SendString (const Standard_CString val)
969 AddString(val,(Standard_Integer) strlen(val));
972 // SendEnum : attention, on envoie un intitule d'Enum ... donc entre . .
974 //=======================================================================
975 //function : SendEnum
977 //=======================================================================
979 void StepData_StepWriter::SendEnum (const TCollection_AsciiString& val)
981 if (val.Length() == 1 && val.Value(1) == '$') { SendUndef(); return; }
983 TCollection_AsciiString aValue = val;
984 if (aValue.Value(1) != '.') aValue.Prepend('.');
985 if (aValue.Value(aValue.Length()) != '.') aValue+='.';
990 // SendEnum : attention, on envoie un intitule d'Enum ... donc entre . .
992 //=======================================================================
993 //function : SendEnum
995 //=======================================================================
997 void StepData_StepWriter::SendEnum (const Standard_CString val)
1000 if (val[0] == '$' && val[1] == '\0') { SendUndef(); return; }
1001 TCollection_AsciiString aValue(val);
1006 //=======================================================================
1007 //function : SendArrReal
1009 //=======================================================================
1011 void StepData_StepWriter::SendArrReal (const Handle(TColStd_HArray1OfReal) &anArr)
1013 AddString(textlist);
1014 if(anArr->Length()>0) {
1016 Send(anArr->Value(1));
1017 for( Standard_Integer i=2; i<=anArr->Length(); i++) {
1018 // AddString(textparam);
1020 Send(anArr->Value(i));
1023 AddString(textendlist);
1027 //=======================================================================
1028 //function : SendUndef
1030 //=======================================================================
1032 void StepData_StepWriter::SendUndef ()
1035 AddString(textundef);
1039 //=======================================================================
1040 //function : SendDerived
1042 //=======================================================================
1044 void StepData_StepWriter::SendDerived ()
1047 AddString(textderived);
1051 // EndEntity : s'il faut mettre ; a la ligne, l'aligner sur debut d'entite ...
1053 //=======================================================================
1054 //function : EndEntity
1056 //=======================================================================
1058 void StepData_StepWriter::EndEntity ()
1060 if (thelevel != 1) throw Interface_InterfaceMismatch("StepWriter : EndEntity"); // decompte de parentheses mauvais ...
1061 AddString(textendent);
1062 thelevel = 0; // on garde theindval : sera traite au prochain NewLine
1063 Standard_Boolean indent = theindent; theindent = Standard_False;
1064 NewLine(Standard_False); theindent = indent;
1065 themult = Standard_False;
1066 // pour forcer indentation si necessaire
1070 // gestion de la ligne courante (cf aussi NewLine/JoinLine)
1072 //=======================================================================
1073 //function : AddString
1075 //=======================================================================
1077 void StepData_StepWriter::AddString(const TCollection_AsciiString& astr,
1078 const Standard_Integer more)
1080 while (!thecurr.CanGet(astr.Length() + more)) {
1081 thefile->Append(thecurr.Moved());
1082 Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1083 thecurr.SetInitial(indst);
1089 //=======================================================================
1090 //function : AddString
1092 //=======================================================================
1094 void StepData_StepWriter::AddString(const Standard_CString astr,
1095 const Standard_Integer lnstr,
1096 const Standard_Integer more)
1098 while (!thecurr.CanGet(lnstr + more)) {
1099 thefile->Append(thecurr.Moved());
1100 Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1101 thecurr.SetInitial(indst);
1103 thecurr.Add(astr,lnstr);
1110 //=======================================================================
1111 //function : CheckList
1113 //=======================================================================
1115 Interface_CheckIterator StepData_StepWriter::CheckList () const
1121 //=======================================================================
1122 //function : NbLines
1124 //=======================================================================
1126 Standard_Integer StepData_StepWriter::NbLines () const
1127 { return thefile->Length(); }
1130 //=======================================================================
1133 //=======================================================================
1135 Handle(TCollection_HAsciiString) StepData_StepWriter::Line
1136 (const Standard_Integer num) const
1137 { return thefile->Value(num); }
1140 //=======================================================================
1143 //=======================================================================
1145 Standard_Boolean StepData_StepWriter::Print (Standard_OStream& S)
1147 Standard_Boolean isGood = (S.good());
1148 Standard_Integer nb = thefile->Length();
1149 for (Standard_Integer i = 1; i <= nb && isGood; i ++)
1150 S << thefile->Value(i)->ToCString() << "\n";
1153 isGood = (S && S.good());