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