0028736: An error to read a binary OCAF document of > 2Gb
[occt.git] / src / FSD / FSD_BinaryFile.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <FSD_BinaryFile.hxx>
17 #include <OSD.hxx>
18 #include <OSD_OpenFile.hxx>
19 #include <Storage_BaseDriver.hxx>
20 #include <Storage_HArrayOfCallBack.hxx>
21 #include <Storage_HeaderData.hxx>
22 #include <Storage_InternalData.hxx>
23 #include <Storage_RootData.hxx>
24 #include <Storage_StreamExtCharParityError.hxx>
25 #include <Storage_StreamFormatError.hxx>
26 #include <Storage_StreamTypeMismatchError.hxx>
27 #include <Storage_StreamWriteError.hxx>
28 #include <Storage_TypeData.hxx>
29 #include <TCollection_AsciiString.hxx>
30 #include <TCollection_ExtendedString.hxx>
31 #include <Standard_Assert.hxx>
32
33 const Standard_CString MAGICNUMBER = "BINFILE";
34
35 //=======================================================================
36 //function : FSD_BinaryFile
37 //purpose  : 
38 //=======================================================================
39
40 FSD_BinaryFile::FSD_BinaryFile() :
41 myStream(0L)
42 {
43   myHeader.testindian  = -1;
44   myHeader.binfo       = -1;
45   myHeader.einfo       = -1;
46   myHeader.bcomment    = -1;
47   myHeader.ecomment    = -1;
48   myHeader.btype       = -1;
49   myHeader.etype       = -1;
50   myHeader.broot       = -1;
51   myHeader.eroot       = -1;
52   myHeader.bref        = -1;
53   myHeader.eref        = -1;
54   myHeader.bdata       = -1;
55   myHeader.edata       = -1;
56 }
57
58 //=======================================================================
59 //function : IsGoodFileType
60 //purpose  : INFO SECTION
61 //           write
62 //=======================================================================
63
64 Storage_Error FSD_BinaryFile::IsGoodFileType(const TCollection_AsciiString& aName)
65 {
66   FSD_BinaryFile      f;
67   Storage_Error s;
68
69   s = f.Open(aName,Storage_VSRead);
70
71   if (s == Storage_VSOk) {
72     TCollection_AsciiString l;
73     Standard_Size        len = strlen(FSD_BinaryFile::MagicNumber());
74
75     f.ReadChar(l,len);
76
77     f.Close();
78
79     if (strncmp(FSD_BinaryFile::MagicNumber(),l.ToCString(),len) != 0) {
80       s = Storage_VSFormatError;
81     }
82   }
83
84   return s;
85 }
86
87 //=======================================================================
88 //function : Open
89 //purpose  : 
90 //=======================================================================
91
92 Storage_Error FSD_BinaryFile::Open(const TCollection_AsciiString& aName,const Storage_OpenMode aMode)
93 {
94   Storage_Error result = Storage_VSOk;
95
96   SetName(aName);
97
98   if (OpenMode() == Storage_VSNone) {
99     if (aMode == Storage_VSRead) {
100       myStream = OSD_OpenFile(aName.ToCString(),"rb");
101     }
102     else if (aMode == Storage_VSWrite) {
103       myStream = OSD_OpenFile(aName.ToCString(),"wb");
104     }
105     else if (aMode == Storage_VSReadWrite) {
106       myStream = OSD_OpenFile(aName.ToCString(),"w+b");
107     }
108     
109     if (myStream == 0L) {
110       result = Storage_VSOpenError;
111     }
112     else {
113       SetOpenMode(aMode);
114     }
115   }
116   else {
117     result = Storage_VSAlreadyOpen;
118   }
119
120   return result;
121 }
122
123 //=======================================================================
124 //function : IsEnd
125 //purpose  : 
126 //=======================================================================
127
128 Standard_Boolean FSD_BinaryFile::IsEnd()
129 {
130   return (feof(myStream) != 0);
131 }
132
133 //=======================================================================
134 //function : Close
135 //purpose  : 
136 //=======================================================================
137
138 Storage_Error FSD_BinaryFile::Close()
139 {
140   Storage_Error result = Storage_VSOk;
141
142   if (OpenMode() != Storage_VSNone) {
143     fclose(myStream);
144     SetOpenMode(Storage_VSNone);
145   }
146   else {
147     result = Storage_VSNotOpen;
148   }
149
150   return result;
151 }
152
153 //=======================================================================
154 //function : MagicNumber
155 //purpose  : ------------------ PROTECTED
156 //=======================================================================
157
158 Standard_CString FSD_BinaryFile::MagicNumber()
159 {
160   return MAGICNUMBER;
161 }
162
163 //=======================================================================
164 //function : ReadChar
165 //purpose  : read <rsize> character from the current position.
166 //=======================================================================
167
168 void FSD_BinaryFile::ReadChar(TCollection_AsciiString& buffer, const Standard_Size rsize)
169 {
170   char             c;
171   Standard_Size ccount = 0;
172
173   buffer.Clear();
174
175   while (!IsEnd() && (ccount < rsize)) {
176     ccount += fread(&c, sizeof(char),1, myStream);
177     buffer += c;
178   }
179 }
180
181 //=======================================================================
182 //function : SkipObject
183 //purpose  : 
184 //=======================================================================
185
186 void FSD_BinaryFile::SkipObject()
187 {
188
189 }
190
191 //=======================================================================
192 //function : PutReference
193 //purpose  : ---------------------- PUBLIC : PUT
194 //=======================================================================
195
196 Storage_BaseDriver& FSD_BinaryFile::PutReference(const Standard_Integer aValue)
197 {
198 #if OCCT_BINARY_FILE_DO_INVERSE
199   Standard_Integer t = InverseInt (aValue);
200   
201   if (!fwrite(&t,sizeof(Standard_Integer),1,myStream)) throw Storage_StreamWriteError();
202 #else
203   if (!fwrite(&aValue,sizeof(Standard_Integer),1,myStream)) throw Storage_StreamWriteError();
204 #endif
205   return *this;
206 }
207
208 //=======================================================================
209 //function : PutCharacter
210 //purpose  : 
211 //=======================================================================
212
213 Storage_BaseDriver& FSD_BinaryFile::PutCharacter(const Standard_Character aValue)
214 {
215   if (!fwrite(&aValue,sizeof(Standard_Character),1,myStream)) throw Storage_StreamWriteError();
216   return *this;
217 }
218
219 //=======================================================================
220 //function : PutExtCharacter
221 //purpose  : 
222 //=======================================================================
223
224 Storage_BaseDriver& FSD_BinaryFile::PutExtCharacter(const Standard_ExtCharacter aValue)
225 {
226 #if OCCT_BINARY_FILE_DO_INVERSE
227   Standard_ExtCharacter t = InverseExtChar (aValue);
228
229   if (!fwrite(&t,sizeof(Standard_ExtCharacter),1,myStream)) throw Storage_StreamWriteError();
230 #else
231   if (!fwrite(&aValue,sizeof(Standard_ExtCharacter),1,myStream)) throw Storage_StreamWriteError();
232 #endif
233   return *this;
234 }
235
236 //=======================================================================
237 //function : PutInteger
238 //purpose  : 
239 //=======================================================================
240
241 Storage_BaseDriver& FSD_BinaryFile::PutInteger(const Standard_Integer aValue)
242 {
243 #if OCCT_BINARY_FILE_DO_INVERSE
244   Standard_Integer t = InverseInt (aValue);
245   
246   if (!fwrite(&t,sizeof(Standard_Integer),1,myStream)) throw Storage_StreamWriteError();
247 #else
248   if (!fwrite(&aValue,sizeof(Standard_Integer),1,myStream)) throw Storage_StreamWriteError();
249 #endif
250
251   return *this;
252 }
253
254 //=======================================================================
255 //function : PutInteger
256 //purpose  : 
257 //=======================================================================
258 Standard_Integer FSD_BinaryFile::PutInteger (Standard_OStream&      theOStream,
259                                              const Standard_Integer theValue,
260                                              const Standard_Boolean theOnlyCount)
261 {
262 #if OCCT_BINARY_FILE_DO_INVERSE
263   Standard_Integer t = InverseInt (theValue);
264 #else
265   Standard_Integer t = theValue;
266 #endif
267
268   if (!theOnlyCount)
269   {
270     theOStream.write ((char*)&t, sizeof(Standard_Integer));
271     if (theOStream.fail())
272     {
273       throw Storage_StreamWriteError();
274     }
275   }
276
277   return sizeof(Standard_Integer);
278 }
279
280 //=======================================================================
281 //function : PutBoolean
282 //purpose  : 
283 //=======================================================================
284
285 Storage_BaseDriver& FSD_BinaryFile::PutBoolean(const Standard_Boolean aValue)
286 {
287 #if OCCT_BINARY_FILE_DO_INVERSE
288   Standard_Integer t = InverseInt ((Standard_Integer) aValue);
289 #else
290   Standard_Integer t = aValue ? 1 : 0;
291 #endif
292   if (!fwrite(&t,sizeof(Standard_Integer),1,myStream)) throw Storage_StreamWriteError();
293   return *this;
294 }
295
296 //=======================================================================
297 //function : PutReal
298 //purpose  : 
299 //=======================================================================
300
301 Storage_BaseDriver& FSD_BinaryFile::PutReal(const Standard_Real aValue)
302 {
303 #if OCCT_BINARY_FILE_DO_INVERSE
304   Standard_Real t = InverseReal (aValue);
305   
306   if (!fwrite(&t,sizeof(Standard_Real),1,myStream)) throw Storage_StreamWriteError();
307 #else
308   if (!fwrite(&aValue,sizeof(Standard_Real),1,myStream)) throw Storage_StreamWriteError();
309 #endif
310   return *this;
311 }
312
313 //=======================================================================
314 //function : PutShortReal
315 //purpose  : 
316 //=======================================================================
317
318 Storage_BaseDriver& FSD_BinaryFile::PutShortReal(const Standard_ShortReal aValue)
319 {
320 #if OCCT_BINARY_FILE_DO_INVERSE
321   Standard_ShortReal t = InverseShortReal (aValue);
322
323   if (!fwrite(&t,sizeof(Standard_ShortReal),1,myStream)) throw Storage_StreamWriteError();
324 #else
325   if (!fwrite(&aValue,sizeof(Standard_ShortReal),1,myStream)) throw Storage_StreamWriteError();
326 #endif
327   return *this;
328 }
329
330 //=======================================================================
331 //function : GetReference
332 //purpose  : ----------------- PUBLIC : GET
333 //=======================================================================
334
335 Storage_BaseDriver& FSD_BinaryFile::GetReference(Standard_Integer& aValue)
336 {
337   if (!fread(&aValue,sizeof(Standard_Integer),1,myStream))
338     throw Storage_StreamTypeMismatchError();
339 #if OCCT_BINARY_FILE_DO_INVERSE
340   aValue = InverseInt (aValue);
341 #endif
342   return *this;
343 }
344
345 //=======================================================================
346 //function : GetReference
347 //purpose  : ----------------- PUBLIC : GET
348 //=======================================================================
349 void FSD_BinaryFile::GetReference(Standard_IStream& theIStream, Standard_Integer& aValue)
350 {
351   theIStream.read ((char*)&aValue, sizeof(Standard_Integer));
352
353   if (theIStream.gcount() != sizeof(Standard_Integer))
354   {
355     throw Storage_StreamTypeMismatchError();
356   }
357
358 #if OCCT_BINARY_FILE_DO_INVERSE
359   aValue = InverseInt (aValue);
360 #endif
361 }
362
363 //=======================================================================
364 //function : GetCharacter
365 //purpose  : 
366 //=======================================================================
367
368 Storage_BaseDriver& FSD_BinaryFile::GetCharacter(Standard_Character& aValue)
369 {
370   if (!fread(&aValue,sizeof(Standard_Character),1,myStream))
371     throw Storage_StreamTypeMismatchError();
372   return *this;
373 }
374
375 //=======================================================================
376 //function : GetExtCharacter
377 //purpose  : 
378 //=======================================================================
379
380 Storage_BaseDriver& FSD_BinaryFile::GetExtCharacter(Standard_ExtCharacter& aValue)
381 {
382   if (!fread(&aValue,sizeof(Standard_ExtCharacter),1,myStream))
383     throw Storage_StreamTypeMismatchError();
384 #if OCCT_BINARY_FILE_DO_INVERSE
385   aValue = InverseExtChar (aValue);
386 #endif
387   return *this;
388 }
389
390 //=======================================================================
391 //function : GetInteger
392 //purpose  : 
393 //=======================================================================
394
395 Storage_BaseDriver& FSD_BinaryFile::GetInteger(Standard_Integer& aValue)
396 {
397   if (!fread(&aValue,sizeof(Standard_Integer),1,myStream))
398     throw Storage_StreamTypeMismatchError();
399 #if OCCT_BINARY_FILE_DO_INVERSE
400   aValue = InverseInt (aValue);
401 #endif
402   return *this;
403 }
404
405 //=======================================================================
406 //function : GetInteger
407 //purpose  : 
408 //=======================================================================
409 void FSD_BinaryFile::GetInteger (Standard_IStream& theIStream, Standard_Integer& theValue)
410 {
411
412   theIStream.read ((char*)&theValue, sizeof(Standard_Integer));
413
414   if (theIStream.gcount() != sizeof(Standard_Integer))
415   {
416     throw Storage_StreamTypeMismatchError();
417   }
418    
419 #if OCCT_BINARY_FILE_DO_INVERSE
420   theValue = InverseInt (theValue);
421 #endif
422 }
423
424 //=======================================================================
425 //function : GetBoolean
426 //purpose  : 
427 //=======================================================================
428
429 Storage_BaseDriver& FSD_BinaryFile::GetBoolean(Standard_Boolean& aValue)
430 {
431   Standard_Integer anInt = 0;
432   if (!fread(&anInt,sizeof(Standard_Integer),1,myStream))
433     throw Storage_StreamTypeMismatchError();
434 #if OCCT_BINARY_FILE_DO_INVERSE
435   anInt = InverseInt (anInt);
436 #endif
437   aValue = (anInt != 0);
438   return *this;
439 }
440
441 //=======================================================================
442 //function : GetReal
443 //purpose  : 
444 //=======================================================================
445
446 Storage_BaseDriver& FSD_BinaryFile::GetReal(Standard_Real& aValue)
447 {
448   if (!fread(&aValue,sizeof(Standard_Real),1,myStream))
449     throw Storage_StreamTypeMismatchError();
450 #if OCCT_BINARY_FILE_DO_INVERSE
451   aValue = InverseReal (aValue);
452 #endif
453   return *this;
454 }
455
456 //=======================================================================
457 //function : GetShortReal
458 //purpose  : 
459 //=======================================================================
460
461 Storage_BaseDriver& FSD_BinaryFile::GetShortReal(Standard_ShortReal& aValue)
462 {
463   if (!fread(&aValue,sizeof(Standard_ShortReal),1,myStream))
464     throw Storage_StreamTypeMismatchError();
465 #if OCCT_BINARY_FILE_DO_INVERSE
466   aValue = InverseShortReal (aValue);
467 #endif
468   return *this;
469 }
470
471 //=======================================================================
472 //function : Destroy
473 //purpose  : 
474 //=======================================================================
475
476 void FSD_BinaryFile::Destroy()
477 {
478   if (OpenMode() != Storage_VSNone) {
479     Close();
480   }
481 }
482
483 //=======================================================================
484 //function : BeginWriteInfoSection
485 //purpose  : -------------------------- INFO : WRITE
486 //=======================================================================
487
488 Storage_Error FSD_BinaryFile::BeginWriteInfoSection() 
489 {
490   union {
491     char ti2[4];
492     Standard_Integer aResult;
493   } aWrapUnion;
494
495   aWrapUnion.ti2[0] = 1;
496   aWrapUnion.ti2[1] = 2;
497   aWrapUnion.ti2[2] = 3;
498   aWrapUnion.ti2[3] = 4;
499
500   myHeader.testindian = aWrapUnion.aResult;
501
502   if (!fwrite(FSD_BinaryFile::MagicNumber(),
503               strlen(FSD_BinaryFile::MagicNumber()),
504               1,
505               myStream))
506     throw Storage_StreamWriteError();
507   
508   myHeader.binfo = ftell(myStream);
509   WriteHeader();
510
511   return Storage_VSOk;
512 }
513
514 //=======================================================================
515 //function : WriteInfo
516 //purpose  : 
517 //=======================================================================
518
519 void FSD_BinaryFile::WriteInfo(const Standard_Integer nbObj,
520                          const TCollection_AsciiString& dbVersion,
521                          const TCollection_AsciiString& date,
522                          const TCollection_AsciiString& schemaName,
523                          const TCollection_AsciiString& schemaVersion,
524                          const TCollection_ExtendedString& appName,
525                          const TCollection_AsciiString& appVersion,
526                          const TCollection_ExtendedString& dataType,
527                          const TColStd_SequenceOfAsciiString& userInfo) 
528 {
529   Standard_Integer i;
530
531   PutInteger(nbObj);
532   WriteString(dbVersion);
533   WriteString(date);
534   WriteString(schemaName);
535   WriteString(schemaVersion);
536   WriteExtendedString(appName);
537   WriteString(appVersion);
538   WriteExtendedString(dataType);
539   i = userInfo.Length();
540
541   PutInteger(i);
542   for (i = 1; i <= userInfo.Length(); i++) {
543     WriteString(userInfo.Value(i));
544   }
545 }
546
547 //=======================================================================
548 //function : WriteInfo
549 //purpose  : 
550 //=======================================================================
551 Standard_Integer FSD_BinaryFile::WriteInfo (Standard_OStream&                    theOStream,
552                                             const Standard_Integer               theObjNb,
553                                             const TCollection_AsciiString&       theStoreVer,
554                                             const TCollection_AsciiString&       theCreationDate,
555                                             const TCollection_AsciiString&       theSchemaName,
556                                             const TCollection_AsciiString&       theSchemaVersion,
557                                             const TCollection_ExtendedString&    theAppName,
558                                             const TCollection_AsciiString&       theAppVer,
559                                             const TCollection_ExtendedString&    theDataType,
560                                             const TColStd_SequenceOfAsciiString& theUserInfo,
561                                             const Standard_Boolean               theOnlyCount) 
562 {
563   Standard_Integer anInfoSize = 0;
564
565   anInfoSize += PutInteger (theOStream, theObjNb, theOnlyCount);
566   anInfoSize += WriteString(theOStream, theStoreVer, theOnlyCount);
567   anInfoSize += WriteString(theOStream, theCreationDate, theOnlyCount);
568   anInfoSize += WriteString(theOStream, theSchemaName, theOnlyCount);
569   anInfoSize += WriteString(theOStream, theSchemaVersion, theOnlyCount);
570   anInfoSize += WriteExtendedString(theOStream, theAppName, theOnlyCount);
571   anInfoSize += WriteString(theOStream, theAppVer, theOnlyCount);
572   anInfoSize += WriteExtendedString(theOStream, theDataType, theOnlyCount);
573   
574   Standard_Integer i = theUserInfo.Length();
575   anInfoSize += PutInteger(theOStream, i, theOnlyCount);
576
577   for (i = 1; i <= theUserInfo.Length(); i++) {
578     anInfoSize += WriteString (theOStream, theUserInfo.Value(i), theOnlyCount);
579   }
580
581   return anInfoSize;
582 }
583
584 //=======================================================================
585 //function : EndWriteInfoSection
586 //purpose  : read
587 //=======================================================================
588
589 Storage_Error FSD_BinaryFile::EndWriteInfoSection() 
590 {
591   myHeader.einfo = ftell(myStream);
592
593   return Storage_VSOk;
594 }
595
596 //=======================================================================
597 //function : EndWriteInfoSection
598 //purpose  : read
599 //=======================================================================
600 Storage_Error FSD_BinaryFile::EndWriteInfoSection(Standard_OStream& theOStream) 
601 {
602   myHeader.einfo = (Standard_Integer)theOStream.tellp();
603
604   return Storage_VSOk;
605 }
606
607 //=======================================================================
608 //function : BeginReadInfoSection
609 //purpose  : 
610 //=======================================================================
611
612 Storage_Error FSD_BinaryFile::BeginReadInfoSection() 
613 {
614   Storage_Error s = Storage_VSOk;
615   TCollection_AsciiString l;
616   Standard_Size        len = strlen(FSD_BinaryFile::MagicNumber());
617
618   ReadChar(l,len);
619
620   if (strncmp(FSD_BinaryFile::MagicNumber(),l.ToCString(),len) != 0) {
621     s = Storage_VSFormatError;
622   }
623   else {
624     ReadHeader();
625   }
626
627   return s;
628 }
629
630 //=======================================================================
631 //function : ReadInfo
632 //purpose  : ------------------- INFO : READ
633 //=======================================================================
634
635 void FSD_BinaryFile::ReadInfo(Standard_Integer& nbObj,
636                         TCollection_AsciiString& dbVersion,
637                         TCollection_AsciiString& date,
638                         TCollection_AsciiString& schemaName,
639                         TCollection_AsciiString& schemaVersion,
640                         TCollection_ExtendedString& appName,
641                         TCollection_AsciiString& appVersion,
642                         TCollection_ExtendedString& dataType,
643                         TColStd_SequenceOfAsciiString& userInfo) 
644 {
645   GetInteger(nbObj);
646   ReadString(dbVersion);
647   ReadString(date);
648   ReadString(schemaName);
649   ReadString(schemaVersion);
650   ReadExtendedString(appName);
651   ReadString(appVersion);
652   ReadExtendedString(dataType);
653
654   Standard_Integer i,len = 0;
655
656   GetInteger(len);
657   TCollection_AsciiString line;
658
659   for (i = 1; i <= len && !IsEnd(); i++) {
660     ReadString(line);
661     userInfo.Append(line);
662   }
663 }
664
665 //=======================================================================
666 //function : ReadInfo
667 //purpose  : 
668 //=======================================================================
669 void FSD_BinaryFile::ReadCompleteInfo (Standard_IStream& theIStream, Handle(Storage_Data)& theData)
670 {
671   FSD_FileHeader aHeaderPos;
672   ReadHeader(theIStream, aHeaderPos);
673
674   if (theData.IsNull())
675   {
676     theData = new Storage_Data();
677   }
678
679   Handle(Storage_InternalData) iData = theData->InternalData();
680   Handle(Storage_TypeData)     tData = theData->TypeData();
681   Handle(Storage_RootData)     rData = theData->RootData();
682   Handle(Storage_HeaderData)   hData = theData->HeaderData();
683
684   ReadHeaderData (theIStream, hData);
685
686   Handle(Storage_HArrayOfCallBack) theCallBack;
687
688   while (theIStream.good() && !theIStream.eof())
689   {
690     Standard_Integer aPos = (Standard_Integer)theIStream.tellg();
691
692     if (aPos >= aHeaderPos.edata)
693     {
694       break;
695     }
696     else if (aPos == aHeaderPos.bcomment)
697     {
698       TColStd_SequenceOfExtendedString mComment;
699       ReadComment (theIStream, mComment);
700
701       for (Standard_Integer i = 1; i <= mComment.Length(); i++)
702       {
703         hData->AddToComments (mComment.Value(i));
704       }
705
706       iData->ReadArray() = new Storage_HPArray(1, theData->NumberOfObjects());
707     }
708     else if (aPos == aHeaderPos.btype)
709     {
710       Standard_Integer aTypeSectionSize = TypeSectionSize (theIStream);
711       theCallBack = new Storage_HArrayOfCallBack (1, aTypeSectionSize);
712
713       TCollection_AsciiString  aTypeName;
714       Standard_Integer         aTypeNum;
715
716       for (Standard_Integer i = 1; i <= aTypeSectionSize; i++)
717       {
718         ReadTypeInformations (theIStream, aTypeNum, aTypeName);
719         tData->AddType (aTypeName,aTypeNum);
720
721         theCallBack->SetValue (aTypeNum, NULL);
722       }
723     }
724     else if (aPos == aHeaderPos.broot)
725     {
726       Standard_Integer aRootSectionSize = RootSectionSize(theIStream);
727
728       Standard_Integer aRef;
729       TCollection_AsciiString aRootName, aTypeName;
730       Handle(Storage_Root) aRoot;
731       Handle(Standard_Persistent) aPer;
732
733       for (Standard_Integer i = 1; i <= aRootSectionSize; i++)
734       {
735         ReadRoot (theIStream, aRootName, aRef, aTypeName);
736
737         aRoot = new Storage_Root(aRootName, aPer);
738         aRoot->SetReference(aRef);
739         aRoot->SetType(aTypeName);
740         rData->AddRoot(aRoot);
741       }
742     }
743     else if (aPos == aHeaderPos.bref)
744     {
745       Standard_Integer aRefSectionSize = RefSectionSize (theIStream);
746
747       Standard_Integer aTypeNum, aRef = 0;
748
749       for (Standard_Integer i = 1; i <= aRefSectionSize; i++)
750       {
751         ReadReferenceType (theIStream, aRef, aTypeNum);
752             
753         iData->ReadArray()->ChangeValue(aRef) = theCallBack->Value(aTypeNum)->New();
754
755         if (!iData->ReadArray()->ChangeValue(aRef).IsNull())
756         {
757           iData->ReadArray()->ChangeValue(aRef)->TypeNum() = aTypeNum;
758         }
759       }
760     }
761     else if (aPos == aHeaderPos.bdata)
762     {
763       //
764     }
765   }
766
767   Handle(Storage_HSeqOfRoot) aRoots = rData->Roots();
768   for(Standard_Integer i = 1; i <= theData->NumberOfRoots(); i++)
769   {
770     const Handle(Storage_Root)& aCurRoot = aRoots->Value(i);
771     rData->UpdateRoot (aCurRoot->Name(), iData->ReadArray()->Value (aCurRoot->Reference()));
772   }
773
774   iData->Clear();
775 }
776
777 //=======================================================================
778 //function : EndReadInfoSection
779 //purpose  : COMMENTS SECTION
780 //           write
781 //=======================================================================
782
783 Storage_Error FSD_BinaryFile::EndReadInfoSection() 
784 {
785   if (!fseek(myStream,myHeader.einfo,SEEK_SET)) return Storage_VSOk;
786   else return Storage_VSSectionNotFound;
787 }
788
789 //=======================================================================
790 //function : BeginWriteCommentSection
791 //purpose  : ---------------- COMMENTS : WRITE
792 //=======================================================================
793
794 Storage_Error FSD_BinaryFile::BeginWriteCommentSection() 
795 {
796   myHeader.bcomment = ftell(myStream);
797   return Storage_VSOk;
798 }
799
800 //=======================================================================
801 //function : BeginWriteCommentSection
802 //purpose  :
803 //=======================================================================
804 Storage_Error FSD_BinaryFile::BeginWriteCommentSection(Standard_OStream& theOStream) 
805 {
806   myHeader.bcomment = (Standard_Integer)theOStream.tellp();
807   return Storage_VSOk;
808 }
809
810 //=======================================================================
811 //function : WriteComment
812 //purpose  : 
813 //=======================================================================
814
815 void FSD_BinaryFile::WriteComment(const TColStd_SequenceOfExtendedString& aCom)
816 {
817  Standard_Integer i,aSize;
818
819  aSize = aCom.Length();
820  PutInteger(aSize);
821  for (i = 1; i <= aSize; i++) {
822    WriteExtendedString(aCom.Value(i));
823  }
824 }
825
826 //=======================================================================
827 //function : WriteComment
828 //purpose  : 
829 //=======================================================================
830 Standard_Integer FSD_BinaryFile::WriteComment (Standard_OStream&                       theOStream,
831                                                const TColStd_SequenceOfExtendedString& theComments,
832                                                const Standard_Boolean                  theOnlyCount)
833 {
834   Standard_Integer aCommentSize = 0;
835
836   Standard_Integer aSize = theComments.Length();
837   aCommentSize += PutInteger(theOStream, aSize, theOnlyCount);
838
839   for (Standard_Integer i = 1; i <= aSize; i++) {
840     aCommentSize += WriteExtendedString (theOStream, theComments.Value(i), theOnlyCount);
841   }
842
843   return aCommentSize;
844 }
845
846 //=======================================================================
847 //function : EndWriteCommentSection
848 //purpose  : read
849 //=======================================================================
850
851 Storage_Error FSD_BinaryFile::EndWriteCommentSection() 
852 {
853   myHeader.ecomment = ftell(myStream);
854
855   return Storage_VSOk;
856 }
857
858 //=======================================================================
859 //function : EndWriteCommentSection
860 //purpose  : read
861 //=======================================================================
862 Storage_Error FSD_BinaryFile::EndWriteCommentSection (Standard_OStream& theOStream) 
863 {
864   myHeader.ecomment = (Standard_Integer)theOStream.tellp();
865
866   return Storage_VSOk;
867 }
868
869 //=======================================================================
870 //function : BeginReadCommentSection
871 //purpose  : ---------------- COMMENTS : READ
872 //=======================================================================
873
874 Storage_Error FSD_BinaryFile::BeginReadCommentSection() 
875 {
876   if (!fseek(myStream,myHeader.bcomment,SEEK_SET)) return Storage_VSOk;
877   else return Storage_VSSectionNotFound;
878 }
879
880 //=======================================================================
881 //function : ReadComment
882 //purpose  : 
883 //=======================================================================
884
885 void FSD_BinaryFile::ReadComment(TColStd_SequenceOfExtendedString& aCom)
886 {
887   TCollection_ExtendedString line;
888   Standard_Integer           len,i;
889
890   GetInteger(len);
891   for (i = 1; i <= len && !IsEnd(); i++) {
892     ReadExtendedString(line);
893     aCom.Append(line);
894   }
895 }
896
897 //=======================================================================
898 //function : ReadComment
899 //purpose  : 
900 //=======================================================================
901 void FSD_BinaryFile::ReadComment (Standard_IStream& theIStream, TColStd_SequenceOfExtendedString& aCom)
902 {
903   TCollection_ExtendedString line;
904   Standard_Integer           len,i;
905
906   GetInteger(theIStream, len);
907   for (i = 1; i <= len && theIStream.good(); i++)
908   {
909     ReadExtendedString(theIStream, line);
910     aCom.Append(line);
911   }
912 }
913
914 //=======================================================================
915 //function : EndReadCommentSection
916 //purpose  : 
917 //=======================================================================
918
919 Storage_Error FSD_BinaryFile::EndReadCommentSection() 
920 {
921   if (!fseek(myStream,myHeader.ecomment,SEEK_SET)) return Storage_VSOk;
922   else return Storage_VSSectionNotFound;
923 }
924
925 //=======================================================================
926 //function : BeginWriteTypeSection
927 //purpose  : --------------- TYPE : WRITE
928 //=======================================================================
929
930 Storage_Error FSD_BinaryFile::BeginWriteTypeSection() 
931 {
932   myHeader.btype = ftell(myStream);
933
934   return Storage_VSOk;
935 }
936
937 //=======================================================================
938 //function : SetTypeSectionSize
939 //purpose  : 
940 //=======================================================================
941
942 void FSD_BinaryFile::SetTypeSectionSize(const Standard_Integer aSize) 
943 {
944   PutInteger(aSize);
945 }
946
947 //=======================================================================
948 //function : WriteTypeInformations
949 //purpose  : 
950 //=======================================================================
951
952 void FSD_BinaryFile::WriteTypeInformations(const Standard_Integer typeNum,
953                                       const TCollection_AsciiString& typeName) 
954 {
955   PutInteger(typeNum);
956   WriteString(typeName);
957 }
958
959 //=======================================================================
960 //function : EndWriteTypeSection
961 //purpose  : read
962 //=======================================================================
963
964 Storage_Error FSD_BinaryFile::EndWriteTypeSection() 
965 {
966   myHeader.etype = ftell(myStream);
967
968   return Storage_VSOk;
969 }
970
971 //=======================================================================
972 //function : BeginReadTypeSection
973 //purpose  : ------------------- TYPE : READ
974 //=======================================================================
975
976 Storage_Error FSD_BinaryFile::BeginReadTypeSection() 
977 {
978  if (!fseek(myStream,myHeader.btype,SEEK_SET)) return Storage_VSOk;
979   else return Storage_VSSectionNotFound;
980 }
981
982 //=======================================================================
983 //function : TypeSectionSize
984 //purpose  : 
985 //=======================================================================
986
987 Standard_Integer FSD_BinaryFile::TypeSectionSize() 
988 {
989   Standard_Integer i;
990
991   GetInteger(i);
992   return i;
993 }
994
995 //=======================================================================
996 //function : TypeSectionSize
997 //purpose  : 
998 //=======================================================================
999 Standard_Integer FSD_BinaryFile::TypeSectionSize(Standard_IStream& theIStream) 
1000 {
1001   Standard_Integer i;
1002
1003   GetInteger(theIStream, i);
1004   return i;
1005 }
1006
1007 //=======================================================================
1008 //function : ReadTypeInformations
1009 //purpose  : 
1010 //=======================================================================
1011
1012 void FSD_BinaryFile::ReadTypeInformations(Standard_Integer& typeNum,TCollection_AsciiString& typeName) 
1013 {
1014   GetInteger(typeNum);
1015   ReadString(typeName);
1016 }
1017
1018 //=======================================================================
1019 //function : ReadTypeInformations
1020 //purpose  : 
1021 //=======================================================================
1022 void FSD_BinaryFile::ReadTypeInformations(Standard_IStream& theIStream, Standard_Integer& typeNum,TCollection_AsciiString& typeName) 
1023 {
1024   GetInteger(theIStream, typeNum);
1025   ReadString(theIStream, typeName);
1026 }
1027
1028 //=======================================================================
1029 //function : EndReadTypeSection
1030 //purpose  : ROOT SECTION
1031 //           write
1032 //=======================================================================
1033
1034 Storage_Error FSD_BinaryFile::EndReadTypeSection() 
1035 {
1036  if (!fseek(myStream,myHeader.etype,SEEK_SET)) return Storage_VSOk;
1037   else return Storage_VSSectionNotFound;
1038 }
1039
1040 //=======================================================================
1041 //function : BeginWriteRootSection
1042 //purpose  : -------------------- ROOT : WRITE
1043 //=======================================================================
1044
1045 Storage_Error FSD_BinaryFile::BeginWriteRootSection() 
1046 {
1047   myHeader.broot = ftell(myStream);
1048
1049   return Storage_VSOk;
1050 }
1051
1052 //=======================================================================
1053 //function : SetRootSectionSize
1054 //purpose  : 
1055 //=======================================================================
1056
1057 void FSD_BinaryFile::SetRootSectionSize(const Standard_Integer aSize) 
1058 {
1059   PutInteger(aSize);
1060 }
1061
1062 //=======================================================================
1063 //function : WriteRoot
1064 //purpose  : 
1065 //=======================================================================
1066
1067 void FSD_BinaryFile::WriteRoot(const TCollection_AsciiString& rootName, const Standard_Integer aRef, const TCollection_AsciiString& rootType) 
1068 {
1069   PutReference(aRef);
1070   WriteString(rootName);
1071   WriteString(rootType);
1072 }
1073
1074 //=======================================================================
1075 //function : EndWriteRootSection
1076 //purpose  : read
1077 //=======================================================================
1078
1079 Storage_Error FSD_BinaryFile::EndWriteRootSection() 
1080 {
1081   myHeader.eroot = ftell(myStream);
1082
1083   return Storage_VSOk;
1084 }
1085
1086 //=======================================================================
1087 //function : BeginReadRootSection
1088 //purpose  : ----------------------- ROOT : READ
1089 //=======================================================================
1090
1091 Storage_Error FSD_BinaryFile::BeginReadRootSection() 
1092 {
1093  if (!fseek(myStream,myHeader.broot,SEEK_SET)) return Storage_VSOk;
1094   else return Storage_VSSectionNotFound;
1095 }
1096
1097 //=======================================================================
1098 //function : RootSectionSize
1099 //purpose  : 
1100 //=======================================================================
1101
1102 Standard_Integer FSD_BinaryFile::RootSectionSize() 
1103 {
1104   Standard_Integer i;
1105   
1106   GetInteger(i);
1107   return i;
1108 }
1109
1110 //=======================================================================
1111 //function : RootSectionSize
1112 //purpose  : 
1113 //=======================================================================
1114 Standard_Integer FSD_BinaryFile::RootSectionSize (Standard_IStream& theIStream) 
1115 {
1116   Standard_Integer i;
1117
1118   GetInteger(theIStream, i);
1119   return i;
1120 }
1121
1122 //=======================================================================
1123 //function : ReadRoot
1124 //purpose  : 
1125 //=======================================================================
1126
1127 void FSD_BinaryFile::ReadRoot(TCollection_AsciiString& rootName, Standard_Integer& aRef,TCollection_AsciiString& rootType) 
1128 {
1129   GetReference(aRef);
1130   ReadString(rootName);
1131   ReadString(rootType);
1132 }
1133
1134 //=======================================================================
1135 //function : ReadRoot
1136 //purpose  : 
1137 //=======================================================================
1138 void FSD_BinaryFile::ReadRoot (Standard_IStream& theIStream, TCollection_AsciiString& rootName, Standard_Integer& aRef,TCollection_AsciiString& rootType) 
1139 {
1140   GetReference(theIStream, aRef);
1141   ReadString(theIStream, rootName);
1142   ReadString(theIStream, rootType);
1143 }
1144
1145 //=======================================================================
1146 //function : EndReadRootSection
1147 //purpose  : REF SECTION
1148 //           write
1149 //=======================================================================
1150
1151 Storage_Error FSD_BinaryFile::EndReadRootSection() 
1152 {
1153  if (!fseek(myStream,myHeader.eroot,SEEK_SET)) return Storage_VSOk;
1154   else return Storage_VSSectionNotFound;
1155 }
1156
1157 //=======================================================================
1158 //function : BeginWriteRefSection
1159 //purpose  : -------------------------- REF : WRITE
1160 //=======================================================================
1161
1162 Storage_Error FSD_BinaryFile::BeginWriteRefSection() 
1163 {
1164   myHeader.bref = ftell(myStream);
1165
1166   return Storage_VSOk;
1167 }
1168
1169 //=======================================================================
1170 //function : SetRefSectionSize
1171 //purpose  : 
1172 //=======================================================================
1173
1174 void FSD_BinaryFile::SetRefSectionSize(const Standard_Integer aSize) 
1175 {
1176   PutInteger(aSize);
1177 }
1178
1179 //=======================================================================
1180 //function : WriteReferenceType
1181 //purpose  : 
1182 //=======================================================================
1183
1184 void FSD_BinaryFile::WriteReferenceType(const Standard_Integer reference,const Standard_Integer typeNum) 
1185 {
1186   PutReference(reference);
1187   PutInteger(typeNum);
1188 }
1189
1190 //=======================================================================
1191 //function : EndWriteRefSection
1192 //purpose  : read
1193 //=======================================================================
1194
1195 Storage_Error FSD_BinaryFile::EndWriteRefSection() 
1196 {
1197   myHeader.eref = ftell(myStream);
1198
1199   return Storage_VSOk;
1200 }
1201
1202 //=======================================================================
1203 //function : BeginReadRefSection
1204 //purpose  : ----------------------- REF : READ
1205 //=======================================================================
1206
1207 Storage_Error FSD_BinaryFile::BeginReadRefSection() 
1208 {
1209  if (!fseek(myStream,myHeader.bref,SEEK_SET)) return Storage_VSOk;
1210   else return Storage_VSSectionNotFound;
1211 }
1212
1213 //=======================================================================
1214 //function : RefSectionSize
1215 //purpose  : 
1216 //=======================================================================
1217
1218 Standard_Integer FSD_BinaryFile::RefSectionSize() 
1219 {
1220   Standard_Integer i;
1221
1222   GetInteger(i);
1223   return i;
1224 }
1225
1226 //=======================================================================
1227 //function : RefSectionSize
1228 //purpose  : 
1229 //=======================================================================
1230 Standard_Integer FSD_BinaryFile::RefSectionSize (Standard_IStream& theIStream) 
1231 {
1232   Standard_Integer i;
1233
1234   GetInteger(theIStream, i);
1235   return i;
1236 }
1237
1238 //=======================================================================
1239 //function : ReadReferenceType
1240 //purpose  : 
1241 //=======================================================================
1242
1243 void FSD_BinaryFile::ReadReferenceType(Standard_Integer& reference,
1244                                  Standard_Integer& typeNum) 
1245 {
1246   GetReference(reference);
1247   GetInteger(typeNum);
1248 }
1249
1250 //=======================================================================
1251 //function : ReadReferenceType
1252 //purpose  : 
1253 //=======================================================================
1254 void FSD_BinaryFile::ReadReferenceType (Standard_IStream& theIStream, Standard_Integer& reference, Standard_Integer& typeNum) 
1255 {
1256   GetReference (theIStream, reference);
1257   GetInteger   (theIStream, typeNum);
1258 }
1259
1260 //=======================================================================
1261 //function : EndReadRefSection
1262 //purpose  : DATA SECTION
1263 //           write
1264 //=======================================================================
1265
1266 Storage_Error FSD_BinaryFile::EndReadRefSection() 
1267 {
1268  if (!fseek(myStream,myHeader.eref,SEEK_SET)) return Storage_VSOk;
1269   else return Storage_VSSectionNotFound;
1270 }
1271
1272 //=======================================================================
1273 //function : BeginWriteDataSection
1274 //purpose  : -------------------- DATA : WRITE
1275 //=======================================================================
1276
1277 Storage_Error FSD_BinaryFile::BeginWriteDataSection() 
1278 {
1279   myHeader.bdata = ftell(myStream);
1280
1281   return Storage_VSOk;
1282 }
1283
1284 //=======================================================================
1285 //function : WritePersistentObjectHeader
1286 //purpose  : 
1287 //=======================================================================
1288
1289 void FSD_BinaryFile::WritePersistentObjectHeader(const Standard_Integer aRef,
1290                                            const Standard_Integer aType) 
1291 {
1292   PutReference(aRef);
1293   PutInteger(aType);
1294 }
1295
1296 //=======================================================================
1297 //function : BeginWritePersistentObjectData
1298 //purpose  : 
1299 //=======================================================================
1300
1301 void FSD_BinaryFile::BeginWritePersistentObjectData() 
1302 {
1303 }
1304
1305 //=======================================================================
1306 //function : BeginWriteObjectData
1307 //purpose  : 
1308 //=======================================================================
1309
1310 void FSD_BinaryFile::BeginWriteObjectData() 
1311 {
1312 }
1313
1314 //=======================================================================
1315 //function : EndWriteObjectData
1316 //purpose  : 
1317 //=======================================================================
1318
1319 void FSD_BinaryFile::EndWriteObjectData() 
1320 {
1321 }
1322
1323 //=======================================================================
1324 //function : EndWritePersistentObjectData
1325 //purpose  : 
1326 //=======================================================================
1327
1328 void FSD_BinaryFile::EndWritePersistentObjectData() 
1329 {
1330 }
1331
1332 //=======================================================================
1333 //function : EndWriteDataSection
1334 //purpose  : read
1335 //=======================================================================
1336
1337 Storage_Error FSD_BinaryFile::EndWriteDataSection() 
1338 {
1339   myHeader.edata = ftell(myStream);
1340   
1341   fseek(myStream,myHeader.binfo,SEEK_SET);
1342   WriteHeader();
1343   return Storage_VSOk;
1344 }
1345
1346 //=======================================================================
1347 //function : BeginReadDataSection
1348 //purpose  : ---------------------- DATA : READ
1349 //=======================================================================
1350
1351 Storage_Error FSD_BinaryFile::BeginReadDataSection() 
1352 {
1353  if (!fseek(myStream,myHeader.bdata,SEEK_SET)) return Storage_VSOk;
1354   else return Storage_VSSectionNotFound;
1355 }
1356
1357 //=======================================================================
1358 //function : ReadPersistentObjectHeader
1359 //purpose  : 
1360 //=======================================================================
1361
1362 void FSD_BinaryFile::ReadPersistentObjectHeader(Standard_Integer& aRef,
1363                                           Standard_Integer& aType) 
1364 {
1365   GetReference(aRef);
1366   GetInteger(aType);
1367 }
1368
1369 //=======================================================================
1370 //function : BeginReadPersistentObjectData
1371 //purpose  : 
1372 //=======================================================================
1373
1374 void FSD_BinaryFile::BeginReadPersistentObjectData() 
1375 {
1376 }
1377
1378 //=======================================================================
1379 //function : BeginReadObjectData
1380 //purpose  : 
1381 //=======================================================================
1382
1383 void FSD_BinaryFile::BeginReadObjectData() 
1384 {
1385 }
1386
1387 //=======================================================================
1388 //function : EndReadObjectData
1389 //purpose  : 
1390 //=======================================================================
1391
1392 void FSD_BinaryFile::EndReadObjectData() 
1393 {
1394 }
1395
1396 //=======================================================================
1397 //function : EndReadPersistentObjectData
1398 //purpose  : 
1399 //=======================================================================
1400
1401 void FSD_BinaryFile::EndReadPersistentObjectData() 
1402 {
1403 }
1404
1405 //=======================================================================
1406 //function : EndReadDataSection
1407 //purpose  : 
1408 //=======================================================================
1409
1410 Storage_Error FSD_BinaryFile::EndReadDataSection() 
1411 {
1412  if (!fseek(myStream,myHeader.edata,SEEK_SET)) return Storage_VSOk;
1413   else return Storage_VSSectionNotFound;
1414 }
1415
1416 //=======================================================================
1417 //function : WriteString
1418 //purpose  : write string at the current position.
1419 //=======================================================================
1420
1421 void FSD_BinaryFile::WriteString(const TCollection_AsciiString& aString)
1422 {
1423   Standard_Integer size;
1424
1425   size = aString.Length();
1426
1427   PutInteger(size);
1428
1429   if (size > 0) {
1430     if (!fwrite(aString.ToCString(),aString.Length(),1,myStream)) throw Storage_StreamWriteError();
1431   }
1432 }
1433
1434 //=======================================================================
1435 //function : WriteString
1436 //purpose  : write string at the current position.
1437 //=======================================================================
1438 Standard_Integer FSD_BinaryFile::WriteString (Standard_OStream&              theOStream,
1439                                               const TCollection_AsciiString& theString,
1440                                               const Standard_Boolean         theOnlyCount)
1441 {
1442   Standard_Integer aNumAndStrLen, anAsciiStrLen;
1443
1444   anAsciiStrLen = aNumAndStrLen = theString.Length();
1445
1446   aNumAndStrLen += PutInteger (theOStream, anAsciiStrLen, theOnlyCount);
1447
1448   if (anAsciiStrLen > 0 && !theOnlyCount)
1449   {
1450     theOStream.write (theString.ToCString(), theString.Length());
1451     if (theOStream.fail())
1452     {
1453       throw Storage_StreamWriteError();
1454     }
1455   }
1456
1457   return aNumAndStrLen;
1458 }
1459
1460 //=======================================================================
1461 //function : ReadString
1462 //purpose  : read string from the current position.
1463 //=======================================================================
1464
1465 void FSD_BinaryFile::ReadString(TCollection_AsciiString& aString)
1466 {
1467   Standard_Integer size = 0;
1468
1469   GetInteger(size);
1470   if (size > 0) {
1471     Standard_Character *c = (Standard_Character *)Standard::Allocate((size+1) * sizeof(Standard_Character));
1472     if (!fread(c,size,1,myStream)) throw Storage_StreamWriteError();
1473     c[size] = '\0';
1474     aString = c;
1475     Standard::Free(c);
1476   }
1477   else {
1478     aString.Clear();
1479   }
1480 }
1481
1482 //=======================================================================
1483 //function : ReadString
1484 //purpose  : read string from the current position.
1485 //=======================================================================
1486 void FSD_BinaryFile::ReadString (Standard_IStream& theIStream, TCollection_AsciiString& aString)
1487 {
1488   Standard_Integer size = 0;
1489
1490   GetInteger(theIStream, size);
1491
1492   if (size > 0)
1493   {
1494     Standard_Character *c = (Standard_Character *)Standard::Allocate((size+1) * sizeof(Standard_Character));
1495
1496     if (!theIStream.good())
1497     {
1498       throw Storage_StreamReadError();
1499     }
1500
1501     theIStream.read (c, size);
1502
1503     if (theIStream.gcount() != size)
1504     {
1505       throw Storage_StreamReadError();
1506     }
1507
1508     c[size] = '\0';
1509     
1510     aString = c;
1511     
1512     Standard::Free(c);
1513   }
1514   else
1515   {
1516     aString.Clear();
1517   }
1518 }
1519
1520 //=======================================================================
1521 //function : WriteExtendedString
1522 //purpose  : write string at the current position.
1523 //=======================================================================
1524
1525 void FSD_BinaryFile::WriteExtendedString(const TCollection_ExtendedString& aString)
1526 {
1527   Standard_Integer size;
1528
1529   size = aString.Length();
1530
1531   PutInteger(size);
1532
1533   if (size > 0) {
1534     Standard_ExtString anExtStr;
1535 #if OCCT_BINARY_FILE_DO_INVERSE
1536     TCollection_ExtendedString aCopy = aString;
1537     anExtStr = aCopy.ToExtString();
1538
1539     Standard_PExtCharacter pChar;
1540     //
1541     pChar=(Standard_PExtCharacter)anExtStr;
1542     
1543     for (Standard_Integer i=0; i < size; i++)
1544       pChar[i] = InverseExtChar (pChar[i]);
1545 #else
1546     anExtStr = aString.ToExtString();
1547 #endif
1548     if (!fwrite(anExtStr,sizeof(Standard_ExtCharacter)*aString.Length(),1,myStream))
1549       throw Storage_StreamWriteError();
1550   }
1551 }
1552
1553 //=======================================================================
1554 //function : WriteExtendedString
1555 //purpose  : write string at the current position.
1556 //=======================================================================
1557 Standard_Integer FSD_BinaryFile::WriteExtendedString (Standard_OStream&                 theOStream,
1558                                                       const TCollection_ExtendedString& theString,
1559                                                       const Standard_Boolean            theOnlyCount)
1560 {
1561   Standard_Integer aNumAndStrLen, anExtStrLen;
1562   anExtStrLen = theString.Length();
1563
1564   aNumAndStrLen = anExtStrLen * sizeof(Standard_ExtCharacter);
1565   aNumAndStrLen += PutInteger (theOStream, anExtStrLen, theOnlyCount);
1566
1567   if (anExtStrLen > 0 && !theOnlyCount)
1568   {
1569     Standard_ExtString anExtStr;
1570 #if OCCT_BINARY_FILE_DO_INVERSE
1571     TCollection_ExtendedString aCopy = theString;
1572     anExtStr = aCopy.ToExtString();
1573
1574     Standard_PExtCharacter pChar;
1575     //
1576     pChar = (Standard_PExtCharacter)anExtStr;
1577
1578     for (Standard_Integer i = 0; i < anExtStrLen; i++)
1579     {
1580       pChar[i] = InverseExtChar (pChar[i]);
1581     }
1582 #else
1583     anExtStr = theString.ToExtString();
1584 #endif
1585
1586     theOStream.write((char*)anExtStr, sizeof(Standard_ExtCharacter)*theString.Length());
1587     if (theOStream.fail())
1588     {
1589       throw Storage_StreamWriteError();
1590     }
1591   }
1592
1593   return aNumAndStrLen;
1594 }
1595
1596 //=======================================================================
1597 //function : ReadExtendedString
1598 //purpose  : read string from the current position.
1599 //=======================================================================
1600
1601 void FSD_BinaryFile::ReadExtendedString(TCollection_ExtendedString& aString)
1602 {
1603   Standard_Integer size = 0;
1604
1605   GetInteger(size);
1606   if (size > 0) {
1607     Standard_ExtCharacter *c = (Standard_ExtCharacter *)
1608       Standard::Allocate((size+1) * sizeof(Standard_ExtCharacter));
1609     if (!fread(c,size*sizeof(Standard_ExtCharacter),1,myStream))
1610       throw Storage_StreamWriteError();
1611     c[size] = '\0';
1612 #if OCCT_BINARY_FILE_DO_INVERSE
1613     for (Standard_Integer i=0; i < size; i++)
1614       c[i] = InverseExtChar (c[i]);
1615 #endif
1616     aString = c;
1617     Standard::Free(c);
1618   }
1619   else {
1620     aString.Clear();
1621   }
1622 }
1623
1624 //=======================================================================
1625 //function : ReadExtendedString
1626 //purpose  : read string from the current position.
1627 //=======================================================================
1628 void FSD_BinaryFile::ReadExtendedString (Standard_IStream& theIStream, TCollection_ExtendedString& aString)
1629 {
1630   Standard_Integer size = 0;
1631
1632   GetInteger (theIStream, size);
1633
1634   if (size > 0)
1635   {
1636     Standard_ExtCharacter *c = (Standard_ExtCharacter *)Standard::Allocate((size+1) * sizeof(Standard_ExtCharacter));
1637
1638     if (!theIStream.good())
1639     {
1640       throw Storage_StreamReadError();
1641     }
1642
1643     const std::streamsize aNbBytes = std::streamsize(sizeof(Standard_ExtCharacter) * size);
1644     theIStream.read ((char *)c, aNbBytes);
1645     if (theIStream.gcount() != aNbBytes)
1646     {
1647       throw Storage_StreamReadError();
1648     }
1649
1650     c[size] = '\0';
1651
1652 #if OCCT_BINARY_FILE_DO_INVERSE
1653     for (Standard_Integer i=0; i < size; i++)
1654     {
1655       c[i] = InverseExtChar (c[i]);
1656     }
1657 #endif
1658     aString = c;
1659     Standard::Free(c);
1660   }
1661   else
1662   {
1663     aString.Clear();
1664   }
1665 }
1666
1667 //=======================================================================
1668 //function : WriteHeader
1669 //purpose  : 
1670 //=======================================================================
1671
1672 void FSD_BinaryFile::WriteHeader()
1673 {
1674   PutInteger(myHeader.testindian);
1675   PutInteger(myHeader.binfo);
1676   PutInteger(myHeader.einfo);
1677   PutInteger(myHeader.bcomment);
1678   PutInteger(myHeader.ecomment);
1679   PutInteger(myHeader.btype);
1680   PutInteger(myHeader.etype);
1681   PutInteger(myHeader.broot);
1682   PutInteger(myHeader.eroot);
1683   PutInteger(myHeader.bref);
1684   PutInteger(myHeader.eref);
1685   PutInteger(myHeader.bdata);
1686   PutInteger(myHeader.edata);
1687 }
1688
1689 //=======================================================================
1690 //function : WriteHeader
1691 //purpose  : 
1692 //=======================================================================
1693 Standard_Integer FSD_BinaryFile::WriteHeader (Standard_OStream&      theOStream, 
1694                                               const FSD_FileHeader&  theHeader,
1695                                               const Standard_Boolean theOnlyCount)
1696 {
1697   Standard_Integer aHeaderSize = 0;
1698
1699   aHeaderSize += PutInteger (theOStream, theHeader.testindian, theOnlyCount);
1700   aHeaderSize += PutInteger (theOStream, theHeader.binfo,      theOnlyCount);
1701   aHeaderSize += PutInteger (theOStream, theHeader.einfo,      theOnlyCount);
1702   aHeaderSize += PutInteger (theOStream, theHeader.bcomment,   theOnlyCount);
1703   aHeaderSize += PutInteger (theOStream, theHeader.ecomment,   theOnlyCount);
1704   aHeaderSize += PutInteger (theOStream, theHeader.btype,      theOnlyCount);
1705   aHeaderSize += PutInteger (theOStream, theHeader.etype,      theOnlyCount);
1706   aHeaderSize += PutInteger (theOStream, theHeader.broot,      theOnlyCount);
1707   aHeaderSize += PutInteger (theOStream, theHeader.eroot,      theOnlyCount);
1708   aHeaderSize += PutInteger (theOStream, theHeader.bref,       theOnlyCount);
1709   aHeaderSize += PutInteger (theOStream, theHeader.eref,       theOnlyCount);
1710   aHeaderSize += PutInteger (theOStream, theHeader.bdata,      theOnlyCount);
1711   aHeaderSize += PutInteger (theOStream, theHeader.edata,      theOnlyCount);
1712
1713    return aHeaderSize;
1714 }
1715
1716 //=======================================================================
1717 //function : ReadHeader
1718 //purpose  : 
1719 //=======================================================================
1720
1721 void FSD_BinaryFile::ReadHeader()
1722 {
1723   GetInteger(myHeader.testindian);
1724   GetInteger(myHeader.binfo);
1725   GetInteger(myHeader.einfo);
1726   GetInteger(myHeader.bcomment);
1727   GetInteger(myHeader.ecomment);
1728   GetInteger(myHeader.btype);
1729   GetInteger(myHeader.etype);
1730   GetInteger(myHeader.broot);
1731   GetInteger(myHeader.eroot);
1732   GetInteger(myHeader.bref);
1733   GetInteger(myHeader.eref);
1734   GetInteger(myHeader.bdata);
1735   GetInteger(myHeader.edata);
1736 }
1737
1738 //=======================================================================
1739 //function : ReadHeader
1740 //purpose  : 
1741 //=======================================================================
1742
1743 void FSD_BinaryFile::ReadHeader(Standard_IStream& theIStream, FSD_FileHeader& theFileHeader)
1744 {
1745   GetInteger (theIStream, theFileHeader.testindian);
1746   GetInteger (theIStream, theFileHeader.binfo);
1747   GetInteger (theIStream, theFileHeader.einfo);
1748   GetInteger (theIStream, theFileHeader.bcomment);
1749   GetInteger (theIStream, theFileHeader.ecomment);
1750   GetInteger (theIStream, theFileHeader.btype);
1751   GetInteger (theIStream, theFileHeader.etype);
1752   GetInteger (theIStream, theFileHeader.broot);
1753   GetInteger (theIStream, theFileHeader.eroot);
1754   GetInteger (theIStream, theFileHeader.bref);
1755   GetInteger (theIStream, theFileHeader.eref);
1756   GetInteger (theIStream, theFileHeader.bdata);
1757   GetInteger (theIStream, theFileHeader.edata);
1758 }
1759
1760 //=======================================================================
1761 //function : ReadHeaderData
1762 //purpose  : 
1763 //=======================================================================
1764 void FSD_BinaryFile::ReadHeaderData( Standard_IStream& theIStream, const Handle(Storage_HeaderData)& theHeaderData )
1765 {
1766   // read info 
1767   TCollection_AsciiString          uinfo,mStorageVersion,mDate,mSchemaName,mSchemaVersion,mApplicationVersion;
1768   TCollection_ExtendedString       mApplicationName,mDataType;
1769   TColStd_SequenceOfAsciiString    mUserInfo;
1770   Standard_Integer                 mNBObj;
1771
1772   FSD_BinaryFile::GetInteger (theIStream, mNBObj);
1773   FSD_BinaryFile::ReadString (theIStream, mStorageVersion);
1774   FSD_BinaryFile::ReadString (theIStream, mDate);
1775   FSD_BinaryFile::ReadString (theIStream, mSchemaName);
1776   FSD_BinaryFile::ReadString (theIStream, mSchemaVersion);
1777   FSD_BinaryFile::ReadExtendedString(theIStream, mApplicationName);
1778   FSD_BinaryFile::ReadString (theIStream, mApplicationVersion);
1779   FSD_BinaryFile::ReadExtendedString(theIStream, mDataType);
1780
1781   Standard_Integer len = 0;
1782   TCollection_AsciiString line;
1783
1784   FSD_BinaryFile::GetInteger(theIStream, len);
1785
1786   for (Standard_Integer i = 1; i <= len && theIStream.good(); i++)
1787   {
1788     FSD_BinaryFile::ReadString (theIStream, line);
1789     mUserInfo.Append(line);
1790   }
1791
1792   theHeaderData->SetNumberOfObjects(mNBObj);
1793   theHeaderData->SetStorageVersion(mStorageVersion);
1794   theHeaderData->SetCreationDate(mDate);
1795   theHeaderData->SetSchemaName(mSchemaName);
1796   theHeaderData->SetSchemaVersion(mSchemaVersion);
1797   theHeaderData->SetApplicationName(mApplicationName);
1798   theHeaderData->SetApplicationVersion(mApplicationVersion);
1799   theHeaderData->SetDataType(mDataType);
1800
1801   for (Standard_Integer i = 1; i <= mUserInfo.Length(); i++) {
1802     theHeaderData->AddToUserInfo(mUserInfo.Value(i));
1803   }
1804 }
1805
1806 //=======================================================================
1807 //function : Tell
1808 //purpose  : return position in the file. Return -1 upon error.
1809 //=======================================================================
1810
1811 Storage_Position FSD_BinaryFile::Tell()
1812 {
1813   return (Storage_Position) ftell(myStream);
1814 }
1815
1816 //=======================================================================
1817 //function : InverseReal
1818 //purpose  : Inverses bytes in the real value
1819 //=======================================================================
1820
1821 Standard_Real FSD_BinaryFile::InverseReal (const Standard_Real theValue)
1822 {
1823   Standard_STATIC_ASSERT(sizeof(Standard_Real) == 2 * sizeof(Standard_Integer));
1824   union {
1825     Standard_Integer i[2];
1826     Standard_Real    aValue;
1827   } aWrapUnion;
1828
1829   aWrapUnion.aValue = theValue;
1830
1831   Standard_Integer aTemp = aWrapUnion.i[1];
1832   aWrapUnion.i[1] = InverseInt(aWrapUnion.i[0]);
1833   aWrapUnion.i[0] = InverseInt(aTemp);
1834
1835   return aWrapUnion.aValue;
1836 }
1837
1838 //=======================================================================
1839 //function : InverseShortReal
1840 //purpose  : Inverses bytes in the short real value
1841 //=======================================================================
1842
1843 Standard_ShortReal FSD_BinaryFile::InverseShortReal (const Standard_ShortReal theValue)
1844 {
1845   Standard_STATIC_ASSERT(sizeof(Standard_ShortReal) == sizeof(Standard_Integer));
1846   union {
1847     Standard_ShortReal aValue;
1848     Standard_Integer   aResult;
1849   } aWrapUnion;
1850
1851   aWrapUnion.aValue  = theValue;
1852   aWrapUnion.aResult = InverseInt (aWrapUnion.aResult);
1853
1854   return aWrapUnion.aValue;
1855 }
1856
1857 //=======================================================================
1858 //function : InverseSize
1859 //purpose  : Inverses bytes in size_t type instance
1860 //=======================================================================
1861
1862 template<int size>
1863 inline uint64_t OCCT_InverseSizeSpecialized (const uint64_t theValue, int);
1864
1865 template<>
1866 inline uint64_t OCCT_InverseSizeSpecialized <4> (const uint64_t theValue, int)
1867 {
1868   return FSD_BinaryFile::InverseInt(static_cast<Standard_Integer>(theValue));
1869 }
1870
1871 template<>
1872 inline uint64_t OCCT_InverseSizeSpecialized <8> (const uint64_t theValue, int)
1873 {
1874   union {
1875     Standard_Integer i[2];
1876     uint64_t    aValue;
1877   } aWrapUnion;
1878
1879   aWrapUnion.aValue = theValue;
1880
1881   Standard_Integer aTemp = aWrapUnion.i[1];
1882   aWrapUnion.i[1] = FSD_BinaryFile::InverseInt(aWrapUnion.i[0]);
1883   aWrapUnion.i[0] = FSD_BinaryFile::InverseInt(aTemp);
1884
1885   return aWrapUnion.aValue;
1886 }
1887
1888 Standard_Size FSD_BinaryFile::InverseSize (const Standard_Size theValue)
1889 {
1890   return (Standard_Size) OCCT_InverseSizeSpecialized <sizeof(Standard_Size)> (theValue, 0);
1891 }
1892
1893 uint64_t FSD_BinaryFile::InverseUint64 (const uint64_t theValue)
1894 {
1895   return OCCT_InverseSizeSpecialized <sizeof(uint64_t)> (theValue, 0);
1896 }