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