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