1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
19 //skl 29.01.2003 - deleted one space symbol at the begining
20 // of strings from Header Section
21 #include <StepData_StepWriter.ixx>
22 #include <StepData_WriterLib.hxx>
23 #include <StepData_ReadWriteModule.hxx>
24 #include <StepData_Protocol.hxx>
25 #include <StepData_UndefinedEntity.hxx>
26 #include <TCollection_HAsciiString.hxx>
27 #include <StepData_SelectMember.hxx>
28 #include <StepData_SelectArrReal.hxx>
30 #include <Interface_EntityIterator.hxx>
31 #include <Interface_ReportEntity.hxx>
32 #include <Interface_Check.hxx>
33 #include <Interface_InterfaceMismatch.hxx>
34 #include <Standard_NoSuchObject.hxx>
35 #include <Interface_Macros.hxx>
39 // StepLong : longueur maxi d une ligne de fichier Step
42 // Constantes litterales (interessantes, pour les performances ET LA MEMOIRE)
44 static TCollection_AsciiString textscope (" &SCOPE");
45 static TCollection_AsciiString textendscope (" ENDSCOPE");
46 static TCollection_AsciiString textcomm (" /* ");
47 static TCollection_AsciiString textendcomm (" */");
48 static TCollection_AsciiString textlist ("(");
49 static TCollection_AsciiString textendlist (")");
50 static TCollection_AsciiString textendent (");");
51 static TCollection_AsciiString textparam (",");
52 static TCollection_AsciiString textundef ("$");
53 static TCollection_AsciiString textderived ("*");
54 static TCollection_AsciiString texttrue (".T.");
55 static TCollection_AsciiString textfalse (".F.");
56 static TCollection_AsciiString textunknown (".U.");
60 //=======================================================================
61 //function : StepData_StepWriter
63 //=======================================================================
65 StepData_StepWriter::StepData_StepWriter(const Handle(StepData_StepModel)& amodel)
66 : thecurr (StepLong) , thefloatw (12)
68 themodel = amodel; thelabmode = thetypmode = 0;
69 thefile = new TColStd_HSequenceOfHAsciiString();
70 thesect = Standard_False; thefirst = Standard_True;
71 themult = Standard_False; thecomm = Standard_False;
72 thelevel = theindval = 0; theindent = Standard_False;
73 // Format flottant : reporte dans le FloatWriter
76 // .... Controle d Envoi des Flottants ....
78 //=======================================================================
79 //function : FloatWriter
81 //=======================================================================
83 Interface_FloatWriter& StepData_StepWriter::FloatWriter ()
84 { return thefloatw; } // s y reporter
87 //=======================================================================
88 //function : LabelMode
90 //=======================================================================
92 Standard_Integer& StepData_StepWriter::LabelMode ()
93 { return thelabmode; }
96 //=======================================================================
99 //=======================================================================
101 Standard_Integer& StepData_StepWriter::TypeMode ()
102 { return thetypmode; }
104 // .... Description des Scopes (AVANT Envoi) ....
107 //=======================================================================
108 //function : SetScope
110 //=======================================================================
112 void StepData_StepWriter::SetScope (const Standard_Integer numscope,
113 const Standard_Integer numin)
115 Standard_Integer nb = themodel->NbEntities();
116 if (numscope <= 0 || numscope > nb || numin <= 0 || numin > nb)
117 Interface_InterfaceMismatch::Raise("StepWriter : SetScope, out of range");
118 if (thescopenext.IsNull()) {
119 thescopebeg = new TColStd_HArray1OfInteger (1,nb); thescopebeg->Init(0);
120 thescopeend = new TColStd_HArray1OfInteger (1,nb); thescopeend->Init(0);
121 thescopenext = new TColStd_HArray1OfInteger (1,nb); thescopenext->Init(0);
123 else if (thescopenext->Value(numin) != 0) {
125 cout << "StepWriter : SetScope (scope : " << numscope << " entity : "
126 << numin << "), Entity already in a Scope"<<endl;
128 Interface_InterfaceMismatch::Raise("StepWriter : SetScope, already set");
130 thescopenext->SetValue(numin,-1); // nouvelle fin de scope
131 if (thescopebeg->Value(numscope) == 0) thescopebeg->SetValue(numscope,numin);
132 Standard_Integer lastin = thescopeend->Value(numscope);
133 if (lastin > 0) thescopenext->SetValue(lastin,numin);
134 thescopeend->SetValue(numscope,numin);
138 //=======================================================================
139 //function : IsInScope
141 //=======================================================================
143 Standard_Boolean StepData_StepWriter::IsInScope(const Standard_Integer num) const
145 if (thescopenext.IsNull()) return Standard_False;
146 return (thescopenext->Value(num) != 0);
149 // ###########################################################################
150 // ## ## ## ## ENVOI DES SECTIONS ## ## ## ##
152 // .... Envoi du Modele Complet ....
155 //=======================================================================
156 //function : SendModel
158 //=======================================================================
160 void StepData_StepWriter::SendModel(const Handle(StepData_Protocol)& protocol,
161 const Standard_Boolean headeronly)
163 StepData_WriterLib lib(protocol);
166 thefile->Append (new TCollection_HAsciiString("ISO-10303-21;"));
169 // .... Header : suite d entites sans Ident ....
171 Interface_EntityIterator header = themodel->Header();
173 for (header.Start(); header.More(); header.Next()) {
174 Handle(Standard_Transient) anent = header.Value();
176 // Write Entity via Lib (similaire a SendEntity)
177 Handle(StepData_ReadWriteModule) module; Standard_Integer CN;
178 if (lib.Select(anent,module,CN)) {
179 if (module->IsComplex(CN)) StartComplex();
181 TCollection_AsciiString styp;
182 if (thetypmode > 0) styp = module->ShortType(CN);
183 if (styp.Length() == 0) styp = module->StepType(CN);
186 module->WriteStep(CN,*this,anent);
187 if (module->IsComplex(CN)) EndComplex();
189 // Pas trouve ci-dessus ... tenter UndefinedEntity
190 DeclareAndCast(StepData_UndefinedEntity,und,anent);
191 if (und.IsNull()) continue;
192 if (und->IsComplex()) StartComplex();
193 und->WriteParams(*this);
194 if (und->IsComplex()) EndComplex();
199 if (headeronly) return;
201 // Data : Comme Header mais avec des Idents ... sinon le code est le meme
204 // .... Erreurs Globales (silya) ....
206 Handle(Interface_Check) achglob = themodel->GlobalCheck();
207 Standard_Integer nbfails = achglob->NbFails();
209 Comment(Standard_True);
210 SendComment("GLOBAL FAIL MESSAGES, recorded at Read time :");
211 for (Standard_Integer ifail = 1; ifail <= nbfails; ifail ++) {
212 SendComment (achglob->Fail(ifail));
214 Comment(Standard_False);
215 NewLine(Standard_False);
218 // .... Sortie des Entites une par une ....
220 Standard_Integer nb = themodel->NbEntities();
221 for (Standard_Integer i = 1 ; i <= nb; i ++) {
222 // Liste principale : on n envoie pas les Entites dans un Scope
223 // Elles le seront par l intermediaire du Scope qui les contient
224 if (!thescopebeg.IsNull()) { if (thescopenext->Value(i) != 0) continue; }
233 // .... DECOUPAGE DU FICHIER EN SECTIONS ....
236 //=======================================================================
237 //function : SendHeader
239 //=======================================================================
241 void StepData_StepWriter::SendHeader ()
243 NewLine(Standard_False);
244 thefile->Append (new TCollection_HAsciiString("HEADER;"));
245 thesect = Standard_True;
249 //=======================================================================
250 //function : SendData
252 //=======================================================================
254 void StepData_StepWriter::SendData ()
256 if (thesect) Interface_InterfaceMismatch::Raise("StepWriter : Data section");
257 NewLine(Standard_False);
258 thefile->Append (new TCollection_HAsciiString("DATA;"));
259 thesect = Standard_True;
263 //=======================================================================
266 //=======================================================================
268 void StepData_StepWriter::EndSec ()
270 thefile->Append (new TCollection_HAsciiString("ENDSEC;"));
271 thesect = Standard_False;
275 //=======================================================================
278 //=======================================================================
280 void StepData_StepWriter::EndFile ()
282 if (thesect) Interface_InterfaceMismatch::Raise("StepWriter : EndFile");
283 NewLine(Standard_False);
284 thefile->Append (new TCollection_HAsciiString("END-ISO-10303-21;"));
285 thesect = Standard_False;
288 // .... ENVOI D UNE ENTITE ....
291 //=======================================================================
292 //function : SendEntity
295 //=======================================================================
297 void StepData_StepWriter::SendEntity(const Standard_Integer num,
298 const StepData_WriterLib& lib)
301 Handle(Standard_Transient) anent = themodel->Entity(num);
302 Standard_Integer idnum = num , idtrue = 0;
304 // themodel->Number(anent) et-ou IdentLabel(anent)
305 if (thelabmode > 0) idtrue = themodel->IdentLabel(anent);
306 if (thelabmode == 1) idnum = idtrue;
307 if (idnum == 0) idnum = num;
308 if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d = ",idnum); //skl 29.01.2003
309 else sprintf(lident,"%d:#%d = ",idnum,idtrue); //skl 29.01.2003
311 // SendIdent repris , lident vient d etre calcule
313 thecurr.Add (lident);
314 themult = Standard_False;
316 // .... Traitement du Scope Eventuel
317 if (!thescopebeg.IsNull()) {
318 Standard_Integer numin = thescopebeg->Value(num);
321 for (Standard_Integer nument = numin; numin > 0; nument = numin) {
322 SendEntity(nument,lib);
323 numin = thescopenext->Value(nument);
329 // .... Envoi de l Entite proprement dite
331 // Write Entity via Lib
333 Handle(StepData_ReadWriteModule) module; Standard_Integer CN;
334 if (themodel->IsRedefinedContent(num)) {
335 // Entite Erreur : Ecrire le Contenu + les Erreurs en Commentaires
336 Handle(Interface_ReportEntity) rep = themodel->ReportEntity(num);
337 DeclareAndCast(StepData_UndefinedEntity,und,rep->Content());
339 thechecks.CCheck(num)->AddFail("Erroneous Entity, Content lost");
340 StartEntity(TCollection_AsciiString("!?LOST_DATA"));
342 thechecks.CCheck(num)->AddWarning("Erroneous Entity, equivalent content");
343 if (und->IsComplex()) AddString(" (",2);
344 und->WriteParams(*this);
345 if (und->IsComplex()) { AddString(") ",2); } //thelevel --; }
347 EndEntity (); // AVANT les Commentaires
348 NewLine(Standard_False);
349 Comment(Standard_True);
350 if (und.IsNull()) SendComment(" ERRONEOUS ENTITY, DATA LOST");
351 SendComment("On Entity above, Fail Messages recorded at Read time :");
352 Handle(Interface_Check) ach = rep->Check();
353 Standard_Integer nbfails = ach->NbFails();
354 for (Standard_Integer ifail = 1; ifail <= nbfails; ifail ++) {
355 SendComment (ach->Fail(ifail));
357 Comment(Standard_False);
358 NewLine(Standard_False);
362 else if (lib.Select(anent,module,CN)) {
363 if (module->IsComplex(CN)) StartComplex();
365 TCollection_AsciiString styp;
366 if (thetypmode > 0) styp = module->ShortType(CN);
367 if (styp.Length() == 0) styp = module->StepType(CN);
370 module->WriteStep(CN,*this,anent);
371 if (module->IsComplex(CN)) EndComplex();
375 // Pas trouve ci-dessus ... tenter UndefinedEntity
376 DeclareAndCast(StepData_UndefinedEntity,und,anent);
377 if (und.IsNull()) return;
378 if (und->IsComplex()) StartComplex();
379 und->WriteParams(*this);
380 if (und->IsComplex()) EndComplex();
385 // ###########################################################################
386 // ## ## ## CONSTITUTION DU TEXTE A ENVOYER ## ## ##
388 // Passer a la ligne. Ligne vide pas comptee sauf si evenempty == Standard_True
391 //=======================================================================
394 //=======================================================================
396 void StepData_StepWriter::NewLine (const Standard_Boolean evenempty)
398 if (evenempty || thecurr.Length() > 0) {
399 thefile->Append(thecurr.Moved());
401 Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
402 thecurr.SetInitial(indst); thecurr.Clear();
406 // Regrouper ligne en cours avec precedente; reste en cours sauf si newline
407 // == Standard_True, auquel cas on commence une nouvelle ligne
408 // Ne fait rien si : total correspondant > StepLong ou debut ou fin d`entite
411 //=======================================================================
412 //function : JoinLast
414 //=======================================================================
416 void StepData_StepWriter::JoinLast (const Standard_Boolean newline)
419 Handle(TCollection_HAsciiString) lst = thefile->Last();
420 Standard_Integer lng = lst->Length();
421 if (thecurr.Length() == 0) return;
422 if (lng + thecurr.Length() > StepLong) return;
423 if (lst->Value(1) == '#' || lst->Search(";") > 0) return;
424 lst->AssignCat(thecurr.Moved());
426 thecurr.Add (lst->ToCString(),lst->Length());
427 thefile->Remove(thefile->Length());
428 thecurr.SetInitial(0); .. inclus dans lst ...
435 //=======================================================================
438 //=======================================================================
440 void StepData_StepWriter::Indent (const Standard_Boolean onent)
441 { theindent = onent; }
444 //=======================================================================
445 //function : SendIdent
447 //=======================================================================
449 void StepData_StepWriter::SendIdent(const Standard_Integer ident)
452 sprintf(lident,"#%d =",ident);
454 thecurr.Add (lident);
455 themult = Standard_False;
459 //=======================================================================
460 //function : SendScope
462 //=======================================================================
464 void StepData_StepWriter::SendScope ()
465 { AddString(textscope); }
468 //=======================================================================
469 //function : SendEndscope
471 //=======================================================================
473 void StepData_StepWriter::SendEndscope ()
475 NewLine(Standard_False);
476 thefile->Append(new TCollection_HAsciiString(textendscope));
480 //=======================================================================
483 //=======================================================================
485 void StepData_StepWriter::Comment (const Standard_Boolean mode)
487 if (mode && !thecomm) AddString(textcomm,20);
488 if (!mode && thecomm) AddString(textendcomm);
493 //=======================================================================
494 //function : SendComment
496 //=======================================================================
498 void StepData_StepWriter::SendComment(const Handle(TCollection_HAsciiString)& text)
500 if (!thecomm) Interface_InterfaceMismatch::Raise("StepWriter : Comment");
501 AddString(text->ToCString(),text->Length());
505 //=======================================================================
506 //function : SendComment
508 //=======================================================================
510 void StepData_StepWriter::SendComment (const Standard_CString text)
512 if (!thecomm) Interface_InterfaceMismatch::Raise("StepWriter : Comment");
513 AddString(text,(Standard_Integer) strlen(text));
517 //=======================================================================
518 //function : StartEntity
520 //=======================================================================
522 void StepData_StepWriter::StartEntity(const TCollection_AsciiString& atype)
524 if (atype.Length() == 0) return;
526 if (thelevel != 1) Interface_InterfaceMismatch::Raise
527 ("StepWriter : StartEntity"); // decompte de parentheses mauvais ...
528 AddString(textendlist);
529 AddString(" ",1); //skl 29.01.2003
531 themult = Standard_True;
532 //AddString(" ",1); //skl 29.01.2003
535 theindval = thecurr.Length();
536 thecurr.SetInitial(0);
537 thefirst = Standard_True;
542 //=======================================================================
543 //function : StartComplex
545 //=======================================================================
547 void StepData_StepWriter::StartComplex ()
549 AddString("( ",2); //skl 29.01.2003
550 } // thelevel unchanged
553 //=======================================================================
554 //function : EndComplex
556 //=======================================================================
558 void StepData_StepWriter::EndComplex ()
559 { AddString(") ",2); } // thelevel unchanged
562 // .... SendField et ce qui va avec
565 //=======================================================================
566 //function : SendField
568 //=======================================================================
570 void StepData_StepWriter::SendField(const StepData_Field& fild,
571 const Handle(StepData_PDescr)& descr)
573 Standard_Boolean done = Standard_True;
574 Standard_Integer kind = fild.Kind (Standard_False); // valeur interne
577 DeclareAndCast(StepData_SelectMember,sm,fild.Transient());
578 SendSelect (sm,descr);
582 // ici les cas simples; ensuite on caste et on voit
583 case 0 : SendUndef(); break;
584 case 1 : Send (fild.Integer ()); break;
585 case 2 : SendBoolean (fild.Boolean ()); break;
586 case 3 : SendLogical (fild.Logical ()); break;
587 case 4 : SendEnum (fild.EnumText ()); break; // enum : descr ?
588 case 5 : Send (fild.Real ()); break;
589 case 6 : Send (fild.String ()); break;
590 case 7 : Send (fild.Entity ()); break;
591 case 8 : done = Standard_False; break;
592 case 9 : SendDerived (); break;
593 default: done = Standard_False; break;
597 // Que reste-t-il : les tableaux ...
598 Standard_Integer arity = fild.Arity();
599 if (arity == 0) { SendUndef(); return; } // PAS NORMAL
602 Standard_Integer i,low = fild.Lower(), up = low + fild.Length() - 1;
603 for (i = low; i <= up; i ++) {
604 kind = fild.ItemKind(i);
605 done = Standard_True;
607 case 0 : SendUndef(); break;
608 case 1 : Send (fild.Integer (i)); break;
609 case 2 : SendBoolean (fild.Boolean (i)); break;
610 case 3 : SendLogical (fild.Logical (i)); break;
611 case 4 : SendEnum (fild.EnumText (i)); break;
612 case 5 : Send (fild.Real (i)); break;
613 case 6 : Send (fild.String (i)); break;
614 case 7 : Send (fild.Entity (i)); break;
615 default: SendUndef(); done = Standard_False; break; // ANORMAL
623 Standard_Integer j,low1 = fild.Lower(1), up1 = low1 + fild.Length(1) - 1;
624 for (j = low1; j <= up1; j ++) {
625 Standard_Integer i=0,low2 = fild.Lower(2), up2 = low2 + fild.Length(2) - 1;
627 for (i = low2; i <= up2; i ++) {
628 kind = fild.ItemKind(i,j);
629 done = Standard_True;
631 case 0 : SendUndef(); break;
632 case 1 : Send (fild.Integer (i,j)); break;
633 case 2 : SendBoolean (fild.Boolean (i,j)); break;
634 case 3 : SendLogical (fild.Logical (i,j)); break;
635 case 4 : SendEnum (fild.EnumText (i,j)); break;
636 case 5 : Send (fild.Real (i,j)); break;
637 case 6 : Send (fild.String (i,j)); break;
638 case 7 : Send (fild.Entity (i,j)); break;
639 default: SendUndef(); done = Standard_False; break; // ANORMAL
650 //=======================================================================
651 //function : SendSelect
653 //=======================================================================
655 void StepData_StepWriter::SendSelect(const Handle(StepData_SelectMember)& sm,
656 const Handle(StepData_PDescr)& descr)
658 // Cas du SelectMember. Traiter le Select puis la valeur
659 // NB : traitement actuel non recursif (pas de SELNAME(SELNAME(..)) )
660 Standard_Boolean selname = Standard_False;
661 if (sm.IsNull()) return; // ??
663 selname = Standard_True;
664 // SendString (sm->Name());
665 // AddString(textlist); // SANS AJOUT DE PARAMETRE !!
666 OpenTypedSub (sm->Name());
668 Standard_Integer kind = sm->Kind();
670 case 0 : SendUndef(); break;
671 case 1 : Send (sm->Integer ()); break;
672 case 2 : SendBoolean (sm->Boolean ()); break;
673 case 3 : SendLogical (sm->Logical ()); break;
674 case 4 : SendEnum (sm->EnumText ()); break; // enum : descr ?
675 case 5 : Send (sm->Real ()); break;
676 case 6 : Send (sm->String ()); break;
677 case 8 : SendArrReal (Handle(StepData_SelectArrReal)::DownCast(sm)->ArrReal()); break;
678 default: break; // ??
680 if (selname) CloseSub();
684 //=======================================================================
685 //function : SendList
687 //=======================================================================
689 void StepData_StepWriter::SendList(const StepData_FieldList& list,
690 const Handle(StepData_ESDescr)& descr)
693 Standard_Integer i, nb = list.NbFields();
694 for (i = 1; i <= nb; i ++) {
695 Handle(StepData_PDescr) pde;
696 if (!descr.IsNull()) pde = descr->Field(i);
697 const StepData_Field fild = list.Field(i);
698 SendField (fild,pde);
703 // .... Send* de base
706 //=======================================================================
709 //=======================================================================
711 void StepData_StepWriter::OpenSub ()
715 thefirst = Standard_True;
720 //=======================================================================
721 //function : OpenTypedSub
723 //=======================================================================
725 void StepData_StepWriter::OpenTypedSub (const Standard_CString subtype)
728 if (subtype[0] != '\0') AddString (subtype,(Standard_Integer) strlen(subtype));
730 thefirst = Standard_True;
735 //=======================================================================
736 //function : CloseSub
738 //=======================================================================
740 void StepData_StepWriter::CloseSub ()
742 AddString(textendlist);
743 thefirst = Standard_False; // le parametre suivant une sous-liste n est donc pas 1er
748 //=======================================================================
749 //function : AddParam
751 //=======================================================================
753 void StepData_StepWriter::AddParam ()
755 if (!thefirst) AddString(textparam);
756 thefirst = Standard_False;
760 //=======================================================================
763 //=======================================================================
765 void StepData_StepWriter::Send (const Standard_Integer val)
769 sprintf(lval,"%d",val);
770 AddString(lval,(Standard_Integer) strlen(lval));
774 //=======================================================================
777 //=======================================================================
779 void StepData_StepWriter::Send (const Standard_Real val)
781 // Valeur flottante, expurgee de "0000" qui trainent et de "E+00"
783 Standard_Integer lng = thefloatw.Write(val,lval);
785 AddString(lval,lng); // gere le format specifique : si besoin est
788 // Send(String) : attention, on envoie un Texte ... donc entre ' '
790 //=======================================================================
793 //=======================================================================
795 void StepData_StepWriter::Send (const TCollection_AsciiString& val)
798 TCollection_AsciiString aval(val); // on duplique pour trafiquer si besoin
799 Standard_Integer nb = aval.Length(); Standard_Integer nn = nb;
800 aval.AssignCat('\''); // comme cela, Insert(i+1) est OK
802 // Conversion des Caracteres speciaux
803 for (Standard_Integer i = nb; i > 0; i --) {
804 char uncar = aval.Value(i);
805 if (uncar == '\'') { aval.Insert(i+1,'\''); nn ++; continue; }
806 if (uncar == '\\') { aval.Insert(i+1,'\\'); nn ++; continue; }
807 if (uncar == '\n') { aval.SetValue(i,'\\'); aval.Insert(i+1,'\\');
808 aval.Insert(i+1,'N' ); nn += 2; continue; }
809 if (uncar == '\t') { aval.SetValue(i,'\\'); aval.Insert(i+1,'\\');
810 aval.Insert(i+1,'T' ); nn += 2; continue; }
812 //:i2 abv 31 Aug 98: ProSTEP TR9: avoid wrapping text or do it at spaces
816 //:i2 AddString ("\'",1); nn ++;
818 // Attention au depassement des 72 caracteres
819 if (thecurr.CanGet(nn)) AddString(aval,0);
822 thefile->Append(thecurr.Moved());
823 Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
824 if ( indst+nn <= StepLong ) thecurr.SetInitial(indst);
825 else thecurr.SetInitial(0);
826 if ( thecurr.CanGet(nn) ) AddString(aval,0);
829 if (nn <= StepLong) {
830 thecurr.Add (aval); // Ca yet, on a tout epuise
831 thecurr.FreezeInitial();
834 Standard_Integer stop = StepLong; // position of last separator
835 for ( ; stop > 0 && aval.Value(stop) != ' '; stop-- );
838 for ( ; stop > 0 && aval.Value(stop) != '\\'; stop-- );
841 for ( ; stop > 0 && aval.Value(stop) != '_'; stop-- );
842 if ( ! stop ) stop = StepLong;
845 TCollection_AsciiString bval = aval.Split(stop);
846 thefile->Append(new TCollection_HAsciiString(aval));
854 // Il faut tronconner ... lignes limitees a 72 caracteres (StepLong)
855 Standard_Integer ncurr = thecurr.Length();
856 Standard_Integer nbuff = StepLong - ncurr;
857 thecurr.Add (aval.ToCString(),nbuff);
858 thefile->Append(thecurr.Moved());
859 aval.Remove(1,nbuff);
862 if (nn <= StepLong) {
863 thecurr.Add (aval); // Ca yet, on a tout epuise
864 thecurr.FreezeInitial();
867 TCollection_AsciiString bval = aval.Split(StepLong);
868 thefile->Append(new TCollection_HAsciiString(bval));
873 // thecurr.Add('\''); deja mis dans aval au debut
877 //=======================================================================
880 //=======================================================================
882 void StepData_StepWriter::Send (const Handle(Standard_Transient)& val)
887 // Interface_InterfaceMismatch::Raise("StepWriter : Sending Null Reference");
888 thechecks.CCheck(thenum)->AddFail("Null Reference");
890 Comment(Standard_True);
891 SendComment(" NUL REF ");
892 Comment(Standard_False);
895 Standard_Integer num = themodel->Number(val);
896 // String ? (si non repertoriee dans le Modele)
898 if (val->IsKind(STANDARD_TYPE(TCollection_HAsciiString))) {
899 DeclareAndCast(TCollection_HAsciiString,strval,val);
900 Send (TCollection_AsciiString(strval->ToCString()));
903 // SelectMember ? (toujours, si non repertoriee)
904 // mais attention, pas de description attachee
905 else if (val->IsKind(STANDARD_TYPE(StepData_SelectMember))) {
906 DeclareAndCast(StepData_SelectMember,sm,val);
907 Handle(StepData_PDescr) descr; // null
908 SendSelect (sm,descr);
910 // Sinon, PAS NORMAL !
912 thechecks.CCheck(thenum)->AddFail("UnknownReference");
914 Comment(Standard_True);
915 SendComment(" UNKNOWN REF ");
916 Comment(Standard_False);
917 // Interface_InterfaceMismatch::Raise("StepWriter : Sending Unknown Reference");
920 // Cas normal : une bonne Entite, on envoie son Ident.
922 Standard_Integer idnum = num, idtrue = 0;
923 if (thelabmode > 0) idtrue = themodel->IdentLabel(val);
924 if (thelabmode == 1) idnum = idtrue;
925 if (idnum == 0) idnum = num;
926 if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d",idnum);
927 else sprintf(lident,"%d:#%d",idnum,idtrue);
929 AddString(lident,(Standard_Integer) strlen(lident));
934 //=======================================================================
935 //function : SendBoolean
937 //=======================================================================
939 void StepData_StepWriter::SendBoolean (const Standard_Boolean val)
941 if (val) SendString(texttrue);
942 else SendString(textfalse);
946 //=======================================================================
947 //function : SendLogical
949 //=======================================================================
951 void StepData_StepWriter::SendLogical (const StepData_Logical val)
953 if (val == StepData_LTrue) SendString(texttrue);
954 else if (val == StepData_LFalse) SendString(textfalse);
955 else SendString(textunknown);
959 // SendString : attention, on donne l'intitule exact
961 //=======================================================================
962 //function : SendString
964 //=======================================================================
966 void StepData_StepWriter::SendString (const TCollection_AsciiString& val)
972 // SendString : attention, on donne l'intitule exact
974 //=======================================================================
975 //function : SendString
977 //=======================================================================
979 void StepData_StepWriter::SendString (const Standard_CString val)
982 AddString(val,(Standard_Integer) strlen(val));
985 // SendEnum : attention, on envoie un intitule d'Enum ... donc entre . .
987 //=======================================================================
988 //function : SendEnum
990 //=======================================================================
992 void StepData_StepWriter::SendEnum (const TCollection_AsciiString& val)
994 if (val.Length() == 1 && val.Value(1) == '$') { SendUndef(); return; }
996 TCollection_AsciiString aValue = val;
997 if (aValue.Value(1) != '.') aValue.Prepend('.');
998 if (aValue.Value(aValue.Length()) != '.') aValue+='.';
1003 // SendEnum : attention, on envoie un intitule d'Enum ... donc entre . .
1005 //=======================================================================
1006 //function : SendEnum
1008 //=======================================================================
1010 void StepData_StepWriter::SendEnum (const Standard_CString val)
1013 if (val[0] == '$' && val[1] == '\0') { SendUndef(); return; }
1014 TCollection_AsciiString aValue(val);
1019 //=======================================================================
1020 //function : SendArrReal
1022 //=======================================================================
1024 void StepData_StepWriter::SendArrReal (const Handle(TColStd_HArray1OfReal) &anArr)
1026 AddString(textlist);
1027 if(anArr->Length()>0) {
1029 Send(anArr->Value(1));
1030 for( Standard_Integer i=2; i<=anArr->Length(); i++) {
1031 // AddString(textparam);
1033 Send(anArr->Value(i));
1036 AddString(textendlist);
1040 //=======================================================================
1041 //function : SendUndef
1043 //=======================================================================
1045 void StepData_StepWriter::SendUndef ()
1048 AddString(textundef);
1052 //=======================================================================
1053 //function : SendDerived
1055 //=======================================================================
1057 void StepData_StepWriter::SendDerived ()
1060 AddString(textderived);
1064 // EndEntity : s'il faut mettre ; a la ligne, l'aligner sur debut d'entite ...
1066 //=======================================================================
1067 //function : EndEntity
1069 //=======================================================================
1071 void StepData_StepWriter::EndEntity ()
1073 if (thelevel != 1) Interface_InterfaceMismatch::Raise
1074 ("StepWriter : EndEntity"); // decompte de parentheses mauvais ...
1075 AddString(textendent);
1076 thelevel = 0; // on garde theindval : sera traite au prochain NewLine
1077 Standard_Boolean indent = theindent; theindent = Standard_False;
1078 NewLine(Standard_False); theindent = indent;
1079 themult = Standard_False;
1080 // pour forcer indentation si necessaire
1084 // gestion de la ligne courante (cf aussi NewLine/JoinLine)
1086 //=======================================================================
1087 //function : AddString
1089 //=======================================================================
1091 void StepData_StepWriter::AddString(const TCollection_AsciiString& astr,
1092 const Standard_Integer more)
1094 while (!thecurr.CanGet(astr.Length() + more)) {
1095 thefile->Append(thecurr.Moved());
1096 Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1097 thecurr.SetInitial(indst);
1103 //=======================================================================
1104 //function : AddString
1106 //=======================================================================
1108 void StepData_StepWriter::AddString(const Standard_CString astr,
1109 const Standard_Integer lnstr,
1110 const Standard_Integer more)
1112 while (!thecurr.CanGet(lnstr + more)) {
1113 thefile->Append(thecurr.Moved());
1114 Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1115 thecurr.SetInitial(indst);
1117 thecurr.Add(astr,lnstr);
1124 //=======================================================================
1125 //function : CheckList
1127 //=======================================================================
1129 Interface_CheckIterator StepData_StepWriter::CheckList () const
1135 //=======================================================================
1136 //function : NbLines
1138 //=======================================================================
1140 Standard_Integer StepData_StepWriter::NbLines () const
1141 { return thefile->Length(); }
1144 //=======================================================================
1147 //=======================================================================
1149 Handle(TCollection_HAsciiString) StepData_StepWriter::Line
1150 (const Standard_Integer num) const
1151 { return thefile->Value(num); }
1154 //=======================================================================
1157 //=======================================================================
1159 Standard_Boolean StepData_StepWriter::Print (Standard_OStream& S)
1161 Standard_Boolean isGood = (S.good());
1162 Standard_Integer nb = thefile->Length();
1163 for (Standard_Integer i = 1; i <= nb && isGood; i ++)
1164 S << thefile->Value(i)->ToCString() << "\n";
1167 isGood = (S && S.good());