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