]> OCCT Git - occt-copy.git/commitdiff
0031918: Application Framework - New binary format for fast reading part of OCAF...
authormpv <mpv@opencascade.com>
Sat, 9 Jan 2021 15:01:53 +0000 (18:01 +0300)
committeragv <agv@opencascade.com>
Sun, 24 Jan 2021 15:23:24 +0000 (18:23 +0300)
Initial implementation of new format for quick reading and writing parts of the documents. It consists in writing shapes and all their contents right in the TNaming_NamedShape attribute placement and skipping the shape section.

For the current moment it is implemented as a new version 12 of the binary format. It will be decided later to have it like this and make this version of the format as default, or setting a special flag for such version reading/writing.

Modifications:
BinLDrivers and BinDrivers packages - modifications related to the quick part tree format flag usage, skipping shape section writing and adding labels sizes into the document to be able to pass labels during the reading quickly.
BinObjMgt_Persistent amd BinObjMgt_Position - to add possibility to write directly into the stream some data just after the attribute. Before this record a data-size is recorded.
BinMXCAFDoc package modifications to write BinMXCAFDoc_LocationDriver location in the same way as shapes write location data right after the attribute (empty) data in this new format.
BinTools package: creation of ShapeReader and ShapeWriter classes with same root class ShapeSetBase with ShapeSet class. These classes allows to write/read shapes directly to the stream. If some object is already in the stream, write a reference - relative position of the duplicated object.
PCDM_ReaderFilter - modified to be able to browse labels tree quickly, without usage of referencing by entry-strings.

# Conflicts:
# src/BinMNaming/BinMNaming_NamedShapeDriver.cxx
# src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.cxx
# src/BinTools/BinTools_ShapeSet.cxx
# src/BinTools/BinTools_ShapeSet.hxx
# src/BinTools/FILES

46 files changed:
src/BinDrivers/BinDrivers_DocumentRetrievalDriver.cxx
src/BinDrivers/BinDrivers_DocumentRetrievalDriver.hxx
src/BinDrivers/BinDrivers_DocumentStorageDriver.cxx
src/BinDrivers/BinDrivers_DocumentStorageDriver.hxx
src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.cxx
src/BinLDrivers/BinLDrivers_DocumentRetrievalDriver.hxx
src/BinLDrivers/BinLDrivers_DocumentSection.cxx
src/BinLDrivers/BinLDrivers_DocumentStorageDriver.cxx
src/BinLDrivers/BinLDrivers_DocumentStorageDriver.hxx
src/BinMNaming/BinMNaming_NamedShapeDriver.cxx
src/BinMNaming/BinMNaming_NamedShapeDriver.hxx
src/BinMNaming/BinMNaming_NamedShapeDriver.lxx
src/BinMXCAFDoc/BinMXCAFDoc.cxx
src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.cxx
src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.hxx
src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.lxx [deleted file]
src/BinMXCAFDoc/FILES
src/BinObjMgt/BinObjMgt_Persistent.cxx
src/BinObjMgt/BinObjMgt_Persistent.hxx
src/BinObjMgt/BinObjMgt_Persistent.lxx
src/BinObjMgt/BinObjMgt_Position.cxx [new file with mode: 0644]
src/BinObjMgt/BinObjMgt_Position.hxx [new file with mode: 0644]
src/BinObjMgt/FILES
src/BinTools/BinTools.cxx
src/BinTools/BinTools.hxx
src/BinTools/BinTools_IStream.cxx [new file with mode: 0644]
src/BinTools/BinTools_IStream.hxx [new file with mode: 0644]
src/BinTools/BinTools_LocationSet.cxx
src/BinTools/BinTools_LocationSet.hxx
src/BinTools/BinTools_ObjectType.hxx [new file with mode: 0644]
src/BinTools/BinTools_Position.cxx [new file with mode: 0644]
src/BinTools/BinTools_Position.hxx [new file with mode: 0644]
src/BinTools/BinTools_ShapeReader.cxx [new file with mode: 0644]
src/BinTools/BinTools_ShapeReader.hxx [new file with mode: 0644]
src/BinTools/BinTools_ShapeSet.cxx
src/BinTools/BinTools_ShapeSet.hxx
src/BinTools/BinTools_ShapeSetBase.cxx [new file with mode: 0644]
src/BinTools/BinTools_ShapeSetBase.hxx [new file with mode: 0644]
src/BinTools/BinTools_ShapeWriter.cxx [new file with mode: 0644]
src/BinTools/BinTools_ShapeWriter.hxx [new file with mode: 0644]
src/BinTools/FILES
src/PCDM/PCDM_ReaderFilter.cxx
src/PCDM/PCDM_ReaderFilter.hxx
src/TDocStd/TDocStd_FormatVersion.hxx
tests/bugs/caf/bug31918_1 [new file with mode: 0644]
tests/bugs/caf/bug31918_2 [new file with mode: 0644]

index e7dde6a91b667fe3ff8924d08386ff2a69a74578..2776f95d13146122aff7fb39e7d2bb5a0840ed6e 100644 (file)
@@ -26,6 +26,7 @@
 #include <Standard_Failure.hxx>
 #include <Standard_IStream.hxx>
 #include <Standard_Type.hxx>
+#include <Standard_NotImplemented.hxx>
 #include <TCollection_ExtendedString.hxx>
 #include <TNaming_NamedShape.hxx>
 
@@ -59,7 +60,6 @@ void BinDrivers_DocumentRetrievalDriver::ReadShapeSection
                               (BinLDrivers_DocumentSection& /*theSection*/,
                                Standard_IStream&            theIS,
                                const Standard_Boolean       /*isMess*/,
-                               const Standard_Boolean       thePostponeShapes,
                                const Message_ProgressRange& theRange)
 
 {
@@ -71,7 +71,7 @@ void BinDrivers_DocumentRetrievalDriver::ReadShapeSection
       OCC_CATCH_SIGNALS
       Handle(BinMNaming_NamedShapeDriver) aNamedShapeDriver =
         Handle(BinMNaming_NamedShapeDriver)::DownCast (aDriver);
-      aNamedShapeDriver->ReadShapeSection (theIS, thePostponeShapes, theRange);
+      aNamedShapeDriver->ReadShapeSection (theIS, theRange);
     }
     catch(Standard_Failure const& anException) {
       const TCollection_ExtendedString aMethStr
@@ -108,4 +108,23 @@ void BinDrivers_DocumentRetrievalDriver::Clear()
   BinLDrivers_DocumentRetrievalDriver::Clear();
 }
 
+//=======================================================================
+//function : EnableQuickPartReading
+//purpose  : 
+//=======================================================================
+void BinDrivers_DocumentRetrievalDriver::EnableQuickPartReading(
+  const Handle(Message_Messenger)& theMessageDriver, Standard_Boolean theValue)
+{
+  if (myDrivers.IsNull())
+    myDrivers = AttributeDrivers(theMessageDriver);
+  if (myDrivers.IsNull())
+    return;
 
+  Handle(BinMDF_ADriver) aDriver;
+  myDrivers->GetDriver(STANDARD_TYPE(TNaming_NamedShape), aDriver);
+  Handle(BinMNaming_NamedShapeDriver) aShapesDriver = Handle(BinMNaming_NamedShapeDriver)::DownCast(aDriver);
+  if (aShapesDriver.IsNull())
+    throw Standard_NotImplemented("Internal Error - TNaming_NamedShape is not found!");
+
+  aShapesDriver->EnableQuickPart(theValue);
+}
index 836edd6f3debd265c9d54b6c3fb8d69cc75470a9..b7c51d8f7b5bc8359d13e0976a189e875904f9a2 100644 (file)
@@ -49,7 +49,6 @@ public:
     (BinLDrivers_DocumentSection& theSection, 
      Standard_IStream& theIS,
      const Standard_Boolean isMess = Standard_False, 
-     const Standard_Boolean thePostponeShapes = Standard_False,
      const Message_ProgressRange& theRange = Message_ProgressRange()) Standard_OVERRIDE;
   
   Standard_EXPORT virtual void CheckShapeSection
@@ -58,6 +57,9 @@ public:
   //! Clears the NamedShape driver
   Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
 
+  //! Enables reading in the quick part access mode.
+  Standard_EXPORT virtual void EnableQuickPartReading(const Handle(Message_Messenger)& theMessageDriver, Standard_Boolean theValue);
+
 
   DEFINE_STANDARD_RTTIEXT(BinDrivers_DocumentRetrievalDriver,BinLDrivers_DocumentRetrievalDriver)
 
index fda11dfff19c42e8f16849204961ff675c83fb0a..b04b5bb12ec232dd6561f6fd819d2396eaeb6f22 100644 (file)
@@ -93,6 +93,46 @@ void BinDrivers_DocumentStorageDriver::SetWithTriangles (const Handle(Message_Me
   aShapesDriver->SetWithTriangles (theWithTriangulation);
 }
 
+void BinDrivers_DocumentStorageDriver::EnableQuickPartWriting(const Handle(Message_Messenger)& theMessageDriver,
+                                                              const Standard_Boolean theValue)
+{
+  if (myDrivers.IsNull())
+  {
+    myDrivers = AttributeDrivers(theMessageDriver);
+  }
+  if (myDrivers.IsNull())
+  {
+    return;
+  }
+
+  Handle(BinMDF_ADriver) aDriver;
+  myDrivers->GetDriver(STANDARD_TYPE(TNaming_NamedShape), aDriver);
+  Handle(BinMNaming_NamedShapeDriver) aShapesDriver = Handle(BinMNaming_NamedShapeDriver)::DownCast(aDriver);
+  if (aShapesDriver.IsNull())
+  {
+    throw Standard_NotImplemented("Internal Error - TNaming_NamedShape is not found!");
+  }
+
+  aShapesDriver->EnableQuickPart(theValue);
+}
+
+//=======================================================================
+//function : Clear
+//purpose  : 
+//=======================================================================
+void BinDrivers_DocumentStorageDriver::Clear()
+{
+  // Clear NamedShape driver
+  Handle(BinMDF_ADriver) aDriver;
+  if (myDrivers->GetDriver(STANDARD_TYPE(TNaming_NamedShape), aDriver))
+  {
+    Handle(BinMNaming_NamedShapeDriver) aNamedShapeDriver =
+      Handle(BinMNaming_NamedShapeDriver)::DownCast(aDriver);
+    aNamedShapeDriver->Clear();
+  }
+  BinLDrivers_DocumentStorageDriver::Clear();
+}
+
 //=======================================================================
 //function : WriteShapeSection
 //purpose  : Implements WriteShapeSection
index 44233713083556728d660ccea61a76a5f38b9f0e..486714fc85e17e8aced8163a2cbc432b0a827a43 100644 (file)
@@ -56,6 +56,13 @@ public:
   Standard_EXPORT void SetWithTriangles (const Handle(Message_Messenger)& theMessageDriver,
                                          const Standard_Boolean theWithTriangulation);
 
+  //! Enables writing in the quick part access mode.
+  Standard_EXPORT void EnableQuickPartWriting(const Handle(Message_Messenger)& theMessageDriver,
+                                              const Standard_Boolean theValue) Standard_OVERRIDE;
+
+  //! Clears the NamedShape driver
+  Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
+
   DEFINE_STANDARD_RTTIEXT(BinDrivers_DocumentStorageDriver,BinLDrivers_DocumentStorageDriver)
 
 };
index 39c69552832eaa1396a94f9eea1f96c4085a40a9..34b1af63dc1b5823058cbd7b9dc44773d7331131 100644 (file)
@@ -50,6 +50,7 @@
 IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentRetrievalDriver,PCDM_RetrievalDriver)
 
 #define SHAPESECTION_POS "SHAPE_SECTION_POS:"
+#define ENDSECTION_POS ":"
 #define SIZEOFSHAPELABEL  18
 
 #define DATATYPE_MIGRATION
@@ -179,7 +180,6 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&
   Standard_Boolean begin = Standard_False;
   Standard_Integer i;
   for (i=1; i <= aUserInfo.Length(); i++) {
-    //const TCollection_AsciiString& aStr = aUserInfo(i);
     TCollection_AsciiString aStr = aUserInfo(i);
     if (aStr == START_TYPES)
       begin = Standard_True;
@@ -227,8 +227,8 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&
   Handle(TDF_Data) aData = (!theFilter.IsNull() && theFilter->IsAppendMode()) ? aDoc->GetData() : new TDF_Data();
   std::streampos aDocumentPos = -1;
 
-  Message_ProgressScope aPS(theRange, "Reading data", 3);
-  Standard_Boolean aPostponeShapes = !theFilter.IsNull() && (theFilter->IsPartTree() || !theFilter->IsPassedAttr("TNaming_NamedShape"));
+  Message_ProgressScope aPS (theRange, "Reading data", 3);
+  Standard_Boolean aQuickPart = IsQuickPart (aFileVer);
 
   // 2b. Read the TOC of Sections
   if (aFileVer >= 3) {
@@ -236,7 +236,8 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&
     do {
       BinLDrivers_DocumentSection::ReadTOC (aSection, theIStream, aFileVer);
       mySections.Append(aSection);
-    } while(!aSection.Name().IsEqual((Standard_CString)SHAPESECTION_POS) && !theIStream.eof());
+    } while (!aSection.Name().IsEqual ((Standard_CString)
+             (aQuickPart ? ENDSECTION_POS : SHAPESECTION_POS)) && !theIStream.eof());
 
     if (theIStream.eof()) {
       // There is no shape section in the file.
@@ -254,14 +255,14 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&
         theIStream.seekg ((std::streampos) aCurSection.Offset());
         if (aCurSection.Name().IsEqual ((Standard_CString)SHAPESECTION_POS))
         {
-          ReadShapeSection (aCurSection, theIStream, false, aPostponeShapes, aPS.Next());
+          ReadShapeSection (aCurSection, theIStream, false, aPS.Next());
           if (!aPS.More())
           {
             myReaderStatus = PCDM_RS_UserBreak;
             return;
           }
         }
-        else
+        else if (!aCurSection.Name().IsEqual ((Standard_CString)ENDSECTION_POS))
           ReadSection (aCurSection, theDoc, theIStream);
       }
     }
@@ -300,7 +301,7 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&
         CheckShapeSection(aShapeSectionPos, theIStream);
         // Read Shapes
         BinLDrivers_DocumentSection aCurSection;
-        ReadShapeSection (aCurSection, theIStream, Standard_False, aPostponeShapes, aPS.Next());
+        ReadShapeSection (aCurSection, theIStream, Standard_False, aPS.Next());
         if (!aPS.More())
         {
           myReaderStatus = PCDM_RS_UserBreak;
@@ -317,8 +318,14 @@ void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&
   Standard_Integer aTag;
   theIStream.read ((char*)&aTag, sizeof(Standard_Integer));
 
+  if (aQuickPart)
+    myPAtt.SetIStream (theIStream); // for reading shapes data from the stream directly
+  EnableQuickPartReading (myMsgDriver, aQuickPart);
+
   // read sub-tree of the root label
-  Standard_Integer nbRead = ReadSubTree (theIStream, aData->Root(), theFilter, aPS.Next());
+  if (!theFilter.IsNull())
+    theFilter->StartIteration();
+  Standard_Integer nbRead = ReadSubTree (theIStream, aData->Root(), theFilter, aQuickPart, aPS.Next());
   if (!aPS.More()) 
   {
     myReaderStatus = PCDM_RS_UserBreak;
@@ -366,6 +373,7 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
 (Standard_IStream& theIS,
   const TDF_Label& theLabel,
   const Handle(PCDM_ReaderFilter)& theFilter,
+  const Standard_Boolean& theQuickPart,
   const Message_ProgressRange& theRange)
 {
   Standard_Integer nbRead = 0;
@@ -374,12 +382,26 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
 
   Message_ProgressScope aPS(theRange, "Reading sub tree", 2, true);
 
-  TCollection_AsciiString anEntry;
   bool aSkipAttrs = Standard_False;
   if (!theFilter.IsNull() && theFilter->IsPartTree())
+    aSkipAttrs = !theFilter->IsPassed();
+
+  if (theQuickPart)
   {
-    TDF_Tool::Entry(theLabel, anEntry);
-    aSkipAttrs = !theFilter->IsPassed(anEntry);
+    uint64_t aLabelSize = 0;
+    theIS.read((char*)&aLabelSize, sizeof(uint64_t));
+#if DO_INVERSE
+    aLabelSize = InverseUint64(aLabelSize);
+#endif
+    // no one sub-label is needed, so, skip everything
+    if (aSkipAttrs && !theFilter->IsSubPassed())
+    {
+      aLabelSize -= sizeof (uint64_t);
+      theIS.seekg (aLabelSize, std::ios_base::cur);
+      if (!theFilter.IsNull())
+        theFilter->Up();
+      return 0;
+    }
   }
 
   // Read attributes:
@@ -395,16 +417,21 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
       return -1;
     }
     if (aSkipAttrs)
+    {
+      if (myPAtt.IsDirect()) // skip direct written stream
+      {
+        uint64_t aStreamSize = 0;
+        theIS.read ((char*)&aStreamSize, sizeof (uint64_t));
+        aStreamSize -= sizeof (uint64_t); // size is already passed, so, reduce it by size
+        theIS.seekg (aStreamSize, std::ios_base::cur);
+      }
       continue;
+    }
 
     // get a driver according to TypeId
     Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver(myPAtt.TypeId());
     if (!aDriver.IsNull()) {
-      if (!theFilter.IsNull() && !theFilter->IsPassed(aDriver->SourceType())) {
-        continue;
-      }
       // create transient attribute
-      nbRead++;
       Standard_Integer anID = myPAtt.Id();
       Handle(TDF_Attribute) tAtt;
       Standard_Boolean isBound = myRelocTable.IsBound(anID);
@@ -413,6 +440,18 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
       else
         tAtt = aDriver->NewEmpty();
 
+      if (!theFilter.IsNull() && !theFilter->IsPassed (tAtt->DynamicType())) {
+        if (myPAtt.IsDirect()) // skip direct written stream
+        {
+          uint64_t aStreamSize = 0;
+          theIS.read ((char*)&aStreamSize, sizeof (uint64_t));
+          aStreamSize -= sizeof (uint64_t); // size is already passed, so, reduce it by size
+          theIS.seekg (aStreamSize, std::ios_base::cur);
+        }
+        continue;
+      }
+      nbRead++;
+
       if (tAtt->Label().IsNull())
       {
         if (!theFilter.IsNull() && theFilter->Mode() != PCDM_ReaderFilter::AppendMode_Forbid && theLabel.IsAttribute(tAtt->ID()))
@@ -482,7 +521,9 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
 
 
     // read sub-tree
-    Standard_Integer nbSubRead = ReadSubTree(theIS, aLab, theFilter, aPS.Next());
+    if (!theFilter.IsNull())
+      theFilter->Down (aTag);
+    Standard_Integer nbSubRead = ReadSubTree (theIS, aLab, theFilter, theQuickPart, aPS.Next());
     // check for error
     if (nbSubRead == -1)
       return -1;
@@ -501,6 +542,8 @@ Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
     myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
     return -1;
   }
+  if (!theFilter.IsNull())
+    theFilter->Up();
 
   return nbRead;
 }
@@ -538,7 +581,6 @@ void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection
                               (BinLDrivers_DocumentSection& theSection,
                                Standard_IStream&            /*theIS*/,
                                const Standard_Boolean isMess,
-                               const Standard_Boolean /*thePostponeShapes*/,
                                const Message_ProgressRange &/*theRange*/)
 
 {
@@ -552,13 +594,12 @@ void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection
 //function : CheckShapeSection
 //purpose  : 
 //=======================================================================
-void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection(
-                                          const Storage_Position& ShapeSectionPos, 
-                                          Standard_IStream& IS)
+void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection
+  (const Storage_Position& ShapeSectionPos, Standard_IStream& IS)
 {
   if (!IS.eof())
   {
-    const std::streamoff endPos = IS.rdbuf()->pubseekoff(0L, std::ios_base::end, std::ios_base::in);
+    const std::streamoff endPos = IS.rdbuf()->pubseekoff (0L, std::ios_base::end, std::ios_base::in);
 #ifdef OCCT_DEBUG
     std::cout << "endPos = " << endPos <<std::endl;
 #endif
@@ -584,9 +625,8 @@ void BinLDrivers_DocumentRetrievalDriver::Clear()
 //function : CheckDocumentVersion
 //purpose  : 
 //=======================================================================
-Standard_Boolean BinLDrivers_DocumentRetrievalDriver::CheckDocumentVersion(
-                                                          const Standard_Integer theFileVersion,
-                                                          const Standard_Integer theCurVersion)
+Standard_Boolean BinLDrivers_DocumentRetrievalDriver::CheckDocumentVersion
+  (const Standard_Integer theFileVersion, const Standard_Integer theCurVersion)
 {
   if (theFileVersion < 2 || theFileVersion > theCurVersion) {
     // file was written with another version
@@ -594,3 +634,12 @@ Standard_Boolean BinLDrivers_DocumentRetrievalDriver::CheckDocumentVersion(
   }
   return Standard_True;
 }
+
+//=======================================================================
+//function : IsQuickPart
+//purpose  : 
+//=======================================================================
+Standard_Boolean BinLDrivers_DocumentRetrievalDriver::IsQuickPart (const Standard_Integer theFileVer)
+{
+  return theFileVer >= TDocStd_FormatVersion_VERSION_11;
+}
index 5c77e85149879f861b43633c54d9d11c979367cd..100175365d092adb842961dbdf9dc54acc32c7df 100644 (file)
@@ -84,6 +84,7 @@ protected:
     (Standard_IStream& theIS, 
      const TDF_Label& theData, 
      const Handle(PCDM_ReaderFilter)& theFilter,
+     const Standard_Boolean& theQuickPart,
      const Message_ProgressRange& theRanges = Message_ProgressRange());
   
   
@@ -98,7 +99,6 @@ protected:
    (BinLDrivers_DocumentSection& theSection,
     Standard_IStream& theIS,
     const Standard_Boolean isMess = Standard_False,
-    const Standard_Boolean thePostponeShapes = Standard_False,
     const Message_ProgressRange& theRange = Message_ProgressRange());
   
   //! checks the shapes section can be correctly retreived.
@@ -114,6 +114,12 @@ protected:
   //! current or lesser than 2, then return false, else true
   Standard_EXPORT virtual Standard_Boolean CheckDocumentVersion (const Standard_Integer theFileVersion, const Standard_Integer theCurVersion);
 
+  //! Return true if document retrieved document allows to read parts quickly.
+  static Standard_Boolean IsQuickPart (const Standard_Integer theFileVer);
+
+  //! Enables reading in the quick part access mode.
+  Standard_EXPORT virtual void EnableQuickPartReading (const Handle(Message_Messenger)& /*theMessageDriver*/, Standard_Boolean /*theValue*/) {}
+
   Handle(BinMDF_ADriverTable) myDrivers;
   BinObjMgt_RRelocationTable myRelocTable;
   Handle(Message_Messenger) myMsgDriver;
index b51ba2fa7d457f6fe065e422c9028d34afb85dac..17ab3bedf82dd940d9a18ecdaff050facfe7b4be 100644 (file)
@@ -228,6 +228,7 @@ void BinLDrivers_DocumentSection::ReadTOC
 #endif
   if (aNameBufferSize > 0) {
     theStream.read ((char *)&aBuf[0], (Standard_Size)aNameBufferSize);
+    aBuf[aNameBufferSize] = '\0';
     theSection.myName = (Standard_CString)&aBuf[0];
 
     uint64_t aValue[3];
index a682929815c5537ef7d8827746f062a201bd03b1..53f3e99f29168c29f575782d4d0783932e16afea 100644 (file)
@@ -21,6 +21,7 @@
 #include <BinMDF_ADriver.hxx>
 #include <BinMDF_ADriverTable.hxx>
 #include <BinObjMgt_Persistent.hxx>
+#include <BinObjMgt_Position.hxx>
 #include <CDM_Application.hxx>
 #include <CDM_Document.hxx>
 #include <Message_Messenger.hxx>
 IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentStorageDriver,PCDM_StorageDriver)
 
 #define SHAPESECTION_POS (Standard_CString)"SHAPE_SECTION_POS:"
+#define ENDSECTION_POS (Standard_CString)":"
 
 //=======================================================================
 //function : BinLDrivers_DocumentStorageDriver
 //purpose  : Constructor
 //=======================================================================
 
-BinLDrivers_DocumentStorageDriver::BinLDrivers_DocumentStorageDriver ()
+BinLDrivers_DocumentStorageDriver::BinLDrivers_DocumentStorageDriver () : myIsQuickPart(Standard_True)
 {
 }
 
@@ -97,9 +99,9 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)&  theD
 {
   myMsgDriver = theDoc->Application()->MessageDriver();
   myMapUnsupported.Clear();
+  mySizesToWrite.Clear();
 
-  Handle(TDocStd_Document) aDoc =
-    Handle(TDocStd_Document)::DownCast(theDoc);
+  Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast (theDoc);
   if (aDoc.IsNull()) {
     SetIsError(Standard_True);
     SetStoreStatus(PCDM_SS_Doc_IsNull);
@@ -129,20 +131,33 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)&  theD
     for (; anIterS.More(); anIterS.Next())
       anIterS.ChangeValue().WriteTOC (theOStream, aDocVer);
 
-    // Shapes Section is the last one, it indicates the end of the table.
-    BinLDrivers_DocumentSection aShapesSection (SHAPESECTION_POS,
-                                                Standard_False);
-    aShapesSection.WriteTOC (theOStream, aDocVer);
+    EnableQuickPartWriting (myMsgDriver, IsQuickPart (aDocVer));
+    BinLDrivers_DocumentSection* aShapesSection = 0;
+    Standard_Boolean aQuickPart = IsQuickPart (aDocVer);
+    if (!aQuickPart)
+    {
+      // Shapes Section is the last one, it indicates the end of the table.
+      aShapesSection = new BinLDrivers_DocumentSection (SHAPESECTION_POS, Standard_False);
+      aShapesSection->WriteTOC (theOStream, aDocVer);
+    }
+    else
+    {
+      // End Section is the last one, it indicates the end of the table.
+      BinLDrivers_DocumentSection anEndSection (ENDSECTION_POS, Standard_False);
+      anEndSection.WriteTOC (theOStream, aDocVer);
+    }
 
 //  3. Write document contents
     // (Storage data to the stream)
     myRelocTable.Clear();
     myPAtt.Init();
+    if (aQuickPart)
+      myPAtt.SetOStream (theOStream); // for writing shapes data into the stream directly
 
     Message_ProgressScope aPS(theRange, "Writing document", 3);
 
 //  Write Doc structure
-    WriteSubTree (aData->Root(), theOStream, aPS.Next()); // Doc is written
+    WriteSubTree (aData->Root(), theOStream, aQuickPart, aPS.Next()); // Doc is written
     if (!aPS.More())
     {
       SetIsError(Standard_True);
@@ -151,12 +166,19 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)&  theD
     }
 
 //  4. Write Shapes section
-    WriteShapeSection (aShapesSection, theOStream, aDocVer, aPS.Next());
+    if (!aQuickPart)
+    {
+      WriteShapeSection (*aShapesSection, theOStream, aDocVer, aPS.Next());
+      delete aShapesSection;
+    }
+    else
+      Clear();
+
     if (!aPS.More())
     {
-       SetIsError(Standard_True);
-       SetStoreStatus(PCDM_SS_UserBreak);
-       return;
+      SetIsError (Standard_True);
+      SetStoreStatus (PCDM_SS_UserBreak);
+      return;
     }
 
     // Write application-defined sections
@@ -167,6 +189,10 @@ void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)&  theD
       aSection.Write (theOStream, aSectionOffset, aDocVer);
     }
 
+//  5. Write sizes along the file where it is needed for quick part mode
+    if (aQuickPart)
+      WriteSizes (theOStream);
+
     // End of processing: close structures and check the status
     myPAtt.Destroy();   // free buffer
     myEmptyLabels.Clear();
@@ -211,7 +237,7 @@ void BinLDrivers_DocumentStorageDriver::UnsupportedAttrMsg
 {
 #ifdef OCCT_DEBUG
   TCollection_ExtendedString aMsg
-    ("BinDrivers_DocumentStorageDriver: warning: attribute driver for type ");
+    ("BinLDrivers_DocumentStorageDriver: warning: attribute driver for type ");
 #endif
   if (!myMapUnsupported.Contains(theType)) {
     myMapUnsupported.Add(theType);
@@ -229,6 +255,7 @@ void BinLDrivers_DocumentStorageDriver::UnsupportedAttrMsg
 void BinLDrivers_DocumentStorageDriver::WriteSubTree
                         (const TDF_Label&             theLabel,
                          Standard_OStream&            theOS,
+                         const Standard_Boolean&      theQuickPart,
                          const Message_ProgressRange& theRange)
 {
   // Skip empty labels
@@ -244,6 +271,13 @@ void BinLDrivers_DocumentStorageDriver::WriteSubTree
 #endif
   theOS.write ((char*)&aTag, sizeof(Standard_Integer));
 
+  Handle(BinObjMgt_Position) aPosition;
+  if (theQuickPart)
+  {
+    aPosition = mySizesToWrite.Append (new BinObjMgt_Position (theOS));
+    aPosition->WriteSize (theOS);
+  }
+
   // Write attributes
   TDF_AttributeIterator itAtt (theLabel);
   for ( ; itAtt.More() && theOS && aPS.More(); itAtt.Next()) {
@@ -251,7 +285,7 @@ void BinLDrivers_DocumentStorageDriver::WriteSubTree
     const Handle(Standard_Type)& aType = tAtt->DynamicType();
     // Get type ID and driver
     Handle(BinMDF_ADriver) aDriver;
-    const Standard_Integer aTypeId = myDrivers->GetDriver (aType,aDriver);
+    const Standard_Integer aTypeId = myDrivers->GetDriver (aType, aDriver);
     if (aTypeId > 0) {
       // Add source to relocation table
       const Standard_Integer anId = myRelocTable.Add (tAtt);
@@ -260,6 +294,12 @@ void BinLDrivers_DocumentStorageDriver::WriteSubTree
       myPAtt.SetTypeId (aTypeId);
       myPAtt.SetId (anId);
       aDriver->Paste (tAtt, myPAtt, myRelocTable);
+      if (!myPAtt.StreamStart().IsNull())
+      {
+        Handle(BinObjMgt_Position) anAttrPosition = myPAtt.StreamStart();
+        anAttrPosition->StoreSize (theOS);
+        mySizesToWrite.Append (anAttrPosition);
+      }
 
       // Write data to the stream -->!!!
       theOS << myPAtt;
@@ -297,16 +337,16 @@ void BinLDrivers_DocumentStorageDriver::WriteSubTree
       SetStoreStatus(PCDM_SS_UserBreak);
       return;
     }
-    WriteSubTree (aChildLab, theOS, aPS.Next());
+    WriteSubTree (aChildLab, theOS, theQuickPart, aPS.Next());
   }
-
   // Write the end label marker
   BinLDrivers_Marker anEndLabel = BinLDrivers_ENDLABEL;
 #if DO_INVERSE
-  anEndLabel = (BinLDrivers_Marker) InverseInt (anEndLabel);
+  anEndLabel = (BinLDrivers_Marker)InverseInt (anEndLabel);
 #endif
-  theOS.write ((char*)&anEndLabel, sizeof(anEndLabel));
-
+  theOS.write ((char*)&anEndLabel, sizeof (anEndLabel));
+  if (theQuickPart)
+    aPosition->StoreSize (theOS);
 }
 
 //=======================================================================
@@ -553,3 +593,34 @@ void BinLDrivers_DocumentStorageDriver::WriteShapeSection
   const Standard_Size aShapesSectionOffset = (Standard_Size) theOS.tellp();
   theSection.Write (theOS, aShapesSectionOffset, theDocVer);
 }
+
+//=======================================================================
+//function : IsQuickPart
+//purpose  : Return true if document should be stored in quick mode for partial reading
+//=======================================================================
+Standard_Boolean BinLDrivers_DocumentStorageDriver::IsQuickPart (const Standard_Integer theVersion) const
+{
+  return theVersion >= TDocStd_FormatVersion_VERSION_11;
+}
+
+//=======================================================================
+//function : Clear
+//purpose  : 
+//=======================================================================
+void BinLDrivers_DocumentStorageDriver::Clear()
+{
+  // empty; should be redefined in subclasses
+}
+
+
+//=======================================================================
+//function : WriteSizes
+//purpose  : 
+//=======================================================================
+void BinLDrivers_DocumentStorageDriver::WriteSizes (Standard_OStream& theOS)
+{
+  NCollection_List<Handle(BinObjMgt_Position)>::Iterator anIter (mySizesToWrite);
+  for (; anIter.More() && theOS; anIter.Next())
+    anIter.Value()->WriteSize (theOS);
+  mySizesToWrite.Clear();
+}
index 2de015c415d4ae64644c2fa1fcdb5b73932cbd17..fc7eb7c24ebd92f48f5344a4dbc4105e1f1157ba 100644 (file)
@@ -36,6 +36,7 @@ class CDM_Document;
 class TDF_Label;
 class TCollection_AsciiString;
 class BinLDrivers_DocumentSection;
+class BinObjMgt_Position;
 
 
 class BinLDrivers_DocumentStorageDriver;
@@ -66,7 +67,8 @@ public:
   //! Create a section that should be written after the OCAF data
   Standard_EXPORT void AddSection (const TCollection_AsciiString& theName, const Standard_Boolean isPostRead = Standard_True);
 
-
+  //! Return true if document should be stored in quick mode for partial reading
+  Standard_EXPORT Standard_Boolean IsQuickPart (const Standard_Integer theVersion) const;
 
 
   DEFINE_STANDARD_RTTIEXT(BinLDrivers_DocumentStorageDriver,PCDM_StorageDriver)
@@ -76,7 +78,8 @@ protected:
   
   //! Write the tree under <theLabel> to the stream <theOS>
   Standard_EXPORT void WriteSubTree (const TDF_Label& theData,
-                                     Standard_OStream& theOS, 
+                                     Standard_OStream& theOS,
+                                     const Standard_Boolean& theQuickPart,
                                      const Message_ProgressRange& theRange = Message_ProgressRange());
   
   //! define the procedure of writing a section to file.
@@ -90,6 +93,13 @@ protected:
                                                   const Standard_Integer theDocVer,
                                                   const Message_ProgressRange& theRange = Message_ProgressRange());
 
+  //! Enables writing in the quick part access mode.
+  Standard_EXPORT virtual void EnableQuickPartWriting (
+    const Handle(Message_Messenger)& /*theMessageDriver*/, const Standard_Boolean /*theValue*/) {}
+
+  //! clears the writing-cash data in drivers if any.
+  Standard_EXPORT virtual void Clear();
+
   Handle(BinMDF_ADriverTable) myDrivers;
   BinObjMgt_SRelocationTable myRelocTable;
   Handle(Message_Messenger) myMsgDriver;
@@ -107,13 +117,18 @@ private:
   
   Standard_EXPORT void UnsupportedAttrMsg (const Handle(Standard_Type)& theType);
 
+  //! Writes sizes along the file where it is needed for quick part mode
+  Standard_EXPORT void WriteSizes (Standard_OStream& theOS);
+
   BinObjMgt_Persistent myPAtt;
   TDF_LabelList myEmptyLabels;
   TColStd_MapOfTransient myMapUnsupported;
   TColStd_IndexedMapOfTransient myTypesMap;
   BinLDrivers_VectorOfDocumentSection mySections;
   TCollection_ExtendedString myFileName;
-
+  Standard_Boolean myIsQuickPart;
+  //! Sizes of labels and some attributes that will be stored in the second pass
+  NCollection_List<Handle(BinObjMgt_Position)> mySizesToWrite;
 };
 
 #endif // _BinLDrivers_DocumentStorageDriver_HeaderFile
index bb79761d35d4895ecb9fba5050bcab745a80675b..e2a89091532bf34bd261e2dd65533edf17f34591 100644 (file)
@@ -18,6 +18,8 @@
 #include <BinObjMgt_Persistent.hxx>
 #include <BinTools_LocationSet.hxx>
 #include <BinTools_ShapeSet.hxx>
+#include <BinTools_ShapeWriter.hxx>
+#include <BinTools_ShapeReader.hxx>
 #include <Message_Messenger.hxx>
 #include <Standard_DomainError.hxx>
 #include <Standard_Type.hxx>
@@ -36,7 +38,7 @@ IMPLEMENT_STANDARD_RTTIEXT(BinMNaming_NamedShapeDriver,BinMDF_ADriver)
 #define SHAPESET "SHAPE_SECTION"
 #define FORMAT_NUMBER 3
 //=======================================================================
-static Standard_Character EvolutionToChar(const TNaming_Evolution theEvol)
+static Standard_Character EvolutionToChar (const TNaming_Evolution theEvol)
 {
   switch(theEvol) {
     case TNaming_PRIMITIVE    : return 'P';
@@ -51,7 +53,7 @@ static Standard_Character EvolutionToChar(const TNaming_Evolution theEvol)
 }
 
 //=======================================================================
-static TNaming_Evolution EvolutionToEnum(const Standard_Character theEvol)
+static TNaming_Evolution EvolutionToEnum (const Standard_Character theEvol)
 {
   switch(theEvol) {
     case 'P': return TNaming_PRIMITIVE;
@@ -65,7 +67,7 @@ static TNaming_Evolution EvolutionToEnum(const Standard_Character theEvol)
   }
 }
 //=======================================================================
-static Standard_Character OrientationToChar(const TopAbs_Orientation theOrient)
+static Standard_Character OrientationToChar (const TopAbs_Orientation theOrient)
 {
   switch(theOrient) {
     case TopAbs_FORWARD    : return 'F';
@@ -77,7 +79,7 @@ static Standard_Character OrientationToChar(const TopAbs_Orientation theOrient)
   }
 }
 //=======================================================================
-static TopAbs_Orientation CharToOrientation(const Standard_Character  theCharOrient)
+static TopAbs_Orientation CharToOrientation (const Standard_Character  theCharOrient)
 {
   switch(theCharOrient) {
     case 'F':  return TopAbs_FORWARD;
@@ -92,45 +94,45 @@ static TopAbs_Orientation CharToOrientation(const Standard_Character  theCharOri
 //=======================================================================
 static void TranslateTo (const TopoDS_Shape&            theShape,
                          BinObjMgt_Persistent&          theResult,
-                         BinTools_ShapeSet&            theShapeSet)
+                         BinTools_ShapeSet            theShapeSet)
 {
   // Check for empty shape
   if (theShape.IsNull()) {
-    theResult.PutInteger(-1);
-    theResult.PutInteger(-1);
-    theResult.PutInteger(-1);
+    theResult.PutInteger (-1);
+    theResult.PutInteger (-1);
+    theResult.PutInteger (-1);
     return;
   }
   // Add to shape set both TShape and Location contained in <theShape>
-  const Standard_Integer aTShapeID = theShapeSet.Add (theShape);
+  const Standard_Integer aTShapeID = theShapeSet->Add (theShape);
   const Standard_Integer aLocID =
-    theShapeSet.Locations().Index (theShape.Location());
+    theShapeSet->Locations().Index (theShape.Location());
 
   // Fill theResult with shape parameters: TShape ID, Location, Orientation
   theResult << aTShapeID;
   theResult << aLocID;
-  theResult << OrientationToChar(theShape.Orientation());
+  theResult << OrientationToChar (theShape.Orientation());
 }
 //=======================================================================
 static int TranslateFrom  (const BinObjMgt_Persistent&  theSource,
                          TopoDS_Shape&                  theResult,
-                         BinTools_ShapeSet&            theShapeSet)
+                         BinTools_ShapeSet*            theShapeSet)
 {
   Standard_Integer aShapeID, aLocID;
   Standard_Character aCharOrient;
   Standard_Boolean Ok = theSource >> aShapeID; //TShapeID;
   if(!Ok) return 1;
   // Read TShape and Orientation
-  if (aShapeID <= 0 || aShapeID > theShapeSet.NbShapes())
+  if (aShapeID <= 0 || aShapeID > theShapeSet->NbShapes())
     return 1;
   Ok = theSource >> aLocID;
   if(!Ok) return 1;
   Ok = theSource >> aCharOrient;
   if(!Ok) return 1;
-  TopAbs_Orientation anOrient = CharToOrientation(aCharOrient);
+  TopAbs_Orientation anOrient = CharToOrientation (aCharOrient);
 
-  theResult.TShape      (theShapeSet.Shape(aShapeID).TShape());//TShape
-  theResult.Location    (theShapeSet.Locations().Location (aLocID)); //Location
+  theResult.TShape      (theShapeSet->Shape (aShapeID).TShape());//TShape
+  theResult.Location    (theShapeSet->Locations().Location (aLocID)); //Location
   theResult.Orientation (anOrient);//Orientation
   return 0;
 }
@@ -142,7 +144,11 @@ static int TranslateFrom  (const BinObjMgt_Persistent&  theSource,
 
 BinMNaming_NamedShapeDriver::BinMNaming_NamedShapeDriver
                         (const Handle(Message_Messenger)& theMsgDriver)
-     : BinMDF_ADriver (theMsgDriver, STANDARD_TYPE(TNaming_NamedShape)->Name()), myShapeSet(Standard_False),myFormatNb(FORMAT_NUMBER)
+     : BinMDF_ADriver (theMsgDriver, STANDARD_TYPE(TNaming_NamedShape)->Name()),
+       myShapeSet (NULL),
+       myFormatNb (BinTools_FormatVersion_VERSION_1),
+       myIsQuickPart (Standard_False),
+       myWithTriangles (Standard_False)
 {
 }
 
@@ -166,11 +172,11 @@ Standard_Boolean BinMNaming_NamedShapeDriver::Paste
                                  const Handle(TDF_Attribute)& theTarget,
                                  BinObjMgt_RRelocationTable&  ) const
 {
-  Handle(TNaming_NamedShape) aTAtt= Handle(TNaming_NamedShape)::DownCast(theTarget);
+  Handle(TNaming_NamedShape) aTAtt= Handle(TNaming_NamedShape)::DownCast (theTarget);
   Standard_Integer aNbShapes;
   theSource >> aNbShapes;
   TDF_Label aLabel = theTarget->Label ();
-  TNaming_Builder   aBuilder   (aLabel);
+  TNaming_Builder aBuilder (aLabel);
   Standard_Integer aVer;
   Standard_Boolean ok = theSource >> aVer;
   if(!ok) return Standard_False;
@@ -178,10 +184,13 @@ Standard_Boolean BinMNaming_NamedShapeDriver::Paste
   Standard_Character aCharEvol;
   ok = theSource >> aCharEvol;
   if(!ok) return Standard_False;
-  TNaming_Evolution anEvol  = EvolutionToEnum(aCharEvol); //Evolution
-  aTAtt->SetVersion(anEvol);
+  TNaming_Evolution anEvol  = EvolutionToEnum (aCharEvol); //Evolution
+  aTAtt->SetVersion (anEvol);
 
-  BinTools_ShapeSet& aShapeSet = (BinTools_ShapeSet&) myShapeSet;
+  BinTools_ShapeSetBase* aShapeSet = const_cast<BinMNaming_NamedShapeDriver*>(this)->ShapeSet (Standard_True);
+  Standard_IStream* aDirectStream = NULL;
+  if (myIsQuickPart) // enables direct reading of shapes from the stream
+    aDirectStream = const_cast<BinObjMgt_Persistent*>(&theSource)->GetIStream();
 
   NCollection_List<TopoDS_Shape> anOldShapes, aNewShapes;
   for (Standard_Integer i = 1; i <= aNbShapes; i++)
@@ -189,10 +198,16 @@ Standard_Boolean BinMNaming_NamedShapeDriver::Paste
     TopoDS_Shape anOldShape, aNewShape;
 
     if (anEvol != TNaming_PRIMITIVE)
-      if (TranslateFrom (theSource, anOldShape, aShapeSet)) return Standard_False;
+      if (myIsQuickPart)
+        aShapeSet->Read (*aDirectStream, anOldShape);
+      else
+        if (TranslateFrom (theSource, anOldShape, static_cast<BinTools_ShapeSet*>(aShapeSet))) return Standard_False;
 
     if (anEvol != TNaming_DELETE)
-      if (TranslateFrom (theSource, aNewShape, aShapeSet)) return Standard_False;
+      if (myIsQuickPart)
+        aShapeSet->Read (*aDirectStream, aNewShape);
+      else
+        if (TranslateFrom (theSource, aNewShape, static_cast<BinTools_ShapeSet*>(aShapeSet))) return Standard_False;
 
     // Here we add shapes in reverse order because TNaming_Builder also adds them in reverse order.
     anOldShapes.Prepend (anOldShape);
@@ -246,24 +261,38 @@ void BinMNaming_NamedShapeDriver::Paste (const Handle(TDF_Attribute)& theSource,
   for (TNaming_Iterator SItr (aSAtt); SItr.More (); SItr.Next ()) NbShapes++;
   //--------------------------------------------------------------
 
-  BinTools_ShapeSet& aShapeSet = (BinTools_ShapeSet&) myShapeSet;
+  BinTools_ShapeSetBase* aShapeSet = const_cast<BinMNaming_NamedShapeDriver*>(this)->ShapeSet (Standard_False);
   TNaming_Evolution anEvol = aSAtt->Evolution();
   
   theTarget << NbShapes;
   theTarget << aSAtt->Version();
-  theTarget << EvolutionToChar(anEvol);
+  theTarget << EvolutionToChar (anEvol);
+
+
+  Standard_OStream* aDirectStream = NULL;
+  if (myIsQuickPart) // enables direct writing of shapes to the stream
+    aDirectStream = theTarget.GetOStream();
 
   Standard_Integer i = 1;  
-  for (TNaming_Iterator SIterator(aSAtt) ;SIterator.More(); SIterator.Next()) {
-    const TopoDS_Shape& OldShape = SIterator.OldShape();
-    const TopoDS_Shape& NewShape = SIterator.NewShape();
+  for (TNaming_Iterator SIterator(aSAtt)SIterator.More(); SIterator.Next()) {
+    const TopoDS_Shape& anOldShape = SIterator.OldShape();
+    const TopoDS_Shape& aNewShape = SIterator.NewShape();
     
-    if ( anEvol != TNaming_PRIMITIVE ) 
-      TranslateTo (OldShape, theTarget, aShapeSet); 
+    if (anEvol != TNaming_PRIMITIVE)
+    {
+      if (myIsQuickPart)
+        aShapeSet->Write (anOldShape, *aDirectStream);
+      else
+        TranslateTo (anOldShape, theTarget, static_cast<BinTools_ShapeSet*>(aShapeSet));
+    }
 
-    if (anEvol != TNaming_DELETE) 
-      TranslateTo (NewShape, theTarget, aShapeSet);
+    if (anEvol != TNaming_DELETE)
+    {
+      if (myIsQuickPart)
+        aShapeSet->Write (aNewShape, *aDirectStream);
+      else
+        TranslateTo (aNewShape, theTarget, static_cast<BinTools_ShapeSet*>(aShapeSet));
+    }
     
     i++;
   }
@@ -279,10 +308,11 @@ void BinMNaming_NamedShapeDriver::Paste (const Handle(TDF_Attribute)& theSource,
 void BinMNaming_NamedShapeDriver::WriteShapeSection (Standard_OStream& theOS,
                                                      const Message_ProgressRange& theRange)
 {
-  theOS << SHAPESET; 
-  myShapeSet.SetFormatNb(myFormatNb);
-  myShapeSet.Write (theOS, theRange);
-  myShapeSet.Clear();
+  myIsQuickPart = Standard_False;
+  theOS << SHAPESET;
+  ShapeSet (Standard_False)->SetFormatNb (myFormatNb);
+  ShapeSet (Standard_False)->Write (theOS, theRange);
+  ShapeSet (Standard_False)->Clear();
 }
 
 //=======================================================================
@@ -292,7 +322,12 @@ void BinMNaming_NamedShapeDriver::WriteShapeSection (Standard_OStream& theOS,
 
 void BinMNaming_NamedShapeDriver::Clear()
 {
-  myShapeSet.Clear();
+  if (myShapeSet)
+  {
+    myShapeSet->Clear();
+    delete myShapeSet;
+    myShapeSet = NULL;
+  }
 }
 
 //=======================================================================
@@ -301,19 +336,48 @@ void BinMNaming_NamedShapeDriver::Clear()
 //=======================================================================
 
 void BinMNaming_NamedShapeDriver::ReadShapeSection (Standard_IStream& theIS,
-                                                    const Standard_Boolean thePostponeShapes,
                                                     const Message_ProgressRange& theRange)
 {
+  myIsQuickPart = Standard_False;
   // check section title string; note that some versions of OCCT (up to 6.3.1) 
   // might avoid writing shape section if it is empty
   std::streamoff aPos = theIS.tellg();
   TCollection_AsciiString aSectionTitle;
   theIS >> aSectionTitle;
   if(aSectionTitle.Length() > 0 && aSectionTitle == SHAPESET) {
-    myShapeSet.Clear();
-    myShapeSet.Read (theIS, thePostponeShapes, theRange);
-    SetFormatNb(myShapeSet.FormatNb());
+    BinTools_ShapeSetBase* aShapeSet = ShapeSet (Standard_True);
+    aShapeSet->Clear();
+    aShapeSet->Read (theIS, theRange);
+    SetFormatNb (aShapeSet->FormatNb());
   }
   else
-    theIS.seekg(aPos); // no shape section is present, try to return to initial point
+    theIS.seekg (aPos); // no shape section is present, try to return to initial point
+}
+
+//=======================================================================
+//function : ShapeSet
+//purpose  : 
+//=======================================================================
+
+BinTools_ShapeSetBase* BinMNaming_NamedShapeDriver::ShapeSet (const Standard_Boolean theReading)
+{
+  if (!myShapeSet)
+    if (myIsQuickPart)
+      if (theReading)
+        myShapeSet = new BinTools_ShapeReader();
+      else
+        myShapeSet = new BinTools_ShapeWriter (myWithTriangles);
+    else
+      myShapeSet = new BinTools_ShapeSet (myWithTriangles);
+  return myShapeSet;
+}
+
+//=======================================================================
+//function : GetShapesLocations
+//purpose  : 
+//=======================================================================
+BinTools_LocationSet& BinMNaming_NamedShapeDriver::GetShapesLocations() const
+{
+  BinTools_ShapeSetBase* aShapeSet = const_cast<BinMNaming_NamedShapeDriver*>(this)->ShapeSet (Standard_False);
+  return static_cast<BinTools_ShapeSet*>(aShapeSet)->ChangeLocations();
 }
index 54bd4bc7f2373747b7440291a8a8f99fc8af5734..b2d93e48027722840b8fa008d32678db9eff62ec 100644 (file)
@@ -53,7 +53,6 @@ public:
   
   //! Input the shapes from Bin Document file
   Standard_EXPORT void ReadShapeSection (Standard_IStream& theIS,
-                                         const Standard_Boolean thePostponeShapes = Standard_False,
                                          const Message_ProgressRange& therange = Message_ProgressRange());
   
   //! Output the shapes into Bin Document file
@@ -64,7 +63,7 @@ public:
   Standard_EXPORT void Clear();
 
   //! Return true if shape should be stored with triangles.
-  Standard_Boolean IsWithTriangles() const { return myShapeSet.IsWithTriangles(); }
+  Standard_Boolean IsWithTriangles() const { return myWithTriangles; }
 
   //! set whether to store triangulation
   void SetWithTriangles (const Standard_Boolean isWithTriangles);
@@ -73,29 +72,33 @@ public:
   //! First : does not write CurveOnSurface UV Points into the file
   //! on reading calls Check() method.
   //! Second: stores CurveOnSurface UV Points.
-    void SetFormatNb (const Standard_Integer theFormat);
+  void SetFormatNb (const Standard_Integer theFormat);
   
   //! get the format of topology
-    Standard_Integer GetFormatNb() const;
+  Standard_Integer GetFormatNb() const;
   
   //! get the format of topology
-    BinTools_LocationSet& GetShapesLocations();
-
+  Standard_EXPORT BinTools_LocationSet& GetShapesLocations() const;
 
+  //! Sets the flag for quick part of the document access: shapes are stored in the attribute.
+  Standard_EXPORT void EnableQuickPart(const Standard_Boolean theValue) { myIsQuickPart = theValue; }
+  //! Returns true if quick part of the document access is enabled: shapes are stored in the attribute.
+  Standard_EXPORT Standard_Boolean IsQuickPart() { return myIsQuickPart; }
 
+  //! Returns shape-set of the needed type
+  Standard_EXPORT BinTools_ShapeSetBase* ShapeSet (const Standard_Boolean theReading);
 
   DEFINE_STANDARD_RTTIEXT(BinMNaming_NamedShapeDriver,BinMDF_ADriver)
 
-protected:
-
-
-
 
 private:
 
 
-  BinTools_ShapeSet myShapeSet;
+  BinTools_ShapeSetBase *myShapeSet;
   Standard_Integer myFormatNb;
+  Standard_Boolean myWithTriangles;
+  //! Enables storing of whole shape data just in the attribute, not in a separated shapes section
+  Standard_Boolean myIsQuickPart;
 
 
 };
index da9a59daeb96a7536dc96135c30a247da405f2b0..744bdf78c9ca76a62f8f4c2a1b8892a504e501df 100644 (file)
@@ -40,15 +40,7 @@ inline void BinMNaming_NamedShapeDriver::SetFormatNb(const Standard_Integer theF
 
 inline void BinMNaming_NamedShapeDriver::SetWithTriangles(const Standard_Boolean isWithTriangles) 
 {
-  myShapeSet.SetWithTriangles(isWithTriangles);
+  myWithTriangles = isWithTriangles;
+  if (myShapeSet)
+    myShapeSet->SetWithTriangles (isWithTriangles);
 }
-
-//=======================================================================
-//function : GetShapesLocations
-//purpose  : 
-//=======================================================================
-inline BinTools_LocationSet& BinMNaming_NamedShapeDriver::GetShapesLocations()
-{
-  return myShapeSet.ChangeLocations();
-}
-
index b458ebe82dd4ebe5bd248e29fed381a696bbb7d3..3a2bac521872cc707b0915f0d4897c26698d26f3 100644 (file)
@@ -51,9 +51,9 @@ void BinMXCAFDoc::AddDrivers(const Handle(BinMDF_ADriverTable)& theDriverTable,
     Handle(BinMNaming_NamedShapeDriver)::DownCast (aNSDriver);
   
   Handle(BinMXCAFDoc_LocationDriver) aLocationDriver = new BinMXCAFDoc_LocationDriver (theMsgDrv);
-  if( !aNamedShapeDriver.IsNull() )
+  if (!aNamedShapeDriver.IsNull())
   {
-    aLocationDriver->SetSharedLocations( &(aNamedShapeDriver->GetShapesLocations()) );
+    aLocationDriver->SetNSDriver (aNamedShapeDriver);
   }
   
   theDriverTable->AddDriver( aLocationDriver);
index 43fa820dfe1a544c07f84f40a53b7d73b937722e..65736d1519c73f2a9cab55ad810dc6e74adefbfe 100644 (file)
@@ -18,6 +18,8 @@
 #include <BinMXCAFDoc_LocationDriver.hxx>
 #include <BinObjMgt_Persistent.hxx>
 #include <BinTools_LocationSet.hxx>
+#include <BinTools_ShapeReader.hxx>
+#include <BinTools_ShapeWriter.hxx>
 #include <Message_Messenger.hxx>
 #include <gp_Mat.hxx>
 #include <gp_Trsf.hxx>
@@ -37,7 +39,7 @@ IMPLEMENT_STANDARD_RTTIEXT(BinMXCAFDoc_LocationDriver,BinMDF_ADriver)
 //=======================================================================
 BinMXCAFDoc_LocationDriver::BinMXCAFDoc_LocationDriver(const Handle(Message_Messenger)& theMsgDriver)
      : BinMDF_ADriver(theMsgDriver, STANDARD_TYPE(XCAFDoc_Location)->Name())
-     , myLocations(0) {
+{
 }
 
 //=======================================================================
@@ -84,6 +86,14 @@ Standard_Boolean BinMXCAFDoc_LocationDriver::Translate(const BinObjMgt_Persisten
                                                        TopLoc_Location& theLoc,
                                                        BinObjMgt_RRelocationTable& theMap) const
 {
+  if (!myNSDriver.IsNull() && myNSDriver->IsQuickPart())
+  {
+    BinTools_IStream aDirectStream (*(const_cast<BinObjMgt_Persistent*>(&theSource)->GetIStream()));
+    BinTools_ShapeReader* aReader = static_cast<BinTools_ShapeReader*>(myNSDriver->ShapeSet (Standard_True));
+    theLoc = *(aReader->ReadLocation (aDirectStream));
+    return Standard_True;
+  }
+
   Standard_Integer anId = 0;
   theSource >> anId;
   
@@ -91,19 +101,25 @@ Standard_Boolean BinMXCAFDoc_LocationDriver::Translate(const BinObjMgt_Persisten
   {
     return Standard_True;
   }
+
+  if (!myNSDriver.IsNull() && myNSDriver->IsQuickPart())
+  { // read directly from the stream
+
+
+  }
   
   Standard_Integer aFileVer = theMap.GetHeaderData()->StorageVersion().IntegerValue();
-  if( aFileVer > 5 && myLocations == 0 )
+  if( aFileVer >= TDocStd_FormatVersion_VERSION_6 && myNSDriver.IsNull() )
   {
     return Standard_False;
   }
   
-  Standard_Integer aPower;
+  Standard_Integer aPower (0);
   Handle(TopLoc_Datum3D) aDatum;
   
-  if( aFileVer > 5 )
+  if (aFileVer >= TDocStd_FormatVersion_VERSION_6)
   {
-    const TopLoc_Location& aLoc = myLocations->Location(anId);
+    const TopLoc_Location& aLoc = myNSDriver->GetShapesLocations().Location (anId);
     aPower = aLoc.FirstPower();
     aDatum = aLoc.FirstDatum();
   } else {
@@ -168,35 +184,42 @@ void BinMXCAFDoc_LocationDriver::Translate(const TopLoc_Location& theLoc,
                                            BinObjMgt_Persistent& theTarget,
                                            BinObjMgt_SRelocationTable& theMap) const
 {
-  if(theLoc.IsIdentity()) 
+  // The location is not identity  
+  if (!myNSDriver.IsNull() && myNSDriver->IsQuickPart())
+  { // write directly to the stream
+    Standard_OStream* aDirectStream = theTarget.GetOStream();
+    BinTools_ShapeWriter* aWriter = static_cast<BinTools_ShapeWriter*>(myNSDriver->ShapeSet (Standard_False));
+    aWriter->WriteLocation (*aDirectStream, theLoc);
+    return;
+  }
+  if(theLoc.IsIdentity())
   {
     theTarget.PutInteger(0);
     return;
   }
   
-  // The location is not identity  
-  if( myLocations == 0 )
+  if (myNSDriver.IsNull())
   {
 #ifdef OCCT_DEBUG
-    std::cout<<"Pointer to LocationSet is NULL\n";
+    std::cout << "NamedShape Driver is NULL\n";
 #endif
     return;
   }
-  
-  Standard_Integer anId = myLocations->Add(theLoc);
+
+  Standard_Integer anId = myNSDriver->GetShapesLocations().Add (theLoc);
   theTarget << anId;
-  
+
   // In earlier version of this driver a datums from location stored in 
   // the relocation table, but now it's not necessary
   // (try to uncomment it if some problems appear)
   /*
   Handle(TopLoc_Datum3D) aDatum = theLoc.FirstDatum();
-  
+
   if(!theMap.Contains(aDatum)) {
     theMap.Add(aDatum);
   }
   */
-  
+
   Translate(theLoc.NextLocation(), theTarget, theMap);
 }
 
index 76fe223d8b5682d81f8e53fde218699be1ef5196..c46d5b8838da84ae8fe362deeee555a215bcae92 100644 (file)
@@ -19,7 +19,7 @@
 #include <Standard.hxx>
 #include <Standard_Type.hxx>
 
-#include <BinTools_LocationSetPtr.hxx>
+#include <BinMNaming_NamedShapeDriver.hxx>
 #include <BinMDF_ADriver.hxx>
 #include <Standard_Boolean.hxx>
 #include <BinObjMgt_RRelocationTable.hxx>
@@ -53,7 +53,7 @@ public:
   //! Translate transient location to storable
   Standard_EXPORT void Translate (const TopLoc_Location& theLoc, BinObjMgt_Persistent& theTarget, BinObjMgt_SRelocationTable& theMap) const;
   
-    void SetSharedLocations (const BinTools_LocationSetPtr& theLocations);
+  void SetNSDriver (const Handle(BinMNaming_NamedShapeDriver)& theNSDriver) { myNSDriver = theNSDriver; }
 
 
 
@@ -68,16 +68,10 @@ protected:
 private:
 
 
-  BinTools_LocationSetPtr myLocations;
-
+  Handle(BinMNaming_NamedShapeDriver) myNSDriver;
 
 };
 
 
-#include <BinMXCAFDoc_LocationDriver.lxx>
-
-
-
-
 
 #endif // _BinMXCAFDoc_LocationDriver_HeaderFile
diff --git a/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.lxx b/src/BinMXCAFDoc/BinMXCAFDoc_LocationDriver.lxx
deleted file mode 100644 (file)
index f4ab83a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Created on: 2011-02-08
-// Created by: Oleg AGASHIN
-// Copyright (c) 2011-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-//=======================================================================
-//function : SetSharedLocations
-//purpose  : 
-//=======================================================================
-inline void BinMXCAFDoc_LocationDriver::SetSharedLocations(const BinTools_LocationSetPtr& theLocations)
-{ 
-  if( myLocations != theLocations )
-  {
-    myLocations = theLocations;
-  }
-}
index 68f84fabf9280d79d09fe1383affdf3d27ae00c4..93026d7d16dbfe444140cba346dfa6fe1ebf7fac 100644 (file)
@@ -14,7 +14,6 @@ BinMXCAFDoc_GraphNodeDriver.cxx
 BinMXCAFDoc_GraphNodeDriver.hxx
 BinMXCAFDoc_LocationDriver.cxx
 BinMXCAFDoc_LocationDriver.hxx
-BinMXCAFDoc_LocationDriver.lxx
 BinMXCAFDoc_MaterialDriver.cxx
 BinMXCAFDoc_MaterialDriver.hxx
 BinMXCAFDoc_NoteDriver.cxx
index cf3983753fe72a4f9597776665366826e9702035..d8900ed810dbf4e265f8b2d687bc9b7789933547 100644 (file)
@@ -15,6 +15,7 @@
 
 
 #include <BinObjMgt_Persistent.hxx>
+#include <BinObjMgt_Position.hxx>
 #include <FSD_FileHeader.hxx>
 #include <Standard_GUID.hxx>
 #include <TCollection_AsciiString.hxx>
@@ -52,7 +53,10 @@ BinObjMgt_Persistent::BinObjMgt_Persistent ()
      : myIndex (1),
        myOffset(BP_HEADSIZE),
        mySize  (BP_HEADSIZE),
-       myIsError (Standard_False)
+       myIsError (Standard_False),
+       myIStream (NULL),
+       myOStream (NULL),
+       myDirectWritingIsEnabled (Standard_False)
 {
   Init();
 }
@@ -76,6 +80,7 @@ void BinObjMgt_Persistent::Init ()
   myOffset = BP_HEADSIZE;
   mySize = BP_HEADSIZE;
   myIsError = Standard_False;
+  myDirectWritingIsEnabled = Standard_False;
 }
 
 //=======================================================================
@@ -85,12 +90,19 @@ void BinObjMgt_Persistent::Init ()
 //           const BinObjMgt_Persistent&) is also available
 //=======================================================================
 
-Standard_OStream& BinObjMgt_Persistent::Write (Standard_OStream& theOS)
+Standard_OStream& BinObjMgt_Persistent::Write (Standard_OStream& theOS, const Standard_Boolean theDirectStream)
 {
+  if (myDirectWritingIsEnabled)
+  { // if direct writing was enabled, everything is already written, just pass this stage
+    myDirectWritingIsEnabled = Standard_False;
+    return theOS;
+  }
   Standard_Integer nbWritten = 0;
   Standard_Integer *aData = (Standard_Integer*) myData(1);
   // update data length
   aData[2] = mySize - BP_HEADSIZE;
+  if (theDirectStream)
+    aData[1] = -aData[1];
 #if DO_INVERSE
   aData[0] = InverseInt (aData[0]);
   aData[1] = InverseInt (aData[1]);
@@ -141,7 +153,9 @@ Standard_IStream& BinObjMgt_Persistent::Read (Standard_IStream& theIS)
     aData[1] = InverseInt (aData[1]);
     aData[2] = InverseInt (aData[2]);
 #endif
-    if (theIS && aData[1] > 0 && aData[2] > 0) {
+    if (myDirectWritingIsEnabled = (aData[1] < 0))
+      aData[1] = -aData[1];
+    if (theIS && aData[2] > 0) {
       mySize += aData[2];
       // read remaining data
       Standard_Integer nbRead = BP_HEADSIZE;
@@ -1164,3 +1178,28 @@ void BinObjMgt_Persistent::inverseShortRealData
     }
   }
 }
+
+//=======================================================================
+//function : GetOStream
+//purpose  : Gets the stream for and enables direct writing
+//=======================================================================
+
+Standard_OStream* BinObjMgt_Persistent::GetOStream()
+{
+  Write (*myOStream, Standard_True); // finishes already stored data save
+  myStreamStart = new BinObjMgt_Position (*myOStream);
+  myStreamStart->WriteSize (*myOStream);
+  myDirectWritingIsEnabled = Standard_True;
+  return myOStream;
+}
+
+//=======================================================================
+//function : GetOStream
+//purpose  : Gets the stream for and enables direct writing
+//=======================================================================
+Standard_IStream* BinObjMgt_Persistent::GetIStream()
+{
+  // skip the stream size first
+  myIStream->seekg (sizeof (uint64_t), std::ios_base::cur);
+  return myIStream;
+}
index a43a51de7b2783712f0c22c149222557e30d404b..2919efc00a885953801f5d65ca413114bd510122 100644 (file)
@@ -35,6 +35,7 @@
 #include <BinObjMgt_PInteger.hxx>
 #include <BinObjMgt_PReal.hxx>
 #include <BinObjMgt_PShortReal.hxx>
+#include <BinObjMgt_Position.hxx>
 #include <Standard_OStream.hxx>
 #include <Standard_IStream.hxx>
 #include <Standard_Address.hxx>
@@ -261,13 +262,13 @@ const BinObjMgt_Persistent& operator >> (Standard_GUID& theValue) const
   //! Indicates an error after Get methods or SetPosition
     Standard_Boolean IsError() const;
   Standard_Boolean operator !() const
-{
-  return IsError();
-}
+  {
+    return IsError();
+  }
   
   //! Indicates a good state after Get methods or SetPosition
     Standard_Boolean IsOK() const;
-operator Standard_Boolean () const { return IsOK(); }
+  operator Standard_Boolean () const { return IsOK(); }
   
   //! Initializes me to reuse again
   Standard_EXPORT void Init();
@@ -289,8 +290,9 @@ operator Standard_Boolean () const { return IsOK(); }
   
   //! Stores <me> to the stream.
   //! inline Standard_OStream& operator<< (Standard_OStream&,
-  //! BinObjMgt_Persistent&) is also available
-  Standard_EXPORT Standard_OStream& Write (Standard_OStream& theOS);
+  //! BinObjMgt_Persistent&) is also available.
+  //! If theDirectStream is true, after this data the direct stream data is stored.
+  Standard_EXPORT Standard_OStream& Write (Standard_OStream& theOS, const Standard_Boolean theDirectStream = Standard_False);
   
   //! Retrieves <me> from the stream.
   //! inline Standard_IStream& operator>> (Standard_IStream&,
@@ -300,19 +302,23 @@ operator Standard_Boolean () const { return IsOK(); }
   //! Frees the allocated memory;
   //! This object can be reused after call to Init
   Standard_EXPORT void Destroy();
-~BinObjMgt_Persistent()
-{
-  Destroy();
-}
-
-
-
-
-protected:
-
-
-
+  ~BinObjMgt_Persistent()
+  {
+    Destroy();
+  }
 
+  //! Sets the stream for direct writing
+  Standard_EXPORT void SetOStream (Standard_OStream& theStream) { myOStream = &theStream; }
+  //! Sets the stream for direct reading
+  Standard_EXPORT void SetIStream (Standard_IStream& theStream) { myIStream = &theStream; }
+  //! Gets the stream for and enables direct writing
+  Standard_EXPORT Standard_OStream* GetOStream();
+  //! Gets the stream for and enables direct reading
+  Standard_EXPORT Standard_IStream* GetIStream();
+  //! Returns true if after this record a direct writing to the stream is performed.
+  Standard_EXPORT Standard_Boolean IsDirect() { return myDirectWritingIsEnabled; }
+  //! Returns the start position of the direct writing in the stream
+  Standard_EXPORT Handle(BinObjMgt_Position) StreamStart() { return myStreamStart; }
 
 private:
 
@@ -358,8 +364,10 @@ private:
   Standard_Integer myOffset;
   Standard_Integer mySize;
   Standard_Boolean myIsError;
-
-
+  Standard_OStream* myOStream; ///< stream to write in case direct writing is enabled
+  Standard_IStream* myIStream; ///< stream to write in case direct reading is enabled
+  Standard_Boolean myDirectWritingIsEnabled;
+  Handle(BinObjMgt_Position) myStreamStart; ///< position where the direct writing to the script is started
 };
 
 
index c7c22afc07a7d5d92f300130d9d34be5521bf01f..9ea3282cf69c8cf09c26948b4e71a8da2de8cf85 100644 (file)
@@ -34,6 +34,7 @@ inline void BinObjMgt_Persistent::SetId (const Standard_Integer theId)
 inline void BinObjMgt_Persistent::SetTypeId (const Standard_Integer theTypeId)
 {
   ((Standard_Integer*) myData(1)) [0] = theTypeId;
+  myStreamStart.Nullify();
 }
 
 //=======================================================================
diff --git a/src/BinObjMgt/BinObjMgt_Position.cxx b/src/BinObjMgt/BinObjMgt_Position.cxx
new file mode 100644 (file)
index 0000000..a5a7b8e
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BinObjMgt_Position.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT (BinObjMgt_Position, Standard_Transient)
+
+//=======================================================================
+//function : BinObjMgt_Position
+//purpose  : 
+//=======================================================================
+BinObjMgt_Position::BinObjMgt_Position (Standard_OStream& theStream) :
+  myPosition (theStream.tellp()), mySize(0)
+{}
+
+//=======================================================================
+//function : StoreSize
+//purpose  : 
+//=======================================================================
+void BinObjMgt_Position::StoreSize (Standard_OStream& theStream)
+{
+  mySize = uint64_t (theStream.tellp() - myPosition);
+}
+
+//=======================================================================
+//function : WriteSize
+//purpose  : 
+//=======================================================================
+void BinObjMgt_Position::WriteSize (Standard_OStream& theStream)
+{
+  if (theStream.tellp() != myPosition)
+    theStream.seekp (myPosition);
+#if DO_INVERSE
+  mySize = FSD_BinaryFile::InverseUint64 (mySize);
+#endif
+  theStream.write ((char*)&mySize, sizeof (uint64_t));
+}
diff --git a/src/BinObjMgt/BinObjMgt_Position.hxx b/src/BinObjMgt/BinObjMgt_Position.hxx
new file mode 100644 (file)
index 0000000..d6029ad
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BinObjMgt_Position_HeaderFile
+#define _BinObjMgt_Position_HeaderFile
+
+#include <Standard_Type.hxx>
+
+class BinObjMgt_Position;
+DEFINE_STANDARD_HANDLE (BinObjMgt_Position, Standard_Transient)
+
+//! Stores and manipulates position in the stream.
+class BinObjMgt_Position : public Standard_Transient
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  //! Creates position using the current stream position.
+  Standard_EXPORT BinObjMgt_Position (Standard_OStream& theStream);
+
+  //! Stores the difference between the current position and the stored one.
+  Standard_EXPORT void StoreSize (Standard_OStream& theStream);
+  //! Writes stored size at the stored position. Changes the current stream position.
+  Standard_EXPORT void WriteSize (Standard_OStream& theStream);
+
+  DEFINE_STANDARD_RTTIEXT (BinObjMgt_Position, Standard_Transient)
+
+private:
+  std::streampos myPosition;
+  uint64_t mySize;
+};
+
+#endif // _BinObjMgt_Position_HeaderFile
index 7954116694fdac9a3af385551aa9850369aa6e2d..4683730dcbb0e3cdc4ce7d70f5b8db6fc1a321fc 100755 (executable)
@@ -5,6 +5,8 @@ BinObjMgt_Persistent.hxx
 BinObjMgt_Persistent.lxx
 BinObjMgt_PExtChar.hxx
 BinObjMgt_PInteger.hxx
+BinObjMgt_Position.cxx
+BinObjMgt_Position.hxx
 BinObjMgt_PReal.hxx
 BinObjMgt_PShortReal.hxx
 BinObjMgt_RRelocationTable.cxx
index 32f6a776887d87aed0faba41d7ac4aca82d81dbd..7c5b3b0f40bdfd96b4b6a7dc6fb65051aa3f6c5d 100644 (file)
@@ -42,7 +42,7 @@ Standard_OStream& BinTools::PutInteger(Standard_OStream& OS, const Standard_Inte
 #if DO_INVERSE
       anIntValue = InverseInt (aValue);
 #endif
-  OS.write((char*)&anIntValue, sizeof(Standard_Integer));  
+  OS.write ((char*)&anIntValue, sizeof (Standard_Integer));  
   return OS;
 }
 
@@ -56,9 +56,9 @@ Standard_OStream& BinTools::PutReal (Standard_OStream& theOS,
 {
 #if DO_INVERSE
   const Standard_Real aRValue = InverseReal (theValue);
-  theOS.write((char*)&aRValue, sizeof(Standard_Real));
+  theOS.write ((char*)&aRValue, sizeof (Standard_Real));
 #else
-  theOS.write((char*)&theValue, sizeof(Standard_Real));
+  theOS.write ((char*)&theValue, sizeof (Standard_Real));
 #endif
   return theOS;
 }
@@ -94,6 +94,35 @@ Standard_OStream& BinTools::PutExtChar(Standard_OStream& OS, const Standard_ExtC
   return OS;
 }
 
+//=======================================================================
+//function : PutBools
+//purpose  :
+//=======================================================================
+
+Standard_OStream& BinTools::PutBools (Standard_OStream& OS,
+    const Standard_Boolean theValue1, const Standard_Boolean theValue2, const Standard_Boolean theValue3)
+{
+  Standard_Byte aValue = (theValue1 ? 1 : 0) | (theValue2 ? 2 : 0) | (theValue3 ? 4 : 0);
+  OS.write((char*)&aValue, sizeof(Standard_Byte));
+  return OS;
+}
+
+//=======================================================================
+//function : PutBools
+//purpose  :
+//=======================================================================
+
+Standard_OStream& BinTools::PutBools (Standard_OStream& OS,
+    const Standard_Boolean theValue1, const Standard_Boolean theValue2, const Standard_Boolean theValue3,
+    const Standard_Boolean theValue4, const Standard_Boolean theValue5, const Standard_Boolean theValue6,
+    const Standard_Boolean theValue7)
+{
+  Standard_Byte aValue = (theValue1 ? 1 : 0) | (theValue2 ? 2 : 0) | (theValue3 ? 4 : 0) | (theValue4 ? 8 : 0) |
+    (theValue5 ? 16 : 0) | (theValue6 ? 32 : 0) | (theValue7 ? 64 : 0);
+  OS.write ((char*)&aValue, sizeof(Standard_Byte));
+  return OS;
+}
+
 //=======================================================================
 //function : GetReal
 //purpose  :
@@ -193,7 +222,7 @@ void BinTools::Read (TopoDS_Shape& theShape, Standard_IStream& theStream,
                      const Message_ProgressRange& theRange)
 {
   BinTools_ShapeSet aShapeSet(Standard_True);
-  aShapeSet.Read (theStream, Standard_False, theRange);
+  aShapeSet.Read (theStream, theRange);
   aShapeSet.ReadSubs (theShape, theStream, aShapeSet.NbShapes());
 }
 
index 07ad4655bbbb1c6dbbc85f5b2ae03da169cf4eed..882502f6f725e1f45ae90e1160e67559516b92cf 100644 (file)
@@ -52,6 +52,14 @@ public:
   Standard_EXPORT static Standard_OStream& PutBool (Standard_OStream& OS, const Standard_Boolean theValue);
   
   Standard_EXPORT static Standard_OStream& PutExtChar (Standard_OStream& OS, const Standard_ExtCharacter theValue);
+
+  Standard_EXPORT static Standard_OStream& PutBools (Standard_OStream& OS,
+    const Standard_Boolean theValue1, const Standard_Boolean theValue2, const Standard_Boolean theValue3);
+
+  Standard_EXPORT static Standard_OStream& PutBools (Standard_OStream& OS,
+    const Standard_Boolean theValue1, const Standard_Boolean theValue2, const Standard_Boolean theValue3,
+    const Standard_Boolean theValue4, const Standard_Boolean theValue5, const Standard_Boolean theValue6,
+    const Standard_Boolean theValue7);
   
   Standard_EXPORT static Standard_IStream& GetReal (Standard_IStream& IS, Standard_Real& theValue);
 
diff --git a/src/BinTools/BinTools_IStream.cxx b/src/BinTools/BinTools_IStream.cxx
new file mode 100644 (file)
index 0000000..fe68403
--- /dev/null
@@ -0,0 +1,257 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BinTools_IStream.hxx>
+#include <Storage_StreamTypeMismatchError.hxx>
+
+//=======================================================================
+//function : BinTools_IStream
+//purpose  : 
+//=======================================================================
+BinTools_IStream::BinTools_IStream (Standard_IStream& theStream)
+  : myStream (&theStream), myPosition (theStream.tellg()), myLastType (BinTools_ObjectType_Unknown)
+{}
+
+//=======================================================================
+//function : ReadType
+//purpose  : 
+//=======================================================================
+BinTools_ObjectType BinTools_IStream::ReadType()
+{
+  myLastType = BinTools_ObjectType (myStream->get());
+  myPosition++;
+  return myLastType;
+}
+
+//=======================================================================
+//function : IsReference
+//purpose  : 
+//=======================================================================
+Standard_Boolean BinTools_IStream::IsReference()
+{
+  return myLastType == BinTools_ObjectType_Reference8 || myLastType == BinTools_ObjectType_Reference16 ||
+         myLastType == BinTools_ObjectType_Reference32 || myLastType == BinTools_ObjectType_Reference64;
+}
+
+//=======================================================================
+//function : ReadReference
+//purpose  : 
+//=======================================================================
+uint64_t BinTools_IStream::ReadReference()
+{
+  uint64_t aDelta = 0;
+  uint64_t aCurrentPos = uint64_t (myStream->tellg());
+  switch (myLastType)
+  {
+  case BinTools_ObjectType_Reference8:
+    aDelta = uint64_t (myStream->get());
+    myPosition++;
+    break;
+  case BinTools_ObjectType_Reference16:
+  {
+    uint16_t aDelta16 = 0;
+    myStream->read ((char*)&aDelta16, sizeof (uint16_t));
+    myPosition += 2;
+#if DO_INVERSE
+    aDelta16 = (0 | ((aDelta16 & 0x00FF) << 8)
+      | ((aDelta16 & 0xFF00) >> 8));
+#endif
+    aDelta = uint64_t (aDelta16);
+    break;
+  }
+  case BinTools_ObjectType_Reference32:
+  {
+    uint32_t aDelta32 = 0;
+    myStream->read ((char*)&aDelta32, sizeof (uint32_t));
+    myPosition += 4;
+#if DO_INVERSE
+    aDelta32 = (0 | ((aDelta32 & 0x000000ff) << 24)
+      | ((aDelta32 & 0x0000ff00) << 8)
+      | ((aDelta32 & 0x00ff0000) >> 8)
+      | ((aDelta32 >> 24) & 0x000000ff));
+#endif
+    aDelta = uint64_t (aDelta32);
+    break;
+  }
+  case BinTools_ObjectType_Reference64:
+    myStream->read ((char*)&aDelta, sizeof (uint64_t));
+    myPosition += 8;
+#if DO_INVERSE
+    aDelta = InverseUint64 (aDelta);
+#endif
+    break;
+  default:
+    break;
+  }
+  if (aDelta == 0)
+  {
+    Standard_SStream aMsg;
+    aMsg << "BinTools_Position::ReadReference: invalid reference " << (char)myLastType << std::endl;
+    throw Standard_Failure (aMsg.str().c_str());
+  }
+  return aCurrentPos - aDelta - 1; // add a type-byte
+}
+
+//=======================================================================
+//function : GoTo
+//purpose  : 
+//=======================================================================
+void BinTools_IStream::GoTo (const uint64_t& thePosition)
+{
+  myStream->seekg (std::streampos (thePosition));
+  myPosition = thePosition;
+}
+
+//=======================================================================
+//function : ShapeType
+//purpose  : 
+//=======================================================================
+TopAbs_ShapeEnum BinTools_IStream::ShapeType()
+{
+  return TopAbs_ShapeEnum ((Standard_Byte (myLastType) - Standard_Byte (BinTools_ObjectType_EndShape) - 1) >> 2);
+}
+
+//=======================================================================
+//function : ShapeOrientation
+//purpose  : 
+//=======================================================================
+TopAbs_Orientation BinTools_IStream::ShapeOrientation()
+{
+  return TopAbs_Orientation ((Standard_Byte (myLastType) - Standard_Byte (BinTools_ObjectType_EndShape) - 1) & 3);
+}
+
+//=======================================================================
+//function : operator bool
+//purpose  : 
+//=======================================================================
+BinTools_IStream::operator bool() const
+{
+  return myStream->operator bool();
+}
+
+//=======================================================================
+//function : operator <<
+//purpose  : 
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (Standard_Real& theValue)
+{
+  if (!myStream->read ((char*)&theValue, sizeof (Standard_Real)))
+    throw Storage_StreamTypeMismatchError();
+  myPosition += sizeof (Standard_Real);
+#if DO_INVERSE
+  theValue = InverseReal (theValue);
+#endif
+  return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose  : 
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (Standard_Integer& theValue)
+{
+  if (!myStream->read ((char*)&theValue, sizeof (Standard_Integer)))
+    throw Storage_StreamTypeMismatchError();
+  myPosition += sizeof (Standard_Integer);
+#if DO_INVERSE
+  theValue = InverseInt (theValue);
+#endif
+  return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose  : 
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (gp_Pnt& theValue)
+{
+  Standard_Real aValue;
+  for (int aCoord = 1; aCoord <= 3; aCoord++)
+  {
+    if (!myStream->read ((char*)&aValue, sizeof (Standard_Real)))
+      throw Storage_StreamTypeMismatchError();
+#if DO_INVERSE
+    aValue = InverseReal (aValue);
+#endif
+    theValue.SetCoord (aCoord, aValue);
+  }
+  myPosition += 3 * sizeof (Standard_Real);
+  return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose  : 
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (Standard_Byte& theValue)
+{
+  myStream->read ((char*)&theValue, sizeof (Standard_Byte));
+  myPosition += sizeof (Standard_Byte);
+  return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose  : 
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (Standard_ShortReal& theValue)
+{
+  myStream->read ((char*)&theValue, sizeof (Standard_ShortReal));
+  myPosition += sizeof (Standard_ShortReal);
+  return *this;
+}
+
+//=======================================================================
+//function : operator <<
+//purpose  : 
+//=======================================================================
+BinTools_IStream& BinTools_IStream::operator >> (gp_Trsf& theValue)
+{
+  Standard_Real aV1[3], aV2[3], aV3[3], aV[3];
+  *this >> aV1[0] >> aV1[1] >> aV1[2] >> aV[0];
+  *this >> aV2[0] >> aV2[1] >> aV2[2] >> aV[1];
+  *this >> aV3[0] >> aV3[1] >> aV3[2] >> aV[2];
+  theValue.SetValues (aV1[0], aV1[1], aV1[2], aV[0],
+                      aV2[0], aV2[1], aV2[2], aV[1],
+                      aV3[0], aV3[1], aV3[2], aV[2]);
+  return *this;
+}
+
+//=======================================================================
+//function : ReadBools
+//purpose  : 
+//=======================================================================
+void BinTools_IStream::ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3)
+{
+  Standard_Byte aByte = ReadByte();
+  theBool1 = (aByte & 1) == 1;
+  theBool2 = (aByte & 2) == 2;
+  theBool3 = (aByte & 4) == 4;
+}
+
+//=======================================================================
+//function : ReadBools
+//purpose  : 
+//=======================================================================
+void BinTools_IStream::ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3,
+  Standard_Boolean& theBool4, Standard_Boolean& theBool5, Standard_Boolean& theBool6, Standard_Boolean& theBool7)
+{
+  Standard_Byte aByte = ReadByte();
+  theBool1 = (aByte & 1) == 1;
+  theBool2 = (aByte & 2) == 2;
+  theBool3 = (aByte & 4) == 4;
+  theBool4 = (aByte & 8) == 8;
+  theBool5 = (aByte & 16) == 16;
+  theBool6 = (aByte & 32) == 32;
+  theBool7 = (aByte & 64) == 64;
+}
diff --git a/src/BinTools/BinTools_IStream.hxx b/src/BinTools/BinTools_IStream.hxx
new file mode 100644 (file)
index 0000000..319005b
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BinTools_IStream_HeaderFile
+#define _BinTools_IStream_HeaderFile
+
+#include <BinTools.hxx>
+#include <BinTools_ObjectType.hxx>
+#include <TopAbs_ShapeEnum.hxx>
+#include <TopAbs_Orientation.hxx>
+#include <gp_Pnt.hxx>
+
+//! Substitution of IStream for shape reader for fast management of position in the file (get and go)
+//! and operation on all reading types.
+class BinTools_IStream
+{
+public:
+
+  //! Creates IStream using the current stream IStream.
+  Standard_EXPORT BinTools_IStream (Standard_IStream& theStream);
+
+  //! Reads and returns the type.
+  Standard_EXPORT BinTools_ObjectType ReadType();
+  //! Returns the last read type.
+  Standard_EXPORT const BinTools_ObjectType& LastType() { return myLastType; }
+  //! Returns the shape type by the last retrieved type.
+  Standard_EXPORT TopAbs_ShapeEnum ShapeType();
+  //! Returns the shape orientation by the last retrieved type.
+  Standard_EXPORT TopAbs_Orientation ShapeOrientation();
+
+  //! Returns the current position in the stream.
+  Standard_EXPORT uint64_t Position() { return myPosition; }
+  //! Moves the current stream position to the given one.
+  Standard_EXPORT void GoTo (const uint64_t& thePosition);
+
+  //! Returns true if the last restored type is one of a reference
+  Standard_EXPORT Standard_Boolean IsReference();
+  //! Reads a reference IStream using the last restored type.
+  Standard_EXPORT uint64_t ReadReference();
+  //! Returns the original IStream.
+  Standard_EXPORT Standard_IStream& Stream() { return *myStream; }
+  //! Makes up to date the myPosition because myStream was used outside and position is changed.
+  Standard_EXPORT void UpdatePosition() { myPosition = uint64_t (myStream->tellg()); }
+
+  //! Returns false if stream reading is failed.
+  Standard_EXPORT operator bool() const;
+  //! Reads real value from the stream.
+  Standard_EXPORT Standard_Real ReadReal() { Standard_Real aValue; *this >> aValue; return aValue; }
+  Standard_EXPORT BinTools_IStream& operator >> (Standard_Real& theValue);
+  //! Reads integer value from the stream.
+  Standard_EXPORT Standard_Integer ReadInteger() { Standard_Integer aValue; *this >> aValue; return aValue; }
+  Standard_EXPORT BinTools_IStream& operator >> (Standard_Integer& theValue);
+  //! Reads point coordinates value from the stream.
+  Standard_EXPORT gp_Pnt ReadPnt() { gp_Pnt aValue; *this >> aValue; return aValue; }
+  Standard_EXPORT BinTools_IStream& operator >> (gp_Pnt& theValue);
+  //! Reads byte value from the stream.
+  Standard_EXPORT Standard_Byte ReadByte() { Standard_Byte aValue; *this >> aValue; return aValue; }
+  Standard_EXPORT BinTools_IStream& operator >> (Standard_Byte& theValue);
+  //! Reads boolean value from the stream (stored as one byte).
+  Standard_EXPORT Standard_Boolean ReadBool() { return ReadByte() != 0; }
+  Standard_EXPORT BinTools_IStream& operator >> (Standard_Boolean& theValue) { theValue = ReadByte() != 0; return *this; }
+  //! Reads short real value from the stream.
+  Standard_EXPORT Standard_ShortReal ReadShortReal() { Standard_ShortReal aValue; *this >> aValue; return aValue; }
+  Standard_EXPORT BinTools_IStream& operator >> (Standard_ShortReal& theValue);
+  //! Reads transformation value from the stream.
+  Standard_EXPORT BinTools_IStream& operator >> (gp_Trsf& theValue);
+  //! Reads 3 boolean values from one byte
+  Standard_EXPORT void ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3);
+  //! Reads 7 boolean values from one byte
+  Standard_EXPORT void ReadBools (Standard_Boolean& theBool1, Standard_Boolean& theBool2, Standard_Boolean& theBool3,
+    Standard_Boolean& theBool4, Standard_Boolean& theBool5, Standard_Boolean& theBool6, Standard_Boolean& theBool7);
+
+
+private:
+  Standard_IStream* myStream; ///< pointer to the stream
+  uint64_t myPosition; ///< equivalent to tellg returned value for fast access
+  BinTools_ObjectType myLastType; ///< last type that was read
+};
+
+#endif // _BinTools_IStream_HeaderFile
index c269197602b2fb458a9cfed91249790bc2efa5ee..3f16450a145f3d357c141d9fccc1d675114ad49a 100644 (file)
@@ -57,7 +57,7 @@ static Standard_IStream& operator >>(Standard_IStream& IS, gp_Trsf& T)
 //function : operator << (gp_Trsf& T)
 //purpose  : 
 //=======================================================================
-static Standard_OStream& operator <<(Standard_OStream& OS,const gp_Trsf& T)
+Standard_OStream& operator <<(Standard_OStream& OS,const gp_Trsf& T)
 {
   gp_XYZ V = T.TranslationPart();
   gp_Mat M = T.VectorialPart();
index d28d4aebbbdf2cc0fceab2f0f9659317f380fc28..b00d598f05b200d2e07ed5bed7005940d89b223a 100644 (file)
@@ -27,6 +27,8 @@
 class Standard_OutOfRange;
 class TopLoc_Location;
 
+//! Operator for writing transformation into the stream
+Standard_OStream& operator << (Standard_OStream& OS, const gp_Trsf& T);
 
 //! The class LocationSet stores a set of location in
 //! a relocatable state.
@@ -68,9 +70,6 @@ public:
   //! is first cleared.
   Standard_EXPORT void Read (Standard_IStream& IS);
 
-
-
-
 protected:
 
 
diff --git a/src/BinTools/BinTools_ObjectType.hxx b/src/BinTools/BinTools_ObjectType.hxx
new file mode 100644 (file)
index 0000000..5db8177
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BinTools_ObjectType_HeaderFile
+#define _BinTools_ObjectType_HeaderFile
+
+//! Enumeration defining objects identifiers in the shape read/write format.
+enum BinTools_ObjectType
+{
+  BinTools_ObjectType_Unknown = 0,
+  BinTools_ObjectType_Reference8,   //!< 8-bits reference
+  BinTools_ObjectType_Reference16,  //!< 16-bits reference
+  BinTools_ObjectType_Reference32,  //!< 32-bits reference
+  BinTools_ObjectType_Reference64,  //!< 64-bits reference
+  BinTools_ObjectType_Location,
+  BinTools_ObjectType_SimpleLocation,
+  BinTools_ObjectType_EmptyLocation,
+  BinTools_ObjectType_LocationEnd,
+  BinTools_ObjectType_Curve,
+  BinTools_ObjectType_EmptyCurve,
+  BinTools_ObjectType_Curve2d,
+  BinTools_ObjectType_EmptyCurve2d,
+  BinTools_ObjectType_Surface,
+  BinTools_ObjectType_EmptySurface,
+  BinTools_ObjectType_Polygon3d,
+  BinTools_ObjectType_EmptyPolygon3d,
+  BinTools_ObjectType_PolygonOnTriangulation,
+  BinTools_ObjectType_EmptyPolygonOnTriangulation,
+  BinTools_ObjectType_Triangulation,
+  BinTools_ObjectType_EmptyTriangulation,
+  BinTools_ObjectType_EmptyShape = 198, //!< identifier of the null shape
+  BinTools_ObjectType_EndShape = 199, //!< identifier of the shape record end
+  // here is the space for TopAbs_ShapeEnum+Orientation types
+};
+
+#endif // _BinTools_ObjectType_HeaderFile
diff --git a/src/BinTools/BinTools_Position.cxx b/src/BinTools/BinTools_Position.cxx
new file mode 100644 (file)
index 0000000..ef9e803
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BinTools_Position.hxx>
+
+//=======================================================================
+//function : BinTools_Position
+//purpose  : 
+//=======================================================================
+BinTools_Position::BinTools_Position (Standard_OStream& theStream) :
+  myOStream (&theStream), myPosition (theStream.tellp())
+{}
+
+//=======================================================================
+//function : WriteReference
+//purpose  : 
+//=======================================================================
+void BinTools_Position::WriteReference() const
+{
+  uint64_t aDelta = uint64_t (myOStream->tellp()) - myPosition;
+  if (aDelta <= 0xFF)
+  {
+    *myOStream << (Standard_Byte)BinTools_ObjectType_Reference8;
+    *myOStream << (Standard_Byte)aDelta;
+  }
+  else if (aDelta <= 0xFFFF)
+  {
+    *myOStream << (Standard_Byte)BinTools_ObjectType_Reference16;
+    uint16_t aDelta16 = uint16_t (aDelta);
+#if DO_INVERSE
+    aDelta16 = (0 | ((aDelta16 & 0x00FF) << 8)
+                  | ((aDelta16 & 0xFF00) >> 8));
+#endif
+    myOStream->write ((char*)&aDelta16, sizeof (uint16_t));
+  }
+  else if (aDelta <= 0xFFFFFFFF)
+  {
+    *myOStream << (Standard_Byte)BinTools_ObjectType_Reference32;
+    uint32_t aDelta32 = uint32_t (aDelta);
+#if DO_INVERSE
+    aDelta32 = (0 | ((aDelta32 & 0x000000ff) << 24)
+                  | ((aDelta32 & 0x0000ff00) << 8)
+                  | ((aDelta32 & 0x00ff0000) >> 8)
+                  | ((aDelta32 >> 24) & 0x000000ff) );
+#endif
+    myOStream->write ((char*)&aDelta32, sizeof (uint32_t));
+  }
+  else
+  {
+    *myOStream << (Standard_Byte)BinTools_ObjectType_Reference64;
+#if DO_INVERSE
+    aDelta = InverseUint64 (aDelta);
+#endif
+    myOStream->write ((char*)&aDelta, sizeof (uint64_t));
+  }
+}
+
+//=======================================================================
+//function : WriteShape
+//purpose  : 
+//=======================================================================
+void BinTools_Position::WriteShape (const TopAbs_ShapeEnum& theType, const TopAbs_Orientation& theOrientation) const
+{
+  Standard_Byte aType = Standard_Byte (BinTools_ObjectType_EndShape) + 1 +   // taking into account that orientation <= 3
+    (Standard_Byte (theType) << 2) + Standard_Byte (theOrientation); // and type <= 8
+  *myOStream << (Standard_Byte)aType;
+}
+
+//=======================================================================
+//function : WriteObject
+//purpose  : 
+//=======================================================================
+void BinTools_Position::WriteObject(const BinTools_ObjectType& theType) const
+{
+  *myOStream << (Standard_Byte)theType;
+}
diff --git a/src/BinTools/BinTools_Position.hxx b/src/BinTools/BinTools_Position.hxx
new file mode 100644 (file)
index 0000000..bb0678e
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BinTools_Position_HeaderFile
+#define _BinTools_Position_HeaderFile
+
+#include <BinTools.hxx>
+#include <BinTools_ObjectType.hxx>
+
+#include <TopAbs_ShapeEnum.hxx>
+#include <TopAbs_Orientation.hxx>
+
+//! Stores and manipulates position in the stream.
+class BinTools_Position
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  //! Creates position using the current stream position.
+  Standard_EXPORT BinTools_Position (Standard_OStream& theStream);
+
+  //! Writes a reference to my position into the stream
+  Standard_EXPORT void WriteReference() const;
+  //! Writes an identifier of shape type and orientation into the stream.
+  Standard_EXPORT void WriteShape (const TopAbs_ShapeEnum& theType, const TopAbs_Orientation& theOrientation) const;
+  //! Writes an identifier of an object into the stream.
+  Standard_EXPORT void WriteObject (const BinTools_ObjectType& theType) const;
+
+private:
+  Standard_OStream* myOStream;
+  std::streampos myPosition;
+};
+
+#endif // _BinTools_Position_HeaderFile
diff --git a/src/BinTools/BinTools_ShapeReader.cxx b/src/BinTools/BinTools_ShapeReader.cxx
new file mode 100644 (file)
index 0000000..0119a3d
--- /dev/null
@@ -0,0 +1,591 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BinTools_ShapeReader.hxx>
+#include <TopoDS.hxx>
+#include <BRep_PointOnCurve.hxx>
+#include <BRep_PointOnCurveOnSurface.hxx>
+#include <BRep_PointOnSurface.hxx>
+#include <BRep_Polygon3D.hxx>
+#include <BRep_Builder.hxx>
+#include <BinTools_CurveSet.hxx>
+#include <BinTools_Curve2dSet.hxx>
+#include <BinTools_SurfaceSet.hxx>
+
+//=======================================================================
+//function : BinTools_ShapeReader
+//purpose  : 
+//=======================================================================
+BinTools_ShapeReader::BinTools_ShapeReader()
+{}
+  
+//=======================================================================
+//function : ~BinTools_ShapeReader
+//purpose  : 
+//=======================================================================
+BinTools_ShapeReader::~BinTools_ShapeReader()
+{}
+
+//=======================================================================
+//function : Clear
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeReader::Clear()
+{
+  BinTools_ShapeSetBase::Clear();
+  myShapePos.Clear();
+  myLocationPos.Clear();
+  myCurvePos.Clear();
+  myCurve2dPos.Clear();
+  mySurfacePos.Clear();
+  myPolygon3dPos.Clear();
+  myPolygonPos.Clear();
+  myTriangulationPos.Clear();
+}
+
+//=======================================================================
+//function : Read
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeReader::Read (Standard_IStream& theStream, TopoDS_Shape& theShape)
+{
+  BinTools_IStream aStream(theStream);
+  theShape = ReadShape(aStream);
+}
+
+//=======================================================================
+//function : ReadShape
+//purpose  : 
+//=======================================================================
+TopoDS_Shape BinTools_ShapeReader::ReadShape (BinTools_IStream& theStream)
+{
+  TopoDS_Shape aResult;
+  uint64_t aPosition = theStream.Position();
+  const BinTools_ObjectType& aType = theStream.ReadType();
+  if (aType == BinTools_ObjectType_EmptyShape || aType == BinTools_ObjectType_EndShape)
+    return aResult;
+
+  if (theStream.IsReference())
+  {
+    uint64_t aRef = theStream.ReadReference();
+    const TopoDS_Shape* aFound = myShapePos.Seek(aRef);
+    if (aFound) // the shape is already retrieved, just add location
+    {
+      aResult = *aFound;
+    }
+    else
+    {
+      uint64_t aCurrent = theStream.Position();
+      theStream.GoTo (aRef); // go to the referenced position
+      aResult = ReadShape (theStream);
+      theStream.GoTo (aCurrent); // returns to the current position
+    }
+    aResult.Location (*ReadLocation (theStream));
+    aResult.Orientation (TopAbs_Orientation (theStream.ReadByte()));
+    return aResult;
+  }
+  // read the shape
+  TopAbs_ShapeEnum aShapeType = theStream.ShapeType();
+  TopAbs_Orientation aShapeOrientation = theStream.ShapeOrientation();
+  const TopLoc_Location* aShapeLocation = ReadLocation (theStream);
+  Standard_Real aTol;
+  static BRep_Builder aBuilder;
+  try {
+    OCC_CATCH_SIGNALS
+      switch (aShapeType) {
+      case TopAbs_VERTEX:
+      {
+        TopoDS_Vertex& aV = TopoDS::Vertex (aResult);
+        // Read the point geometry
+        theStream >> aTol;
+        gp_Pnt aPnt = theStream.ReadPnt();
+        aBuilder.MakeVertex (aV, aPnt, aTol);
+        Handle(BRep_TVertex) aTV = Handle(BRep_TVertex)::DownCast (aV.TShape());
+        BRep_ListOfPointRepresentation& aLpr = aTV->ChangePoints();
+        static TopLoc_Location anEmptyLoc;
+        while (theStream) {
+          Standard_Byte aPrsType = theStream.ReadByte();
+          if (aPrsType == 0) // end of the cycle
+            break;
+          Standard_Real aParam = theStream.ReadReal();
+          Handle(BRep_PointRepresentation) aPR;
+          switch (aPrsType) {
+          case 1:
+          {
+            Handle(Geom_Curve) aCurve = ReadCurve (theStream);
+            if (!aCurve.IsNull())
+              aPR = new BRep_PointOnCurve (aParam, aCurve, anEmptyLoc);
+            break;
+          }
+          case 2:
+          {
+            Handle(Geom2d_Curve) aCurve2d = ReadCurve2d (theStream);
+            Handle(Geom_Surface) aSurface = ReadSurface (theStream);
+            if (!aCurve2d.IsNull() && aSurface.IsNull())
+              aPR = new BRep_PointOnCurveOnSurface (aParam, aCurve2d, aSurface, anEmptyLoc);
+            break;
+          }
+          case 3:
+          {
+            Standard_Real aParam2 = theStream.ReadReal();
+            Handle(Geom_Surface) aSurface = ReadSurface (theStream);
+            if (!aSurface.IsNull())
+              aPR = new BRep_PointOnSurface (aParam, aParam2, aSurface, anEmptyLoc);
+            break;
+          }
+          default:
+          {
+            Standard_SStream aMsg;
+            aMsg << "BinTools_ShapeReader::Read: UnExpected BRep_PointRepresentation = " << aPrsType << std::endl;
+            throw Standard_Failure (aMsg.str().c_str());
+          }
+          }
+          const TopLoc_Location* aPRLoc = ReadLocation (theStream);
+          if (!aPR.IsNull())
+          {
+            aPR->Location (*aPRLoc);
+            aLpr.Append (aPR);
+          }
+        }
+        break;
+      }
+      case TopAbs_EDGE:
+      {
+        TopoDS_Edge& aE = TopoDS::Edge (aResult);
+        aBuilder.MakeEdge(aE);
+        // Read the curve geometry 
+        theStream >> aTol;
+        Standard_Boolean aSameParameter, aSameRange, aDegenerated;
+        theStream.ReadBools (aSameParameter, aSameRange, aDegenerated);
+        aBuilder.SameParameter (aE, aSameParameter);
+        aBuilder.SameRange (aE, aSameRange);
+        aBuilder.Degenerated (aE, aDegenerated);
+        Standard_Real aFirst, aLast;
+        while (theStream) {
+          Standard_Byte aPrsType = theStream.ReadByte(); //{0|1|2|3|4|5|6|7}
+          if (aPrsType == 0)
+            break;
+          switch (aPrsType)
+          {
+          case 1: // -1- Curve 3D
+          {
+            Handle(Geom_Curve) aCurve = ReadCurve (theStream);
+            const TopLoc_Location* aLoc = ReadLocation (theStream);
+            theStream >> aFirst;
+            theStream >> aLast;
+            if (!aCurve.IsNull())
+            {
+              aBuilder.UpdateEdge (aE, aCurve, *aLoc, aTol);
+              aBuilder.Range (aE, aFirst, aLast, Standard_True);
+            }
+            break;
+          }
+          case 2: // -2- Curve on surf
+          case 3: // -3- Curve on closed surf
+          {
+            Standard_Boolean aClosed = (aPrsType == 3);
+            Handle(Geom2d_Curve) aCurve2d_2, aCurve2d_1 = ReadCurve2d (theStream);
+            GeomAbs_Shape aReg = GeomAbs_C0;
+            if (aClosed) {
+              aCurve2d_2 = ReadCurve2d (theStream);
+              aReg = (GeomAbs_Shape)theStream.ReadByte();
+            }
+            Handle(Geom_Surface) aSurface = ReadSurface (theStream);
+            const TopLoc_Location* aLoc = ReadLocation (theStream);
+            // range
+            theStream >> aFirst;
+            theStream >> aLast;
+            if (!aCurve2d_1.IsNull() && (!aClosed || !aCurve2d_2.IsNull()) && !aSurface.IsNull())
+            {
+              if (aClosed)
+              {
+                aBuilder.UpdateEdge (aE, aCurve2d_1, aCurve2d_2, aSurface, *aLoc, aTol);
+                aBuilder.Continuity (aE, aSurface, aSurface, *aLoc, *aLoc, aReg);
+              }
+              else
+                aBuilder.UpdateEdge (aE, aCurve2d_1, aSurface, *aLoc, aTol);
+              aBuilder.Range (aE, aSurface, *aLoc, aFirst, aLast);
+            }
+            break;
+          }
+          case 4: // -4- Regularity
+          {
+            GeomAbs_Shape aReg = (GeomAbs_Shape)theStream.ReadByte();
+            Handle(Geom_Surface) aSurface1 = ReadSurface (theStream);
+            const TopLoc_Location* aLoc1 = ReadLocation (theStream);
+            Handle(Geom_Surface) aSurface2 = ReadSurface (theStream);
+            const TopLoc_Location* aLoc2 = ReadLocation (theStream);
+            if (!aSurface1.IsNull() && !aSurface2.IsNull())
+              aBuilder.Continuity (aE, aSurface1, aSurface2, *aLoc1, *aLoc2, aReg);
+            break;
+          }
+          case 5: // -5- Polygon3D                     
+          {
+            Handle(Poly_Polygon3D) aPolygon = ReadPolygon3d (theStream);
+            const TopLoc_Location* aLoc = ReadLocation (theStream);
+            aBuilder.UpdateEdge (aE, aPolygon, *aLoc);
+            break;
+          }
+          case 6: // -6- Polygon on triangulation
+          case 7: // -7- Polygon on closed triangulation
+          {
+            Standard_Boolean aClosed = (aPrsType == 7);
+            Handle(Poly_PolygonOnTriangulation) aPoly2, aPoly1 = ReadPolygon (theStream);
+            if (aClosed)
+              aPoly2 = ReadPolygon (theStream);
+            Handle(Poly_Triangulation) aTriangulation = ReadTriangulation (theStream);
+            const TopLoc_Location* aLoc = ReadLocation (theStream);
+            if (aClosed)
+              aBuilder.UpdateEdge (aE, aPoly1, aPoly2, aTriangulation, *aLoc);
+            else
+              aBuilder.UpdateEdge (aE, aPoly1, aTriangulation, *aLoc);
+            // range            
+            break;
+          }
+          default:
+          {
+            Standard_SStream aMsg;
+            aMsg << "Unexpected Curve Representation =" << aPrsType << std::endl;
+            throw Standard_Failure (aMsg.str().c_str());
+          }
+
+          }
+        }
+        break;
+      }
+      case TopAbs_WIRE:
+        aBuilder.MakeWire (TopoDS::Wire (aResult));
+        break;
+      case TopAbs_FACE:
+      {
+        TopoDS_Face& aF = TopoDS::Face (aResult);
+        aBuilder.MakeFace (aF);
+        Standard_Boolean aNatRes = theStream.ReadBool();
+        theStream >> aTol;
+        Handle(Geom_Surface) aSurface = ReadSurface (theStream);
+        const TopLoc_Location* aLoc = ReadLocation (theStream);
+        aBuilder.UpdateFace (aF, aSurface, *aLoc, aTol);
+        aBuilder.NaturalRestriction (aF, aNatRes);
+        if (theStream.ReadByte() == 2) // triangulation
+          aBuilder.UpdateFace (aF, ReadTriangulation (theStream));
+        break;
+      }
+      case TopAbs_SHELL:
+        aBuilder.MakeShell (TopoDS::Shell (aResult));
+        break;
+      case TopAbs_SOLID:
+        aBuilder.MakeSolid (TopoDS::Solid (aResult));
+        break;
+      case TopAbs_COMPSOLID:
+        aBuilder.MakeCompSolid (TopoDS::CompSolid (aResult));
+        break;
+      case TopAbs_COMPOUND:
+        aBuilder.MakeCompound (TopoDS::Compound (aResult));
+        break;
+      default:
+      {
+        Standard_SStream aMsg;
+        aMsg << "Unexpected topology type = " << aShapeType << std::endl;
+        throw Standard_Failure (aMsg.str().c_str());
+        break;
+      }
+      }
+  }
+  catch (Standard_Failure const& anException)
+  {
+    Standard_SStream aMsg;
+    aMsg << "EXCEPTION in BinTools_ShapeReader::Read" << std::endl;
+    aMsg << anException << std::endl;
+    throw Standard_Failure (aMsg.str().c_str());
+  }
+  // read flags and subs
+  Standard_Boolean aFree, aMod, aChecked, anOrient, aClosed, anInf, aConv;
+  theStream.ReadBools (aFree, aMod, aChecked, anOrient, aClosed, anInf, aConv);
+  // sub-shapes
+  for(TopoDS_Shape aSub = ReadShape (theStream); !aSub.IsNull(); aSub = ReadShape (theStream))
+    aBuilder.Add (aResult, aSub);
+  aResult.Free (aFree);
+  aResult.Modified (aMod);
+  aResult.Checked (aChecked);
+  aResult.Orientable (anOrient);
+  aResult.Closed (aClosed);
+  aResult.Infinite (anInf);
+  aResult.Convex (aConv);
+  myShapePos.Bind (aPosition, aResult);
+  aResult.Orientation (aShapeOrientation);
+  aResult.Location (*aShapeLocation);
+  return aResult;
+}
+
+//=======================================================================
+//function : ReadLocation
+//purpose  : 
+//=======================================================================
+const TopLoc_Location* BinTools_ShapeReader::ReadLocation (BinTools_IStream& theStream)
+{
+  static const TopLoc_Location* anEmptyLoc = new TopLoc_Location;
+
+  uint64_t aPosition = theStream.Position();
+  const BinTools_ObjectType& aType = theStream.ReadType();
+  if (aType == BinTools_ObjectType_EmptyLocation || aType == BinTools_ObjectType_LocationEnd)
+    return anEmptyLoc;
+  if (theStream.IsReference())
+  {
+    uint64_t aRef = theStream.ReadReference();
+    const TopLoc_Location* aFound = myLocationPos.Seek (aRef);
+    if (aFound) // the location is already retrieved
+      return aFound;
+    uint64_t aCurrent = theStream.Position();
+    theStream.GoTo (aRef); // go to the referenced position
+    const TopLoc_Location* aResult = ReadLocation (theStream);
+    theStream.GoTo (aCurrent); // returns to the current position
+    return aResult;
+  }
+  // read the location directly from the stream
+  TopLoc_Location aLoc;
+  if (aType == BinTools_ObjectType_SimpleLocation)
+  {
+    gp_Trsf aTrsf;
+    theStream >> aTrsf;
+    aLoc = aTrsf;
+  }
+  else if (aType == BinTools_ObjectType_Location)
+  {
+    for(const TopLoc_Location* aNextLoc = ReadLocation (theStream); !aNextLoc->IsIdentity();
+                               aNextLoc = ReadLocation (theStream))
+      aLoc = aNextLoc->Powered (theStream.ReadInteger()) * aLoc;
+  }
+  myLocationPos.Bind (aPosition, aLoc);
+  return myLocationPos.Seek (aPosition);
+}
+
+//=======================================================================
+//function : ReadCurve
+//purpose  : 
+//=======================================================================
+Handle(Geom_Curve) BinTools_ShapeReader::ReadCurve (BinTools_IStream& theStream)
+{
+  Handle(Geom_Curve) aResult;
+  uint64_t aPosition = theStream.Position();
+  theStream.ReadType();
+  if (theStream.IsReference())
+  { // get by reference
+    uint64_t aRef = theStream.ReadReference();
+    const Handle(Geom_Curve)* aFound = myCurvePos.Seek (aRef);
+    if (aFound) // the location is already retrieved
+      return *aFound;
+    uint64_t aCurrent = theStream.Position();
+    theStream.GoTo (aRef); // go to the referenced position
+    aResult = ReadCurve (theStream);
+    theStream.GoTo (aCurrent); // returns to the current position
+  }
+  else if (theStream.LastType() == BinTools_ObjectType_Curve)
+  { // read from the stream
+    BinTools_CurveSet::ReadCurve (theStream.Stream(), aResult);
+    theStream.UpdatePosition();
+    myCurvePos.Bind (aPosition, aResult);
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : ReadCurve2d
+//purpose  : 
+//=======================================================================
+Handle(Geom2d_Curve) BinTools_ShapeReader::ReadCurve2d (BinTools_IStream& theStream)
+{
+  Handle(Geom2d_Curve) aResult;
+  uint64_t aPosition = theStream.Position();
+  theStream.ReadType();
+  if (theStream.IsReference())
+  { // get by reference
+    uint64_t aRef = theStream.ReadReference();
+    const Handle(Geom2d_Curve)* aFound = myCurve2dPos.Seek (aRef);
+    if (aFound) // the location is already retrieved
+      return *aFound;
+    uint64_t aCurrent = theStream.Position();
+    theStream.GoTo (aRef); // go to the referenced position
+    aResult = ReadCurve2d (theStream);
+    theStream.GoTo (aCurrent); // returns to the current position
+  }
+  else if (theStream.LastType() == BinTools_ObjectType_Curve2d)
+  { // read from the stream
+    BinTools_Curve2dSet::ReadCurve2d (theStream.Stream(), aResult);
+    theStream.UpdatePosition();
+    myCurve2dPos.Bind (aPosition, aResult);
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : ReadSurface
+//purpose  : 
+//=======================================================================
+Handle(Geom_Surface) BinTools_ShapeReader::ReadSurface (BinTools_IStream& theStream)
+{
+  Handle(Geom_Surface) aResult;
+  uint64_t aPosition = theStream.Position();
+  theStream.ReadType();
+  if (theStream.IsReference())
+  { // get by reference
+    uint64_t aRef = theStream.ReadReference();
+    const Handle(Geom_Surface)* aFound = mySurfacePos.Seek (aRef);
+    if (aFound) // the location is already retrieved
+      return *aFound;
+    uint64_t aCurrent = theStream.Position();
+    theStream.GoTo (aRef); // go to the referenced position
+    aResult = ReadSurface (theStream);
+    theStream.GoTo (aCurrent); // returns to the current position
+  }
+  else if (theStream.LastType() == BinTools_ObjectType_Surface)
+  { // read from the stream
+    BinTools_SurfaceSet::ReadSurface (theStream.Stream(), aResult);
+    theStream.UpdatePosition();
+    mySurfacePos.Bind (aPosition, aResult);
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : ReadPolygon3d
+//purpose  : 
+//=======================================================================
+Handle(Poly_Polygon3D) BinTools_ShapeReader::ReadPolygon3d (BinTools_IStream& theStream)
+{
+  Handle(Poly_Polygon3D) aResult;
+  uint64_t aPosition = theStream.Position();
+  theStream.ReadType();
+  if (theStream.IsReference())
+  { // get by reference
+    uint64_t aRef = theStream.ReadReference();
+    const Handle(Poly_Polygon3D)* aFound = myPolygon3dPos.Seek (aRef);
+    if (aFound) // the location is already retrieved
+      return *aFound;
+    uint64_t aCurrent = theStream.Position();
+    theStream.GoTo (aRef); // go to the referenced position
+    aResult = ReadPolygon3d (theStream);
+    theStream.GoTo (aCurrent); // returns to the current position
+  }
+  else if (theStream.LastType() == BinTools_ObjectType_Polygon3d)
+  { // read from the stream
+    Standard_Integer aNbNodes = theStream.ReadInteger();
+    Standard_Boolean aHasParameters = theStream.ReadBool();
+    aResult = new Poly_Polygon3D (aNbNodes, aHasParameters);
+    aResult->Deflection (theStream.ReadReal());
+    TColgp_Array1OfPnt& aNodes = aResult->ChangeNodes();
+    for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+      theStream >> aNodes.ChangeValue (aNodeIter);
+    if (aHasParameters)
+    {
+      TColStd_Array1OfReal& aParam = aResult->ChangeParameters();
+      for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+        theStream >> aParam.ChangeValue (aNodeIter);
+    }
+    myPolygon3dPos.Bind (aPosition, aResult);
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : ReadPolygon
+//purpose  : 
+//=======================================================================
+Handle(Poly_PolygonOnTriangulation) BinTools_ShapeReader::ReadPolygon (BinTools_IStream& theStream)
+{
+  Handle(Poly_PolygonOnTriangulation) aResult;
+  uint64_t aPosition = theStream.Position();
+  theStream.ReadType();
+  if (theStream.IsReference())
+  { // get by reference
+    uint64_t aRef = theStream.ReadReference();
+    const Handle(Poly_PolygonOnTriangulation)* aFound = myPolygonPos.Seek (aRef);
+    if (aFound) // the location is already retrieved
+      return *aFound;
+    uint64_t aCurrent = theStream.Position();
+    theStream.GoTo (aRef); // go to the referenced position
+    aResult = ReadPolygon (theStream);
+    theStream.GoTo (aCurrent); // returns to the current position
+  }
+  else if (theStream.LastType() == BinTools_ObjectType_PolygonOnTriangulation)
+  { // read from the stream
+    Standard_Integer aNbNodes = theStream.ReadInteger();
+    aResult = new Poly_PolygonOnTriangulation (aNbNodes, Standard_False);
+    TColStd_Array1OfInteger& aNodes = aResult->ChangeNodes();
+    for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+      theStream >> aNodes.ChangeValue (aNodeIter);
+    aResult->Deflection (theStream.ReadReal());
+    if (theStream.ReadBool())
+    {
+      Handle(TColStd_HArray1OfReal) aParams = new TColStd_HArray1OfReal (1, aNbNodes);
+      for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+        theStream >> aParams->ChangeValue (aNodeIter);
+      aResult->SetParameters (aParams);
+    }
+    myPolygonPos.Bind (aPosition, aResult);
+  }
+  return aResult;
+}
+
+//=======================================================================
+//function : ReadTriangulation
+//purpose  : 
+//=======================================================================
+Handle(Poly_Triangulation) BinTools_ShapeReader::ReadTriangulation (BinTools_IStream& theStream)
+{
+  Handle(Poly_Triangulation) aResult;
+  uint64_t aPosition = theStream.Position();
+  const BinTools_ObjectType& aType = theStream.ReadType();
+  if (theStream.IsReference())
+  { // get by reference
+    uint64_t aRef = theStream.ReadReference();
+    const Handle(Poly_Triangulation)* aFound = myTriangulationPos.Seek (aRef);
+    if (aFound) // the location is already retrieved
+      return *aFound;
+    uint64_t aCurrent = theStream.Position();
+    theStream.GoTo (aRef); // go to the referenced position
+    aResult = ReadTriangulation (theStream);
+    theStream.GoTo (aCurrent); // returns to the current position
+  }
+  else if (aType == BinTools_ObjectType_Triangulation)
+  { // read from the stream
+    Standard_Integer aNbNodes = theStream.ReadInteger();
+    Standard_Integer aNbTriangles = theStream.ReadInteger();
+    Standard_Boolean aHasUV = theStream.ReadBool();
+    aResult = new Poly_Triangulation (aNbNodes, aNbTriangles, aHasUV);
+    aResult->Deflection (theStream.ReadReal());
+    TColgp_Array1OfPnt& aNodes = aResult->ChangeNodes();
+    for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+      theStream >> aNodes.ChangeValue (aNodeIter);
+    if (aHasUV)
+    {
+      TColgp_Array1OfPnt2d& aUVNodes = aResult->ChangeUVNodes();
+      for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+      {
+        gp_XY& anUV = aUVNodes.ChangeValue (aNodeIter).ChangeCoord();
+        theStream >> anUV.ChangeCoord (1);
+        theStream >> anUV.ChangeCoord (2);
+      }
+    }
+    // read the triangles
+    Poly_Array1OfTriangle& aTriangles = aResult->ChangeTriangles();
+    for (Standard_Integer aTriIter = 1; aTriIter <= aNbTriangles; ++aTriIter)
+    {
+      Poly_Triangle& aTri = aTriangles.ChangeValue (aTriIter);
+      theStream >> aTri.ChangeValue (1);
+      theStream >> aTri.ChangeValue (2);
+      theStream >> aTri.ChangeValue (3);
+    }
+    myTriangulationPos.Bind (aPosition, aResult);
+  }
+  return aResult;
+}
diff --git a/src/BinTools/BinTools_ShapeReader.hxx b/src/BinTools/BinTools_ShapeReader.hxx
new file mode 100644 (file)
index 0000000..aab8861
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BinTools_ShapeReader_HeaderFile
+#define _BinTools_ShapeReader_HeaderFile
+
+#include <BinTools_ShapeSetBase.hxx>
+#include <BinTools_IStream.hxx>
+#include <NCollection_DataMap.hxx>
+
+class TopLoc_Location;
+class Geom_Curve;
+class Geom2d_Curve;
+class Geom_Surface;
+class Poly_Polygon3D;
+class Poly_PolygonOnTriangulation;
+class Poly_Triangulation;
+
+
+//! Reads topology from IStream in binary format without grouping of objects by types
+//! and using relative positions in a file as references.
+class BinTools_ShapeReader : public BinTools_ShapeSetBase
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+  
+  //! Initializes a shape reader.
+  Standard_EXPORT BinTools_ShapeReader();
+  
+  Standard_EXPORT virtual ~BinTools_ShapeReader();
+
+  //! Clears the content of the set.
+  Standard_EXPORT virtual void Clear() override;
+  
+  //! Reads the shape from stream using previously restored shapes and objects by references.
+  Standard_EXPORT void Read (Standard_IStream& theStream, TopoDS_Shape& theShape) override;
+
+  //! Reads location from the stream.
+  Standard_EXPORT const TopLoc_Location* ReadLocation (BinTools_IStream& theStream);
+
+private:
+  //! Reads the shape from stream using previously restored shapes and objects by references.
+  TopoDS_Shape ReadShape (BinTools_IStream& theStream);
+  //! Reads curve from the stream.
+  Handle(Geom_Curve) ReadCurve (BinTools_IStream& theStream);
+  //! Reads curve2d from the stream.
+  Handle(Geom2d_Curve) ReadCurve2d (BinTools_IStream& theStream);
+  //! Reads surface from the stream.
+  Handle(Geom_Surface) ReadSurface (BinTools_IStream& theStream);
+  //! Reads ploygon3d from the stream.
+  Handle(Poly_Polygon3D) ReadPolygon3d (BinTools_IStream& theStream);
+  //! Reads polygon on triangulation from the stream.
+  Handle(Poly_PolygonOnTriangulation) ReadPolygon (BinTools_IStream& theStream);
+  //! Reads triangulation from the stream.
+  Handle(Poly_Triangulation) ReadTriangulation (BinTools_IStream& theStream);
+
+  /// position of the shape previously restored
+  NCollection_DataMap<uint64_t, TopoDS_Shape> myShapePos;
+  NCollection_DataMap<uint64_t, TopLoc_Location> myLocationPos;
+  NCollection_DataMap<uint64_t, Handle(Geom_Curve)> myCurvePos;
+  NCollection_DataMap<uint64_t, Handle(Geom2d_Curve)> myCurve2dPos;
+  NCollection_DataMap<uint64_t, Handle(Geom_Surface)> mySurfacePos;
+  NCollection_DataMap<uint64_t, Handle(Poly_Polygon3D)> myPolygon3dPos;
+  NCollection_DataMap<uint64_t, Handle(Poly_PolygonOnTriangulation)> myPolygonPos;
+  NCollection_DataMap<uint64_t, Handle(Poly_Triangulation)> myTriangulationPos;
+};
+
+#endif // _BinTools_ShapeReader_HeaderFile
index bcb4aeb54c1920bd13bc85de7ce838b2d71b404b..0d396cca45bcad603c0fed377ea11dd62b9e7626 100644 (file)
 #include <Message_ProgressRange.hxx>
 
 #include <string.h>
-//#define MDTV_DEB 1
-const char* Version_1  = "Open CASCADE Topology V1 (c)";
-const char* Version_2  = "Open CASCADE Topology V2 (c)";
-const char* Version_3  = "Open CASCADE Topology V3 (c)";
-//=======================================================================
-//function : operator << (gp_Pnt)
-//purpose  : 
-//=======================================================================
 
-static Standard_OStream& operator <<(Standard_OStream& OS, const gp_Pnt P)
-{
-  BinTools::PutReal(OS, P.X());
-  BinTools::PutReal(OS, P.Y());
-  BinTools::PutReal(OS, P.Z());
-  return OS;
-}
 //=======================================================================
 //function : BinTools_ShapeSet
 //purpose  : 
 //=======================================================================
-
-BinTools_ShapeSet::BinTools_ShapeSet(const Standard_Boolean isWithTriangles)
-     :myFormatNb(3), myWithTriangles(isWithTriangles)
+BinTools_ShapeSet::BinTools_ShapeSet (const Standard_Boolean theWithTriangles)
+  : BinTools_ShapeSetBase (theWithTriangles)
 {}
 
 //=======================================================================
@@ -87,24 +71,6 @@ BinTools_ShapeSet::BinTools_ShapeSet(const Standard_Boolean isWithTriangles)
 BinTools_ShapeSet::~BinTools_ShapeSet()
 {}
 
-//=======================================================================
-//function : SetFormatNb
-//purpose  : 
-//=======================================================================
-void BinTools_ShapeSet::SetFormatNb(const Standard_Integer theFormatNb)
-{
-  myFormatNb = theFormatNb;
-}
-
-//=======================================================================
-//function : FormatNb
-//purpose  : 
-//=======================================================================
-Standard_Integer BinTools_ShapeSet::FormatNb() const
-{
-  return myFormatNb;
-}
-
 //=======================================================================
 //function : Clear
 //purpose  : 
@@ -132,19 +98,15 @@ Standard_Integer BinTools_ShapeSet::Add (const TopoDS_Shape& theShape)
   if (theShape.IsNull()) return 0;
   myLocations.Add(theShape.Location());
   TopoDS_Shape aS2 = theShape;
-  aS2.Location(TopLoc_Location());
-
-  const int* anIndex = myShapes.Seek2(aS2);
-  if (!anIndex)
-  {
-    AddShape (aS2);
+  aS2.Location (TopLoc_Location());
+  Standard_Integer anIndex = myShapes.FindIndex (aS2);
+  if (anIndex == 0) {
+    AddShape  (aS2);
     for (TopoDS_Iterator its (aS2, Standard_False, Standard_False); its.More(); its.Next())
       Add (its.Value());
-    int aNewIndex = myShapes.Size() + 1;
-    myShapes.Bind(aNewIndex, aS2);
-    return aNewIndex;
+    anIndex = myShapes.Add (aS2);
   }
-  return *anIndex;
+  return anIndex;
 }
 
 
@@ -153,22 +115,9 @@ Standard_Integer BinTools_ShapeSet::Add (const TopoDS_Shape& theShape)
 //purpose  : 
 //=======================================================================
 
-const TopoDS_Shape& BinTools_ShapeSet::Shape(const Standard_Integer theIndx) 
+const TopoDS_Shape& BinTools_ShapeSet::Shape (const Standard_Integer theIndx)
 {
-  const TopoDS_Shape* aShape = myShapes.Seek1 (theIndx);
-  if (!aShape && myStream)
-  {
-    std::streampos aCurrentPos = myStream->tellg();
-    myStream->seekg(myShapesPositions.Value(theIndx));
-    TopoDS_Shape aNewShape;
-    TopAbs_ShapeEnum T = (TopAbs_ShapeEnum)myStream->get();
-    ReadShape (T, *myStream, aNewShape);
-    ReadFlagsAndSubs (aNewShape, T, *myStream, myShapesPositions.Length());
-    myShapes.Bind(theIndx, aNewShape);
-    myStream->seekg(aCurrentPos);
-    return myShapes.Find1(theIndx);
-  }
-  return *aShape;
+  return myShapes (theIndx);
 }
 
 //=======================================================================
@@ -176,9 +125,9 @@ const TopoDS_Shape& BinTools_ShapeSet::Shape(const Standard_Integer theIndx)
 //purpose  : 
 //=======================================================================
 
-Standard_Integer BinTools_ShapeSet::Index(const TopoDS_Shape& theShape) const
+Standard_Integer BinTools_ShapeSet::Index (const TopoDS_Shape& theShape) const
 {
-  return myShapes.Find2(theShape);
+  return myShapes.FindIndex (theShape);
 }
 
 //=======================================================================
@@ -264,7 +213,7 @@ void BinTools_ShapeSet::AddShape (const TopoDS_Shape& S)
         mySurfaces.Add(CR->Surface2());
         ChangeLocations().Add(CR->Location2());
       }
-      else if (myWithTriangles) { 
+      else if (IsWithTriangles()) { 
         if (CR->IsPolygon3D()) {
           if (!CR->Polygon3D().IsNull()) {
             myPolygons3D.Add(CR->Polygon3D());
@@ -296,8 +245,7 @@ void BinTools_ShapeSet::AddShape (const TopoDS_Shape& S)
     Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(S.TShape());
     if (!TF->Surface().IsNull())  mySurfaces.Add(TF->Surface());
 
-    if (myWithTriangles
-     || TF->Surface().IsNull())
+    if (IsWithTriangles() || TF->Surface().IsNull())
     {
       Handle(Poly_Triangulation) Tr = TF->Triangulation();
       if (!Tr.IsNull()) myTriangulations.Add(Tr);
@@ -340,13 +288,16 @@ void  BinTools_ShapeSet::WriteGeometry (Standard_OStream& OS,
 //=======================================================================
 
 void  BinTools_ShapeSet::Write (Standard_OStream& OS,
-                                const Message_ProgressRange& theRange) const
+                                const Message_ProgressRange& theRange)
 {
 
   // write the copyright
-  if (myFormatNb == 3)
+  if (FormatNb() == BinTools_FormatVersion_VERSION_3)
+  {
     OS << "\n" << Version_3 << "\n";
-  else if (myFormatNb == 2)
+  }
+  else if (FormatNb() == BinTools_FormatVersion_VERSION_2)
+  {
     OS << "\n" << Version_2 << "\n";
   else
     OS << "\n" << Version_1 << "\n";
@@ -378,7 +329,7 @@ void  BinTools_ShapeSet::Write (Standard_OStream& OS,
   // subshapes are written first
   for (i = 1; i <= nbShapes && aPSinner.More(); i++, aPSinner.Next()) {
 
-    const TopoDS_Shape& S = myShapes.Find1(i);
+    const TopoDS_Shape& S = myShapes (i);
     
     // Type
     OS << (Standard_Byte)S.ShapeType();
@@ -411,10 +362,8 @@ void  BinTools_ShapeSet::Write (Standard_OStream& OS,
 //purpose  : 
 //=======================================================================
 void  BinTools_ShapeSet::Read (Standard_IStream& IS,
-                               const Standard_Boolean thePostponeShapes,
                                const Message_ProgressRange& theRange)
 {
-  myPostponed = thePostponeShapes;
   Clear();
 
   // Check the version
@@ -467,26 +416,14 @@ void  BinTools_ShapeSet::Read (Standard_IStream& IS,
   IS >> nbShapes;
   IS.get();//remove lf 
   Message_ProgressScope aPSinner(aPSouter.Next(), "Reading Shapes", nbShapes);
-  for (int i = 1; i <= nbShapes && aPSinner.More(); i++, aPSinner.Next()) {
-
-    if (myPostponed)
-    {
-      std::streampos aCurrentPos = IS.tellg();
-      myShapesPositions.Append (aCurrentPos);
-      TopAbs_ShapeEnum T = (TopAbs_ShapeEnum)IS.get();
-      PassShape (T, IS);
-      PassFlagsAndSubs (IS);
-    }
-    else {
-      TopoDS_Shape S;
-      TopAbs_ShapeEnum T = (TopAbs_ShapeEnum)IS.get();
-      ReadShape (T, IS, S);
-      ReadFlagsAndSubs (S, T, IS, nbShapes);
-      myShapes.Bind(i, S);
-    }
+  for (int i = 1; i <= nbShapes && aPSinner.More(); i++, aPSinner.Next())
+  {
+    TopoDS_Shape S;
+    TopAbs_ShapeEnum T = (TopAbs_ShapeEnum)IS.get();
+    ReadShape (T, IS, S);
+    ReadFlagsAndSubs (S, T, IS, nbShapes);
+    myShapes.Add (S);
   }
-  if (myPostponed)
-    myStream = &IS;
 }
 
 //=======================================================================
@@ -495,7 +432,7 @@ void  BinTools_ShapeSet::Read (Standard_IStream& IS,
 //=======================================================================
 
 void  BinTools_ShapeSet::Write (const TopoDS_Shape& S, 
-                                Standard_OStream& OS)const
+                                Standard_OStream& OS)
 {
   if (S.IsNull()) 
 
@@ -503,13 +440,13 @@ void  BinTools_ShapeSet::Write (const TopoDS_Shape& S,
   else {    
 // {TopAbs_FORWARD, TopAbs_REVERSED, TopAbs_INTERNAL, TopAbs_EXTERNAL} 
     OS << (Standard_Byte) S.Orientation();
-    BinTools::PutInteger(OS, myShapes.Extent() - myShapes.Find2(S.Located(TopLoc_Location())) + 1);
-    BinTools::PutInteger(OS, Locations().Index(S.Location()));
+    BinTools::PutInteger (OS, myShapes.Extent() - myShapes.FindIndex (S.Located (TopLoc_Location())) + 1);
+    BinTools::PutInteger (OS, Locations().Index (S.Location()));
   }    
 }
 
 //=======================================================================
-//function : Read
+//function : ReadFlagsAndSubs
 //purpose  : 
 //=======================================================================
 
@@ -536,8 +473,8 @@ void BinTools_ShapeSet::ReadFlagsAndSubs(TopoDS_Shape& S, const TopAbs_ShapeEnum
 
   S.Free(aFree);
   S.Modified(aMod);
-  if (myFormatNb != BinTools_FormatVersion_VERSION_2
-   && myFormatNb != BinTools_FormatVersion_VERSION_3)
+  if (FormatNb() != BinTools_FormatVersion_VERSION_2 &&
+      FormatNb() != BinTools_FormatVersion_VERSION_3)
   {
     aChecked = false; // force check at reading
   }
@@ -548,13 +485,17 @@ void BinTools_ShapeSet::ReadFlagsAndSubs(TopoDS_Shape& S, const TopAbs_ShapeEnum
   S.Convex (aConv);
   // check
 
-    if (myFormatNb == BinTools_FormatVersion_VERSION_1)
+  if (FormatNb() == BinTools_FormatVersion_VERSION_1)
     if (T == TopAbs_FACE) {
       const TopoDS_Face& F = TopoDS::Face(S);
       BRepTools::Update(F);
     }
 }
 
+//=======================================================================
+//function : ReadSubs
+//purpose  : 
+//=======================================================================
 void BinTools_ShapeSet::ReadSubs(TopoDS_Shape& S, Standard_IStream& IS,
                                  const Standard_Integer nbshapes)
 {
@@ -576,16 +517,6 @@ void BinTools_ShapeSet::ReadSubs(TopoDS_Shape& S, Standard_IStream& IS,
   }
 }
 
-
-void BinTools_ShapeSet::PassFlagsAndSubs(Standard_IStream& IS)
-{
-  IS.ignore(7 * sizeof(Standard_Byte)); // 7 shape flags
-  Standard_Character aChar = '\0';
-  for (IS >> aChar; aChar != '*'; IS >> aChar)
-    if (aChar != '*')
-      IS.ignore(2 * sizeof(Standard_Integer)); // sub-shape and its location indices
-}
-
 //=======================================================================
 //function : ReadGeometry
 //purpose  : 
@@ -731,7 +662,8 @@ void BinTools_ShapeSet::WriteShape (const TopoDS_Shape& S,
          BinTools::PutReal(OS, last);
 
         // Write UV Points for higher performance
-         if (FormatNb() >= 2)
+         if (FormatNb() == BinTools_FormatVersion_VERSION_2
+          || FormatNb() == BinTools_FormatVersion_VERSION_3)
            {
              gp_Pnt2d Pf,Pl;
              if (CR->IsCurveOnClosedSurface()) {
@@ -761,7 +693,7 @@ void BinTools_ShapeSet::WriteShape (const TopoDS_Shape& S,
          
        }
 
-       else if (myWithTriangles) { 
+       else if (IsWithTriangles()) { 
          if (CR->IsPolygon3D()) {
            Handle(BRep_Polygon3D) GC = Handle(BRep_Polygon3D)::DownCast(itrc.Value());
            if (!GC->Polygon3D().IsNull()) {
@@ -811,8 +743,7 @@ void BinTools_ShapeSet::WriteShape (const TopoDS_Shape& S,
                                : 0);
       BinTools::PutInteger (OS, Locations().Index (TF->Location()));
 
-      if (myWithTriangles
-       || TF->Surface().IsNull())
+      if (IsWithTriangles() || TF->Surface().IsNull())
       {
        if (!(TF->Triangulation()).IsNull()) {
          OS << (Standard_Byte) 2;
@@ -833,7 +764,7 @@ void BinTools_ShapeSet::WriteShape (const TopoDS_Shape& S,
 }
 
 //=======================================================================
-//function : ReadGeometry
+//function : ReadShape
 //purpose  : 
 //=======================================================================
 
@@ -874,7 +805,7 @@ void  BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T,
         BRep_ListOfPointRepresentation& lpr = TV->ChangePoints();
         TopLoc_Location L;
         do {
-          if (myFormatNb == BinTools_FormatVersion_VERSION_3) {
+          if (FormatNb() == BinTools_FormatVersion_VERSION_3) {
             val = (Standard_Integer)IS.get();//case {0|1|2|3}
             if (val > 0 && val <= 3)
               BinTools::GetReal(IS, p1);
@@ -1037,7 +968,8 @@ void  BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T,
             BinTools::GetReal(IS, last);
 
             // read UV Points // for XML Persistence higher performance
-            if (FormatNb() >= 2)
+            if (FormatNb() == BinTools_FormatVersion_VERSION_2
+             || FormatNb() == BinTools_FormatVersion_VERSION_3)
             {
               BinTools::GetReal(IS, PfX);
               BinTools::GetReal(IS, PfY);
@@ -1053,8 +985,8 @@ void  BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T,
               break;
 
             if (closed) {
-              if (myFormatNb == BinTools_FormatVersion_VERSION_2
-               || myFormatNb == BinTools_FormatVersion_VERSION_3)
+              if (FormatNb() == BinTools_FormatVersion_VERSION_2
+               || FormatNb() == BinTools_FormatVersion_VERSION_3)
               {
                 myBuilder.UpdateEdge(E, myCurves2d.Curve2d(pc),
                   myCurves2d.Curve2d(pc2),
@@ -1079,8 +1011,8 @@ void  BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T,
             }
             else
             {
-              if (myFormatNb == BinTools_FormatVersion_VERSION_2
-               || myFormatNb == BinTools_FormatVersion_VERSION_3)
+              if (FormatNb() == BinTools_FormatVersion_VERSION_2
+               || FormatNb() == BinTools_FormatVersion_VERSION_3)
               {
                 myBuilder.UpdateEdge(E, myCurves2d.Curve2d(pc),
                   mySurfaces.Surface(s),
@@ -1246,117 +1178,6 @@ void  BinTools_ShapeSet::ReadShape (const TopAbs_ShapeEnum T,
   }
 }
 
-//=======================================================================
-//function : PassShape
-//purpose  : 
-//=======================================================================
-
-void  BinTools_ShapeSet::PassShape (const TopAbs_ShapeEnum T, Standard_IStream& IS)
-{
-  Standard_Integer val;
-
-  switch (T) {
-  case TopAbs_VERTEX:
-    IS.ignore(4 * sizeof(Standard_Real)); // tolerance + 3 coordinates
-    do {
-      if (myFormatNb > 2) {
-        val = (Standard_Integer)IS.get();
-        if (val > 0 && val <= 3)
-          IS.ignore(sizeof(Standard_Real)); // parameter
-      }
-      else {
-        std::streampos aPos = IS.tellg();
-        IS.ignore(sizeof(Standard_Real));
-        val = (Standard_Integer)IS.get();
-        if (val != 1 && val != 2 && val != 3) {
-          IS.seekg(aPos);
-          val = (Standard_Integer)IS.get();
-          if (val > 0 && val <= 3)
-            IS.ignore(sizeof(Standard_Real)); // parameter
-        }
-      }
-      switch (val) {
-      case 0:
-        break;
-      case 1:
-        IS.ignore(sizeof(Standard_Integer)); // index of curve
-        break;
-      case 2:
-        IS.ignore(sizeof(Standard_Integer) * 2); // curve 2d and surface indices
-        break;
-      case 3:
-        IS.ignore(sizeof(Standard_Real) + sizeof(Standard_Integer)); // parameter + surface index
-        break;
-      default:
-      {
-        Standard_SStream aMsg;
-        aMsg << "BinTools_SurfaceSet::ReadGeometry: UnExpected BRep_PointRepresentation = " << val << std::endl;
-        throw Standard_Failure(aMsg.str().c_str());
-      }
-      }
-
-      if (val > 0)
-        IS.ignore(sizeof(Standard_Integer));//Locations index
-    } while (val > 0);
-    break;
-  case TopAbs_EDGE:
-    IS.ignore(sizeof(Standard_Real) + 3); // tolerance + 3 flags
-    do {
-      val = (Standard_Integer)IS.get();
-      switch (val) {
-      case 0:
-        break;
-      case 1:
-        IS.ignore(2 * sizeof(Standard_Integer) + 2 * sizeof(Standard_Real)); // curve and location indices + 2 parameters
-        break;
-      case 2: // -2- Curve on surf
-      case 3: // -3- Curve on closed surf
-        IS.ignore((val == 3 ? 4 : 3) * sizeof(Standard_Integer) + (val == 3 ? 1 : 0) + (FormatNb() >= 2 ? 6 : 2) * sizeof(Standard_Real));
-        break;
-      case 4: // -4- Regularity
-        IS.ignore(1 + 4 * sizeof(Standard_Integer)); // reg byte + surace + location + surface + location indices
-        break;
-      case 5: // -5- Polygon3D                     
-        IS.ignore(2 * sizeof(Standard_Integer)); // polygon + location indices
-        break;
-      case 6: // -6- Polygon on triangulation
-      case 7: // -7- Polygon on closed triangulation
-        IS.ignore((val == 7 ? 4 : 3) * sizeof(Standard_Integer)); // polygon + triangulation + location indices
-        break;
-      default:
-      {
-        Standard_SStream aMsg;
-        aMsg << "Unexpected Curve Representation =" << val << std::endl;
-        throw Standard_Failure(aMsg.str().c_str());
-      }
-      }
-    } while (val > 0);
-    break;
-  case TopAbs_WIRE:
-    break;
-  case TopAbs_FACE:
-    IS.ignore(1 + sizeof(Standard_Real) + 2 * sizeof(Standard_Integer)); // flag + tolerance + surface and location indices
-    if ((Standard_Byte)IS.get() == 2)
-      IS.ignore(sizeof(Standard_Integer)); // triangulation index
-  break;
-  case TopAbs_SHELL:
-    break;
-  case TopAbs_SOLID:
-    break;
-  case TopAbs_COMPSOLID:
-    break;
-  case TopAbs_COMPOUND:
-    break;
-  default:
-  {
-    Standard_SStream aMsg;
-    aMsg << "Unexpected topology type = " << T << std::endl;
-    throw Standard_Failure(aMsg.str().c_str());
-    break;
-  }
-  }
-}
-
 //=======================================================================
 //function : AddShapes
 //purpose  : 
@@ -1368,7 +1189,6 @@ void BinTools_ShapeSet::AddShapes(TopoDS_Shape&       S1,
   myBuilder.Add(S1,S2);
 }
 
-
 //=======================================================================
 //function : WritePolygonOnTriangulation
 //purpose  :
@@ -1739,5 +1559,5 @@ void BinTools_ShapeSet::ReadTriangulation (Standard_IStream& IS,
 
 Standard_Integer  BinTools_ShapeSet::NbShapes() const
 {
-  return myPostponed ? myShapesPositions.Length() : myShapes.Extent();
+  return myShapes.Extent();
 }
index c3e486249f1c67badf3637bdc71d6c64e9b19a4b..279f1b1e4d59b5bcc032bca22201614d227e7715 100644 (file)
 #ifndef _BinTools_ShapeSet_HeaderFile
 #define _BinTools_ShapeSet_HeaderFile
 
-#include <Standard.hxx>
-#include <Standard_DefineAlloc.hxx>
-#include <Standard_Handle.hxx>
+#include <BinTools_ShapeSetBase.hxx>
 
-#include <NCollection_DoubleMap.hxx>
-#include <BinTools_FormatVersion.hxx>
-#include <NCollection_Sequence.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
 #include <BinTools_LocationSet.hxx>
-#include <Standard_Integer.hxx>
 #include <BRep_Builder.hxx>
 #include <BinTools_SurfaceSet.hxx>
 #include <BinTools_CurveSet.hxx>
 #include <BinTools_Curve2dSet.hxx>
 #include <TColStd_IndexedMapOfTransient.hxx>
-#include <Standard_Boolean.hxx>
 #include <Standard_OStream.hxx>
 #include <Standard_IStream.hxx>
-#include <TopAbs_ShapeEnum.hxx>
-#include <TopTools_ShapeMapHasher.hxx>
-#include <TColStd_MapIntegerHasher.hxx>
-
-class TopoDS_Shape;
-class BinTools_LocationSet;
 
 
 //! Writes topology in OStream in binary format
-class BinTools_ShapeSet 
+class BinTools_ShapeSet : public BinTools_ShapeSetBase
 {
 public:
 
@@ -55,22 +43,6 @@ public:
   
   Standard_EXPORT virtual ~BinTools_ShapeSet();
 
-  //! Return true if shape should be stored with triangles.
-  Standard_Boolean IsWithTriangles() const { return myWithTriangles; }
-
-  //! Define if shape will be stored with triangles.
-  //! Ignored (always written) if face defines only triangulation (no surface).
-  void SetWithTriangles (const Standard_Boolean isWithTriangles) { myWithTriangles = isWithTriangles; }
-
-  Standard_EXPORT void SetFormatNb (const Standard_Integer theFormatNb);
-  
-  //! two formats available for the moment:
-  //! First: does not write CurveOnSurface UV Points into the file
-  //! on reading calls Check() method.
-  //! Second: stores CurveOnSurface UV Points.
-  //! On reading format is recognized from Version string.
-  Standard_EXPORT Standard_Integer FormatNb() const;
-  
   //! Clears the content of the set.
   Standard_EXPORT virtual void Clear();
   
@@ -105,7 +77,7 @@ public:
   //! Write the flags, the subshapes.
   Standard_EXPORT virtual void Write
     (Standard_OStream& OS,
-     const Message_ProgressRange& theRange = Message_ProgressRange()) const;
+     const Message_ProgressRange& theRange = Message_ProgressRange());
   
   //! Reads the content of me from the binary stream  <IS>. me
   //! is first cleared.
@@ -121,13 +93,12 @@ public:
   //! Reads the flag, the subshapes.
   Standard_EXPORT virtual void Read
     (Standard_IStream& IS,
-     const Standard_Boolean thePostponeShapes = Standard_False,
      const Message_ProgressRange& theRange = Message_ProgressRange());
   
   //! Writes   on  <OS>   the shape   <S>.    Writes the
   //! orientation, the index of the TShape and the index
   //! of the Location.
-  Standard_EXPORT virtual void Write (const TopoDS_Shape& S, Standard_OStream& OS) const;
+  Standard_EXPORT virtual void Write (const TopoDS_Shape& S, Standard_OStream& OS);
   
   //! Writes the geometry of  me  on the stream <OS> in a
   //! binary format that can be read back by Read.
@@ -150,8 +121,8 @@ public:
   Standard_EXPORT virtual void ReadSubs
   (TopoDS_Shape& S, Standard_IStream& IS, const Standard_Integer NbShapes);
 
-  //! Passes in <IS> a shape flags and sub-shapes indices.
-  Standard_EXPORT virtual void PassFlagsAndSubs(Standard_IStream& IS);
+  //! An empty virtual method for redefinition in shape-reader.
+  Standard_EXPORT virtual void Read (Standard_IStream& /*theStream*/, TopoDS_Shape& /*theShape*/) {};
 
   //! Writes the shape <S> on the stream <OS> in a
   //! binary format that can be read back by Read.
@@ -160,9 +131,6 @@ public:
   //! Reads  a shape of type <T> from the stream <IS> and returns it in <S>.
   Standard_EXPORT virtual void ReadShape (const TopAbs_ShapeEnum T, Standard_IStream& IS, TopoDS_Shape& S);
 
-  //! Passes in the input stream of a shape of type <T>.
-  Standard_EXPORT virtual void PassShape (const TopAbs_ShapeEnum T, Standard_IStream& IS);
-
   //! Stores the shape <S>.
   Standard_EXPORT virtual void AddShape (const TopoDS_Shape& S);
   
@@ -210,12 +178,8 @@ public:
 
 private:
 
-  NCollection_DoubleMap<int, TopoDS_Shape, TColStd_MapIntegerHasher, TopTools_ShapeMapHasher> myShapes; ///< index and its shape (started from 1)
-  NCollection_Sequence<std::streampos> myShapesPositions; ///< positions in the file of the shape start for postponed reading
-  Standard_Boolean myPostponed; ///< postponed reading stores buffer positions, but does not create shapes
-  Standard_IStream* myStream; ///< stream used for postponed reading of shapes
+  TopTools_IndexedMapOfShape myShapes; ///< index and its shape (started from 1)
   BinTools_LocationSet myLocations;
-  Standard_Integer myFormatNb;
   BRep_Builder myBuilder;
   BinTools_SurfaceSet mySurfaces;
   BinTools_CurveSet myCurves;
@@ -224,7 +188,6 @@ private:
   NCollection_IndexedMap<Handle(Poly_Polygon3D), TColStd_MapTransientHasher> myPolygons3D;
   NCollection_IndexedMap<Handle(Poly_Triangulation), TColStd_MapTransientHasher> myTriangulations;
   NCollection_IndexedMap<Handle(Poly_PolygonOnTriangulation), TColStd_MapTransientHasher> myNodes;
-  Standard_Boolean myWithTriangles;
 };
 
 #endif // _BinTools_ShapeSet_HeaderFile
diff --git a/src/BinTools/BinTools_ShapeSetBase.cxx b/src/BinTools/BinTools_ShapeSetBase.cxx
new file mode 100644 (file)
index 0000000..bfe0f73
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BinTools.hxx>
+#include <BinTools_ShapeSetBase.hxx>
+#include <TopoDS_Shape.hxx>
+
+Standard_CString BinTools_ShapeSetBase::Version_1  = "Open CASCADE Topology V1 (c)";
+Standard_CString BinTools_ShapeSetBase::Version_2  = "Open CASCADE Topology V2 (c)";
+Standard_CString BinTools_ShapeSetBase::Version_3  = "Open CASCADE Topology V3 (c)";
+
+//=======================================================================
+//function : operator << (gp_Pnt)
+//purpose  : 
+//=======================================================================
+Standard_OStream& operator << (Standard_OStream& OS, const gp_Pnt P)
+{
+  BinTools::PutReal (OS, P.X());
+  BinTools::PutReal (OS, P.Y());
+  BinTools::PutReal (OS, P.Z());
+  return OS;
+}
+
+//=======================================================================
+//function : BinTools_ShapeSetBase
+//purpose  : 
+//=======================================================================
+
+BinTools_ShapeSetBase::BinTools_ShapeSetBase (const Standard_Boolean theWithTriangles)
+     : myFormatNb (BinTools_FormatVersion_CURRENT), myWithTriangles (theWithTriangles)
+{}
+
+//=======================================================================
+//function : ~BinTools_ShapeSetBase
+//purpose  : 
+//=======================================================================
+
+BinTools_ShapeSetBase::~BinTools_ShapeSetBase()
+{}
+
+//=======================================================================
+//function : SetFormatNb
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeSetBase::SetFormatNb (const Standard_Integer theFormatNb)
+{
+  Standard_ASSERT_RETURN(theFormatNb == BinTools_FormatVersion_VERSION_1 ||
+                         theFormatNb == BinTools_FormatVersion_VERSION_2 ||
+                         theFormatNb == BinTools_FormatVersion_VERSION_3,
+    "Error: unsupported BinTools version.", );
+
+  myFormatNb = theFormatNb;
+}
diff --git a/src/BinTools/BinTools_ShapeSetBase.hxx b/src/BinTools/BinTools_ShapeSetBase.hxx
new file mode 100644 (file)
index 0000000..2a09175
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BinTools_ShapeSetBase_HeaderFile
+#define _BinTools_ShapeSetBase_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <Standard_OStream.hxx>
+#include <Standard_IStream.hxx>
+#include <Message_ProgressRange.hxx>
+#include <BinTools_FormatVersion.hxx>
+
+class TopoDS_Shape;
+class gp_Pnt;
+
+//! Writes to the stream a gp_Pnt data
+Standard_OStream& operator << (Standard_OStream& OS, const gp_Pnt P);
+
+//! A base class for all readers/writers of TopoDS_Shape into/from stream.
+class BinTools_ShapeSetBase
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+  
+  //! A default constructor..
+  //! Parameter <theWithTriangles> is added for XML Persistence
+  Standard_EXPORT BinTools_ShapeSetBase (const Standard_Boolean theWithTriangles = Standard_False);
+  
+  Standard_EXPORT virtual ~BinTools_ShapeSetBase();
+
+  //! Return true if shape should be stored with triangles.
+  Standard_Boolean IsWithTriangles() const { return myWithTriangles; }
+
+  //! Define if shape will be stored with triangles.
+  //! Ignored (always written) if face defines only triangulation (no surface).
+  void SetWithTriangles (const Standard_Boolean theWithTriangles) { myWithTriangles = theWithTriangles; }
+
+  //! Sets the BinTools_FormatVersion.
+  Standard_EXPORT void SetFormatNb (const Standard_Integer theFormatNb);
+
+  //! Returns the BinTools_FormatVersion.
+  Standard_EXPORT Standard_Integer FormatNb() const { return myFormatNb; }
+  
+  //! Clears the content of the set.
+  Standard_EXPORT virtual void Clear() {}
+  
+  //! Writes the content of  me  on the stream <OS> in binary
+  //! format that can be read back by Read.
+  //!
+  //! Writes the locations.
+  //!
+  //! Writes the geometry calling WriteGeometry.
+  //!
+  //! Dumps the shapes from last to first.
+  //! For each shape  :
+  //! Write the type.
+  //! calls WriteGeometry(S).
+  //! Write the flags, the subshapes.
+  Standard_EXPORT virtual void Write
+    (Standard_OStream& /*OS*/, const Message_ProgressRange& /*theRange*/ = Message_ProgressRange()) {}
+  
+  //! Reads the content of me from the binary stream  <IS>. me
+  //! is first cleared.
+  //!
+  //! Reads the locations.
+  //!
+  //! Reads the geometry calling ReadGeometry.
+  //!
+  //! Reads the shapes.
+  //! For each shape
+  //! Reads the type.
+  //! calls ReadGeometry(T,S).
+  //! Reads the flag, the subshapes.
+  Standard_EXPORT virtual void Read
+    (Standard_IStream& /*IS*/, const Message_ProgressRange& /*theRange*/ = Message_ProgressRange()) {}
+  
+  //! Writes   on  <OS>   the shape   <S>.    Writes the
+  //! orientation, the index of the TShape and the index
+  //! of the Location.
+  Standard_EXPORT virtual void Write (const TopoDS_Shape& /*theShape*/, Standard_OStream& /*theStream*/) {}
+  
+  //! An empty virtual method for redefinition in shape-reader.
+  Standard_EXPORT virtual void Read (Standard_IStream& /*theStream*/, TopoDS_Shape& /*theShape*/) {}
+
+  static Standard_CString Version_1;
+  static Standard_CString Version_2;
+  static Standard_CString Version_3;
+
+private:
+
+  Standard_Integer myFormatNb;
+  Standard_Boolean myWithTriangles;
+};
+
+#endif // _BinTools_ShapeSet_HeaderFile
diff --git a/src/BinTools/BinTools_ShapeWriter.cxx b/src/BinTools/BinTools_ShapeWriter.cxx
new file mode 100644 (file)
index 0000000..36222d9
--- /dev/null
@@ -0,0 +1,513 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BinTools_ShapeWriter.hxx>
+#include <BinTools_LocationSet.hxx>
+
+#include <TopoDS.hxx>
+#include <BRep_TEdge.hxx>
+#include <BRep_GCurve.hxx>
+#include <BRep_Polygon3D.hxx>
+#include <BRep_PolygonOnTriangulation.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <BRep_Tool.hxx>
+#include <BRep_TVertex.hxx>
+#include <BRep_PointRepresentation.hxx>
+#include <BRep_TFace.hxx>
+#include <BinTools_CurveSet.hxx>
+#include <BinTools_Curve2dSet.hxx>
+#include <BinTools_SurfaceSet.hxx>
+
+//=======================================================================
+//function : BinTools_ShapeWriter
+//purpose  : 
+//=======================================================================
+BinTools_ShapeWriter::BinTools_ShapeWriter (const Standard_Boolean theWithTriangles)
+  : BinTools_ShapeSetBase (theWithTriangles)
+{}
+  
+//=======================================================================
+//function : ~BinTools_ShapeWriter
+//purpose  : 
+//=======================================================================
+BinTools_ShapeWriter::~BinTools_ShapeWriter()
+{}
+
+//=======================================================================
+//function : Clear
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::Clear()
+{
+  BinTools_ShapeSetBase::Clear();
+  myShapePos.Clear();
+  myLocationPos.Clear();
+  myCurvePos.Clear();
+  myCurve2dPos.Clear();
+  mySurfacePos.Clear();
+  myPolygon3dPos.Clear();
+  myPolygonPos.Clear();
+  myTriangulationPos.Clear();
+}
+  
+//=======================================================================
+//function : Write
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::Write (const TopoDS_Shape& theShape, Standard_OStream& theStream)
+{
+  WriteShape (theStream, theShape);
+}
+
+//=======================================================================
+//function : WriteShape
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::WriteShape (Standard_OStream& theStream, const TopoDS_Shape& theShape)
+{
+  if (theShape.IsNull())
+  {
+    BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyShape);
+    return;
+  }
+  TopoDS_Shape aShape = theShape.Located (TopLoc_Location());
+  const BinTools_Position* anExisting = myShapePos.Seek (aShape);
+  if (anExisting) // shape is already there, so, write reference to it
+  {
+    anExisting->WriteReference();
+    WriteLocation (theStream, theShape.Location());
+    theStream << Standard_Byte (theShape.Orientation ());
+    return;
+  }
+  BinTools_Position aNewPos (theStream);
+  myShapePos.Bind (aShape, aNewPos);
+  aNewPos.WriteShape (aShape.ShapeType(), aShape.Orientation());
+  WriteLocation (theStream, theShape.Location());
+
+  try {
+    OCC_CATCH_SIGNALS
+    switch (aShape.ShapeType())
+    {
+    case TopAbs_VERTEX:
+    {
+      TopoDS_Vertex aV = TopoDS::Vertex (aShape);
+      BinTools::PutReal (theStream, BRep_Tool::Tolerance (aV));
+      gp_Pnt aP = BRep_Tool::Pnt (aV);
+      theStream << aP;
+      Handle(BRep_TVertex) aTV = Handle(BRep_TVertex)::DownCast (aShape.TShape());
+      for(BRep_ListIteratorOfListOfPointRepresentation anIter (aTV->Points()); anIter.More(); anIter.Next())
+      {
+        const Handle(BRep_PointRepresentation)& aPR = anIter.Value();
+        if (aPR->IsPointOnCurve())
+        {
+          theStream << (Standard_Byte)1; // 1
+          BinTools::PutReal (theStream, aPR->Parameter());
+          WriteCurve (theStream, aPR->Curve());
+        }
+        else if (aPR->IsPointOnCurveOnSurface())
+        {
+          theStream << (Standard_Byte)2;// 2
+          BinTools::PutReal (theStream, aPR->Parameter());
+          WriteCurve (theStream, aPR->PCurve());
+          WriteSurface (theStream, aPR->Surface());
+        }
+        else if (aPR->IsPointOnSurface())
+        {
+          theStream << (Standard_Byte)3;// 3
+          BinTools::PutReal (theStream, aPR->Parameter2());
+          BinTools::PutReal (theStream, aPR->Parameter());
+          WriteSurface (theStream, aPR->Surface());
+        }
+        WriteLocation (theStream, aPR->Location());
+      }
+      theStream.put ((Standard_Byte)0);
+    }
+    break;
+    case TopAbs_EDGE:
+    {
+      Handle(BRep_TEdge) aTE = Handle(BRep_TEdge)::DownCast (aShape.TShape());
+      BinTools::PutReal (theStream, aTE->Tolerance());
+      BinTools::PutBools (theStream, aTE->SameParameter(), aTE->SameRange(), aTE->Degenerated());
+      Standard_Real aFirst, aLast;
+      for(BRep_ListIteratorOfListOfCurveRepresentation anIter = aTE->Curves(); anIter.More(); anIter.Next())
+      {
+        const Handle(BRep_CurveRepresentation)& aCR = anIter.Value();
+        if (aCR->IsCurve3D())
+        {
+          if (!aCR->Curve3D().IsNull())
+          {
+            Handle(BRep_GCurve) aGC = Handle(BRep_GCurve)::DownCast (aCR);
+            aGC->Range (aFirst, aLast);
+            theStream << (Standard_Byte)1;//CURVE_3D;
+            WriteCurve (theStream, aCR->Curve3D());
+            WriteLocation (theStream, aCR->Location());
+            BinTools::PutReal (theStream, aFirst);
+            BinTools::PutReal (theStream, aLast);
+          }
+        }
+        else if (aCR->IsCurveOnSurface()) {
+          Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast (aCR);
+          GC->Range (aFirst, aLast);
+          if (!aCR->IsCurveOnClosedSurface())
+            // -2- Curve on surf
+            theStream << (Standard_Byte)2;
+          else
+            // -3- Curve on closed surf
+            theStream << (Standard_Byte)3;
+          WriteCurve (theStream, aCR->PCurve());
+
+          if (aCR->IsCurveOnClosedSurface()) {//+ int|char
+            WriteCurve (theStream, aCR->PCurve2());
+            theStream << (Standard_Byte)aCR->Continuity();
+          }
+          WriteSurface (theStream, aCR->Surface());
+          WriteLocation (theStream, aCR->Location());
+          BinTools::PutReal (theStream, aFirst);
+          BinTools::PutReal (theStream, aLast);
+        }
+        else if (aCR->IsRegularity())
+        {
+          // -4- Regularity
+          theStream << (Standard_Byte)4;
+          theStream << (Standard_Byte)aCR->Continuity();
+          WriteSurface (theStream, aCR->Surface());
+          WriteLocation (theStream, aCR->Location());
+          WriteSurface (theStream, aCR->Surface2());
+          WriteLocation (theStream, aCR->Location2());
+        }
+        else if (IsWithTriangles())
+        {
+          if (aCR->IsPolygon3D())
+          {
+            Handle(BRep_Polygon3D) aGC = Handle(BRep_Polygon3D)::DownCast (aCR);
+            if (!aGC->Polygon3D().IsNull())
+            {
+              // -5- Polygon3D
+              theStream << (Standard_Byte)5;
+              WritePolygon (theStream, aCR->Polygon3D());
+              WriteLocation (theStream, aCR->Location());
+            }
+          }
+          else if (aCR->IsPolygonOnTriangulation())
+          {
+            Handle(BRep_PolygonOnTriangulation) aPT = Handle(BRep_PolygonOnTriangulation)::DownCast (aCR);
+            if (!aCR->IsPolygonOnClosedTriangulation())
+              // -6- Polygon on triangulation
+              theStream << (Standard_Byte)6;
+            else
+              // -7- Polygon on closed triangulation
+              theStream << (Standard_Byte)7;
+            WritePolygon (theStream, aPT->PolygonOnTriangulation());
+
+            if (aCR->IsPolygonOnClosedTriangulation())
+              WritePolygon (theStream, aPT->PolygonOnTriangulation2());
+            // edge triangulation does not need normals
+            WriteTriangulation (theStream, aPT->Triangulation());
+            WriteLocation (theStream, aCR->Location());
+          }
+        }
+      }
+      theStream << (Standard_Byte)0;
+    }
+    break;
+    case TopAbs_FACE:
+    {
+
+      Handle(BRep_TFace) aTF = Handle(BRep_TFace)::DownCast (aShape.TShape());
+      const TopoDS_Face& aF = TopoDS::Face (aShape);
+
+      // Write the surface geometry
+      Standard_Boolean aNatRes = BRep_Tool::NaturalRestriction (aF);
+      BinTools::PutBool (theStream, aNatRes);
+      BinTools::PutReal (theStream, aTF->Tolerance());
+      WriteSurface (theStream, aTF->Surface());
+      WriteLocation (theStream, aTF->Location());
+
+      if (IsWithTriangles() || aTF->Surface().IsNull())
+      {
+        if (!(aTF->Triangulation()).IsNull())
+        {
+          theStream << (Standard_Byte)2;
+          WriteTriangulation (theStream, aTF->Triangulation());
+        }
+        else
+          theStream << (Standard_Byte)1;
+      }
+      else
+        theStream << (Standard_Byte)0;//without triangulation
+    }
+    break;
+  }
+  }
+  catch (Standard_Failure const& anException)
+  {
+    Standard_SStream aMsg;
+    aMsg << "EXCEPTION in BinTools_ShapeWriter::WriteShape" << std::endl;
+    aMsg << anException << std::endl;
+    throw Standard_Failure(aMsg.str().c_str());
+  }
+  BinTools::PutBools (theStream, aShape.Free(), aShape.Modified(), aShape.Checked(),
+    aShape.Orientable(), aShape.Closed(), aShape.Infinite(), aShape.Convex());
+  // process sub-shapes
+  for (TopoDS_Iterator aSub (aShape, Standard_False, Standard_False); aSub.More(); aSub.Next())
+    WriteShape (theStream, aSub.Value());
+  aNewPos.WriteObject (BinTools_ObjectType_EndShape);
+}
+
+//=======================================================================
+//function : WriteLocation
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::WriteLocation (Standard_OStream& theStream, const TopLoc_Location& theLocation)
+{
+  if (theLocation.IsIdentity())
+  {
+    BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyLocation);
+    return;
+  }
+  const BinTools_Position* aLoc = myLocationPos.Seek (theLocation);
+  if (aLoc)
+  {
+    aLoc->WriteReference();
+    return;
+  }
+  BinTools_Position aNewLoc (theStream);
+  try
+  {
+    OCC_CATCH_SIGNALS
+    TopLoc_Location aL2 = theLocation.NextLocation();
+    Standard_Boolean isSimple = aL2.IsIdentity();
+    Standard_Integer aPower = theLocation.FirstPower();
+    TopLoc_Location aL1 = theLocation.FirstDatum();
+    Standard_Boolean elementary = (isSimple && aPower == 1);
+    if (elementary)
+    {
+      aNewLoc.WriteObject (BinTools_ObjectType_SimpleLocation);
+      theStream << theLocation.Transformation();
+    }
+    else
+    {
+      aNewLoc.WriteObject (BinTools_ObjectType_Location);
+      WriteLocation (theStream, aL1);
+      BinTools::PutInteger (theStream, aPower);
+      while (!aL2.IsIdentity()) {
+        aL1 = aL2.FirstDatum();
+        aPower = aL2.FirstPower();
+        aL2 = aL2.NextLocation();
+        WriteLocation (theStream, aL1);
+        BinTools::PutInteger (theStream, aPower);
+      }
+      aNewLoc.WriteObject (BinTools_ObjectType_LocationEnd);
+    }
+    myLocationPos.Bind (theLocation, aNewLoc);
+  }
+  catch (Standard_Failure const& anException) {
+    Standard_SStream aMsg;
+    aMsg << "EXCEPTION in BinTools_ShapeWriter::WriteLocation" << std::endl;
+    aMsg << anException << std::endl;
+    throw Standard_Failure (aMsg.str().c_str());
+  }
+}
+
+//=======================================================================
+//function : WriteCurve
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::WriteCurve (Standard_OStream& theStream, const Handle(Geom_Curve)& theCurve)
+{
+  if (theCurve.IsNull())
+  {
+    BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyCurve);
+    return;
+  }
+  const BinTools_Position* aCurve = myCurvePos.Seek (theCurve);
+  if (aCurve)
+  {
+    aCurve->WriteReference();
+    return;
+  }
+  BinTools_Position aNewCurve (theStream);
+  aNewCurve.WriteObject (BinTools_ObjectType_Curve);
+  BinTools_CurveSet::WriteCurve (theCurve, theStream);
+  myCurvePos.Bind (theCurve, aNewCurve);
+}
+
+//=======================================================================
+//function : WriteCurve
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::WriteCurve (Standard_OStream& theStream, const Handle(Geom2d_Curve)& theCurve)
+{
+  if (theCurve.IsNull())
+  {
+    BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyCurve2d);
+    return;
+  }
+  const BinTools_Position* aCurve = myCurve2dPos.Seek (theCurve);
+  if (aCurve)
+  {
+    aCurve->WriteReference();
+    return;
+  }
+  BinTools_Position aNewCurve (theStream);
+  aNewCurve.WriteObject (BinTools_ObjectType_Curve2d);
+  BinTools_Curve2dSet::WriteCurve2d (theCurve, theStream);
+  myCurve2dPos.Bind (theCurve, aNewCurve);
+}
+
+//=======================================================================
+//function : WriteSurface
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::WriteSurface (Standard_OStream& theStream, const Handle(Geom_Surface)& theSurface)
+{
+  if (theSurface.IsNull())
+  {
+    BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptySurface);
+    return;
+  }
+  const BinTools_Position* aSurface = mySurfacePos.Seek (theSurface);
+  if (aSurface)
+  {
+    aSurface->WriteReference();
+    return;
+  }
+  BinTools_Position aNewSurface (theStream);
+  aNewSurface.WriteObject (BinTools_ObjectType_Surface);
+  BinTools_SurfaceSet::WriteSurface (theSurface, theStream);
+  mySurfacePos.Bind (theSurface, aNewSurface);
+}
+
+//=======================================================================
+//function : WritePolygon
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::WritePolygon (Standard_OStream& theStream, const Handle(Poly_Polygon3D)& thePolygon)
+{
+  if (thePolygon.IsNull())
+  {
+    BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyPolygon3d);
+    return;
+  }
+  const BinTools_Position* aPolygon = myPolygon3dPos.Seek (thePolygon);
+  if (aPolygon)
+  {
+    aPolygon->WriteReference();
+    return;
+  }
+  BinTools_Position aNewPolygon (theStream);
+  aNewPolygon.WriteObject (BinTools_ObjectType_Polygon3d);
+
+  const Standard_Integer aNbNodes = thePolygon->NbNodes();
+  BinTools::PutInteger (theStream, aNbNodes);
+  BinTools::PutBool (theStream, thePolygon->HasParameters());
+  BinTools::PutReal (theStream, thePolygon->Deflection());
+  const TColgp_Array1OfPnt& aNodes = thePolygon->Nodes();
+  for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+    theStream << aNodes.Value (aNodeIter);
+  if (thePolygon->HasParameters())
+  {
+    const TColStd_Array1OfReal& aParam = thePolygon->Parameters();
+    for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+      BinTools::PutReal (theStream, aParam.Value (aNodeIter));
+  }
+
+  myPolygon3dPos.Bind (thePolygon, aNewPolygon);
+}
+
+//=======================================================================
+//function : WritePolygon
+//purpose  : 
+//=======================================================================
+void BinTools_ShapeWriter::WritePolygon (Standard_OStream& theStream,
+                                         const Handle(Poly_PolygonOnTriangulation)& thePolygon)
+{
+  if (thePolygon.IsNull())
+  {
+    BinTools_Position (theStream).WriteObject (BinTools_ObjectType_EmptyPolygonOnTriangulation);
+    return;
+  }
+  const BinTools_Position* aPolygon = myPolygonPos.Seek (thePolygon);
+  if (aPolygon)
+  {
+    aPolygon->WriteReference();
+    return;
+  }
+  BinTools_Position aNewPolygon (theStream);
+  aNewPolygon.WriteObject (BinTools_ObjectType_PolygonOnTriangulation);
+
+  const TColStd_Array1OfInteger& aNodes = thePolygon->Nodes();
+  BinTools::PutInteger (theStream, aNodes.Length());
+  for (Standard_Integer aNodeIter = 1; aNodeIter <= aNodes.Length(); ++aNodeIter)
+    BinTools::PutInteger (theStream, aNodes.Value(aNodeIter));
+  BinTools::PutReal (theStream, thePolygon->Deflection());
+  if (const Handle(TColStd_HArray1OfReal)& aParam = thePolygon->Parameters())
+  {
+    BinTools::PutBool (theStream, Standard_True);
+    for (Standard_Integer aNodeIter = 1; aNodeIter <= aParam->Length(); ++aNodeIter)
+      BinTools::PutReal (theStream, aParam->Value(aNodeIter));
+  }
+  else
+    BinTools::PutBool (theStream, Standard_False);
+
+  myPolygonPos.Bind (thePolygon, aNewPolygon);
+}
+
+void BinTools_ShapeWriter::WriteTriangulation (Standard_OStream& theStream,
+                                               const Handle(Poly_Triangulation)& theTriangulation)
+{
+  if (theTriangulation.IsNull())
+  {
+    BinTools_Position(theStream).WriteObject (BinTools_ObjectType_EmptyTriangulation);
+    return;
+  }
+  const BinTools_Position* aTriangulation = myTriangulationPos.Seek (theTriangulation);
+  if (aTriangulation)
+  {
+    aTriangulation->WriteReference();
+    return;
+  }
+  BinTools_Position aNewTriangulation (theStream);
+  aNewTriangulation.WriteObject (BinTools_ObjectType_Triangulation);
+
+  const Standard_Integer aNbNodes = theTriangulation->NbNodes();
+  const Standard_Integer aNbTriangles = theTriangulation->NbTriangles();
+  BinTools::PutInteger (theStream, aNbNodes);
+  BinTools::PutInteger (theStream, aNbTriangles);
+  BinTools::PutBool (theStream, theTriangulation->HasUVNodes() ? 1 : 0);
+  BinTools::PutReal (theStream, theTriangulation->Deflection());
+  // write the 3d nodes
+  const TColgp_Array1OfPnt& aNodes = theTriangulation->Nodes();
+  for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+    theStream << aNodes.Value (aNodeIter);
+  if (theTriangulation->HasUVNodes())
+  {
+    const TColgp_Array1OfPnt2d& aUVNodes = theTriangulation->UVNodes();
+    for (Standard_Integer aNodeIter = 1; aNodeIter <= aNbNodes; ++aNodeIter)
+    {
+      const gp_Pnt2d aUV = aUVNodes.Value (aNodeIter);
+      BinTools::PutReal (theStream, aUV.X());
+      BinTools::PutReal (theStream, aUV.Y());
+    }
+  }
+  const Poly_Array1OfTriangle& aTriangles = theTriangulation->Triangles();
+  for (Standard_Integer aTriIter = 1; aTriIter <= aNbTriangles; ++aTriIter)
+  {
+    const Poly_Triangle& aTri = aTriangles.Value (aTriIter);
+    BinTools::PutInteger (theStream, aTri.Value (1));
+    BinTools::PutInteger (theStream, aTri.Value (2));
+    BinTools::PutInteger (theStream, aTri.Value (3));
+  }
+  myTriangulationPos.Bind (theTriangulation, aNewTriangulation);
+}
diff --git a/src/BinTools/BinTools_ShapeWriter.hxx b/src/BinTools/BinTools_ShapeWriter.hxx
new file mode 100644 (file)
index 0000000..11b5776
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright (c) 2020 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BinTools_ShapeWriter_HeaderFile
+#define _BinTools_ShapeWriter_HeaderFile
+
+#include <BinTools_ShapeSetBase.hxx>
+#include <BinTools_Position.hxx>
+#include <NCollection_DataMap.hxx>
+#include <TopTools_ShapeMapHasher.hxx>
+
+class TopLoc_Location;
+class Geom_Curve;
+class Geom2d_Curve;
+class Geom_Surface;
+class Poly_Polygon3D;
+class Poly_PolygonOnTriangulation;
+class Poly_Triangulation;
+
+//! Writes topology in OStream in binary format without grouping of objects by types
+//! and using relative positions in a file as references.
+class BinTools_ShapeWriter : public BinTools_ShapeSetBase
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+  
+  //! Builds an empty ShapeSet.
+  //! Parameter <theWithTriangles> is added for XML Persistence
+  Standard_EXPORT BinTools_ShapeWriter (const Standard_Boolean theWithTriangles = Standard_False);
+  
+  Standard_EXPORT virtual ~BinTools_ShapeWriter();
+
+  //! Clears the content of the set.
+  Standard_EXPORT virtual void Clear() override;
+  
+  //! Writes the shape to stream using previously stored shapes and objects to refer them.
+  Standard_EXPORT virtual void Write (const TopoDS_Shape& theShape, Standard_OStream& theStream) override;
+
+  //! Writes location to the stream (all the needed sub-information or reference if it is already used).
+  Standard_EXPORT virtual void WriteLocation (Standard_OStream& theStream, const TopLoc_Location& theLocation);
+
+private:
+  //! Writes shape to the stream (all the needed sub-information or reference if it is already used).
+  virtual void WriteShape (Standard_OStream& theStream, const TopoDS_Shape& theShape);
+  //! Writes curve to the stream (all the needed sub-information or reference if it is already used).
+  void WriteCurve (Standard_OStream& theStream, const Handle(Geom_Curve)& theCurve);
+  //! Writes curve2d to the stream (all the needed sub-information or reference if it is already used).
+  void WriteCurve (Standard_OStream& theStream, const Handle(Geom2d_Curve)& theCurve);
+  //! Writes surface to the stream.
+  void WriteSurface (Standard_OStream& theStream, const Handle(Geom_Surface)& theSurface);
+  //! Writes ploygon3d to the stream.
+  void WritePolygon (Standard_OStream& theStream, const Handle(Poly_Polygon3D)& thePolygon);
+  //! Writes polygon on triangulation to the stream.
+  void WritePolygon (Standard_OStream& theStream, const Handle(Poly_PolygonOnTriangulation)& thePolygon);
+  //! Writes triangulation to the stream.
+  void WriteTriangulation (Standard_OStream& theStream, const Handle(Poly_Triangulation)& theTriangulation);
+
+  /// position of the shape previously stored
+  NCollection_DataMap<TopoDS_Shape, BinTools_Position, TopTools_ShapeMapHasher> myShapePos;
+  NCollection_DataMap<TopLoc_Location, BinTools_Position> myLocationPos;
+  NCollection_DataMap<Handle(Geom_Curve), BinTools_Position> myCurvePos;
+  NCollection_DataMap<Handle(Geom2d_Curve), BinTools_Position> myCurve2dPos;
+  NCollection_DataMap<Handle(Geom_Surface), BinTools_Position> mySurfacePos;
+  NCollection_DataMap<Handle(Poly_Polygon3D), BinTools_Position> myPolygon3dPos;
+  NCollection_DataMap<Handle(Poly_PolygonOnTriangulation), BinTools_Position> myPolygonPos;
+  NCollection_DataMap<Handle(Poly_Triangulation), BinTools_Position> myTriangulationPos;
+};
+
+#endif // _BinTools_ShapeWriter_HeaderFile
index fd4a059d363b472239fe731971d08c4f1614a6ab..2b7455af35b519c32d0dd06985e73eb1fd40fa51 100644 (file)
@@ -4,10 +4,21 @@ BinTools_Curve2dSet.cxx
 BinTools_Curve2dSet.hxx
 BinTools_CurveSet.cxx
 BinTools_CurveSet.hxx
+BinTools_IStream.cxx
+BinTools_IStream.hxx
 BinTools_LocationSet.cxx
 BinTools_LocationSet.hxx
 BinTools_LocationSetPtr.hxx
 BinTools_ShapeSet.cxx
 BinTools_ShapeSet.hxx
+BinTools_ShapeSetBase.cxx
+BinTools_ShapeSetBase.hxx
 BinTools_SurfaceSet.cxx
 BinTools_SurfaceSet.hxx
+BinTools_ObjectType.hxx
+BinTools_Position.hxx
+BinTools_Position.cxx
+BinTools_ShapeReader.hxx
+BinTools_ShapeReader.cxx
+BinTools_ShapeWriter.hxx
+BinTools_ShapeWriter.cxx
index 9a74bb4d89cadb1d4fe7a263ac9fb02b1741e3eb..20d0230fc20f355cc9413b2d964dc884e198b0e0 100644 (file)
@@ -36,6 +36,11 @@ void PCDM_ReaderFilter::Clear()
   mySubTrees.Clear();
 }
 
+PCDM_ReaderFilter::~PCDM_ReaderFilter()
+{
+  ClearTree();
+}
+
 Standard_Boolean PCDM_ReaderFilter::IsPassed (const Handle(Standard_Type)& theAttributeID) const
 {
   return IsPassedAttr(theAttributeID->Name());
@@ -51,12 +56,12 @@ Standard_Boolean PCDM_ReaderFilter::IsPassed (const TCollection_AsciiString& the
 {
   if (mySubTrees.IsEmpty())
     return true;
-  NCollection_List<TCollection_AsciiString>::Iterator anEntry (mySubTrees);
-  for (; anEntry.More(); anEntry.Next()) {
+  for (NCollection_List<TCollection_AsciiString>::Iterator anEntry (mySubTrees); anEntry.More(); anEntry.Next())
+  {
     if (theEntry.StartsWith (anEntry.Value()))
     {
-      if (theEntry.Length() > anEntry.Value().Length() && // case when theEntry="0:10" should not match "0:1"
-        theEntry.Value (anEntry.Value().Length() + 1) != ':')
+      if (theEntry.Length() > anEntry.Value().Length() &&
+          theEntry.Value (anEntry.Value().Length() + 1) != ':')  // case when theEntry="0:10" should not match "0:1"
         continue;
       return true;
     }
@@ -64,7 +69,107 @@ Standard_Boolean PCDM_ReaderFilter::IsPassed (const TCollection_AsciiString& the
   return false;
 }
 
+Standard_Boolean PCDM_ReaderFilter::IsSubPassed (const TCollection_AsciiString& theEntry) const
+{
+  if (mySubTrees.IsEmpty() || theEntry.Length() == 2) // root is always passed if any sub is defined
+    return true;
+  for (NCollection_List<TCollection_AsciiString>::Iterator anEntry (mySubTrees); anEntry.More(); anEntry.Next())
+  {
+    if (theEntry.Length() < anEntry.Value().Length() &&
+        anEntry.Value().Value (theEntry.Length() + 1) == ':' && // case when theEntry="0:1" should not match "0:10"
+        anEntry.Value().StartsWith (theEntry))
+      return true;
+  }
+  return false;
+}
+
 Standard_Boolean PCDM_ReaderFilter::IsPartTree()
 {
   return !(mySubTrees.IsEmpty() || (mySubTrees.Size() == 1 && mySubTrees.First().Length() < 3));
 }
+
+void PCDM_ReaderFilter::StartIteration()
+{
+  myCurrent = &myTree;
+  myCurrentDepth = 0;
+  ClearTree();
+  myTree.Bind(-1, NULL);
+  if (mySubTrees.IsEmpty())
+    return;
+  // create an iteration-tree by the mySubTrees entries
+  for (NCollection_List<TCollection_AsciiString>::Iterator aTreeIter (mySubTrees); aTreeIter.More(); aTreeIter.Next())
+  {
+    TagTree* aMap = &myTree;
+    TCollection_AsciiString aTagStr, anEntry = aTreeIter.Value();
+    for (Standard_Integer aTagIndex = 2; Standard_True; ++aTagIndex) // skip the root tag
+    {
+      aTagStr = anEntry.Token(":", aTagIndex);
+      if (aTagStr.IsEmpty())
+        break;
+      Standard_Integer aTag = aTagStr.IntegerValue();
+      if (aMap->IsBound (aTag))
+      {
+        aMap = (TagTree*)aMap->Find (aTag);
+      }
+      else
+      {
+        TagTree* aNewMap = new TagTree;
+        aNewMap->Bind (-1, aMap); // to be able to iterate up, keep father map in the child
+        aMap->Bind(aTag, aNewMap);
+        aMap = aNewMap;
+      }
+    }
+    aMap->Bind (-2, NULL); // identifier that this node is in subtrees definition
+  }
+}
+
+void PCDM_ReaderFilter::Up()
+{
+  if (myCurrentDepth == 0)
+    myCurrent = (TagTree*)myCurrent->Find(-1);
+  else
+    myCurrentDepth--;
+}
+
+void PCDM_ReaderFilter::Down (const int& theTag)
+{
+  if (myCurrentDepth== 0)
+  {
+    if (myCurrent->IsBound (theTag))
+      myCurrent= (TagTree*)myCurrent->Find (theTag);
+    else
+      ++myCurrentDepth;
+  }
+  else
+    ++myCurrentDepth;
+}
+
+Standard_Boolean PCDM_ReaderFilter::IsPassed() const
+{
+  return myCurrent->IsBound(-2);
+}
+
+Standard_Boolean PCDM_ReaderFilter::IsSubPassed() const
+{
+  return myCurrentDepth == 0;
+}
+
+void PCDM_ReaderFilter::ClearSubTree (const Standard_Address theMap)
+{
+  if (theMap)
+  {
+    TagTree* aMap = (TagTree*)theMap;
+    for (TagTree::Iterator aTagIter (*aMap); aTagIter.More(); aTagIter.Next())
+      if (aTagIter.Key() != -1)
+        ClearSubTree (aTagIter.Value());
+    delete aMap;
+  }
+}
+
+void PCDM_ReaderFilter::ClearTree()
+{
+  for (TagTree::Iterator aTagIter (myTree); aTagIter.More(); aTagIter.Next())
+    if (aTagIter.Key() != -1)
+      ClearSubTree (aTagIter.Value());
+  myTree.Clear();
+}
index b78a5c3933c9dba96d64105472782b69fa195f3d..73b680b3b94600cc7a6eddbbb9ffece00f18351c 100644 (file)
@@ -56,8 +56,11 @@ public:
   //! Creates a filter to append the content of file to open to existing document.
   Standard_EXPORT PCDM_ReaderFilter (const AppendMode theAppend);
 
+  //! Destructor for the filter content
+  Standard_EXPORT ~PCDM_ReaderFilter();
+
   //! Adds skipped attribute by type.
-  Standard_EXPORT void AddSkipped(const Handle(Standard_Type)& theSkipped) { mySkip.Add(theSkipped->Name()); }
+  Standard_EXPORT void AddSkipped (const Handle(Standard_Type)& theSkipped) { mySkip.Add(theSkipped->Name()); }
   //! Adds skipped attribute by type name.
   Standard_EXPORT void AddSkipped (const TCollection_AsciiString& theSkipped) { mySkip.Add (theSkipped); }
 
@@ -78,6 +81,8 @@ public:
   Standard_EXPORT virtual Standard_Boolean IsPassedAttr (const TCollection_AsciiString& theAttributeType) const;
   //! Returns true if content of the label must be read.
   Standard_EXPORT virtual Standard_Boolean IsPassed (const TCollection_AsciiString& theEntry) const;
+  //! Returns true if some sub-label of the given label is passed.
+  Standard_EXPORT virtual Standard_Boolean IsSubPassed (const TCollection_AsciiString& theEntry) const;
   //! Returns true if only part of the document tree will be retrieved.
   Standard_EXPORT virtual Standard_Boolean IsPartTree();
 
@@ -86,17 +91,46 @@ public:
   //! Returns true if appending to the document is performed.
   Standard_EXPORT Standard_Boolean IsAppendMode() { return myAppend != PCDM_ReaderFilter::AppendMode_Forbid; }
 
+  //! Starts the tree iterator. It is used for fast searching of passed labels if the whole tree of labels
+  //! is parsed. So, on each iteration step the methods Up and Down must be called after the iteration start.
+  Standard_EXPORT virtual void StartIteration();
+  //! Iteration to the child label.
+  Standard_EXPORT virtual void Up();
+  //! Iteration to the child with defined tag.
+  Standard_EXPORT virtual void Down (const int& theTag);
+  //! Returns true if content of the currently iterated label must be read.
+  Standard_EXPORT virtual Standard_Boolean IsPassed() const;
+  //! Returns true if some sub-label of the currently iterated label is passed.
+  Standard_EXPORT virtual Standard_Boolean IsSubPassed() const;
+
   DEFINE_STANDARD_RTTIEXT (PCDM_ReaderFilter, Standard_Transient)
 
+private:
+  //! Clears the iteration tree
+  Standard_EXPORT void ClearTree();
+  //! Clears the iteration sub-tree
+  Standard_EXPORT static void ClearSubTree (const Standard_Address theMap);
+
 protected:
-  // Append mode for reading files into existing document
+  //! Append mode for reading files into existing document
   AppendMode myAppend;
-  // Class names of attributes that must be skipped during the read
+  //! Class names of attributes that must be skipped during the read
   NCollection_Map<TCollection_AsciiString> mySkip;
-  // Class names of only attributes to read (if it is not empty, mySkip is unused)
+  //! Class names of only attributes to read (if it is not empty, mySkip is unused)
   NCollection_Map<TCollection_AsciiString> myRead;
-  // Paths to the labels that must be read. If it is empty, read all.
+  //! Paths to the labels that must be read. If it is empty, read all.
   NCollection_List<TCollection_AsciiString> mySubTrees;
+
+  //! Map from tag of a label to sub-tree of this tag. Used for fast browsing the tree
+  //! and compare with entities that must be read.
+  typedef NCollection_DataMap<Standard_Integer, Standard_Address> TagTree;
+  //! Whole tree that correspond to retrieved document.
+  TagTree myTree;
+  //! Pointer to the current node of the iterator.
+  TagTree* myCurrent;
+  //! If a node does not described in the read-entries, the iterator goes inside of this subtree just by
+  //! keeping the depth of iteration.
+  Standard_Integer myCurrentDepth;
 };
 
 #endif // _PCDM_ReaderFilter_HeaderFile
index 3634ee6020af873d6b9d467b95f48421d8e43c81..0f27913322dcea6da9a4afeecd33fa156b804919 100644 (file)
@@ -63,7 +63,10 @@ enum TDocStd_FormatVersion
   TDocStd_FormatVersion_VERSION_10,    //!< OCCT 7.2.0
                                        //!< * BIN: ReadTOC changed to handle 64-bit file length [#0028736]
 
-  TDocStd_FormatVersion_CURRENT = TDocStd_FormatVersion_VERSION_10 //!< The latest version
+  TDocStd_FormatVersion_VERSION_11,    //!< OCCT 7.6.0
+                                       //!< * BIN: New binary format for fast reading part of OCAF document [#0031918]
+
+  TDocStd_FormatVersion_CURRENT = TDocStd_FormatVersion_VERSION_11 //!< The latest version
 };
 
 #endif // _TDocStdFormatVersion_HeaderFile
diff --git a/tests/bugs/caf/bug31918_1 b/tests/bugs/caf/bug31918_1
new file mode 100644 (file)
index 0000000..35e358f
--- /dev/null
@@ -0,0 +1,89 @@
+puts "==========="
+puts "0031918: Application Framework - New binary format for fast reading part of OCAF document"
+puts "==========="
+
+set docname ${imagedir}/doc_${casename}.cbfl
+
+NewDocument D0 BinLOcaf
+UndoLimit D0 10
+
+NewCommand D0
+
+# set an array 1000 values from 100 to 1099
+set values "100 "
+for {set i 101} {$i < 1100} {incr i} {set values "$values $i"}
+
+# set 100 arrays to sub-labels of 0:1 0:2 0:3 and 0:4
+for {set lab 1} {$lab <= 4} {incr lab} {
+  for {set sublab 1} {$sublab <= 100} {incr sublab} {
+   set command "SetIntArray D0 0:$lab:$sublab 0 1 1000 $values"
+   eval $command
+   SetReal D0 0:$lab:$sublab 0.1
+  }
+}
+
+CommitCommand D0
+
+SaveAs D0 ${docname}
+Close D0
+
+set whole_time [lindex [time {
+  Open ${docname} D1
+  Close D1
+} 20] 0]
+puts "Whole document open time $whole_time mcs"
+
+set quater_time [lindex [time {
+  Open ${docname} D2 -read0:2
+  Close D2
+} 20] 0]
+puts "Quater of document open time $quater_time mcs"
+
+# Check that open of quater of the document is at least twice faster than open of whole.
+if { [expr $quater_time * 2] > $whole_time } {
+  puts "Error : loading of quater of the document content too slow relatively to the whole document load"
+}
+
+set four_quaters_time [lindex [time {
+  Open ${docname} D3 -read0:1 -read0:2 -read0:3 -read0:4
+  Close D3
+} 20] 0]
+puts "Four quaters of document open time $four_quaters_time mcs"
+
+# Check that open of four quaters of the document is not too much slower than opening of the whole document.
+if { [expr $four_quaters_time * 0.9] > $whole_time } {
+  puts "Error : loading of four quaters of the document content too slow relatively to the whole document load"
+}
+
+set no_arrays_time [lindex [time {
+  Open ${docname} D4 -skipTDataStd_IntegerArray -read0:2
+}] 0]
+puts "Quater of document without arrays open time $no_arrays_time mcs"
+
+set attrs [Attributes D4 0:2:13]
+if {"${attrs}" != "TDataStd_Real "} {
+  puts "Error : loading of document skipping arrays contains invalid attributes list '${attrs}'"
+}
+
+if {![catch {Attributes D4 0:1:1:13}] || ![catch {Attributes D4 0:1:3:14}] || ![catch {Attributes D4 0:1:4:1}]} {
+  puts "Error : loading of document skipping arrays and sub-trees contains invalid attributes list"
+}
+
+set append_arrays_time [lindex [time {
+  Open ${docname} D4 -append -readTDataStd_IntegerArray -read0:2 -read0:3
+}] 0]
+puts "Half of document arrays open time $append_arrays_time mcs"
+
+set attrs [Attributes D4 0:2:13]
+if {"${attrs}" != "TDataStd_Real TDataStd_IntegerArray "} {
+  puts "Error : loading of document reading arrays separately contains invalid attributes list '${attrs}'"
+}
+set attrs [Attributes D4 0:3:1]
+if {"${attrs}" != "TDataStd_IntegerArray "} {
+  puts "Error : loading of document reading arrays separately contains invalid attributes list on subtree 3 '${attrs}'"
+}
+if {![catch {Attributes D4 0:1:1:13}] || ![catch {Attributes D4 0:1:4:1}]} {
+  puts "Error : loading of document reading arrays separately contains invalid attributes list on 1 and 4 subtrees"
+}
+
+Close D4
diff --git a/tests/bugs/caf/bug31918_2 b/tests/bugs/caf/bug31918_2
new file mode 100644 (file)
index 0000000..9b4eb1b
--- /dev/null
@@ -0,0 +1,123 @@
+puts "==========="
+puts "0031918: Application Framework - New binary format for fast reading part of OCAF document"
+puts "==========="
+
+pload XDE
+
+NewDocument D0 BinOcaf
+
+# creates part-shape by the given sizes
+proc store_part {nx ny dx dy dz entry} {
+  global D0
+  box b1 0 0 0 [expr $nx + .5] [expr $ny + .5] 1
+  box b2 0.5 0.5 0 [expr $nx - .5] [expr $nx - .5] 0.4
+  cut base b1 b2
+
+  set command "compound"
+  for {set x 0} {$x < $nx} {incr x} {
+    for {set y 0} {$y < $ny} {incr y} {
+      pcylinder c${x}_$y 0.25 1.01
+      ttranslate c${x}_$y [expr $x+.75] [expr $y+.75] 0.39
+      set command "$command c${x}_$y"
+    }
+  }
+  eval "$command cc"
+  bop base cc
+  bopfuse part
+  ttranslate part $dx $dy $dz
+  Label D0 $entry
+  SetShape D0 $entry part
+}
+
+store_part 16 16 0 0 0 0:1:1
+
+for {set n 1} {$n < 5} {incr n} {
+  store_part 4 4 $n $n $n 0:2:$n
+  store_part 4 4 [expr 16-4-$n] $n $n 0:2:[expr $n+4]
+  store_part 4 4 $n [expr 16-4-$n] $n 0:2:[expr $n+8]
+  store_part 4 4 [expr 16-4-$n] [expr 16-4-$n] $n 0:2:[expr $n+12]
+}
+store_part 6 6 5 5 5 0:3:1
+store_part 4 4 6 6 6 0:3:2
+GetShape D0 0:3:2 top2
+
+set docname ${imagedir}/doc_${casename}.cbf
+set save_time [lindex [time {
+  SaveAs D0 ${docname}
+}] 0]
+puts "Save time $save_time mcs"
+
+Close D0
+
+set whole_time [lindex [time {
+  Open ${docname} D1
+  Close D1
+} 20] 0]
+puts "Whole document open time $whole_time mcs"
+
+set half_time1 [lindex [time {
+  Open ${docname} D2 -read0:1 -read0:3
+  Close D2
+} 20] 0]
+puts "First half of document open time $half_time1 mcs"
+
+set half_time2 [lindex [time {
+  Open ${docname} D3 -read0:2
+  Close D3
+} 20] 0]
+puts "Second half of document open time $half_time2 mcs"
+
+# Check that open of two halfs of the document separately is not too much slower than open of the whole
+if { [expr ($half_time1 + $half_time2) * 0.9] > $whole_time } {
+  puts "Error : loading of half of the document content is too slow relatively to the whole document load"
+}
+
+Open ${docname} D4 -read0:3:2
+GetShape D4 0:3:2 opened_top2
+checkshape opened_top2
+
+# check shapes are the same before open and after
+if {[string first [whatis top2] [whatis opened_top2]] != 7} {
+  puts "Error : saved and opened shapes are different"
+}
+Open ${docname} D4 -append -read0:1 -read0:2
+GetShape D4 0:1:1 s
+checkshape s
+for {set n 1} {$n < 16} {incr n} {
+  GetShape D4 0:2:$n s
+  checkshape s
+}
+Close D4
+
+set no_shapes_time [lindex [time {
+  Open ${docname} D5 -skipTNaming_NamedShape
+  Close D5
+} 20] 0]
+puts "Document without shapes open time $no_shapes_time mcs"
+
+# Check that open of the document without shapes is much faster than open of the whole
+if { [expr $no_shapes_time * 20] > $whole_time } {
+  puts "Error : loading of the document without shapes is too slow relatively to the whole document load"
+}
+
+# check shapes storage with triangulations
+set length_wo_tirangulation [string length [dump s]]
+vinit
+vdisplay top2 -displaymode 1
+NewDocument D6 BinOcaf
+UndoLimit D6 10
+SetShape D6 0:1 top2
+StoreTriangulation 1
+SaveAs D6 ${docname}
+Close D6
+
+Open ${docname} D7
+GetShape D7 0:1 top3
+Close D7
+
+checkshape top3
+
+set length_with_tirangulation [string length [dump top3]]
+if { [expr $length_with_tirangulation / 7] < $length_wo_tirangulation } {
+  puts "Error : looks like shape stored with triangulation loaded without trianulation"
+}