b51f9dae36856a6f3b060f66f336e67a804abbe7
[occt.git] / src / FSD / FSD_CmpFile.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <FSD_CmpFile.ixx>
16 #include <OSD.hxx>
17
18 #include <Storage_StreamModeError.hxx>
19 #include <Storage_StreamUnknownTypeError.hxx>
20 #include <Standard_PCharacter.hxx>
21
22 // Propagate the improvement (BUC60808) on all platforms
23 // #ifdef WNT
24 #define BUC60808
25 // BUC60808 : standard output in MS Visual C++ limites the quantity of figures (digits)
26 // in part of number after fixed point. The quantity of figures after fixed point 
27 // could not be more than 15 when we output double number using standard MS VS output operator '<<'.
28 // For example, the maximum double value DBL_MAX = 1.7976931348623157e+308 (see float.h) after 
29 // cout<<setprecision(17)<<DBL_MAX  becomes 1.79769313486232e+308  in stream of output 
30 // (it could be a file stream). When the number 1.79769313486232e+308 is read from the
31 // i/o streame (file, for example) it occurs more than allowed maximum value of double 
32 // type - 1.7976931348623157e+308.  Such value is considered as infinite. When it is written 
33 // to file (for example)  again it is written as 1.#INF. Such value can't be read from file next time.
34 //#endif
35
36 const Standard_CString MAGICNUMBER = "CMPFILE";
37
38 //=======================================================================
39 //function : FSD_CmpFile
40 //purpose  : 
41 //=======================================================================
42
43 FSD_CmpFile::FSD_CmpFile()
44 {
45
46 }
47
48 //=======================================================================
49 //function : IsGoodFileType
50 //purpose  : INFO SECTION
51 //           write
52 //=======================================================================
53
54 Storage_Error FSD_CmpFile::IsGoodFileType(const TCollection_AsciiString& aName)
55 {
56   FSD_CmpFile      f;
57   Storage_Error s;
58
59   s = f.Open(aName,Storage_VSRead);
60
61   if (s == Storage_VSOk) {
62     TCollection_AsciiString l;
63     Standard_Size        len = strlen(FSD_CmpFile::MagicNumber());
64
65     f.ReadChar(l,len);
66
67     f.Close();
68
69     if (strncmp(FSD_CmpFile::MagicNumber(),l.ToCString(),len) != 0) {
70       s = Storage_VSFormatError;
71     }
72   }
73
74   return s;
75 }
76
77 //=======================================================================
78 //function : Open
79 //purpose  : 
80 //=======================================================================
81
82 Storage_Error FSD_CmpFile::Open(const TCollection_AsciiString& aName,const Storage_OpenMode aMode)
83 {
84   Storage_Error result = Storage_VSOk;
85
86   SetName(aName);
87
88   if (OpenMode() == Storage_VSNone) {
89
90 #if !defined(IRIX) && !defined(DECOSF1)
91     if (aMode == Storage_VSRead) {
92       myStream.open(aName.ToCString(),ios::in|ios::binary); // ios::nocreate is not portable
93     }
94     else if (aMode == Storage_VSWrite) {
95       myStream.open(aName.ToCString(),ios::out|ios::binary);
96     }
97     else if (aMode == Storage_VSReadWrite) {
98       myStream.open(aName.ToCString(),ios::in|ios::out|ios::binary);
99     }
100 #else
101     if (aMode == Storage_VSRead) {
102       myStream.open(aName.ToCString(),ios::in); // ios::nocreate is not portable
103     }
104     else if (aMode == Storage_VSWrite) {
105       myStream.open(aName.ToCString(),ios::out);
106     }
107     else if (aMode == Storage_VSReadWrite) {
108       myStream.open(aName.ToCString(),ios::in|ios::out);
109     }
110 #endif
111
112     if (myStream.fail()) {
113       result = Storage_VSOpenError;
114     }
115     else {
116       myStream.precision(17);
117       myStream.imbue (std::locale::classic()); // use always C locale
118       SetOpenMode(aMode);
119     }
120   }
121   else {
122     result = Storage_VSAlreadyOpen;
123   }
124   return result;
125 }
126
127 //=======================================================================
128 //function : IsEnd
129 //purpose  : 
130 //=======================================================================
131
132 Standard_Boolean FSD_CmpFile::IsEnd()
133 {
134   return myStream.eof();
135 }
136
137 //=======================================================================
138 //function : Close
139 //purpose  : 
140 //=======================================================================
141
142 Storage_Error FSD_CmpFile::Close()
143 {
144   Storage_Error result = Storage_VSOk;
145
146   if (OpenMode() != Storage_VSNone) {
147     myStream.close();
148     SetOpenMode(Storage_VSNone);
149   }
150   else {
151     result = Storage_VSNotOpen;
152   }
153
154   return result;
155 }
156
157 //=======================================================================
158 //function : MagicNumber
159 //purpose  : ------------------ PROTECTED
160 //=======================================================================
161
162 const Standard_CString FSD_CmpFile::MagicNumber()
163 {
164   return MAGICNUMBER;
165 }
166
167 //=======================================================================
168 //function : FlushEndOfLine
169 //purpose  : 
170 //=======================================================================
171
172 void FSD_CmpFile::FlushEndOfLine()
173 {
174   TCollection_AsciiString aDummy;
175   ReadLine (aDummy); // flush is nothing more than to read till the line-break
176   /*
177   static char Buffer[8192];
178   char c;
179   Standard_Boolean IsEnd = Standard_False;
180
181   while (!IsEnd && !FSD_CmpFile::IsEnd()) {
182     Buffer[0] = '\0';
183     myStream.get(Buffer,8192,'\n');
184
185     if (myStream.get(c) && c != '\r' && c != '\n') {
186     }
187     else {
188       IsEnd = Standard_True;
189     }
190   }
191   */
192 }
193
194 //=======================================================================
195 //function : ReadLine
196 //purpose  : read from the current position to the end of line.
197 //=======================================================================
198
199 void FSD_CmpFile::ReadLine(TCollection_AsciiString& buffer)
200 {
201   char Buffer[8193];
202   //char c;
203   Standard_Boolean IsEnd = Standard_False;
204   
205   buffer.Clear();
206
207   while (!IsEnd && !FSD_CmpFile::IsEnd()) {
208     Buffer[0] = '\0';
209     //myStream.get(Buffer,8192,'\n');
210     myStream.getline(Buffer,8192,'\n');
211     for (Standard_Size lv = (strlen(Buffer)- 1); lv > 1 && (Buffer[lv] == '\r' || Buffer[lv] == '\n') ;lv--) {
212       Buffer[lv] = '\0';
213     }  
214     
215 //     if (myStream.get(c) && c != '\r' && c != '\n') {
216 //       buffer += Buffer;
217 //       buffer += c;
218 //     }
219 //     else {
220       buffer += Buffer;
221       IsEnd = Standard_True;
222 //     }
223   }
224 }
225
226 //=======================================================================
227 //function : WriteExtendedLine
228 //purpose  : write from the current position to the end of line.
229 //=======================================================================
230
231 void FSD_CmpFile::WriteExtendedLine(const TCollection_ExtendedString& buffer)
232 {
233 #if 0
234   Standard_ExtString extBuffer;
235   Standard_Integer   i,c,d;
236
237   extBuffer = buffer.ToExtString();
238
239   for (i = 0; i < buffer.Length(); i++) {
240     c = (extBuffer[i] & 0x0000FF00 ) >> 8 ;
241     d = extBuffer[i] & 0x000000FF;
242
243     myStream << (char)c << (char)d;
244   }
245
246   myStream << (char)0 << "\n";
247 #endif
248   Standard_ExtString extBuffer;
249   Standard_Integer   i;
250
251   extBuffer = buffer.ToExtString();
252   PutInteger(buffer.Length());
253   for (i = 0; i < buffer.Length(); i++) {
254     PutExtCharacter(extBuffer[i]);
255   }
256
257   myStream << "\n";
258 }
259
260 //=======================================================================
261 //function : ReadExtendedLine
262 //purpose  : 
263 //=======================================================================
264
265 void FSD_CmpFile::ReadExtendedLine(TCollection_ExtendedString& buffer)
266 {
267   Standard_ExtCharacter c;
268   Standard_Integer i;
269
270   GetInteger(i);
271
272   for (i = 0; i < buffer.Length(); i++) {
273     GetExtCharacter(c);
274     buffer += c;
275   }
276
277   FlushEndOfLine();
278 }
279
280 //=======================================================================
281 //function : ReadChar
282 //purpose  : read <rsize> character from the current position.
283 //=======================================================================
284
285 void FSD_CmpFile::ReadChar(TCollection_AsciiString& buffer, const Standard_Size rsize)
286 {
287   char             c;
288   Standard_Size ccount = 0;
289
290   buffer.Clear();
291
292   while (!IsEnd() && (ccount < rsize)) {
293     myStream.get(c);
294     buffer += c;
295     ccount++;
296   }
297 }
298
299 //=======================================================================
300 //function : ReadString
301 //purpose  : read from the first none space character position to the end of line.
302 //=======================================================================
303
304 void FSD_CmpFile::ReadString(TCollection_AsciiString& buffer)
305 {
306   char Buffer[8193];
307   char *bpos;
308   Standard_Boolean IsEnd = Standard_False,isFirstTime = Standard_True;
309   
310   buffer.Clear();
311   
312   while (!IsEnd && !FSD_CmpFile::IsEnd()) {
313     Buffer[0] = '\0';
314     //myStream.get(Buffer,8192,'\n');
315     myStream.getline(Buffer,8192,'\n');
316     for (Standard_Size lv = (strlen(Buffer)- 1); lv > 1 && (Buffer[lv] == '\r' || Buffer[lv] == '\n') ;lv--) {
317       Buffer[lv] = '\0';
318     }  
319     bpos = Buffer;
320
321     // LeftAdjust
322     //
323     if (isFirstTime) {
324       isFirstTime = Standard_False;
325       while (*bpos == '\n' || *bpos == ' ') bpos++;
326     }
327 //     char c;
328 //     if (myStream.get(c) && c != '\n') {
329 //       buffer += bpos;
330 //       buffer += c;
331 //     }
332 //     else {
333       buffer += bpos;
334       IsEnd = Standard_True;
335 //     }
336   }
337 }
338
339 //=======================================================================
340 //function : ReadWord
341 //purpose  : read from the current position to the next white space or end of line.
342 //=======================================================================
343
344 void FSD_CmpFile::ReadWord(TCollection_AsciiString& buffer)
345 {
346   char c = '\0';
347   char b[8193],*tmpb;
348   Standard_Boolean IsEnd = Standard_False;
349   Standard_Integer i;
350
351   tmpb = b;
352   memset(b,'\0',8193);
353   buffer.Clear();
354
355   while (!IsEnd && !FSD_CmpFile::IsEnd()) {
356     myStream.get(c);
357     if ((c != ' ') && (c != '\n')) IsEnd = Standard_True;
358   }
359
360   IsEnd = Standard_False;
361   i = 0;
362
363   while (!IsEnd && !FSD_CmpFile::IsEnd()) {
364     if (i == 8192) {
365       buffer += b;
366       tmpb = b;
367       memset(b,'\0',8193);
368       i = 0;
369     }
370     *tmpb = c;
371     tmpb++; i++;
372     myStream.get(c);
373     if ((c == '\n') || (c == ' ')) IsEnd = Standard_True;
374   }
375
376   buffer += b;
377 }
378
379 //=======================================================================
380 //function : FindTag
381 //purpose  : 
382 //=======================================================================
383
384 Storage_Error FSD_CmpFile::FindTag(const Standard_CString aTag)
385 {
386   TCollection_AsciiString l;
387   
388   ReadString(l);
389
390   while ((strcmp(l.ToCString(),aTag) != 0) && !IsEnd()) {
391     ReadString(l);
392   }
393
394   if (IsEnd()) {
395     return Storage_VSSectionNotFound;
396   }
397   else {
398     return Storage_VSOk;
399   }
400 }
401
402 //=======================================================================
403 //function : SkipObject
404 //purpose  : 
405 //=======================================================================
406
407 void FSD_CmpFile::SkipObject()
408 {
409   FlushEndOfLine();
410 }
411
412 //=======================================================================
413 //function : PutReference
414 //purpose  : ---------------------- PUBLIC : PUT
415 //=======================================================================
416
417 Storage_BaseDriver& FSD_CmpFile::PutReference(const Standard_Integer aValue)
418 {
419   myStream << aValue << " ";
420   if (myStream.bad()) Storage_StreamWriteError::Raise();
421   return *this;
422 }
423
424 //=======================================================================
425 //function : PutCharacter
426 //purpose  : 
427 //=======================================================================
428
429 Storage_BaseDriver& FSD_CmpFile::PutCharacter(const Standard_Character aValue)
430 {
431   unsigned short i;
432
433   i = aValue;
434   myStream << i << " ";
435   if (myStream.bad()) Storage_StreamWriteError::Raise();
436   return *this;
437 }
438
439 //=======================================================================
440 //function : PutExtCharacter
441 //purpose  : 
442 //=======================================================================
443
444 Storage_BaseDriver& FSD_CmpFile::PutExtCharacter(const Standard_ExtCharacter aValue)
445 {
446   myStream << aValue << " ";
447   if (myStream.bad()) Storage_StreamWriteError::Raise();
448   return *this;
449 }
450
451 //=======================================================================
452 //function : PutInteger
453 //purpose  : 
454 //=======================================================================
455
456 Storage_BaseDriver& FSD_CmpFile::PutInteger(const Standard_Integer aValue)
457 {
458   myStream << aValue << " ";
459   if (myStream.bad()) Storage_StreamWriteError::Raise();
460   return *this;
461 }
462
463 //=======================================================================
464 //function : PutBoolean
465 //purpose  : 
466 //=======================================================================
467
468 Storage_BaseDriver& FSD_CmpFile::PutBoolean(const Standard_Boolean aValue)
469 {
470   myStream << ((Standard_Integer)aValue) << " ";
471   if (myStream.bad()) Storage_StreamWriteError::Raise();
472   return *this;
473 }
474
475 //=======================================================================
476 //function : PutReal
477 //purpose  : 
478 //=======================================================================
479
480 Storage_BaseDriver& FSD_CmpFile::PutReal(const Standard_Real aValue)
481 {
482   myStream << ((Standard_Real)aValue) << " ";
483   if (myStream.bad()) Storage_StreamWriteError::Raise();
484   return *this;
485 }
486
487 //=======================================================================
488 //function : PutShortReal
489 //purpose  : 
490 //=======================================================================
491
492 Storage_BaseDriver& FSD_CmpFile::PutShortReal(const Standard_ShortReal aValue)
493 {
494   myStream << aValue << " ";
495   if (myStream.bad()) Storage_StreamWriteError::Raise();
496   return *this;
497 }
498
499 //=======================================================================
500 //function : GetReference
501 //purpose  : ----------------- PUBLIC : GET
502 //=======================================================================
503
504 Storage_BaseDriver& FSD_CmpFile::GetReference(Standard_Integer& aValue)
505 {
506   if (!(myStream >> aValue)) Storage_StreamTypeMismatchError::Raise();
507
508   return *this;
509 }
510
511 //=======================================================================
512 //function : GetCharacter
513 //purpose  : 
514 //=======================================================================
515
516 Storage_BaseDriver& FSD_CmpFile::GetCharacter(Standard_Character& aValue)
517 {
518   unsigned short i = 0;
519   if (!(myStream >> i)) {
520     // SGI : donne une erreur mais a une bonne valeur pour les caracteres ecrits
521     //       signes (-80 fait ios::badbit, mais la variable i est initialisee)
522     //
523     if (i == 0) Storage_StreamTypeMismatchError::Raise();
524     myStream.clear(ios::goodbit);
525   }
526   aValue = (char)i;
527
528   return *this;
529 }
530
531 //=======================================================================
532 //function : GetExtCharacter
533 //purpose  : 
534 //=======================================================================
535
536 Storage_BaseDriver& FSD_CmpFile::GetExtCharacter(Standard_ExtCharacter& aValue)
537 {
538   if (!(myStream >> aValue)) Storage_StreamTypeMismatchError::Raise();
539   
540   return *this;
541 }
542
543 //=======================================================================
544 //function : GetInteger
545 //purpose  : 
546 //=======================================================================
547
548 Storage_BaseDriver& FSD_CmpFile::GetInteger(Standard_Integer& aValue)
549 {
550   if (!(myStream >> aValue)) Storage_StreamTypeMismatchError::Raise();
551
552   return *this;
553 }
554
555 //=======================================================================
556 //function : GetBoolean
557 //purpose  : 
558 //=======================================================================
559
560 Storage_BaseDriver& FSD_CmpFile::GetBoolean(Standard_Boolean& aValue)
561 {
562   if (!(myStream >> aValue)) Storage_StreamTypeMismatchError::Raise();
563
564   return *this;
565 }
566
567 //=======================================================================
568 //function : GetReal
569 //purpose  : 
570 //=======================================================================
571
572 Storage_BaseDriver& FSD_CmpFile::GetReal(Standard_Real& aValue)
573 {
574 #ifdef BUC60808
575   char realbuffer[100];
576
577   realbuffer[0] = '\0';
578   if (!(myStream >> realbuffer)) {
579     cerr << "%%%ERROR: read error of double at offset " << myStream.tellg() << endl;
580     cerr << "\t buffer is" << realbuffer<< endl;
581     Storage_StreamTypeMismatchError::Raise();
582   }
583   if (!OSD::CStringToReal(realbuffer,aValue)) {
584     cerr << "%%%ERROR: read error of double at offset " << myStream.tellg() << endl;
585     cerr << "\t buffer is" << realbuffer<< endl;
586     Storage_StreamTypeMismatchError::Raise();
587   }
588
589   return *this;
590 #else
591   if (!(myStream >> aValue)) Storage_StreamTypeMismatchError::Raise();
592
593   return *this;
594 #endif
595 }
596
597 //=======================================================================
598 //function : GetShortReal
599 //purpose  : 
600 //=======================================================================
601
602 Storage_BaseDriver& FSD_CmpFile::GetShortReal(Standard_ShortReal& aValue)
603 {
604 #ifdef BUC60808
605   char realbuffer[100];
606   Standard_Real r = 0.0;
607
608   realbuffer[0] = '\0';
609   if (!(myStream >> realbuffer)) Storage_StreamTypeMismatchError::Raise();
610   if (!OSD::CStringToReal(realbuffer,r))
611     Storage_StreamTypeMismatchError::Raise();
612
613   aValue = (Standard_ShortReal)r;
614
615   return *this;
616 #else
617   if (!(myStream >> aValue)) Storage_StreamTypeMismatchError::Raise();
618  return *this;
619 #endif
620 }
621
622 //=======================================================================
623 //function : Destroy
624 //purpose  : 
625 //=======================================================================
626
627 void FSD_CmpFile::Destroy()
628 {
629   if (OpenMode() != Storage_VSNone) {
630     Close();
631   }
632 }
633
634 //=======================================================================
635 //function : BeginWriteInfoSection
636 //purpose  : -------------------------- INFO : WRITE
637 //=======================================================================
638
639 Storage_Error FSD_CmpFile::BeginWriteInfoSection() 
640 {
641   myStream << FSD_CmpFile::MagicNumber() << '\n';
642   myStream << "BEGIN_INFO_SECTION\n";
643   if (myStream.bad()) Storage_StreamWriteError::Raise();
644
645   return Storage_VSOk;
646 }
647
648 //=======================================================================
649 //function : WriteInfo
650 //purpose  : 
651 //=======================================================================
652
653 void FSD_CmpFile::WriteInfo(const Standard_Integer nbObj,
654                          const TCollection_AsciiString& dbVersion,
655                          const TCollection_AsciiString& date,
656                          const TCollection_AsciiString& schemaName,
657                          const TCollection_AsciiString& schemaVersion,
658                          const TCollection_ExtendedString& appName,
659                          const TCollection_AsciiString& appVersion,
660                          const TCollection_ExtendedString& dataType,
661                          const TColStd_SequenceOfAsciiString& userInfo) 
662 {
663   Standard_Integer i;
664
665   myStream << nbObj;
666   myStream << "\n";
667   myStream << dbVersion.ToCString() << "\n";
668   myStream << date.ToCString() << "\n";
669   myStream << schemaName.ToCString() << "\n";
670   myStream << schemaVersion.ToCString() << "\n";
671   WriteExtendedLine(appName);
672   myStream << appVersion.ToCString() << "\n";
673   WriteExtendedLine(dataType);
674   myStream << userInfo.Length() << "\n";
675
676   if (myStream.bad()) Storage_StreamWriteError::Raise();
677
678   for (i = 1; i <= userInfo.Length(); i++) {
679     myStream << userInfo.Value(i).ToCString() << "\n";
680     if (myStream.bad()) Storage_StreamWriteError::Raise();
681   }
682 }
683
684 //=======================================================================
685 //function : EndWriteInfoSection
686 //purpose  : read
687 //=======================================================================
688
689 Storage_Error FSD_CmpFile::EndWriteInfoSection() 
690 {
691   myStream << "END_INFO_SECTION\n";
692   if (myStream.bad())  Storage_StreamWriteError::Raise();
693   return Storage_VSOk;
694 }
695
696 //=======================================================================
697 //function : BeginReadInfoSection
698 //purpose  : 
699 //=======================================================================
700
701 Storage_Error FSD_CmpFile::BeginReadInfoSection() 
702 {
703   Storage_Error s;
704   TCollection_AsciiString l;
705   Standard_Size        len = strlen(FSD_CmpFile::MagicNumber());
706
707   ReadChar(l,len);
708   
709   if (strncmp(FSD_CmpFile::MagicNumber(),l.ToCString(),len) != 0) {
710     s = Storage_VSFormatError;
711   }
712   else {
713     s = FindTag("BEGIN_INFO_SECTION");
714   }
715
716   return s;
717 }
718
719 //=======================================================================
720 //function : ReadInfo
721 //purpose  : ------------------- INFO : READ
722 //=======================================================================
723
724 void FSD_CmpFile::ReadInfo(Standard_Integer& nbObj,
725                         TCollection_AsciiString& dbVersion,
726                         TCollection_AsciiString& date,
727                         TCollection_AsciiString& schemaName,
728                         TCollection_AsciiString& schemaVersion,
729                         TCollection_ExtendedString& appName,
730                         TCollection_AsciiString& appVersion,
731                         TCollection_ExtendedString& dataType,
732                         TColStd_SequenceOfAsciiString& userInfo) 
733 {
734   if (!(myStream >> nbObj)) Storage_StreamTypeMismatchError::Raise();
735
736   FlushEndOfLine();
737
738   ReadLine(dbVersion);
739   ReadLine(date);
740   ReadLine(schemaName);
741   ReadLine(schemaVersion);
742   ReadExtendedLine(appName);
743   ReadLine(appVersion);
744   ReadExtendedLine(dataType);
745
746   Standard_Integer i,len = 0;
747
748   if (!(myStream >> len)) Storage_StreamTypeMismatchError::Raise();
749
750   FlushEndOfLine();
751
752   TCollection_AsciiString line;
753
754   for (i = 1; i <= len && !IsEnd(); i++) {
755     ReadLine(line);
756     userInfo.Append(line);
757     line.Clear();
758   }
759 }
760
761 //=======================================================================
762 //function : EndReadInfoSection
763 //purpose  : COMMENTS SECTION
764 //           write
765 //=======================================================================
766
767 Storage_Error FSD_CmpFile::EndReadInfoSection() 
768 {
769   return FindTag("END_INFO_SECTION");
770 }
771
772 //=======================================================================
773 //function : BeginWriteCommentSection
774 //purpose  : ---------------- COMMENTS : WRITE
775 //=======================================================================
776
777 Storage_Error FSD_CmpFile::BeginWriteCommentSection() 
778 {
779   myStream << "BEGIN_COMMENT_SECTION\n";
780   if (myStream.bad()) Storage_StreamWriteError::Raise();
781   return Storage_VSOk;
782 }
783
784 //=======================================================================
785 //function : WriteComment
786 //purpose  : 
787 //=======================================================================
788
789 void FSD_CmpFile::WriteComment(const TColStd_SequenceOfExtendedString& aCom)
790 {
791  Standard_Integer i,aSize;
792
793  aSize = aCom.Length();
794  myStream << aSize << "\n";
795  if (myStream.bad()) Storage_StreamWriteError::Raise();
796
797  for (i = 1; i <= aSize; i++) {
798    WriteExtendedLine(aCom.Value(i));
799    if (myStream.bad()) Storage_StreamWriteError::Raise();
800  }
801 }
802
803 //=======================================================================
804 //function : EndWriteCommentSection
805 //purpose  : read
806 //=======================================================================
807
808 Storage_Error FSD_CmpFile::EndWriteCommentSection() 
809 {
810   myStream << "END_COMMENT_SECTION\n";
811   if (myStream.bad()) Storage_StreamWriteError::Raise();
812   return Storage_VSOk;
813 }
814
815 //=======================================================================
816 //function : BeginReadCommentSection
817 //purpose  : ---------------- COMMENTS : READ
818 //=======================================================================
819
820 Storage_Error FSD_CmpFile::BeginReadCommentSection() 
821 {
822   return FindTag("BEGIN_COMMENT_SECTION");
823 }
824
825 //=======================================================================
826 //function : ReadComment
827 //purpose  : 
828 //=======================================================================
829
830 void FSD_CmpFile::ReadComment(TColStd_SequenceOfExtendedString& aCom)
831 {
832   TCollection_ExtendedString line;
833   Standard_Integer           len,i;
834
835   if (!(myStream >> len)) Storage_StreamTypeMismatchError::Raise();
836   
837   FlushEndOfLine();  
838
839   for (i = 1; i <= len && !IsEnd(); i++) {
840     ReadExtendedLine(line);
841     aCom.Append(line);
842     line.Clear();
843   }
844 }
845
846 //=======================================================================
847 //function : EndReadCommentSection
848 //purpose  : 
849 //=======================================================================
850
851 Storage_Error FSD_CmpFile::EndReadCommentSection() 
852 {
853   return FindTag("END_COMMENT_SECTION");
854 }
855
856 //=======================================================================
857 //function : BeginWriteTypeSection
858 //purpose  : --------------- TYPE : WRITE
859 //=======================================================================
860
861 Storage_Error FSD_CmpFile::BeginWriteTypeSection() 
862 {
863   myStream << "BEGIN_TYPE_SECTION\n";
864   if (myStream.bad()) Storage_StreamWriteError::Raise();
865   return Storage_VSOk;
866 }
867
868 //=======================================================================
869 //function : SetTypeSectionSize
870 //purpose  : 
871 //=======================================================================
872
873 void FSD_CmpFile::SetTypeSectionSize(const Standard_Integer aSize) 
874 {
875   myStream << aSize << "\n";
876   if (myStream.bad()) Storage_StreamWriteError::Raise();
877 }
878
879 //=======================================================================
880 //function : WriteTypeInformations
881 //purpose  : 
882 //=======================================================================
883
884 void FSD_CmpFile::WriteTypeInformations(const Standard_Integer typeNum,
885                                       const TCollection_AsciiString& typeName) 
886 {
887   myStream << typeNum << " " << typeName.ToCString() << "\n";
888   if (myStream.bad()) Storage_StreamWriteError::Raise();
889 }
890
891 //=======================================================================
892 //function : EndWriteTypeSection
893 //purpose  : read
894 //=======================================================================
895
896 Storage_Error FSD_CmpFile::EndWriteTypeSection() 
897 {
898   myStream << "END_TYPE_SECTION\n";
899   if (myStream.bad()) Storage_StreamWriteError::Raise();
900   return Storage_VSOk;
901 }
902
903 //=======================================================================
904 //function : BeginReadTypeSection
905 //purpose  : ------------------- TYPE : READ
906 //=======================================================================
907
908 Storage_Error FSD_CmpFile::BeginReadTypeSection() 
909 {
910   return FindTag("BEGIN_TYPE_SECTION");
911 }
912
913 //=======================================================================
914 //function : TypeSectionSize
915 //purpose  : 
916 //=======================================================================
917
918 Standard_Integer FSD_CmpFile::TypeSectionSize() 
919 {
920   Standard_Integer i;
921
922   if (!(myStream >> i)) Storage_StreamTypeMismatchError::Raise();
923
924   FlushEndOfLine();
925
926   return i;
927 }
928
929 //=======================================================================
930 //function : ReadTypeInformations
931 //purpose  : 
932 //=======================================================================
933
934 void FSD_CmpFile::ReadTypeInformations(Standard_Integer& typeNum,
935                                     TCollection_AsciiString& typeName) 
936 {
937   if (!(myStream >> typeNum)) Storage_StreamTypeMismatchError::Raise();
938   if (!(myStream >> typeName)) Storage_StreamTypeMismatchError::Raise();
939   FlushEndOfLine();
940 }
941
942 //=======================================================================
943 //function : EndReadTypeSection
944 //purpose  : ROOT SECTION
945 //           write
946 //=======================================================================
947
948 Storage_Error FSD_CmpFile::EndReadTypeSection() 
949 {
950   return FindTag("END_TYPE_SECTION");
951 }
952
953 //=======================================================================
954 //function : BeginWriteRootSection
955 //purpose  : -------------------- ROOT : WRITE
956 //=======================================================================
957
958 Storage_Error FSD_CmpFile::BeginWriteRootSection() 
959 {
960   myStream << "BEGIN_ROOT_SECTION\n";
961   if (myStream.bad()) Storage_StreamWriteError::Raise();
962   return Storage_VSOk;
963 }
964
965 //=======================================================================
966 //function : SetRootSectionSize
967 //purpose  : 
968 //=======================================================================
969
970 void FSD_CmpFile::SetRootSectionSize(const Standard_Integer aSize) 
971 {
972   myStream << aSize << "\n";
973   if (myStream.bad()) Storage_StreamWriteError::Raise();
974 }
975
976 //=======================================================================
977 //function : WriteRoot
978 //purpose  : 
979 //=======================================================================
980
981 void FSD_CmpFile::WriteRoot(const TCollection_AsciiString& rootName, const Standard_Integer aRef, const TCollection_AsciiString& rootType) 
982 {
983   myStream << aRef << " " << rootName.ToCString() << " " << rootType.ToCString() << "\n";
984   if (myStream.bad()) Storage_StreamWriteError::Raise();
985 }
986
987 //=======================================================================
988 //function : EndWriteRootSection
989 //purpose  : read
990 //=======================================================================
991
992 Storage_Error FSD_CmpFile::EndWriteRootSection() 
993 {
994   myStream << "END_ROOT_SECTION\n";
995   if (myStream.bad()) Storage_StreamWriteError::Raise();
996   return Storage_VSOk;
997 }
998
999 //=======================================================================
1000 //function : BeginReadRootSection
1001 //purpose  : ----------------------- ROOT : READ
1002 //=======================================================================
1003
1004 Storage_Error FSD_CmpFile::BeginReadRootSection() 
1005 {
1006   return FindTag("BEGIN_ROOT_SECTION");
1007 }
1008
1009 //=======================================================================
1010 //function : RootSectionSize
1011 //purpose  : 
1012 //=======================================================================
1013
1014 Standard_Integer FSD_CmpFile::RootSectionSize() 
1015 {
1016   Standard_Integer i;
1017
1018   if (!(myStream >> i)) Storage_StreamTypeMismatchError::Raise();
1019   
1020   FlushEndOfLine();
1021   
1022   return i;
1023 }
1024
1025 //=======================================================================
1026 //function : ReadRoot
1027 //purpose  : 
1028 //=======================================================================
1029
1030 void FSD_CmpFile::ReadRoot(TCollection_AsciiString& rootName, Standard_Integer& aRef,TCollection_AsciiString& rootType) 
1031 {
1032   if (!(myStream >> aRef)) Storage_StreamTypeMismatchError::Raise();
1033   ReadWord(rootName);
1034   ReadWord(rootType);
1035 }
1036
1037 //=======================================================================
1038 //function : EndReadRootSection
1039 //purpose  : REF SECTION
1040 //           write
1041 //=======================================================================
1042
1043 Storage_Error FSD_CmpFile::EndReadRootSection() 
1044 {
1045   return FindTag("END_ROOT_SECTION");
1046 }
1047
1048 //=======================================================================
1049 //function : BeginWriteRefSection
1050 //purpose  : -------------------------- REF : WRITE
1051 //=======================================================================
1052
1053 Storage_Error FSD_CmpFile::BeginWriteRefSection() 
1054 {
1055   myStream << "BEGIN_REF_SECTION\n";
1056   if (myStream.bad()) Storage_StreamWriteError::Raise();
1057   return Storage_VSOk;
1058 }
1059
1060 //=======================================================================
1061 //function : SetRefSectionSize
1062 //purpose  : 
1063 //=======================================================================
1064
1065 void FSD_CmpFile::SetRefSectionSize(const Standard_Integer aSize) 
1066 {
1067   myStream << aSize << "\n";
1068   if (myStream.bad()) Storage_StreamWriteError::Raise();
1069 }
1070
1071 //=======================================================================
1072 //function : WriteReferenceType
1073 //purpose  : 
1074 //=======================================================================
1075
1076 void FSD_CmpFile::WriteReferenceType(const Standard_Integer reference,
1077                                   const Standard_Integer typeNum) 
1078 {
1079   myStream << reference << " " << typeNum << "\n";
1080   if (myStream.bad()) Storage_StreamWriteError::Raise();
1081 }
1082
1083 //=======================================================================
1084 //function : EndWriteRefSection
1085 //purpose  : read
1086 //=======================================================================
1087
1088 Storage_Error FSD_CmpFile::EndWriteRefSection() 
1089 {
1090   myStream << "END_REF_SECTION\n";
1091   if (myStream.bad()) Storage_StreamWriteError::Raise();
1092   return Storage_VSOk;
1093 }
1094
1095 //=======================================================================
1096 //function : BeginReadRefSection
1097 //purpose  : ----------------------- REF : READ
1098 //=======================================================================
1099
1100 Storage_Error FSD_CmpFile::BeginReadRefSection() 
1101 {
1102   return FindTag("BEGIN_REF_SECTION");
1103 }
1104
1105 //=======================================================================
1106 //function : RefSectionSize
1107 //purpose  : 
1108 //=======================================================================
1109
1110 Standard_Integer FSD_CmpFile::RefSectionSize() 
1111 {
1112   Standard_Integer i;
1113
1114   if (!(myStream >> i)) Storage_StreamTypeMismatchError::Raise();
1115   FlushEndOfLine();
1116
1117   return i;
1118 }
1119
1120 //=======================================================================
1121 //function : ReadReferenceType
1122 //purpose  : 
1123 //=======================================================================
1124
1125 void FSD_CmpFile::ReadReferenceType(Standard_Integer& reference,
1126                                  Standard_Integer& typeNum) 
1127 {
1128   if (!(myStream >> reference)) Storage_StreamTypeMismatchError::Raise();
1129   if (!(myStream >> typeNum)) Storage_StreamTypeMismatchError::Raise();
1130   FlushEndOfLine();
1131 }
1132
1133 //=======================================================================
1134 //function : EndReadRefSection
1135 //purpose  : DATA SECTION
1136 //           write
1137 //=======================================================================
1138
1139 Storage_Error FSD_CmpFile::EndReadRefSection() 
1140 {
1141   return FindTag("END_REF_SECTION");
1142 }
1143
1144 //=======================================================================
1145 //function : BeginWriteDataSection
1146 //purpose  : -------------------- DATA : WRITE
1147 //=======================================================================
1148
1149 Storage_Error FSD_CmpFile::BeginWriteDataSection() 
1150 {
1151   myStream << "BEGIN_DATA_SECTION";
1152   if (myStream.bad()) Storage_StreamWriteError::Raise();
1153   return Storage_VSOk;
1154 }
1155
1156 //=======================================================================
1157 //function : WritePersistentObjectHeader
1158 //purpose  : 
1159 //=======================================================================
1160
1161 void FSD_CmpFile::WritePersistentObjectHeader(const Standard_Integer aRef,
1162                                            const Standard_Integer aType) 
1163 {
1164   myStream << "\n#" << aRef << "%" << aType << " ";
1165   if (myStream.bad()) Storage_StreamWriteError::Raise();
1166 }
1167
1168 //=======================================================================
1169 //function : BeginWritePersistentObjectData
1170 //purpose  : 
1171 //=======================================================================
1172
1173 void FSD_CmpFile::BeginWritePersistentObjectData() 
1174 {
1175   if (myStream.bad()) Storage_StreamWriteError::Raise();
1176 }
1177
1178 //=======================================================================
1179 //function : BeginWriteObjectData
1180 //purpose  : 
1181 //=======================================================================
1182
1183 void FSD_CmpFile::BeginWriteObjectData() 
1184 {
1185   if (myStream.bad()) Storage_StreamWriteError::Raise();
1186 }
1187
1188 //=======================================================================
1189 //function : EndWriteObjectData
1190 //purpose  : 
1191 //=======================================================================
1192
1193 void FSD_CmpFile::EndWriteObjectData() 
1194 {
1195   if (myStream.bad()) Storage_StreamWriteError::Raise();
1196 }
1197
1198 //=======================================================================
1199 //function : EndWritePersistentObjectData
1200 //purpose  : 
1201 //=======================================================================
1202
1203 void FSD_CmpFile::EndWritePersistentObjectData() 
1204 {
1205   if (myStream.bad()) Storage_StreamWriteError::Raise();
1206 }
1207
1208 //=======================================================================
1209 //function : EndWriteDataSection
1210 //purpose  : read
1211 //=======================================================================
1212
1213 Storage_Error FSD_CmpFile::EndWriteDataSection() 
1214 {
1215   myStream << "\nEND_DATA_SECTION\n";
1216   if (myStream.bad()) Storage_StreamWriteError::Raise();
1217   return Storage_VSOk;
1218 }
1219
1220 //=======================================================================
1221 //function : BeginReadDataSection
1222 //purpose  : ---------------------- DATA : READ
1223 //=======================================================================
1224
1225 Storage_Error FSD_CmpFile::BeginReadDataSection() 
1226 {
1227   return FindTag("BEGIN_DATA_SECTION");
1228 }
1229
1230 //=======================================================================
1231 //function : ReadPersistentObjectHeader
1232 //purpose  : 
1233 //=======================================================================
1234
1235 void FSD_CmpFile::ReadPersistentObjectHeader(Standard_Integer& aRef,
1236                                           Standard_Integer& aType) 
1237 {
1238   char c;
1239
1240   myStream.get(c);
1241
1242   while (c != '#') {
1243     if (IsEnd() || (c != ' ') || (c == '\r')|| (c == '\n')) {
1244       Storage_StreamFormatError::Raise();
1245     }
1246     myStream.get(c);
1247   }
1248
1249   if (!(myStream >> aRef)) Storage_StreamTypeMismatchError::Raise();
1250
1251   myStream.get(c);
1252
1253   while (c != '%') {
1254     if (IsEnd() || (c != ' ') || (c == '\r')|| (c == '\n')) {
1255       Storage_StreamFormatError::Raise();
1256     }
1257     myStream.get(c);
1258   }
1259
1260   if (!(myStream >> aType)) Storage_StreamTypeMismatchError::Raise();
1261 //  cout << "REF:" << aRef << " TYPE:"<< aType << endl;
1262 }
1263
1264 //=======================================================================
1265 //function : BeginReadPersistentObjectData
1266 //purpose  : 
1267 //=======================================================================
1268
1269 void FSD_CmpFile::BeginReadPersistentObjectData() 
1270 {
1271 //cout << "BeginReadPersistentObjectData" << endl;
1272 }
1273
1274 //=======================================================================
1275 //function : BeginReadObjectData
1276 //purpose  : 
1277 //=======================================================================
1278
1279 void FSD_CmpFile::BeginReadObjectData() 
1280 {
1281 //  cout << "BeginReadObjectData" << endl;
1282 }
1283
1284 //=======================================================================
1285 //function : EndReadObjectData
1286 //purpose  : 
1287 //=======================================================================
1288
1289 void FSD_CmpFile::EndReadObjectData() 
1290 {
1291 //  cout << "EndReadObjectData" << endl;
1292 }
1293
1294 //=======================================================================
1295 //function : EndReadPersistentObjectData
1296 //purpose  : 
1297 //=======================================================================
1298
1299 void FSD_CmpFile::EndReadPersistentObjectData() 
1300 {
1301   char c;
1302
1303   myStream.get(c);
1304   while (c != '\n' && (c != '\r')) {
1305     if (IsEnd() || (c != ' ')) {
1306       Storage_StreamFormatError::Raise();
1307     }
1308     myStream.get(c);
1309   }
1310  if (c == '\r') {
1311    myStream.get(c);
1312  }
1313 //  cout << "EndReadPersistentObjectData" << endl;
1314 }
1315
1316 //=======================================================================
1317 //function : EndReadDataSection
1318 //purpose  : 
1319 //=======================================================================
1320
1321 Storage_Error FSD_CmpFile::EndReadDataSection() 
1322 {
1323   return FindTag("END_DATA_SECTION");
1324 }
1325
1326 //=======================================================================
1327 //function : Tell
1328 //purpose  : return position in the file. Return -1 upon error.
1329 //=======================================================================
1330
1331 Storage_Position FSD_CmpFile::Tell()
1332 {
1333   switch (OpenMode()) {
1334   case Storage_VSRead:
1335     return (Storage_Position) myStream.tellp();
1336   case Storage_VSWrite:
1337     return (Storage_Position) myStream.tellg();
1338   case Storage_VSReadWrite: {
1339     Storage_Position aPosR  = (Storage_Position) myStream.tellp();
1340     Storage_Position aPosW  = (Storage_Position) myStream.tellg();
1341     if (aPosR < aPosW)
1342       return aPosW;
1343     else
1344       return aPosR;
1345   }
1346   default: return -1;
1347   }
1348 }