0031918: Application Framework - New binary format for fast reading part of OCAF...
[occt.git] / src / BinLDrivers / BinLDrivers_DocumentRetrievalDriver.cxx
1 // Created on: 2002-10-31
2 // Created by: Michael SAZONOV
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16
17 #include <BinLDrivers.hxx>
18 #include <BinLDrivers_DocumentRetrievalDriver.hxx>
19 #include <BinLDrivers_DocumentSection.hxx>
20 #include <BinLDrivers_Marker.hxx>
21 #include <BinMDataStd.hxx>
22 #include <BinMDF_ADriver.hxx>
23 #include <BinMDF_ADriverTable.hxx>
24 #include <BinObjMgt_Persistent.hxx>
25 #include <CDM_Application.hxx>
26 #include <CDM_Document.hxx>
27 #include <Message_Messenger.hxx>
28 #include <FSD_BinaryFile.hxx>
29 #include <FSD_FileHeader.hxx>
30 #include <OSD_OpenFile.hxx>
31 #include <PCDM_Document.hxx>
32 #include <PCDM_ReadWriter.hxx>
33 #include <Standard_ErrorHandler.hxx>
34 #include <Standard_Stream.hxx>
35 #include <Standard_Type.hxx>
36 #include <Storage_HeaderData.hxx>
37 #include <Storage_Schema.hxx>
38 #include <TCollection_AsciiString.hxx>
39 #include <TCollection_ExtendedString.hxx>
40 #include <TDF_Attribute.hxx>
41 #include <TDF_Data.hxx>
42 #include <TDF_Label.hxx>
43 #include <TDF_Tool.hxx>
44 #include <TDocStd_Document.hxx>
45 #include <TDocStd_FormatVersion.hxx>
46 #include <TDocStd_Owner.hxx>
47 #include <Message_ProgressScope.hxx>
48 #include <PCDM_ReaderFilter.hxx>
49
50
51 IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentRetrievalDriver,PCDM_RetrievalDriver)
52
53 #define SHAPESECTION_POS "SHAPE_SECTION_POS:"
54 #define ENDSECTION_POS ":"
55 #define SIZEOFSHAPELABEL  18
56
57 #define DATATYPE_MIGRATION
58 //#define DATATYPE_MIGRATION_DEB
59 //=======================================================================
60 //function : BinLDrivers_DocumentRetrievalDriver
61 //purpose  : Constructor
62 //=======================================================================
63
64 BinLDrivers_DocumentRetrievalDriver::BinLDrivers_DocumentRetrievalDriver ()
65 {
66   myReaderStatus = PCDM_RS_OK;
67 }
68
69 //=======================================================================
70 //function : Read
71 //purpose  :
72 //=======================================================================
73 void BinLDrivers_DocumentRetrievalDriver::Read
74                          (const TCollection_ExtendedString& theFileName,
75                           const Handle(CDM_Document)&       theNewDocument,
76                           const Handle(CDM_Application)&    theApplication,
77                           const Handle(PCDM_ReaderFilter)&  theFilter,
78                           const Message_ProgressRange&      theRange)
79 {
80   std::ifstream aFileStream;
81   OSD_OpenStream (aFileStream, theFileName, std::ios::in | std::ios::binary);
82
83   if (aFileStream.is_open() && aFileStream.good())
84   {
85     Handle(Storage_Data) dData;
86     TCollection_ExtendedString aFormat = PCDM_ReadWriter::FileFormat (aFileStream, dData);
87
88     Read (aFileStream, dData, theNewDocument, theApplication, theFilter, theRange);
89     if (!theRange.More())
90     {
91       myReaderStatus = PCDM_RS_UserBreak;
92       return;
93     }
94   }
95   else
96   {
97     myReaderStatus = PCDM_RS_OpenError;
98   }
99 }
100
101 #define MODIFICATION_COUNTER "MODIFICATION_COUNTER: "
102 #define REFERENCE_COUNTER "REFERENCE_COUNTER: "
103
104 #define START_TYPES "START_TYPES"
105 #define END_TYPES "END_TYPES"
106
107 //=======================================================================
108 //function : Read
109 //purpose  :
110 //=======================================================================
111 void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&                theIStream,
112                                                 const Handle(Storage_Data)&      theStorageData,
113                                                 const Handle(CDM_Document)&      theDoc,
114                                                 const Handle(CDM_Application)&   theApplication,
115                                                 const Handle(PCDM_ReaderFilter)& theFilter,
116                                                 const Message_ProgressRange&     theRange)
117 {
118   myReaderStatus = PCDM_RS_DriverFailure;
119   myMsgDriver = theApplication -> MessageDriver();
120
121   const TCollection_ExtendedString aMethStr
122     ("BinLDrivers_DocumentRetrievalDriver: ");
123
124   Handle(TDocStd_Document) aDoc =
125     Handle(TDocStd_Document)::DownCast(theDoc);
126   if (aDoc.IsNull()) {
127 #ifdef OCCT_DEBUG
128     myMsgDriver->Send (aMethStr + "error: null document", Message_Fail);
129 #endif
130     myReaderStatus = PCDM_RS_NoDocument;
131     return;
132   }
133
134   // 1. the information section
135   Handle(Storage_HeaderData) aHeaderData;
136   
137   if (!theStorageData.IsNull())
138   {
139     aHeaderData = theStorageData->HeaderData();
140   }
141
142   if (!aHeaderData.IsNull())
143   {
144     for (Standard_Integer i = 1; i <= aHeaderData->UserInfo().Length(); i++)
145     {
146       const TCollection_AsciiString& aLine = aHeaderData->UserInfo().Value(i);
147
148       if(aLine.Search(REFERENCE_COUNTER) != -1)
149       {
150         theDoc->SetReferenceCounter (aLine.Token(" ", 2).IntegerValue());
151       }
152       else if(aLine.Search(MODIFICATION_COUNTER) != -1)
153       {
154         theDoc->SetModifications (aLine.Token(" ", 2).IntegerValue());
155       }
156     }
157   }
158
159   // 1.a Version of writer
160   if (!aHeaderData->StorageVersion().IsIntegerValue()) {
161     // file has no format version
162     myMsgDriver->Send (aMethStr + "error: file has no format version", Message_Fail);
163     myReaderStatus = PCDM_RS_FormatFailure;
164     return;
165   }
166   TDocStd_FormatVersion aFileVer = static_cast<TDocStd_FormatVersion>(aHeaderData->StorageVersion().IntegerValue());
167   TDocStd_FormatVersion aCurrVer = TDocStd_Document::CurrentStorageFormatVersion();
168   // maintain one-way compatibility starting from version 2+
169   if (!CheckDocumentVersion(aFileVer, aCurrVer)) {
170     myReaderStatus = PCDM_RS_NoVersion;
171     // file was written with another version
172     myMsgDriver->Send (aMethStr + "error: wrong file version: " +
173                  aHeaderData->StorageVersion() + " while current is " +
174                  TDocStd_Document::CurrentStorageFormatVersion(), Message_Fail);
175     return;
176   }
177
178   // 1.b Retrieve the Types table
179   TColStd_SequenceOfAsciiString aTypeNames; //Sequence of types in file
180   const TColStd_SequenceOfAsciiString& aUserInfo = aHeaderData->UserInfo();
181   Standard_Boolean begin = Standard_False;
182   Standard_Integer i;
183   for (i=1; i <= aUserInfo.Length(); i++) {
184     TCollection_AsciiString aStr = aUserInfo(i);
185     if (aStr == START_TYPES)
186       begin = Standard_True;
187     else if (aStr == END_TYPES)
188       break;
189     else if (begin) {
190       if ( aFileVer < TDocStd_FormatVersion_VERSION_8) {
191 #ifdef DATATYPE_MIGRATION
192         TCollection_AsciiString  newName;       
193         if(Storage_Schema::CheckTypeMigration(aStr, newName)) {
194 #ifdef OCCT_DEBUG
195           std::cout << "CheckTypeMigration:OldType = " <<aStr << " Len = "<<aStr.Length()<<std::endl;
196           std::cout << "CheckTypeMigration:NewType = " <<newName  << " Len = "<< newName.Length()<<std::endl;
197 #endif
198           aStr = newName;
199         }
200 #endif  
201       } 
202       aTypeNames.Append (aStr);    
203     }
204   }
205   if (myDrivers.IsNull())
206     myDrivers = AttributeDrivers (myMsgDriver);
207   myDrivers->AssignIds (aTypeNames); 
208
209   // recognize types not supported by drivers
210   myMapUnsupported.Clear();
211   for (i=1; i <= aTypeNames.Length(); i++)
212     if (myDrivers->GetDriver(i).IsNull()) 
213       myMapUnsupported.Add(i);
214   if (!myMapUnsupported.IsEmpty()) {
215     myMsgDriver->Send (aMethStr + "warning: "
216                   "the following attributes have no driver:", Message_Warning);
217     for (i=1; i <= aTypeNames.Length(); i++)
218       if (myMapUnsupported.Contains(i))
219         myMsgDriver->Send (aTypeNames(i), Message_Warning);
220   }
221
222   // 2. Read document contents
223   // 2a. Retrieve data from the stream:
224   myRelocTable.Clear();
225   myRelocTable.SetHeaderData(aHeaderData);
226   mySections.Clear();
227   myPAtt.Init();
228   Handle(TDF_Data) aData = (!theFilter.IsNull() && theFilter->IsAppendMode()) ? aDoc->GetData() : new TDF_Data();
229   std::streampos aDocumentPos = -1;
230
231   Message_ProgressScope aPS (theRange, "Reading data", 3);
232   Standard_Boolean aQuickPart = IsQuickPart (aFileVer);
233
234   // 2b. Read the TOC of Sections
235   if (aFileVer >= TDocStd_FormatVersion_VERSION_3) {
236     BinLDrivers_DocumentSection aSection;
237     do {
238       BinLDrivers_DocumentSection::ReadTOC (aSection, theIStream, aFileVer);
239       mySections.Append(aSection);
240     } while (!aSection.Name().IsEqual (aQuickPart ? ENDSECTION_POS : SHAPESECTION_POS) && !theIStream.eof());
241
242     if (theIStream.eof()) {
243       // There is no shape section in the file.
244       myMsgDriver->Send (aMethStr + "error: shape section is not found", Message_Fail);
245       myReaderStatus = PCDM_RS_ReaderException;
246       return;
247     }
248
249     aDocumentPos = theIStream.tellg(); // position of root label
250
251     BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
252     for (; anIterS.More(); anIterS.Next()) {
253       BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue();
254       if (aCurSection.IsPostRead() == Standard_False) {
255         theIStream.seekg ((std::streampos) aCurSection.Offset());
256         if (aCurSection.Name().IsEqual (SHAPESECTION_POS))
257         {
258           ReadShapeSection (aCurSection, theIStream, false, aPS.Next());
259           if (!aPS.More())
260           {
261             myReaderStatus = PCDM_RS_UserBreak;
262             return;
263           }
264         }
265         else if (!aCurSection.Name().IsEqual (ENDSECTION_POS))
266           ReadSection (aCurSection, theDoc, theIStream);
267       }
268     }
269   } else { //aFileVer < 3
270     aDocumentPos = theIStream.tellg(); // position of root label
271
272     // retrieve SHAPESECTION_POS string
273     char aShapeSecLabel[SIZEOFSHAPELABEL + 1];
274     aShapeSecLabel[SIZEOFSHAPELABEL] = 0x00;
275     theIStream.read ((char*)&aShapeSecLabel, SIZEOFSHAPELABEL);// SHAPESECTION_POS
276     TCollection_AsciiString aShapeLabel(aShapeSecLabel);
277     // detect if a file was written in old fashion (version 2 without shapes)
278     // and if so then skip reading ShapeSection
279     if (aShapeLabel.Length() > 0) {
280       // version 2+(with shapes) and higher goes here
281       if(aShapeLabel.Length() <= 0 || aShapeLabel != SHAPESECTION_POS) {
282         myMsgDriver->Send (aMethStr + "error: Format failure", Message_Fail);
283         myReaderStatus = PCDM_RS_FormatFailure;
284         return;
285       }
286
287       // retrieve ShapeSection Position
288       Standard_Integer aShapeSectionPos; // go to ShapeSection
289       theIStream.read ((char*)&aShapeSectionPos, sizeof(Standard_Integer));
290
291 #ifdef DO_INVERSE
292       aShapeSectionPos = InverseInt (aShapeSectionPos);
293 #endif
294 #ifdef OCCT_DEBUG
295       std::cout <<"aShapeSectionPos = " <<aShapeSectionPos <<std::endl;
296 #endif
297       if(aShapeSectionPos) { 
298         aDocumentPos = theIStream.tellg();
299         theIStream.seekg((std::streampos) aShapeSectionPos);
300
301         CheckShapeSection(aShapeSectionPos, theIStream);
302         // Read Shapes
303         BinLDrivers_DocumentSection aCurSection;
304         ReadShapeSection (aCurSection, theIStream, Standard_False, aPS.Next());
305         if (!aPS.More())
306         {
307           myReaderStatus = PCDM_RS_UserBreak;
308           return;
309         }
310       }
311     }
312   } // end of reading Sections or shape section
313
314   // Return to read of the Document structure
315   theIStream.seekg(aDocumentPos);
316
317   // read the header (tag) of the root label
318   Standard_Integer aTag;
319   theIStream.read ((char*)&aTag, sizeof(Standard_Integer));
320
321   if (aQuickPart)
322     myPAtt.SetIStream (theIStream); // for reading shapes data from the stream directly
323   EnableQuickPartReading (myMsgDriver, aQuickPart);
324
325   // read sub-tree of the root label
326   if (!theFilter.IsNull())
327     theFilter->StartIteration();
328   Standard_Integer nbRead = ReadSubTree (theIStream, aData->Root(), theFilter, aQuickPart, aPS.Next());
329   if (!aPS.More()) 
330   {
331     myReaderStatus = PCDM_RS_UserBreak;
332     return;
333   }
334   
335   Clear();
336   if (!aPS.More())
337   {
338     myReaderStatus = PCDM_RS_UserBreak;
339     return;
340   }
341   aPS.Next();
342     
343   if (nbRead > 0) {
344     // attach data to the document
345     if (theFilter.IsNull() || !theFilter->IsAppendMode())
346     {
347       aDoc->SetData(aData);
348       TDocStd_Owner::SetDocument(aData, aDoc);
349       aDoc->SetComments(aHeaderData->Comments());
350     }
351     myReaderStatus = PCDM_RS_OK;
352   }
353
354   // Read Sections (post-reading type)
355   if (aFileVer >= TDocStd_FormatVersion_VERSION_3) {
356     BinLDrivers_VectorOfDocumentSection::Iterator aSectIter (mySections);
357     for (; aSectIter.More(); aSectIter.Next()) {
358       BinLDrivers_DocumentSection& aCurSection = aSectIter.ChangeValue();
359       if (aCurSection.IsPostRead()) {
360         theIStream.seekg ((std::streampos) aCurSection.Offset());
361         ReadSection (aCurSection, theDoc, theIStream); 
362       }
363     }
364   }
365 }
366
367 //=======================================================================
368 //function : ReadSubTree
369 //purpose  :
370 //=======================================================================
371
372 Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
373 (Standard_IStream& theIS,
374   const TDF_Label& theLabel,
375   const Handle(PCDM_ReaderFilter)& theFilter,
376   const Standard_Boolean& theQuickPart,
377   const Message_ProgressRange& theRange)
378 {
379   Standard_Integer nbRead = 0;
380   TCollection_ExtendedString aMethStr
381   ("BinLDrivers_DocumentRetrievalDriver: ");
382
383   Message_ProgressScope aPS(theRange, "Reading sub tree", 2, true);
384
385   bool aSkipAttrs = Standard_False;
386   if (!theFilter.IsNull() && theFilter->IsPartTree())
387     aSkipAttrs = !theFilter->IsPassed();
388
389   if (theQuickPart)
390   {
391     uint64_t aLabelSize = 0;
392     theIS.read((char*)&aLabelSize, sizeof(uint64_t));
393 #if DO_INVERSE
394     aLabelSize = InverseUint64(aLabelSize);
395 #endif
396     // no one sub-label is needed, so, skip everything
397     if (aSkipAttrs && !theFilter->IsSubPassed())
398     {
399       aLabelSize -= sizeof (uint64_t);
400       theIS.seekg (aLabelSize, std::ios_base::cur);
401       if (!theFilter.IsNull())
402         theFilter->Up();
403       return 0;
404     }
405   }
406
407   // Read attributes:
408   for (theIS >> myPAtt;
409     theIS && myPAtt.TypeId() > 0 &&             // not an end marker ?
410     myPAtt.Id() > 0 &&                          // not a garbage ?
411     !theIS.eof();
412     theIS >> myPAtt)
413   {
414     if (!aPS.More())
415     {
416       myReaderStatus = PCDM_RS_UserBreak;
417       return -1;
418     }
419     if (aSkipAttrs)
420     {
421       if (myPAtt.IsDirect()) // skip direct written stream
422       {
423         uint64_t aStreamSize = 0;
424         theIS.read ((char*)&aStreamSize, sizeof (uint64_t));
425         aStreamSize -= sizeof (uint64_t); // size is already passed, so, reduce it by size
426         theIS.seekg (aStreamSize, std::ios_base::cur);
427       }
428       continue;
429     }
430
431     // get a driver according to TypeId
432     Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver(myPAtt.TypeId());
433     if (!aDriver.IsNull()) {
434       // create transient attribute
435       Standard_Integer anID = myPAtt.Id();
436       Handle(TDF_Attribute) tAtt;
437       Standard_Boolean isBound = myRelocTable.IsBound(anID);
438       if (isBound)
439         tAtt = Handle(TDF_Attribute)::DownCast(myRelocTable.Find(anID));
440       else
441         tAtt = aDriver->NewEmpty();
442
443       if (!theFilter.IsNull() && !theFilter->IsPassed (tAtt->DynamicType())) {
444         if (myPAtt.IsDirect()) // skip direct written stream
445         {
446           uint64_t aStreamSize = 0;
447           theIS.read ((char*)&aStreamSize, sizeof (uint64_t));
448           aStreamSize -= sizeof (uint64_t); // size is already passed, so, reduce it by size
449           theIS.seekg (aStreamSize, std::ios_base::cur);
450         }
451         continue;
452       }
453       nbRead++;
454
455       if (tAtt->Label().IsNull())
456       {
457         if (!theFilter.IsNull() && theFilter->Mode() != PCDM_ReaderFilter::AppendMode_Forbid && theLabel.IsAttribute(tAtt->ID()))
458         {
459           if (theFilter->Mode() == PCDM_ReaderFilter::AppendMode_Protect)
460             continue; // do not overwrite the existing attribute
461           if (theFilter->Mode() == PCDM_ReaderFilter::AppendMode_Overwrite)
462             theLabel.ForgetAttribute(tAtt->ID()); // forget old attribute to write a new one
463         }
464         try
465         {
466           theLabel.AddAttribute(tAtt);
467         }
468         catch (const Standard_DomainError&)
469         {
470           // For attributes that can have arbitrary GUID (e.g. TDataStd_Integer), exception
471           // will be raised in valid case if attribute of that type with default GUID is already
472           // present  on the same label; the reason is that actual GUID will be read later.
473           // To avoid this, set invalid (null) GUID to the newly added attribute (see #29669)
474           static const Standard_GUID fbidGuid;
475           tAtt->SetID(fbidGuid);
476           theLabel.AddAttribute(tAtt);
477         }
478       }
479       else
480         myMsgDriver->Send(aMethStr +
481           "warning: attempt to attach attribute " +
482           aDriver->TypeName() + " to a second label", Message_Warning);
483
484       Standard_Boolean ok = aDriver->Paste(myPAtt, tAtt, myRelocTable);
485       if (!ok) {
486         // error converting persistent to transient
487         myMsgDriver->Send(aMethStr + "warning: failure reading attribute " +
488           aDriver->TypeName(), Message_Warning);
489       }
490       else if (!isBound)
491         myRelocTable.Bind(anID, tAtt);
492     }
493     else if (!myMapUnsupported.Contains(myPAtt.TypeId()))
494       myMsgDriver->Send(aMethStr + "warning: type ID not registered in header: "
495         + myPAtt.TypeId(), Message_Warning);
496
497   }
498   if (!theIS || myPAtt.TypeId() != BinLDrivers_ENDATTRLIST) {
499     // unexpected EOF or garbage data
500     myMsgDriver->Send(aMethStr + "error: unexpected EOF or garbage data", Message_Fail);
501     myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
502     return -1;
503   }
504
505   // Read children:
506   // read the tag of a child label
507   Standard_Integer aTag = BinLDrivers_ENDLABEL;
508   theIS.read((char*)&aTag, sizeof(Standard_Integer));
509 #ifdef DO_INVERSE
510   aTag = InverseInt(aTag);
511 #endif
512
513   while (theIS && aTag >= 0 && !theIS.eof()) { // not an end marker ?
514     // create sub-label
515     TDF_Label aLab = theLabel.FindChild(aTag, Standard_True);
516     if (!aPS.More())
517     {
518       myReaderStatus = PCDM_RS_UserBreak;
519       return -1;
520     }
521
522
523     // read sub-tree
524     if (!theFilter.IsNull())
525       theFilter->Down (aTag);
526     Standard_Integer nbSubRead = ReadSubTree (theIS, aLab, theFilter, theQuickPart, aPS.Next());
527     // check for error
528     if (nbSubRead == -1)
529       return -1;
530     nbRead += nbSubRead;
531
532     // read the tag of the next child
533     theIS.read((char*)&aTag, sizeof(Standard_Integer));
534 #ifdef DO_INVERSE
535     aTag = InverseInt(aTag);
536 #endif
537   }
538
539   if (aTag != BinLDrivers_ENDLABEL) {
540     // invalid end label marker
541     myMsgDriver->Send(aMethStr + "error: invalid end label marker", Message_Fail);
542     myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
543     return -1;
544   }
545   if (!theFilter.IsNull())
546     theFilter->Up();
547
548   return nbRead;
549 }
550
551 //=======================================================================
552 //function : AttributeDrivers
553 //purpose  :
554 //=======================================================================
555
556 Handle(BinMDF_ADriverTable) BinLDrivers_DocumentRetrievalDriver::AttributeDrivers
557        (const Handle(Message_Messenger)& theMessageDriver)
558 {
559   return BinLDrivers::AttributeDrivers (theMessageDriver);
560 }
561
562 //=======================================================================
563 //function : ReadSection
564 //purpose  : 
565 //=======================================================================
566
567 void BinLDrivers_DocumentRetrievalDriver::ReadSection
568                                 (BinLDrivers_DocumentSection& /*theSection*/,
569                                  const Handle(CDM_Document)&  /*theDocument*/,
570                                  Standard_IStream&            /*theIS*/)
571 {
572   // empty; should be redefined in subclasses
573 }
574
575 //=======================================================================
576 //function : ReadShapeSection
577 //purpose  : 
578 //=======================================================================
579
580 void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection
581                               (BinLDrivers_DocumentSection& theSection,
582                                Standard_IStream&            /*theIS*/,
583                                const Standard_Boolean isMess,
584                                const Message_ProgressRange &/*theRange*/)
585
586 {
587   if(isMess && theSection.Length()) {
588     const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: ");
589     myMsgDriver->Send (aMethStr + "warning: Geometry is not supported by Lite schema. ", Message_Warning);
590   }
591 }
592
593 //=======================================================================
594 //function : CheckShapeSection
595 //purpose  : 
596 //=======================================================================
597 void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection
598   (const Storage_Position& ShapeSectionPos, Standard_IStream& IS)
599 {
600   if (!IS.eof())
601   {
602     const std::streamoff endPos = IS.rdbuf()->pubseekoff (0L, std::ios_base::end, std::ios_base::in);
603 #ifdef OCCT_DEBUG
604     std::cout << "endPos = " << endPos <<std::endl;
605 #endif
606     if(ShapeSectionPos != endPos) {
607       const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: ");
608       myMsgDriver->Send (aMethStr + "warning: Geometry is not supported by Lite schema. ", Message_Warning);
609     }
610   }
611 }
612
613 //=======================================================================
614 //function : Clear
615 //purpose  : 
616 //=======================================================================
617 void BinLDrivers_DocumentRetrievalDriver::Clear()
618 {
619   myPAtt.Destroy();    // free buffer
620   myRelocTable.Clear();
621   myMapUnsupported.Clear();
622 }
623
624 //=======================================================================
625 //function : CheckDocumentVersion
626 //purpose  : 
627 //=======================================================================
628 Standard_Boolean BinLDrivers_DocumentRetrievalDriver::CheckDocumentVersion
629   (const Standard_Integer theFileVersion, const Standard_Integer theCurVersion)
630 {
631   if (theFileVersion < TDocStd_FormatVersion_LOWER || theFileVersion > theCurVersion) {
632     // file was written with another version
633     return Standard_False;
634   }
635   return Standard_True;
636 }
637
638 //=======================================================================
639 //function : IsQuickPart
640 //purpose  : 
641 //=======================================================================
642 Standard_Boolean BinLDrivers_DocumentRetrievalDriver::IsQuickPart (const Standard_Integer theFileVer)
643 {
644   return theFileVer >= TDocStd_FormatVersion_VERSION_12;
645 }