diff --git a/src/QABugs/QABugs_20.cxx b/src/QABugs/QABugs_20.cxx index e5db0780fa..e6a6a960d5 100644 --- a/src/QABugs/QABugs_20.cxx +++ b/src/QABugs/QABugs_20.cxx @@ -59,6 +59,8 @@ #include #include +#include + //======================================================================= //function : SurfaceGenOCC26675_1 //purpose : Generates a surface for intersect (in corresponding @@ -2340,6 +2342,99 @@ static Standard_Integer OCC28829 (Draw_Interpretor&, Standard_Integer, const cha return 0; } +#include +#include +#include +#include +#include +#include + +#ifdef max + #undef max +#endif + +static Standard_Integer OCC28887 (Draw_Interpretor&, Standard_Integer theNbArgs, const char** theArgVec) +{ + if (theNbArgs < 3) + { + std::cout << "Syntax error: wrong number of arguments!\n"; + return 1; + } + + const TCollection_AsciiString aFilePath (theArgVec[1]); + const TCollection_AsciiString aName (theArgVec[2]); + Handle(NCollection_Buffer) aBuffer; + { + std::ifstream aFile; + OSD_OpenStream (aFile, aFilePath.ToCString(), std::ios::binary | std::ios::in); + if (!aFile.is_open()) + { + std::cout << "Error: input file '" << aFilePath << "' cannot be read\n"; + return 1; + } + aFile.seekg (0, std::ios_base::end); + const int64_t aFileLength = int64_t (aFile.tellg()); + if (aFileLength > int64_t (std::numeric_limits::max()) + || aFileLength < 1) + { + std::cout << "Error: input file '" << aFilePath << "' is too large\n"; + return 1; + } + aFile.seekg (0, std::ios_base::beg); + + aBuffer = new NCollection_Buffer (NCollection_BaseAllocator::CommonBaseAllocator()); + if (!aBuffer->Allocate (size_t(aFileLength))) + { + std::cout << "Error: memory allocation (" << aFileLength << ") has failed\n"; + return 1; + } + + aFile.read ((char* )aBuffer->ChangeData(), aBuffer->Size()); + if (!aFile.good()) + { + std::cout << "Error: input file '" << aFilePath << "' reading failure\n"; + return 1; + } + } + + Standard_ArrayStreamBuffer aStreamBuffer ((const char* )aBuffer->ChangeData(), aBuffer->Size()); + std::istream aStream (&aStreamBuffer); + // just play with seeking + aStream.seekg (0, std::ios_base::end); + aStream.seekg (0, std::ios_base::beg); + if (aFilePath.EndsWith (".brep") + || aFilePath.EndsWith (".rle")) + { + TopoDS_Shape aShape; + BRep_Builder aBuilder; + BRepTools::Read (aShape, aStream, aBuilder); + DBRep::Set (aName.ToCString(), aShape); + } + else + { + Handle(TDocStd_Document) aDoc; + Handle(TDocStd_Application) anApp = DDocStd::GetApplication(); + Standard_CString aNameVar = aName.ToCString(); + if (DDocStd::GetDocument (aNameVar, aDoc, Standard_False)) + { + std::cout << "Error: document with name " << aName << " already exists\n"; + return 1; + } + + if (anApp->Open (aStream, aDoc) != PCDM_RS_OK) + { + std::cout << "Error: cannot open XDE document\n"; + return 1; + } + + Handle(DDocStd_DrawDocument) aDrawDoc = new DDocStd_DrawDocument (aDoc); + TDataStd_Name::Set (aDoc->GetData()->Root(), aName.ToCString()); + Draw::Set (aName.ToCString(), aDrawDoc); + } + + return 0; +} + void QABugs::Commands_20(Draw_Interpretor& theCommands) { const char *group = "QABugs"; @@ -2363,6 +2458,10 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) { theCommands.Add("OCC28594", "OCC28594", __FILE__, OCC28594, group); theCommands.Add("OCC28784", "OCC28784 result shape", __FILE__, OCC28784, group); theCommands.Add("OCC28829", "OCC28829: perform invalid FPE operation", __FILE__, OCC28829, group); + theCommands.Add("OCC28887", + "OCC28887 filePath result" + "\n\t\t: Check interface for reading BRep from memory.", + __FILE__, OCC28887, group); return; } diff --git a/src/Standard/FILES b/src/Standard/FILES index 3ebe4f93df..da33f5a0e9 100755 --- a/src/Standard/FILES +++ b/src/Standard/FILES @@ -2,6 +2,8 @@ Standard.cxx Standard.hxx Standard_AbortiveTransaction.hxx Standard_Address.hxx +Standard_ArrayStreamBuffer.hxx +Standard_ArrayStreamBuffer.cxx Standard_Assert.hxx Standard_Atomic.hxx Standard_Boolean.hxx diff --git a/src/Standard/Standard_ArrayStreamBuffer.cxx b/src/Standard/Standard_ArrayStreamBuffer.cxx new file mode 100644 index 0000000000..803e3341ce --- /dev/null +++ b/src/Standard/Standard_ArrayStreamBuffer.cxx @@ -0,0 +1,183 @@ +// Copyright (c) 2016 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 + +// ======================================================================= +// function : Standard_ArrayStreamBuffer +// purpose : +// ======================================================================= +Standard_ArrayStreamBuffer::Standard_ArrayStreamBuffer (const char* theBegin, + const size_t theSize) +: myBegin (theBegin), + myEnd (theBegin + theSize), + myCurrent(theBegin) +{ + // +} + +// ======================================================================= +// function : ~Standard_ArrayStreamBuffer +// purpose : +// ======================================================================= +Standard_ArrayStreamBuffer::~Standard_ArrayStreamBuffer() +{ + // +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void Standard_ArrayStreamBuffer::Init (const char* theBegin, + const size_t theSize) +{ + myBegin = theBegin; + myEnd = theBegin + theSize; + myCurrent = theBegin; +} + +// ======================================================================= +// function : underflow +// purpose : +// ======================================================================= +Standard_ArrayStreamBuffer::int_type Standard_ArrayStreamBuffer::underflow() +{ + if (myCurrent == myEnd) + { + return traits_type::eof(); + } + + return traits_type::to_int_type(*myCurrent); +} + +// ======================================================================= +// function : uflow +// purpose : +// ======================================================================= +Standard_ArrayStreamBuffer::int_type Standard_ArrayStreamBuffer::uflow() +{ + if (myCurrent == myEnd) + { + return traits_type::eof(); + } + + return traits_type::to_int_type(*myCurrent++); +} + +// ======================================================================= +// function : pbackfail +// purpose : +// ======================================================================= +Standard_ArrayStreamBuffer::int_type Standard_ArrayStreamBuffer::pbackfail (int_type ch) +{ + if (myCurrent == myBegin + || (ch != traits_type::eof() + && ch != myCurrent[-1])) + { + return traits_type::eof(); + } + + return traits_type::to_int_type(*--myCurrent); +} + +// ======================================================================= +// function : showmanyc +// purpose : +// ======================================================================= +std::streamsize Standard_ArrayStreamBuffer::showmanyc() +{ + if (myCurrent > myEnd) + { + // assert + } + return myEnd - myCurrent; +} + +// ======================================================================= +// function : seekoff +// purpose : +// ======================================================================= +Standard_ArrayStreamBuffer::pos_type Standard_ArrayStreamBuffer::seekoff (off_type theOff, + std::ios_base::seekdir theWay, + std::ios_base::openmode theWhich) +{ + switch (theWay) + { + case std::ios_base::beg: + { + myCurrent = myBegin + theOff; + if (myCurrent >= myEnd) + { + myCurrent = myEnd; + } + break; + } + case std::ios_base::cur: + { + myCurrent += theOff; + if (myCurrent >= myEnd) + { + myCurrent = myEnd; + } + break; + } + case std::ios_base::end: + { + myCurrent = myEnd - theOff; + if (myCurrent < myBegin) + { + myCurrent = myBegin; + } + break; + } + default: + { + break; + } + } + (void )theWhich; + return myCurrent - myBegin; +} + +// ======================================================================= +// function : seekpos +// purpose : +// ======================================================================= +Standard_ArrayStreamBuffer::pos_type Standard_ArrayStreamBuffer::seekpos (pos_type thePosition, + std::ios_base::openmode theWhich) +{ + return seekoff (off_type(thePosition), std::ios_base::beg, theWhich); +} + +// ======================================================================= +// function : xsgetn +// purpose : +// ======================================================================= +std::streamsize Standard_ArrayStreamBuffer::xsgetn (char* thePtr, + std::streamsize theCount) +{ + const char* aCurrent = myCurrent + theCount; + if (aCurrent >= myEnd) + { + aCurrent = myEnd; + } + size_t aCopied = aCurrent - myCurrent; + if (aCopied == 0) + { + return 0; + } + memcpy (thePtr, myCurrent, aCopied); + myCurrent = aCurrent; + return aCopied; +} diff --git a/src/Standard/Standard_ArrayStreamBuffer.hxx b/src/Standard/Standard_ArrayStreamBuffer.hxx new file mode 100644 index 0000000000..6e5973bf36 --- /dev/null +++ b/src/Standard/Standard_ArrayStreamBuffer.hxx @@ -0,0 +1,113 @@ +// Copyright (c) 2016 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 _Standard_ArrayStreamBuffer_HeaderFile +#define _Standard_ArrayStreamBuffer_HeaderFile + +#include + +#include + +//! Custom buffer object implementing STL interface std::streambuf for streamed reading from allocated memory block. +//! Implements minimal sub-set of methods for passing buffer to std::istream, including seek support. +//! +//! This class can be used for creating a seekable input stream in cases, +//! when the source data does not satisfies Reader requirements (non-seekable stream, compressed data) +//! or represents an in-memory resource. +//! +//! The memory itself is NOT managed by this class - it is up to the caller to ensure that passed memory pointer +//! is not released during Standard_ArrayStreamBuffer lifetime. +//! +//! Usage example: +//! @code +//! const char* theBuffer; +//! const size_t theBufferLength; +//! Standard_ArrayStreamBuffer aStreamBuffer (theBuffer, theBufferLength); +//! std::istream aStream (&aStreamBuffer); +//! TopoDS_Shape aShape; +//! BRep_Builder aBuilder; +//! BRepTools::Read (aShape, aStream, aBuilder); +//! @endcode +class Standard_ArrayStreamBuffer : public std::streambuf +{ +public: + + //! Main constructor. + //! Passed pointer is stored as is (memory is NOT copied nor released with destructor). + //! @param theBegin pointer to the beggining of pre-allocated buffer + //! @param theSize length of pre-allocated buffer + Standard_EXPORT Standard_ArrayStreamBuffer (const char* theBegin, + const size_t theSize); + + //! Destructor. + Standard_EXPORT virtual ~Standard_ArrayStreamBuffer(); + + //! (Re)-initialize the stream. + //! Passed pointer is stored as is (memory is NOT copied nor released with destructor). + //! @param theBegin pointer to the beggining of pre-allocated buffer + //! @param theSize length of pre-allocated buffer + Standard_EXPORT virtual void Init (const char* theBegin, + const size_t theSize); + +protected: + + //! Get character on underflow. + //! Virtual function called by other member functions to get the current character + //! in the controlled input sequence without changing the current position. + Standard_EXPORT virtual int_type underflow() Standard_OVERRIDE; + + //! Get character on underflow and advance position. + //! Virtual function called by other member functions to get the current character + //! in the controlled input sequence and then advance the position indicator to the next character. + Standard_EXPORT virtual int_type uflow() Standard_OVERRIDE; + + //! Put character back in the case of backup underflow. + //! Virtual function called by other member functions to put a character back + //! into the controlled input sequence and decrease the position indicator. + Standard_EXPORT virtual int_type pbackfail (int_type ch) Standard_OVERRIDE; + + //! Get number of characters available. + //! Virtual function (to be read s-how-many-c) called by other member functions + //! to get an estimate on the number of characters available in the associated input sequence. + Standard_EXPORT virtual std::streamsize showmanyc() Standard_OVERRIDE; + + //! Seek to specified position. + Standard_EXPORT virtual pos_type seekoff (off_type theOff, + std::ios_base::seekdir theWay, + std::ios_base::openmode theWhich) Standard_OVERRIDE; + + //! Change to specified position, according to mode. + Standard_EXPORT virtual pos_type seekpos (pos_type thePosition, + std::ios_base::openmode theWhich) Standard_OVERRIDE; + +public: + + //! Read a bunch of bytes at once. + Standard_EXPORT virtual std::streamsize xsgetn (char* thePtr, + std::streamsize theCount) Standard_OVERRIDE; + +private: + + // copying is not allowed + Standard_ArrayStreamBuffer (const Standard_ArrayStreamBuffer& ); + Standard_ArrayStreamBuffer& operator= (const Standard_ArrayStreamBuffer& ); + +protected: + + const char* myBegin; + const char* myEnd; + const char* myCurrent; + +}; + +#endif // _Standard_ArrayStreamBuffer_HeaderFile diff --git a/tests/bugs/xde/bug28887_1 b/tests/bugs/xde/bug28887_1 new file mode 100644 index 0000000000..77516f59f0 --- /dev/null +++ b/tests/bugs/xde/bug28887_1 @@ -0,0 +1,15 @@ +puts "==========" +puts "OCC28887 Test case for Standard_ArrayStreamBuffer class - streaming interface for reading from allocated memory block" +puts "==========" +puts "" + +pload QAcommands VISUALIZATION +OCC28887 [locate_data_file face.brep] f + +vclear +vclose ALL +vinit View1 +vaxo +vdisplay -dispMode 1 f +vfit +vdump $::imagedir/${::casename}.png diff --git a/tests/bugs/xde/bug28887_2 b/tests/bugs/xde/bug28887_2 new file mode 100644 index 0000000000..26a628b432 --- /dev/null +++ b/tests/bugs/xde/bug28887_2 @@ -0,0 +1,16 @@ +puts "==========" +puts "OCC28887 Test case for Standard_ArrayStreamBuffer class - streaming interface for reading from allocated memory block" +puts "==========" +puts "" + +pload QAcommands VISUALIZATION DCAF +catch { Close doc } +OCC28887 [locate_data_file bug23384-doc_subshapes.xbf] doc + +vclear +vclose ALL +XShow doc +vaxo +vfit +vsetdispmode 1 +vdump $::imagedir/${::casename}.png