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