0027838: Foundation Classes - support wchar_t* input within TCollection_AsciiString...
[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.hxx>
16
17 #include <OSD.hxx>
18 #include <OSD_OpenFile.hxx>
19 #include <Standard_PCharacter.hxx>
20 #include <Storage_BaseDriver.hxx>
21 #include <Storage_StreamExtCharParityError.hxx>
22 #include <Storage_StreamFormatError.hxx>
23 #include <Storage_StreamModeError.hxx>
24 #include <Storage_StreamTypeMismatchError.hxx>
25 #include <Storage_StreamUnknownTypeError.hxx>
26 #include <Storage_StreamWriteError.hxx>
27 #include <TCollection_AsciiString.hxx>
28 #include <TCollection_ExtendedString.hxx>
29
30 const Standard_CString MAGICNUMBER = "CMPFILE";
31
32 //=======================================================================
33 //function : FSD_CmpFile
34 //purpose  : 
35 //=======================================================================
36
37 FSD_CmpFile::FSD_CmpFile()
38 {
39
40 }
41
42 //=======================================================================
43 //function : IsGoodFileType
44 //purpose  : INFO SECTION
45 //           write
46 //=======================================================================
47
48 Storage_Error FSD_CmpFile::IsGoodFileType(const TCollection_AsciiString& aName)
49 {
50   FSD_CmpFile      f;
51   Storage_Error s;
52
53   s = f.Open(aName,Storage_VSRead);
54
55   if (s == Storage_VSOk) {
56     TCollection_AsciiString l;
57     Standard_Size        len = strlen(FSD_CmpFile::MagicNumber());
58
59     f.ReadChar(l,len);
60
61     f.Close();
62
63     if (strncmp(FSD_CmpFile::MagicNumber(),l.ToCString(),len) != 0) {
64       s = Storage_VSFormatError;
65     }
66   }
67
68   return s;
69 }
70
71 //=======================================================================
72 //function : Open
73 //purpose  : 
74 //=======================================================================
75
76 Storage_Error FSD_CmpFile::Open(const TCollection_AsciiString& aName,const Storage_OpenMode aMode)
77 {
78   Storage_Error result = Storage_VSOk;
79
80   SetName(aName);
81
82   if (OpenMode() == Storage_VSNone) {
83     std::ios_base::openmode anOpenMode = std::ios_base::openmode(0);
84     switch (aMode)
85     {
86       case Storage_VSNone:
87       {
88         break;
89       }
90       case Storage_VSRead:
91       {
92         // ios::nocreate is not portable
93       #if !defined(IRIX) && !defined(DECOSF1)
94         anOpenMode = ios::in | ios::binary;
95       #else
96         anOpenMode = ios::in;
97       #endif
98         break;
99       }
100       case Storage_VSWrite:
101       {
102       #if !defined(IRIX) && !defined(DECOSF1)
103         anOpenMode = ios::out | ios::binary;
104       #else
105         anOpenMode = ios::out;
106       #endif
107         break;
108       }
109       case Storage_VSReadWrite:
110       {
111       #if !defined(IRIX) && !defined(DECOSF1)
112         anOpenMode = ios::in | ios::out | ios::binary;
113       #else
114         anOpenMode = ios::in | ios::out;
115       #endif
116         break;
117       }
118     }
119     if (anOpenMode != 0)
120     {
121       OSD_OpenStream (myStream, aName, anOpenMode);
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 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 << (short )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   short aChar = 0;
550   if (!(myStream >> aChar)) Storage_StreamTypeMismatchError::Raise();
551   aValue = aChar;
552   return *this;
553 }
554
555 //=======================================================================
556 //function : GetInteger
557 //purpose  : 
558 //=======================================================================
559
560 Storage_BaseDriver& FSD_CmpFile::GetInteger(Standard_Integer& aValue)
561 {
562   if (!(myStream >> aValue)) Storage_StreamTypeMismatchError::Raise();
563
564   return *this;
565 }
566
567 //=======================================================================
568 //function : GetBoolean
569 //purpose  : 
570 //=======================================================================
571
572 Storage_BaseDriver& FSD_CmpFile::GetBoolean(Standard_Boolean& aValue)
573 {
574   if (!(myStream >> aValue)) Storage_StreamTypeMismatchError::Raise();
575
576   return *this;
577 }
578
579 //=======================================================================
580 //function : GetReal
581 //purpose  : 
582 //=======================================================================
583
584 Storage_BaseDriver& FSD_CmpFile::GetReal(Standard_Real& aValue)
585 {
586   char realbuffer[100];
587
588   realbuffer[0] = '\0';
589   if (!(myStream >> realbuffer)) {
590 #ifdef OCCT_DEBUG
591     cerr << "%%%ERROR: read error of double at offset " << myStream.tellg() << endl;
592     cerr << "\t buffer is" << realbuffer<< endl;
593 #endif
594     Storage_StreamTypeMismatchError::Raise();
595   }
596   if (!OSD::CStringToReal(realbuffer,aValue)) {
597 #ifdef OCCT_DEBUG
598     cerr << "%%%ERROR: read error of double at offset " << myStream.tellg() << endl;
599     cerr << "\t buffer is" << realbuffer<< endl;
600 #endif
601     Storage_StreamTypeMismatchError::Raise();
602   }
603
604   return *this;
605 }
606
607 //=======================================================================
608 //function : GetShortReal
609 //purpose  : 
610 //=======================================================================
611
612 Storage_BaseDriver& FSD_CmpFile::GetShortReal(Standard_ShortReal& aValue)
613 {
614   char realbuffer[100];
615   Standard_Real r = 0.0;
616
617   realbuffer[0] = '\0';
618   if (!(myStream >> realbuffer)) Storage_StreamTypeMismatchError::Raise();
619   if (!OSD::CStringToReal(realbuffer,r))
620     Storage_StreamTypeMismatchError::Raise();
621
622   aValue = (Standard_ShortReal)r;
623
624   return *this;
625 }
626
627 //=======================================================================
628 //function : Destroy
629 //purpose  : 
630 //=======================================================================
631
632 void FSD_CmpFile::Destroy()
633 {
634   if (OpenMode() != Storage_VSNone) {
635     Close();
636   }
637 }
638
639 //=======================================================================
640 //function : BeginWriteInfoSection
641 //purpose  : -------------------------- INFO : WRITE
642 //=======================================================================
643
644 Storage_Error FSD_CmpFile::BeginWriteInfoSection() 
645 {
646   myStream << FSD_CmpFile::MagicNumber() << '\n';
647   myStream << "BEGIN_INFO_SECTION\n";
648   if (myStream.bad()) Storage_StreamWriteError::Raise();
649
650   return Storage_VSOk;
651 }
652
653 //=======================================================================
654 //function : WriteInfo
655 //purpose  : 
656 //=======================================================================
657
658 void FSD_CmpFile::WriteInfo(const Standard_Integer nbObj,
659                          const TCollection_AsciiString& dbVersion,
660                          const TCollection_AsciiString& date,
661                          const TCollection_AsciiString& schemaName,
662                          const TCollection_AsciiString& schemaVersion,
663                          const TCollection_ExtendedString& appName,
664                          const TCollection_AsciiString& appVersion,
665                          const TCollection_ExtendedString& dataType,
666                          const TColStd_SequenceOfAsciiString& userInfo) 
667 {
668   Standard_Integer i;
669
670   myStream << nbObj;
671   myStream << "\n";
672   myStream << dbVersion.ToCString() << "\n";
673   myStream << date.ToCString() << "\n";
674   myStream << schemaName.ToCString() << "\n";
675   myStream << schemaVersion.ToCString() << "\n";
676   WriteExtendedLine(appName);
677   myStream << appVersion.ToCString() << "\n";
678   WriteExtendedLine(dataType);
679   myStream << userInfo.Length() << "\n";
680
681   if (myStream.bad()) Storage_StreamWriteError::Raise();
682
683   for (i = 1; i <= userInfo.Length(); i++) {
684     myStream << userInfo.Value(i).ToCString() << "\n";
685     if (myStream.bad()) Storage_StreamWriteError::Raise();
686   }
687 }
688
689 //=======================================================================
690 //function : EndWriteInfoSection
691 //purpose  : read
692 //=======================================================================
693
694 Storage_Error FSD_CmpFile::EndWriteInfoSection() 
695 {
696   myStream << "END_INFO_SECTION\n";
697   if (myStream.bad())  Storage_StreamWriteError::Raise();
698   return Storage_VSOk;
699 }
700
701 //=======================================================================
702 //function : BeginReadInfoSection
703 //purpose  : 
704 //=======================================================================
705
706 Storage_Error FSD_CmpFile::BeginReadInfoSection() 
707 {
708   Storage_Error s;
709   TCollection_AsciiString l;
710   Standard_Size        len = strlen(FSD_CmpFile::MagicNumber());
711
712   ReadChar(l,len);
713   
714   if (strncmp(FSD_CmpFile::MagicNumber(),l.ToCString(),len) != 0) {
715     s = Storage_VSFormatError;
716   }
717   else {
718     s = FindTag("BEGIN_INFO_SECTION");
719   }
720
721   return s;
722 }
723
724 //=======================================================================
725 //function : ReadInfo
726 //purpose  : ------------------- INFO : READ
727 //=======================================================================
728
729 void FSD_CmpFile::ReadInfo(Standard_Integer& nbObj,
730                         TCollection_AsciiString& dbVersion,
731                         TCollection_AsciiString& date,
732                         TCollection_AsciiString& schemaName,
733                         TCollection_AsciiString& schemaVersion,
734                         TCollection_ExtendedString& appName,
735                         TCollection_AsciiString& appVersion,
736                         TCollection_ExtendedString& dataType,
737                         TColStd_SequenceOfAsciiString& userInfo) 
738 {
739   if (!(myStream >> nbObj)) Storage_StreamTypeMismatchError::Raise();
740
741   FlushEndOfLine();
742
743   ReadLine(dbVersion);
744   ReadLine(date);
745   ReadLine(schemaName);
746   ReadLine(schemaVersion);
747   ReadExtendedLine(appName);
748   ReadLine(appVersion);
749   ReadExtendedLine(dataType);
750
751   Standard_Integer i,len = 0;
752
753   if (!(myStream >> len)) Storage_StreamTypeMismatchError::Raise();
754
755   FlushEndOfLine();
756
757   TCollection_AsciiString line;
758
759   for (i = 1; i <= len && !IsEnd(); i++) {
760     ReadLine(line);
761     userInfo.Append(line);
762     line.Clear();
763   }
764 }
765
766 //=======================================================================
767 //function : ReadCompleteInfo
768 //purpose  : 
769 //           
770 //=======================================================================
771 void FSD_CmpFile::ReadCompleteInfo( Standard_IStream& /*theIStream*/, Handle(Storage_Data)& /*theData*/)
772 {
773
774 }
775
776 //=======================================================================
777 //function : EndReadInfoSection
778 //purpose  : COMMENTS SECTION
779 //           write
780 //=======================================================================
781
782 Storage_Error FSD_CmpFile::EndReadInfoSection() 
783 {
784   return FindTag("END_INFO_SECTION");
785 }
786
787 //=======================================================================
788 //function : BeginWriteCommentSection
789 //purpose  : ---------------- COMMENTS : WRITE
790 //=======================================================================
791
792 Storage_Error FSD_CmpFile::BeginWriteCommentSection() 
793 {
794   myStream << "BEGIN_COMMENT_SECTION\n";
795   if (myStream.bad()) Storage_StreamWriteError::Raise();
796   return Storage_VSOk;
797 }
798
799 //=======================================================================
800 //function : WriteComment
801 //purpose  : 
802 //=======================================================================
803
804 void FSD_CmpFile::WriteComment(const TColStd_SequenceOfExtendedString& aCom)
805 {
806  Standard_Integer i,aSize;
807
808  aSize = aCom.Length();
809  myStream << aSize << "\n";
810  if (myStream.bad()) Storage_StreamWriteError::Raise();
811
812  for (i = 1; i <= aSize; i++) {
813    WriteExtendedLine(aCom.Value(i));
814    if (myStream.bad()) Storage_StreamWriteError::Raise();
815  }
816 }
817
818 //=======================================================================
819 //function : EndWriteCommentSection
820 //purpose  : read
821 //=======================================================================
822
823 Storage_Error FSD_CmpFile::EndWriteCommentSection() 
824 {
825   myStream << "END_COMMENT_SECTION\n";
826   if (myStream.bad()) Storage_StreamWriteError::Raise();
827   return Storage_VSOk;
828 }
829
830 //=======================================================================
831 //function : BeginReadCommentSection
832 //purpose  : ---------------- COMMENTS : READ
833 //=======================================================================
834
835 Storage_Error FSD_CmpFile::BeginReadCommentSection() 
836 {
837   return FindTag("BEGIN_COMMENT_SECTION");
838 }
839
840 //=======================================================================
841 //function : ReadComment
842 //purpose  : 
843 //=======================================================================
844
845 void FSD_CmpFile::ReadComment(TColStd_SequenceOfExtendedString& aCom)
846 {
847   TCollection_ExtendedString line;
848   Standard_Integer           len,i;
849
850   if (!(myStream >> len)) Storage_StreamTypeMismatchError::Raise();
851   
852   FlushEndOfLine();  
853
854   for (i = 1; i <= len && !IsEnd(); i++) {
855     ReadExtendedLine(line);
856     aCom.Append(line);
857     line.Clear();
858   }
859 }
860
861 //=======================================================================
862 //function : EndReadCommentSection
863 //purpose  : 
864 //=======================================================================
865
866 Storage_Error FSD_CmpFile::EndReadCommentSection() 
867 {
868   return FindTag("END_COMMENT_SECTION");
869 }
870
871 //=======================================================================
872 //function : BeginWriteTypeSection
873 //purpose  : --------------- TYPE : WRITE
874 //=======================================================================
875
876 Storage_Error FSD_CmpFile::BeginWriteTypeSection() 
877 {
878   myStream << "BEGIN_TYPE_SECTION\n";
879   if (myStream.bad()) Storage_StreamWriteError::Raise();
880   return Storage_VSOk;
881 }
882
883 //=======================================================================
884 //function : SetTypeSectionSize
885 //purpose  : 
886 //=======================================================================
887
888 void FSD_CmpFile::SetTypeSectionSize(const Standard_Integer aSize) 
889 {
890   myStream << aSize << "\n";
891   if (myStream.bad()) Storage_StreamWriteError::Raise();
892 }
893
894 //=======================================================================
895 //function : WriteTypeInformations
896 //purpose  : 
897 //=======================================================================
898
899 void FSD_CmpFile::WriteTypeInformations(const Standard_Integer typeNum,
900                                       const TCollection_AsciiString& typeName) 
901 {
902   myStream << typeNum << " " << typeName.ToCString() << "\n";
903   if (myStream.bad()) Storage_StreamWriteError::Raise();
904 }
905
906 //=======================================================================
907 //function : EndWriteTypeSection
908 //purpose  : read
909 //=======================================================================
910
911 Storage_Error FSD_CmpFile::EndWriteTypeSection() 
912 {
913   myStream << "END_TYPE_SECTION\n";
914   if (myStream.bad()) Storage_StreamWriteError::Raise();
915   return Storage_VSOk;
916 }
917
918 //=======================================================================
919 //function : BeginReadTypeSection
920 //purpose  : ------------------- TYPE : READ
921 //=======================================================================
922
923 Storage_Error FSD_CmpFile::BeginReadTypeSection() 
924 {
925   return FindTag("BEGIN_TYPE_SECTION");
926 }
927
928 //=======================================================================
929 //function : TypeSectionSize
930 //purpose  : 
931 //=======================================================================
932
933 Standard_Integer FSD_CmpFile::TypeSectionSize() 
934 {
935   Standard_Integer i;
936
937   if (!(myStream >> i)) Storage_StreamTypeMismatchError::Raise();
938
939   FlushEndOfLine();
940
941   return i;
942 }
943
944 //=======================================================================
945 //function : ReadTypeInformations
946 //purpose  : 
947 //=======================================================================
948
949 void FSD_CmpFile::ReadTypeInformations(Standard_Integer& typeNum,
950                                     TCollection_AsciiString& typeName) 
951 {
952   if (!(myStream >> typeNum)) Storage_StreamTypeMismatchError::Raise();
953   if (!(myStream >> typeName)) Storage_StreamTypeMismatchError::Raise();
954   FlushEndOfLine();
955 }
956
957 //=======================================================================
958 //function : EndReadTypeSection
959 //purpose  : ROOT SECTION
960 //           write
961 //=======================================================================
962
963 Storage_Error FSD_CmpFile::EndReadTypeSection() 
964 {
965   return FindTag("END_TYPE_SECTION");
966 }
967
968 //=======================================================================
969 //function : BeginWriteRootSection
970 //purpose  : -------------------- ROOT : WRITE
971 //=======================================================================
972
973 Storage_Error FSD_CmpFile::BeginWriteRootSection() 
974 {
975   myStream << "BEGIN_ROOT_SECTION\n";
976   if (myStream.bad()) Storage_StreamWriteError::Raise();
977   return Storage_VSOk;
978 }
979
980 //=======================================================================
981 //function : SetRootSectionSize
982 //purpose  : 
983 //=======================================================================
984
985 void FSD_CmpFile::SetRootSectionSize(const Standard_Integer aSize) 
986 {
987   myStream << aSize << "\n";
988   if (myStream.bad()) Storage_StreamWriteError::Raise();
989 }
990
991 //=======================================================================
992 //function : WriteRoot
993 //purpose  : 
994 //=======================================================================
995
996 void FSD_CmpFile::WriteRoot(const TCollection_AsciiString& rootName, const Standard_Integer aRef, const TCollection_AsciiString& rootType) 
997 {
998   myStream << aRef << " " << rootName.ToCString() << " " << rootType.ToCString() << "\n";
999   if (myStream.bad()) Storage_StreamWriteError::Raise();
1000 }
1001
1002 //=======================================================================
1003 //function : EndWriteRootSection
1004 //purpose  : read
1005 //=======================================================================
1006
1007 Storage_Error FSD_CmpFile::EndWriteRootSection() 
1008 {
1009   myStream << "END_ROOT_SECTION\n";
1010   if (myStream.bad()) Storage_StreamWriteError::Raise();
1011   return Storage_VSOk;
1012 }
1013
1014 //=======================================================================
1015 //function : BeginReadRootSection
1016 //purpose  : ----------------------- ROOT : READ
1017 //=======================================================================
1018
1019 Storage_Error FSD_CmpFile::BeginReadRootSection() 
1020 {
1021   return FindTag("BEGIN_ROOT_SECTION");
1022 }
1023
1024 //=======================================================================
1025 //function : RootSectionSize
1026 //purpose  : 
1027 //=======================================================================
1028
1029 Standard_Integer FSD_CmpFile::RootSectionSize() 
1030 {
1031   Standard_Integer i;
1032
1033   if (!(myStream >> i)) Storage_StreamTypeMismatchError::Raise();
1034   
1035   FlushEndOfLine();
1036   
1037   return i;
1038 }
1039
1040 //=======================================================================
1041 //function : ReadRoot
1042 //purpose  : 
1043 //=======================================================================
1044
1045 void FSD_CmpFile::ReadRoot(TCollection_AsciiString& rootName, Standard_Integer& aRef,TCollection_AsciiString& rootType) 
1046 {
1047   if (!(myStream >> aRef)) Storage_StreamTypeMismatchError::Raise();
1048   ReadWord(rootName);
1049   ReadWord(rootType);
1050 }
1051
1052 //=======================================================================
1053 //function : EndReadRootSection
1054 //purpose  : REF SECTION
1055 //           write
1056 //=======================================================================
1057
1058 Storage_Error FSD_CmpFile::EndReadRootSection() 
1059 {
1060   return FindTag("END_ROOT_SECTION");
1061 }
1062
1063 //=======================================================================
1064 //function : BeginWriteRefSection
1065 //purpose  : -------------------------- REF : WRITE
1066 //=======================================================================
1067
1068 Storage_Error FSD_CmpFile::BeginWriteRefSection() 
1069 {
1070   myStream << "BEGIN_REF_SECTION\n";
1071   if (myStream.bad()) Storage_StreamWriteError::Raise();
1072   return Storage_VSOk;
1073 }
1074
1075 //=======================================================================
1076 //function : SetRefSectionSize
1077 //purpose  : 
1078 //=======================================================================
1079
1080 void FSD_CmpFile::SetRefSectionSize(const Standard_Integer aSize) 
1081 {
1082   myStream << aSize << "\n";
1083   if (myStream.bad()) Storage_StreamWriteError::Raise();
1084 }
1085
1086 //=======================================================================
1087 //function : WriteReferenceType
1088 //purpose  : 
1089 //=======================================================================
1090
1091 void FSD_CmpFile::WriteReferenceType(const Standard_Integer reference,
1092                                   const Standard_Integer typeNum) 
1093 {
1094   myStream << reference << " " << typeNum << "\n";
1095   if (myStream.bad()) Storage_StreamWriteError::Raise();
1096 }
1097
1098 //=======================================================================
1099 //function : EndWriteRefSection
1100 //purpose  : read
1101 //=======================================================================
1102
1103 Storage_Error FSD_CmpFile::EndWriteRefSection() 
1104 {
1105   myStream << "END_REF_SECTION\n";
1106   if (myStream.bad()) Storage_StreamWriteError::Raise();
1107   return Storage_VSOk;
1108 }
1109
1110 //=======================================================================
1111 //function : BeginReadRefSection
1112 //purpose  : ----------------------- REF : READ
1113 //=======================================================================
1114
1115 Storage_Error FSD_CmpFile::BeginReadRefSection() 
1116 {
1117   return FindTag("BEGIN_REF_SECTION");
1118 }
1119
1120 //=======================================================================
1121 //function : RefSectionSize
1122 //purpose  : 
1123 //=======================================================================
1124
1125 Standard_Integer FSD_CmpFile::RefSectionSize() 
1126 {
1127   Standard_Integer i;
1128
1129   if (!(myStream >> i)) Storage_StreamTypeMismatchError::Raise();
1130   FlushEndOfLine();
1131
1132   return i;
1133 }
1134
1135 //=======================================================================
1136 //function : ReadReferenceType
1137 //purpose  : 
1138 //=======================================================================
1139
1140 void FSD_CmpFile::ReadReferenceType(Standard_Integer& reference,
1141                                  Standard_Integer& typeNum) 
1142 {
1143   if (!(myStream >> reference)) Storage_StreamTypeMismatchError::Raise();
1144   if (!(myStream >> typeNum)) Storage_StreamTypeMismatchError::Raise();
1145   FlushEndOfLine();
1146 }
1147
1148 //=======================================================================
1149 //function : EndReadRefSection
1150 //purpose  : DATA SECTION
1151 //           write
1152 //=======================================================================
1153
1154 Storage_Error FSD_CmpFile::EndReadRefSection() 
1155 {
1156   return FindTag("END_REF_SECTION");
1157 }
1158
1159 //=======================================================================
1160 //function : BeginWriteDataSection
1161 //purpose  : -------------------- DATA : WRITE
1162 //=======================================================================
1163
1164 Storage_Error FSD_CmpFile::BeginWriteDataSection() 
1165 {
1166   myStream << "BEGIN_DATA_SECTION";
1167   if (myStream.bad()) Storage_StreamWriteError::Raise();
1168   return Storage_VSOk;
1169 }
1170
1171 //=======================================================================
1172 //function : WritePersistentObjectHeader
1173 //purpose  : 
1174 //=======================================================================
1175
1176 void FSD_CmpFile::WritePersistentObjectHeader(const Standard_Integer aRef,
1177                                            const Standard_Integer aType) 
1178 {
1179   myStream << "\n#" << aRef << "%" << aType << " ";
1180   if (myStream.bad()) Storage_StreamWriteError::Raise();
1181 }
1182
1183 //=======================================================================
1184 //function : BeginWritePersistentObjectData
1185 //purpose  : 
1186 //=======================================================================
1187
1188 void FSD_CmpFile::BeginWritePersistentObjectData() 
1189 {
1190   if (myStream.bad()) Storage_StreamWriteError::Raise();
1191 }
1192
1193 //=======================================================================
1194 //function : BeginWriteObjectData
1195 //purpose  : 
1196 //=======================================================================
1197
1198 void FSD_CmpFile::BeginWriteObjectData() 
1199 {
1200   if (myStream.bad()) Storage_StreamWriteError::Raise();
1201 }
1202
1203 //=======================================================================
1204 //function : EndWriteObjectData
1205 //purpose  : 
1206 //=======================================================================
1207
1208 void FSD_CmpFile::EndWriteObjectData() 
1209 {
1210   if (myStream.bad()) Storage_StreamWriteError::Raise();
1211 }
1212
1213 //=======================================================================
1214 //function : EndWritePersistentObjectData
1215 //purpose  : 
1216 //=======================================================================
1217
1218 void FSD_CmpFile::EndWritePersistentObjectData() 
1219 {
1220   if (myStream.bad()) Storage_StreamWriteError::Raise();
1221 }
1222
1223 //=======================================================================
1224 //function : EndWriteDataSection
1225 //purpose  : read
1226 //=======================================================================
1227
1228 Storage_Error FSD_CmpFile::EndWriteDataSection() 
1229 {
1230   myStream << "\nEND_DATA_SECTION\n";
1231   if (myStream.bad()) Storage_StreamWriteError::Raise();
1232   return Storage_VSOk;
1233 }
1234
1235 //=======================================================================
1236 //function : BeginReadDataSection
1237 //purpose  : ---------------------- DATA : READ
1238 //=======================================================================
1239
1240 Storage_Error FSD_CmpFile::BeginReadDataSection() 
1241 {
1242   return FindTag("BEGIN_DATA_SECTION");
1243 }
1244
1245 //=======================================================================
1246 //function : ReadPersistentObjectHeader
1247 //purpose  : 
1248 //=======================================================================
1249
1250 void FSD_CmpFile::ReadPersistentObjectHeader(Standard_Integer& aRef,
1251                                           Standard_Integer& aType) 
1252 {
1253   char c;
1254
1255   myStream.get(c);
1256
1257   while (c != '#') {
1258     if (IsEnd() || (c != ' ') || (c == '\r')|| (c == '\n')) {
1259       Storage_StreamFormatError::Raise();
1260     }
1261     myStream.get(c);
1262   }
1263
1264   if (!(myStream >> aRef)) Storage_StreamTypeMismatchError::Raise();
1265
1266   myStream.get(c);
1267
1268   while (c != '%') {
1269     if (IsEnd() || (c != ' ') || (c == '\r')|| (c == '\n')) {
1270       Storage_StreamFormatError::Raise();
1271     }
1272     myStream.get(c);
1273   }
1274
1275   if (!(myStream >> aType)) Storage_StreamTypeMismatchError::Raise();
1276 //  cout << "REF:" << aRef << " TYPE:"<< aType << endl;
1277 }
1278
1279 //=======================================================================
1280 //function : BeginReadPersistentObjectData
1281 //purpose  : 
1282 //=======================================================================
1283
1284 void FSD_CmpFile::BeginReadPersistentObjectData() 
1285 {
1286 //cout << "BeginReadPersistentObjectData" << endl;
1287 }
1288
1289 //=======================================================================
1290 //function : BeginReadObjectData
1291 //purpose  : 
1292 //=======================================================================
1293
1294 void FSD_CmpFile::BeginReadObjectData() 
1295 {
1296 //  cout << "BeginReadObjectData" << endl;
1297 }
1298
1299 //=======================================================================
1300 //function : EndReadObjectData
1301 //purpose  : 
1302 //=======================================================================
1303
1304 void FSD_CmpFile::EndReadObjectData() 
1305 {
1306 //  cout << "EndReadObjectData" << endl;
1307 }
1308
1309 //=======================================================================
1310 //function : EndReadPersistentObjectData
1311 //purpose  : 
1312 //=======================================================================
1313
1314 void FSD_CmpFile::EndReadPersistentObjectData() 
1315 {
1316   char c;
1317
1318   myStream.get(c);
1319   while (c != '\n' && (c != '\r')) {
1320     if (IsEnd() || (c != ' ')) {
1321       Storage_StreamFormatError::Raise();
1322     }
1323     myStream.get(c);
1324   }
1325  if (c == '\r') {
1326    myStream.get(c);
1327  }
1328 //  cout << "EndReadPersistentObjectData" << endl;
1329 }
1330
1331 //=======================================================================
1332 //function : EndReadDataSection
1333 //purpose  : 
1334 //=======================================================================
1335
1336 Storage_Error FSD_CmpFile::EndReadDataSection() 
1337 {
1338   return FindTag("END_DATA_SECTION");
1339 }
1340
1341 //=======================================================================
1342 //function : Tell
1343 //purpose  : return position in the file. Return -1 upon error.
1344 //=======================================================================
1345
1346 Storage_Position FSD_CmpFile::Tell()
1347 {
1348   switch (OpenMode()) {
1349   case Storage_VSRead:
1350     return (Storage_Position) myStream.tellp();
1351   case Storage_VSWrite:
1352     return (Storage_Position) myStream.tellg();
1353   case Storage_VSReadWrite: {
1354     Storage_Position aPosR  = (Storage_Position) myStream.tellp();
1355     Storage_Position aPosW  = (Storage_Position) myStream.tellg();
1356     if (aPosR < aPosW)
1357       return aPosW;
1358     else
1359       return aPosR;
1360   }
1361   default: return -1;
1362   }
1363 }