0032099: Visualization - define OSD_FileSystem class managing opening of file streams CR31500 IR-2021-02-12
authorosa <osa@opencascade.com>
Fri, 5 Feb 2021 14:51:17 +0000 (17:51 +0300)
committerbugmaster <bugmaster@opencascade.com>
Sat, 13 Feb 2021 08:04:19 +0000 (11:04 +0300)
1) Remove unnecessary includes of "Standard_OStream.hxx" file and add it only into files where it is really used.
2) Create the base interface for a file stream provider OSD_FileSystem and its inheritor OSD_CachedFileSystem that keeping last stream to be reused for opening a stream with the same URL.
3) Use OSD_CachedFileSystem object instead of RWGltf_GltfSharedIStream during Gltf reading.

23 files changed:
src/GccEnt/GccEnt.hxx
src/Graphic3d/Graphic3d_Vertex.hxx
src/IGESData/IGESData_IGESDumper.hxx
src/OSD/FILES
src/OSD/OSD_CachedFileSystem.cxx [new file with mode: 0644]
src/OSD/OSD_CachedFileSystem.hxx [new file with mode: 0644]
src/OSD/OSD_FileSystem.cxx [new file with mode: 0644]
src/OSD/OSD_FileSystem.hxx [new file with mode: 0644]
src/OSD/OSD_FileSystemSelector.cxx [new file with mode: 0644]
src/OSD/OSD_FileSystemSelector.hxx [new file with mode: 0644]
src/OSD/OSD_LocalFileSystem.cxx [new file with mode: 0644]
src/OSD/OSD_LocalFileSystem.hxx [new file with mode: 0644]
src/OSD/OSD_StreamBuffer.hxx [new file with mode: 0644]
src/RWGltf/RWGltf_CafReader.cxx
src/RWGltf/RWGltf_PrimitiveArrayReader.cxx
src/RWGltf/RWGltf_PrimitiveArrayReader.hxx
src/Standard/Standard_CString.cxx
src/Standard/Standard_ExtCharacter.hxx
src/Standard/Standard_Mutex.cxx
src/Standard/Standard_Real.cxx
src/Standard/Standard_ShortReal.cxx
src/TopLoc/TopLoc_Location.hxx
src/gp/gp_Mat.hxx

index dbaf7b5..67ba510 100644 (file)
@@ -21,6 +21,7 @@
 #include <Standard.hxx>
 #include <Standard_DefineAlloc.hxx>
 #include <Standard_Handle.hxx>
+#include <Standard_OStream.hxx>
 
 class GccEnt_QualifiedLin;
 class gp_Lin2d;
index 1f5d785..09c92d9 100644 (file)
@@ -21,6 +21,7 @@
 #include <Standard_Macro.hxx>
 #include <Standard_ShortReal.hxx>
 #include <Standard_Real.hxx>
+#include <Standard_OStream.hxx>
 
 //! This class represents a graphical 3D point.
 class Graphic3d_Vertex
index 08b863a..074b809 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <IGESData_SpecificLib.hxx>
 #include <Standard_Integer.hxx>
+#include <Standard_OStream.hxx>
+
 class IGESData_IGESModel;
 class Interface_InterfaceError;
 class IGESData_Protocol;
index d7615db..63dd8a2 100755 (executable)
@@ -1,5 +1,7 @@
 OSD.cxx
 OSD.hxx
+OSD_CachedFileSystem.cxx
+OSD_CachedFileSystem.hxx
 OSD_Chronometer.cxx
 OSD_Chronometer.hxx
 OSD_Directory.cxx
@@ -39,12 +41,18 @@ OSD_FileIterator.cxx
 OSD_FileIterator.hxx
 OSD_FileNode.cxx
 OSD_FileNode.hxx
+OSD_FileSystem.cxx
+OSD_FileSystem.hxx
+OSD_FileSystemSelector.cxx
+OSD_FileSystemSelector.hxx
 OSD_FromWhere.hxx
 OSD_Function.hxx
 OSD_Host.cxx
 OSD_Host.hxx
 OSD_KindFile.hxx
 OSD_LoadMode.hxx
+OSD_LocalFileSystem.cxx
+OSD_LocalFileSystem.hxx
 OSD_LockType.hxx
 OSD_MAllocHook.cxx
 OSD_MAllocHook.hxx
@@ -82,6 +90,7 @@ OSD_SIGQUIT.hxx
 OSD_SIGSEGV.hxx
 OSD_SIGSYS.hxx
 OSD_SingleProtection.hxx
+OSD_StreamBuffer.hxx
 OSD_SysType.hxx
 OSD_Thread.cxx
 OSD_Thread.hxx
diff --git a/src/OSD/OSD_CachedFileSystem.cxx b/src/OSD/OSD_CachedFileSystem.cxx
new file mode 100644 (file)
index 0000000..2002bc3
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (c) 2021 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 <OSD_CachedFileSystem.hxx>
+#include <OSD_OpenFile.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(OSD_CachedFileSystem, OSD_FileSystem)
+
+//=======================================================================
+// function : IsSupportedPath
+// purpose :
+//=======================================================================
+Standard_Boolean OSD_CachedFileSystem::IsSupportedPath (const TCollection_AsciiString& theUrl) const
+{
+  return OSD_FileSystem::DefaultFileSystem()->IsSupportedPath (theUrl);
+}
+
+//=======================================================================
+// function : IsOpenIStream
+// purpose :
+//=======================================================================
+Standard_Boolean OSD_CachedFileSystem::IsOpenIStream (const opencascade::std::shared_ptr<std::istream>& theStream) const
+{
+  return OSD_FileSystem::DefaultFileSystem()->IsOpenIStream (theStream);
+}
+
+//=======================================================================
+// function : OpenIStream
+// purpose :
+//=======================================================================
+opencascade::std::shared_ptr<std::istream> OSD_CachedFileSystem::OpenIStream (const TCollection_AsciiString& theUrl,
+                                                                              const std::ios_base::openmode theParams,
+                                                                              const int64_t theOffset,
+                                                                              const opencascade::std::shared_ptr<std::istream>& /*theOldStream*/)
+{
+  if (myStream.Url != theUrl)
+  {
+    myStream.Url = theUrl;
+    myStream.Reset();
+  }
+  myStream.Stream = OSD_FileSystem::DefaultFileSystem()->OpenIStream (theUrl, theParams, theOffset, myStream.Stream);
+  return myStream.Stream;
+}
+
+//=======================================================================
+// function : OpenStreamBuffer
+// purpose :
+//=======================================================================
+opencascade::std::shared_ptr<std::streambuf> OSD_CachedFileSystem::OpenStreamBuffer (const TCollection_AsciiString& theUrl,
+                                                                                     const std::ios_base::openmode theMode,
+                                                                                     const int64_t theOffset,
+                                                                                     int64_t* theOutBufSize)
+{
+  if (myStream.Url != theUrl)
+  {
+    myStream.Url = theUrl;
+    myStream.Reset();
+  }
+  myStream.StreamBuf = OSD_FileSystem::DefaultFileSystem()->OpenStreamBuffer (theUrl, theMode, theOffset, theOutBufSize);
+  return myStream.StreamBuf;
+}
diff --git a/src/OSD/OSD_CachedFileSystem.hxx b/src/OSD/OSD_CachedFileSystem.hxx
new file mode 100644 (file)
index 0000000..37f4153
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright (c) 2021 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 _OSD_CachedFileSystem_HeaderFile
+#define _OSD_CachedFileSystem_HeaderFile
+
+#include <OSD_FileSystem.hxx>
+
+//! File system keeping last stream created by OSD_FileSystem::DefaultFileSystem() to be reused for opening a stream with the same URL.
+//! Note that as file is kept in opened state, application will need destroying this object to ensure all files being closed.
+//! This interface could be handy in context of reading numerous objects pointing to the same file (at different offset).
+//! Make sure to create a dedicated OSD_CachedFileSystem for each working thread to avoid data races.
+class OSD_CachedFileSystem : public OSD_FileSystem
+{
+  DEFINE_STANDARD_RTTIEXT(OSD_CachedFileSystem, OSD_FileSystem)
+public:
+
+  //! Constructor.
+  OSD_CachedFileSystem() {}
+
+  //! Returns TRUE if URL defines a supported protocol.
+  Standard_EXPORT virtual Standard_Boolean IsSupportedPath (const TCollection_AsciiString& theUrl) const Standard_OVERRIDE;
+
+  //! Returns TRUE if current input stream is opened for reading operations.
+  Standard_EXPORT virtual Standard_Boolean IsOpenIStream (const opencascade::std::shared_ptr<std::istream>& theStream) const Standard_OVERRIDE;
+
+  //! Opens stream for specified file URL for reading operations or returns previously created stream pointing to the same URL.
+  Standard_EXPORT virtual opencascade::std::shared_ptr<std::istream> OpenIStream
+                          (const TCollection_AsciiString& theUrl,
+                           const std::ios_base::openmode theParams,
+                           const int64_t theOffset,
+                           const opencascade::std::shared_ptr<std::istream>& theOldStream) Standard_OVERRIDE;
+
+  //! Opens stream buffer for specified file URL.
+  Standard_EXPORT virtual opencascade::std::shared_ptr<std::streambuf> OpenStreamBuffer
+                          (const TCollection_AsciiString& theUrl,
+                           const std::ios_base::openmode theMode,
+                           const int64_t theOffset = 0,
+                           int64_t* theOutBufSize = NULL) Standard_OVERRIDE;
+
+protected:
+
+  // Auxiliary structure to save shared stream with path to it.
+  struct OSD_CachedStream
+  {
+    TCollection_AsciiString                      Url;
+    opencascade::std::shared_ptr<std::istream>   Stream;
+    opencascade::std::shared_ptr<std::streambuf> StreamBuf;
+
+    void Reset()
+    {
+      Stream.reset();
+      StreamBuf.reset();
+    }
+  };
+
+protected:
+
+  OSD_CachedStream myStream;
+
+};
+
+#endif // _OSD_CachedFileSystem_HeaderFile
diff --git a/src/OSD/OSD_FileSystem.cxx b/src/OSD/OSD_FileSystem.cxx
new file mode 100644 (file)
index 0000000..a0e4f62
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright (c) 2021 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 <OSD_FileSystem.hxx>
+#include <OSD_FileSystemSelector.hxx>
+#include <OSD_LocalFileSystem.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(OSD_FileSystem, Standard_Transient)
+
+//=======================================================================
+// function : createDefaultFileSystem
+// purpose :
+//=======================================================================
+static Handle(OSD_FileSystem) createDefaultFileSystem()
+{
+  Handle(OSD_FileSystemSelector) aSystem = new OSD_FileSystemSelector();
+  aSystem->AddProtocol (new OSD_LocalFileSystem());
+  return aSystem;
+}
+
+//=======================================================================
+// function : OSD_FileSystem
+// purpose :
+//=======================================================================
+OSD_FileSystem::OSD_FileSystem()
+{
+}
+
+//=======================================================================
+// function : ~OSD_FileSystem
+// purpose :
+//=======================================================================
+OSD_FileSystem::~OSD_FileSystem()
+{
+}
+
+//=======================================================================
+// function : DefaultFileSystem
+// purpose :
+//=======================================================================
+const Handle(OSD_FileSystem)& OSD_FileSystem::DefaultFileSystem()
+{
+  static const Handle(OSD_FileSystem) aDefSystem = createDefaultFileSystem();
+  return aDefSystem;
+}
+
+//=======================================================================
+// function : openIStream
+// purpose :
+//=======================================================================
+opencascade::std::shared_ptr<std::istream> OSD_FileSystem::OpenIStream (const TCollection_AsciiString& theUrl,
+                                                                        const std::ios_base::openmode theMode,
+                                                                        const int64_t theOffset,
+                                                                        const opencascade::std::shared_ptr<std::istream>& theOldStream)
+{
+  Standard_ASSERT_RAISE (theOffset >= -1, "Incorrect negative stream position during stream opening");
+
+  opencascade::std::shared_ptr<std::istream> aNewStream;
+  opencascade::std::shared_ptr<OSD_IStreamBuffer> anOldStream = opencascade::std::dynamic_pointer_cast<OSD_IStreamBuffer> (theOldStream);
+  if (anOldStream.get() != NULL
+   && theUrl.IsEqual (anOldStream->Url().c_str())
+   && IsOpenIStream (anOldStream))
+  {
+    if (!anOldStream->good())
+    {
+      // Reset flags without re-opening
+      anOldStream->clear();
+    }
+    aNewStream = anOldStream;
+    if (theOffset >= 0)
+    {
+      aNewStream->seekg ((std::streamoff )theOffset, std::ios_base::beg);
+    }
+  }
+  if (aNewStream.get() == NULL)
+  {
+    opencascade::std::shared_ptr<std::streambuf> aFileBuf = OpenStreamBuffer (theUrl, theMode | std::ios_base::in);
+    if (aFileBuf.get() == NULL)
+    {
+      return opencascade::std::shared_ptr<std::istream>();
+    }
+
+    aNewStream.reset (new OSD_IStreamBuffer (theUrl.ToCString(), aFileBuf));
+    if (theOffset > 0)
+    {
+      aNewStream->seekg ((std::streamoff )theOffset, std::ios_base::beg);
+    }
+  }
+  return aNewStream;
+}
diff --git a/src/OSD/OSD_FileSystem.hxx b/src/OSD/OSD_FileSystem.hxx
new file mode 100644 (file)
index 0000000..f37bfdc
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright (c) 2021 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 _OSD_FileSystem_HeaderFile
+#define _OSD_FileSystem_HeaderFile
+
+#include <OSD_StreamBuffer.hxx>
+#include <TCollection_AsciiString.hxx>
+
+//! Base interface for a file stream provider.
+//! It is intended to be implemented for specific file protocol.
+class OSD_FileSystem : public Standard_Transient
+{
+  DEFINE_STANDARD_RTTIEXT(OSD_FileSystem, Standard_Transient)
+public:
+
+  //! Returns a global file system, which a selector between registered file systems.
+  Standard_EXPORT static const Handle(OSD_FileSystem)& DefaultFileSystem();
+
+public:
+
+  //! Returns TRUE if URL defines a supported protocol.
+  virtual Standard_Boolean IsSupportedPath (const TCollection_AsciiString& theUrl) const = 0;
+
+  //! Returns TRUE if current input stream is opened for reading operations.
+  virtual Standard_Boolean IsOpenIStream (const opencascade::std::shared_ptr<std::istream>& theStream) const = 0;
+
+  //! Opens stream for specified file URL for reading operations (std::istream).
+  //! Default implementation create a stream from file buffer returned by OSD_FileSystem::OpenFileBuffer().
+  //! @param theUrl       [in] path to open
+  //! @param theMode      [in] flags describing the requested input mode for the stream (std::ios_base::in will be implicitly added)
+  //! @param theOffset    [in] expected stream position from the begining of the file (beginning of the stream by default);
+  //!                          -1 would keep seek position undefined (in case of re-using theOldStream)
+  //! @param theOldStream [in] a pointer to existing stream pointing to theUrl to be reused (without re-opening)
+  //! @return pointer to newly created opened stream, to theOldStream if it can be reused or NULL in case of failure.
+  Standard_EXPORT virtual opencascade::std::shared_ptr<std::istream> OpenIStream
+                          (const TCollection_AsciiString& theUrl,
+                           const std::ios_base::openmode theMode,
+                           const int64_t theOffset = 0,
+                           const opencascade::std::shared_ptr<std::istream>& theOldStream = opencascade::std::shared_ptr<std::istream>());
+
+  //! Opens stream buffer for specified file URL.
+  //! @param theUrl        [in]  path to open
+  //! @param theMode       [in]  flags describing the requested input mode for the stream
+  //! @param theOffset     [in]  expected stream position from the begining of the buffer (beginning of the stream buffer by default)
+  //! @param theOutBufSize [out] total buffer size (only if buffer is opened for read)
+  //! @return pointer to newly created opened stream buffer or NULL in case of failure.
+  virtual opencascade::std::shared_ptr<std::streambuf> OpenStreamBuffer (const TCollection_AsciiString& theUrl,
+                                                                         const std::ios_base::openmode theMode,
+                                                                         const int64_t theOffset = 0,
+                                                                         int64_t* theOutBufSize = NULL) = 0;
+
+  //! Constructor.
+  Standard_EXPORT OSD_FileSystem();
+
+  //! Destructor.
+  Standard_EXPORT virtual ~OSD_FileSystem();
+};
+#endif // _OSD_FileSystem_HeaderFile
diff --git a/src/OSD/OSD_FileSystemSelector.cxx b/src/OSD/OSD_FileSystemSelector.cxx
new file mode 100644 (file)
index 0000000..18cff9c
--- /dev/null
@@ -0,0 +1,132 @@
+// Copyright (c) 2021 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 <OSD_FileSystemSelector.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(OSD_FileSystemSelector, OSD_FileSystem)
+
+//=======================================================================
+// function : AddProtocol
+// purpose :
+//=======================================================================
+void OSD_FileSystemSelector::AddProtocol (const Handle(OSD_FileSystem)& theFileSystem, bool theIsPreferred)
+{
+  myProtocols.Remove (theFileSystem); // avoid duplicates
+  if (theIsPreferred)
+  {
+    myProtocols.Prepend (theFileSystem);
+  }
+  else
+  {
+    myProtocols.Append (theFileSystem);
+  }
+}
+
+//=======================================================================
+// function : RemoveProtocol
+// purpose :
+//=======================================================================
+void OSD_FileSystemSelector::RemoveProtocol (const Handle(OSD_FileSystem)& theFileSystem)
+{
+  myProtocols.Remove (theFileSystem);
+}
+
+//=======================================================================
+// function : IsSupportedPath
+// purpose :
+//=======================================================================
+Standard_Boolean OSD_FileSystemSelector::IsSupportedPath (const TCollection_AsciiString& theUrl) const
+{
+  for (NCollection_List<Handle(OSD_FileSystem)>::Iterator aProtIter(myProtocols); aProtIter.More(); aProtIter.Next())
+  {
+    if (aProtIter.Value()->IsSupportedPath (theUrl))
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+//=======================================================================
+// function : IsOpenIStream
+// purpose :
+//=======================================================================
+Standard_Boolean OSD_FileSystemSelector::IsOpenIStream (const opencascade::std::shared_ptr<std::istream>& theStream) const
+{
+  opencascade::std::shared_ptr<OSD_IStreamBuffer> aFileStream = opencascade::std::dynamic_pointer_cast<OSD_IStreamBuffer> (theStream);
+  if (aFileStream.get() == NULL)
+  {
+    return false;
+  }
+  for (NCollection_List<Handle(OSD_FileSystem)>::Iterator aProtIter(myProtocols); aProtIter.More(); aProtIter.Next())
+  {
+    const Handle(OSD_FileSystem)& aFileSystem = aProtIter.Value();
+    if (aFileSystem->IsSupportedPath (TCollection_AsciiString (aFileStream->Url().c_str())))
+    {
+      if (aFileSystem->IsOpenIStream (theStream))
+      {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+//=======================================================================
+// function : OpenIStream
+// purpose :
+//=======================================================================
+opencascade::std::shared_ptr<std::istream> OSD_FileSystemSelector::OpenIStream (const TCollection_AsciiString& theUrl,
+                                                                                const std::ios_base::openmode theMode,
+                                                                                const int64_t theOffset,
+                                                                                const opencascade::std::shared_ptr<std::istream>& theOldStream)
+{
+  for (NCollection_List<Handle(OSD_FileSystem)>::Iterator aProtIter (myProtocols); aProtIter.More(); aProtIter.Next())
+  {
+    const Handle(OSD_FileSystem)& aFileSystem = aProtIter.Value();
+    if (aFileSystem->IsSupportedPath (theUrl))
+    {
+      opencascade::std::shared_ptr<std::istream> aStream = aFileSystem->OpenIStream (theUrl, theMode, theOffset, theOldStream);
+      if (aStream.get() != NULL)
+      {
+        return aStream;
+      }
+    }
+  }
+  return opencascade::std::shared_ptr<std::istream>();
+}
+
+
+//=======================================================================
+// function : OpenStreamBuffer
+// purpose :
+//=======================================================================
+opencascade::std::shared_ptr<std::streambuf> OSD_FileSystemSelector::OpenStreamBuffer (const TCollection_AsciiString& theUrl,
+                                                                                       const std::ios_base::openmode theMode,
+                                                                                       const int64_t theOffset,
+                                                                                       int64_t* theOutBufSize)
+{
+  for (NCollection_List<Handle(OSD_FileSystem)>::Iterator aProtIter (myProtocols); aProtIter.More(); aProtIter.Next())
+  {
+    const Handle(OSD_FileSystem)& aFileSystem = aProtIter.Value();
+    if (aFileSystem->IsSupportedPath (theUrl))
+    {
+      opencascade::std::shared_ptr<std::streambuf> aBuf = aFileSystem->OpenStreamBuffer (theUrl, theMode, theOffset, theOutBufSize);
+      if (aBuf.get() != NULL)
+      {
+        return aBuf;
+      }
+    }
+  }
+  return opencascade::std::shared_ptr<std::streambuf>();
+}
diff --git a/src/OSD/OSD_FileSystemSelector.hxx b/src/OSD/OSD_FileSystemSelector.hxx
new file mode 100644 (file)
index 0000000..79d3adc
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (c) 2021 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 _OSD_FileSystemSelector_HeaderFile
+#define _OSD_FileSystemSelector_HeaderFile
+
+#include <OSD_FileSystem.hxx>
+
+#include <NCollection_List.hxx>
+
+//! File system implementation which tried to open stream using registered list of file systems.
+class OSD_FileSystemSelector : public OSD_FileSystem
+{
+  DEFINE_STANDARD_RTTIEXT(OSD_FileSystemSelector, OSD_FileSystem)
+public:
+
+  //! Constructor.
+  OSD_FileSystemSelector() {}
+
+  //! Registers file system within the global file system selector returned by OSD_FileSystem::DefaultFileSystem().
+  //! @param theFileSystem  [in] file system to register
+  //! @param theIsPreferred [in] add to the beginning of the list when TRUE, or add to the end otherwise
+  Standard_EXPORT void AddProtocol (const Handle(OSD_FileSystem)& theFileSystem, bool theIsPreferred = false);
+
+  //! Unregisters file system within the global file system selector returned by OSD_FileSystem::DefaultFileSystem().
+  Standard_EXPORT void RemoveProtocol (const Handle(OSD_FileSystem)& theFileSystem);
+
+public:
+
+  //! Returns TRUE if URL defines a supported protocol.
+  Standard_EXPORT virtual bool IsSupportedPath (const TCollection_AsciiString& theUrl) const Standard_OVERRIDE;
+
+  //! Returns TRUE if current input stream is opened for reading operations.
+  Standard_EXPORT virtual Standard_Boolean IsOpenIStream (const opencascade::std::shared_ptr<std::istream>& theStream) const Standard_OVERRIDE;
+
+  //! Opens input stream using one of registered protocols.
+  Standard_EXPORT virtual opencascade::std::shared_ptr<std::istream> OpenIStream
+                          (const TCollection_AsciiString& theUrl,
+                           const std::ios_base::openmode theMode,
+                           const int64_t theOffset = 0,
+                           const opencascade::std::shared_ptr<std::istream>& theOldStream = opencascade::std::shared_ptr<std::istream>()) Standard_OVERRIDE;
+
+  //! Opens stream buffer using one of registered protocols.
+  Standard_EXPORT virtual opencascade::std::shared_ptr<std::streambuf> OpenStreamBuffer
+                          (const TCollection_AsciiString& theUrl,
+                           const std::ios_base::openmode theMode,
+                           const int64_t theOffset = 0,
+                           int64_t* theOutBufSize = NULL) Standard_OVERRIDE;
+
+protected:
+
+  NCollection_List<Handle(OSD_FileSystem)> myProtocols;
+
+};
+
+#endif // _OSD_FileSystemSelector_HeaderFile
diff --git a/src/OSD/OSD_LocalFileSystem.cxx b/src/OSD/OSD_LocalFileSystem.cxx
new file mode 100644 (file)
index 0000000..b13a466
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (c) 2021 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 <OSD_LocalFileSystem.hxx>
+#include <OSD_OpenFile.hxx>
+#include <OSD_Path.hxx>
+#include <Standard_Assert.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(OSD_LocalFileSystem, OSD_FileSystem)
+
+//=======================================================================
+// function : IsSupportedPath
+// purpose :
+//=======================================================================
+Standard_Boolean OSD_LocalFileSystem::IsSupportedPath (const TCollection_AsciiString& theUrl) const
+{
+  return !OSD_Path::IsRemoteProtocolPath (theUrl.ToCString());
+}
+
+//=======================================================================
+// function : IsOpenIStream
+// purpose :
+//=======================================================================
+Standard_Boolean OSD_LocalFileSystem::IsOpenIStream (const opencascade::std::shared_ptr<std::istream>& theStream) const
+{
+  opencascade::std::shared_ptr<OSD_IStreamBuffer> aFileStream = opencascade::std::dynamic_pointer_cast<OSD_IStreamBuffer> (theStream);
+  if (aFileStream.get() == NULL)
+  {
+    return false;
+  }
+  const std::filebuf* aFileBuf = dynamic_cast<const std::filebuf*> (aFileStream->rdbuf());
+  return (aFileBuf != NULL) ? aFileBuf->is_open() : false;
+}
+
+//=======================================================================
+// function : OpenStreamBuffer
+// purpose :
+//=======================================================================
+opencascade::std::shared_ptr<std::streambuf> OSD_LocalFileSystem::OpenStreamBuffer (const TCollection_AsciiString& theUrl,
+                                                                                    const std::ios_base::openmode theMode,
+                                                                                    const int64_t theOffset,
+                                                                                    int64_t* theOutBufSize)
+{
+  Standard_ASSERT_RAISE (theOffset >= 0, "Incorrect negative stream position during stream buffer opening");
+  opencascade::std::shared_ptr<std::filebuf> aNewBuf(new std::filebuf());
+  if (!OSD_OpenStream (*aNewBuf, TCollection_ExtendedString(theUrl), theMode))
+  {
+    return opencascade::std::shared_ptr<std::streambuf>();
+  }
+  // if buffer is opened for read, find the file size
+  if (theOutBufSize && ((theMode & std::ios::in) != 0))
+  {
+    *theOutBufSize = (int64_t )aNewBuf->pubseekoff (0, std::ios_base::end, std::ios_base::in);
+    if (aNewBuf->pubseekoff ((std::streamoff )theOffset, std::ios_base::beg, std::ios_base::in) < 0)
+    {
+      *theOutBufSize = 0;
+      return opencascade::std::shared_ptr<std::streambuf>();
+    }
+  }
+  else if (theOffset > 0 && aNewBuf->pubseekoff ((std::streamoff )theOffset, std::ios_base::beg,
+           (theMode & std::ios::in) != 0 ? std::ios_base::in : std::ios_base::out) < 0)
+  {
+    return opencascade::std::shared_ptr<std::streambuf>();
+  }
+  return aNewBuf;
+}
diff --git a/src/OSD/OSD_LocalFileSystem.hxx b/src/OSD/OSD_LocalFileSystem.hxx
new file mode 100644 (file)
index 0000000..789461c
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (c) 2021 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 _OSD_LocalFileSystem_HeaderFile
+#define _OSD_LocalFileSystem_HeaderFile
+
+#include <OSD_FileSystem.hxx>
+
+//! A file system opening local files (or files from mount systems).
+class OSD_LocalFileSystem : public OSD_FileSystem
+{
+  DEFINE_STANDARD_RTTIEXT(OSD_LocalFileSystem, OSD_FileSystem)
+public:
+
+  //! Constructor.
+  OSD_LocalFileSystem() {}
+
+  //! Returns TRUE if URL defines a supported protocol.
+  Standard_EXPORT virtual Standard_Boolean IsSupportedPath (const TCollection_AsciiString& theUrl) const Standard_OVERRIDE;
+
+  //! Returns TRUE if current input stream is opened for reading operations.
+  Standard_EXPORT virtual Standard_Boolean IsOpenIStream (const opencascade::std::shared_ptr<std::istream>& theStream) const Standard_OVERRIDE;
+
+  //! Opens stream buffer for specified file URL.
+  Standard_EXPORT virtual opencascade::std::shared_ptr<std::streambuf> OpenStreamBuffer
+                          (const TCollection_AsciiString& theUrl,
+                           const std::ios_base::openmode theMode,
+                           const int64_t theOffset = 0,
+                           int64_t* theOutBufSize = NULL) Standard_OVERRIDE;
+};
+#endif // _OSD_LocalFileSystem_HeaderFile
diff --git a/src/OSD/OSD_StreamBuffer.hxx b/src/OSD/OSD_StreamBuffer.hxx
new file mode 100644 (file)
index 0000000..59836e6
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (c) 2021 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 _OSD_StreamBuffer_HeaderFile
+#define _OSD_StreamBuffer_HeaderFile
+
+#include <Standard_Std.hxx>
+
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <string>
+
+//! A file stream implementation initialized from std::shared_ptr<std::streambuf>.
+template <typename T>
+class OSD_StreamBuffer : public T
+{
+public:
+
+  //! Main constructor.
+  OSD_StreamBuffer (const std::string& theUrl,
+                    const opencascade::std::shared_ptr<std::streambuf>& theBuffer)
+  : T (theBuffer.get()), myUrl (theUrl), myBuffer (theBuffer) {}
+
+  //! Return an opened URL.
+  const std::string& Url() const { return myUrl; }
+
+protected:
+
+  std::string                                  myUrl;
+  opencascade::std::shared_ptr<std::streambuf> myBuffer;
+};
+
+typedef OSD_StreamBuffer<std::istream>  OSD_IStreamBuffer;
+typedef OSD_StreamBuffer<std::ostream>  OSD_OStreamBuffer;
+typedef OSD_StreamBuffer<std::iostream> OSD_IOStreamBuffer;
+
+#endif // _OSD_StreamBuffer_HeaderFile
index 4b852f3..8631f0e 100644 (file)
@@ -22,6 +22,7 @@
 #include <Message.hxx>
 #include <Message_Messenger.hxx>
 #include <Message_ProgressScope.hxx>
+#include <OSD_CachedFileSystem.hxx>
 #include <OSD_OpenFile.hxx>
 #include <OSD_ThreadPool.hxx>
 
@@ -36,6 +37,7 @@ public:
 
   struct GltfReaderTLS
   {
+    Handle(OSD_FileSystem) FileSystem;
     Handle(RWGltf_PrimitiveArrayReader) Reader;
   };
 
@@ -66,11 +68,15 @@ public:
       aTlsData.Reader->SetErrorPrefix (myErrPrefix);
       aTlsData.Reader->SetCoordinateSystemConverter (myCafReader->myCoordSysConverter);
     }
+    if (aTlsData.FileSystem.IsNull())
+    {
+      aTlsData.FileSystem = new OSD_CachedFileSystem();
+    }
 
     TopLoc_Location aDummyLoc;
     TopoDS_Face& aFace = myFaceList->ChangeValue (theFaceIndex);
     Handle(RWGltf_GltfLatePrimitiveArray) aLateData = Handle(RWGltf_GltfLatePrimitiveArray)::DownCast (BRep_Tool::Triangulation (aFace, aDummyLoc));
-    Handle(Poly_Triangulation) aPolyData = aTlsData.Reader->Load (aLateData);
+    Handle(Poly_Triangulation) aPolyData = aTlsData.Reader->Load (aLateData, aTlsData.FileSystem);
     BRep_Builder aBuilder;
     aBuilder.UpdateFace (aFace, aPolyData);
 
index bad11f8..bb3c06f 100644 (file)
@@ -19,7 +19,7 @@
 #include <BRep_Builder.hxx>
 #include <Message.hxx>
 #include <Message_Messenger.hxx>
-#include <OSD_OpenFile.hxx>
+#include <OSD_CachedFileSystem.hxx>
 #include <Standard_ArrayStreamBuffer.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Iterator.hxx>
@@ -39,7 +39,8 @@ void RWGltf_PrimitiveArrayReader::reportError (const TCollection_AsciiString& th
 // function : load
 // purpose  :
 // =======================================================================
-bool RWGltf_PrimitiveArrayReader::load (const Handle(RWGltf_GltfLatePrimitiveArray)& theMesh)
+bool RWGltf_PrimitiveArrayReader::load (const Handle(RWGltf_GltfLatePrimitiveArray)& theMesh,
+                                        const Handle(OSD_FileSystem)& theFileSystem)
 {
   reset();
   if (theMesh.IsNull()
@@ -68,31 +69,13 @@ bool RWGltf_PrimitiveArrayReader::load (const Handle(RWGltf_GltfLatePrimitiveArr
       return false;
     }
 
-    if (mySharedStream.Path != aData.StreamUri)
+    opencascade::std::shared_ptr<std::istream> aSharedStream = theFileSystem->OpenIStream (aData.StreamUri, std::ios::in | std::ios::binary, aData.StreamOffset);
+    if (aSharedStream.get() == NULL)
     {
-      mySharedStream.Stream.close();
-      mySharedStream.Path = aData.StreamUri;
-    }
-    if (!mySharedStream.Stream.is_open())
-    {
-      OSD_OpenStream (mySharedStream.Stream, aData.StreamUri.ToCString(), std::ios::in | std::ios::binary);
-      if (!mySharedStream.Stream.is_open())
-      {
-        mySharedStream.Stream.close();
-        reportError (TCollection_AsciiString ("Buffer '") + theMesh->Id() + "refers to non-existing file '" + aData.StreamUri + "'.");
-        return false;
-      }
-    }
-
-    mySharedStream.Stream.seekg ((std::streamoff )aData.StreamOffset, std::ios_base::beg);
-    if (!mySharedStream.Stream.good())
-    {
-      mySharedStream.Stream.close();
-      reportError (TCollection_AsciiString ("Buffer '") + theMesh->Id() + "refers to invalid location.");
+      reportError (TCollection_AsciiString ("Buffer '") + theMesh->Id() + "refers to invalid file '" + aData.StreamUri + "'.");
       return false;
     }
-
-    if (!readBuffer (mySharedStream.Stream, theMesh->Id(), aData.Accessor, aData.Type, theMesh->PrimitiveMode()))
+    if (!readBuffer (*aSharedStream.get(), theMesh->Id(), aData.Accessor, aData.Type, theMesh->PrimitiveMode()))
     {
       return false;
     }
index 41774b4..8ce47df 100644 (file)
 #include <TCollection_AsciiString.hxx>
 
 class RWGltf_GltfLatePrimitiveArray;
-
-//! The interface for shared file.
-struct RWGltf_GltfSharedIStream
-{
-  std::ifstream           Stream; //!< shared file
-  TCollection_AsciiString Path;   //!< path to currently opened stream
-};
+class OSD_FileSystem;
 
 //! Interface for reading primitive array from glTF buffer.
 class RWGltf_PrimitiveArrayReader : public Standard_Transient
@@ -53,9 +47,10 @@ public:
   void SetCoordinateSystemConverter (const RWMesh_CoordinateSystemConverter& theConverter) { myCoordSysConverter = theConverter; }
 
   //! Load primitive array.
-  Handle(Poly_Triangulation) Load (const Handle(RWGltf_GltfLatePrimitiveArray)& theMesh)
+  Handle(Poly_Triangulation) Load (const Handle(RWGltf_GltfLatePrimitiveArray)& theMesh,
+                                   const Handle(OSD_FileSystem)& theFileSystem)
   {
-    if (load (theMesh))
+    if (load (theMesh, theFileSystem))
     {
       return result();
     }
@@ -68,7 +63,8 @@ protected:
   Standard_EXPORT virtual void reset() = 0;
 
   //! Load primitive array.
-  Standard_EXPORT virtual bool load (const Handle(RWGltf_GltfLatePrimitiveArray)& theMesh);
+  Standard_EXPORT virtual bool load (const Handle(RWGltf_GltfLatePrimitiveArray)& theMesh,
+                                     const Handle(OSD_FileSystem)& theFileSystem);
 
   //! Return result primitive array.
   Standard_EXPORT virtual Handle(Poly_Triangulation) result() = 0;
@@ -92,7 +88,6 @@ protected:
 protected:
 
   TCollection_AsciiString          myErrorPrefix;
-  RWGltf_GltfSharedIStream         mySharedStream;
   RWMesh_CoordinateSystemConverter myCoordSysConverter;
 
 };
index b9a40d6..9f5b4e3 100755 (executable)
@@ -23,7 +23,6 @@
 #include <Standard_CLocaleSentry.hxx>
 #include <Standard_CString.hxx>
 #include <Standard_Type.hxx>
-#include <Standard_OStream.hxx>
 #include <string.h>
 #include <stdarg.h>
 
index f42fbbd..4a54ce0 100644 (file)
@@ -25,7 +25,6 @@
 #define _Standard_ExtCharacter_HeaderFile
 
 #include <Standard_TypeDef.hxx>
-#include <Standard_OStream.hxx>
 
 #include <string.h>
 
index 0de020f..f7bccb8 100644 (file)
@@ -14,7 +14,6 @@
 // commercial license or contractual agreement.
 
 #include <Standard_Mutex.hxx>
-#include <Standard_OStream.hxx>
 
 #include <errno.h>
 
index d9791b7..ce39497 100644 (file)
@@ -18,7 +18,6 @@
 #include <Standard_NumericError.hxx>
 #include <Standard_NullValue.hxx>
 #include <Standard_Stream.hxx>
-#include <Standard_OStream.hxx>
 
 static const Standard_Real ACosLimit = 1. + Epsilon(1.);
 
index 2de2d0f..fe42f1a 100644 (file)
@@ -16,7 +16,6 @@
 #include <Standard_RangeError.hxx>
 #include <Standard_NullValue.hxx>
 #include <Standard_Stream.hxx>
-#include <Standard_OStream.hxx>
 
 //============================================================================
 // function : HashCode
index dc25847..002a034 100644 (file)
@@ -25,6 +25,7 @@
 #include <Standard_Boolean.hxx>
 #include <Standard_Integer.hxx>
 #include <Standard_OStream.hxx>
+
 class Standard_NoSuchObject;
 class Standard_ConstructionError;
 class gp_Trsf;
index b3b090c..ce5433b 100644 (file)
@@ -22,6 +22,8 @@
 #include <Standard_Real.hxx>
 #include <Standard_Integer.hxx>
 #include <Standard_Boolean.hxx>
+#include <Standard_OStream.hxx>
+
 class Standard_ConstructionError;
 class Standard_OutOfRange;
 class gp_XYZ;