From f00abcb359a4bff180466899e10b8e155979aa67 Mon Sep 17 00:00:00 2001 From: stv Date: Thu, 2 Jul 2015 10:29:44 +0300 Subject: [PATCH] Fix for problem with using nonseekable streams (ex boost filtering_streams with zip compressor/decompressor). --- src/CDF/CDF_Application.cxx | 2 - src/PCDM/PCDM_DOMHeaderParser.cxx | 22 +++- src/Storage/Storage_IStream.cdl | 7 +- src/Storage/Storage_IStream.cxx | 120 ++++++++++++------ src/Storage/Storage_OStream.cdl | 6 +- src/Storage/Storage_OStream.cxx | 44 +++---- .../XmlLDrivers_DocumentRetrievalDriver.cxx | 27 +++- 7 files changed, 153 insertions(+), 75 deletions(-) diff --git a/src/CDF/CDF_Application.cxx b/src/CDF/CDF_Application.cxx index c700e84fce..b7ddf1620f 100644 --- a/src/CDF/CDF_Application.cxx +++ b/src/CDF/CDF_Application.cxx @@ -200,8 +200,6 @@ PCDM_ReaderStatus CDF_Application::CanRetrieve(Handle(Storage_IODevice)& aDevice } } - aDevice->Close(); - return PCDM_RS_OK; } diff --git a/src/PCDM/PCDM_DOMHeaderParser.cxx b/src/PCDM/PCDM_DOMHeaderParser.cxx index 9bcbcc9f23..7cabf17605 100644 --- a/src/PCDM/PCDM_DOMHeaderParser.cxx +++ b/src/PCDM/PCDM_DOMHeaderParser.cxx @@ -22,17 +22,29 @@ Standard_Boolean PCDM_DOMHeaderParser::parse( const Handle(Storage_IODevice)& an { Standard_Boolean aRes = Standard_True; Handle(Storage_File) aFile = Handle(Storage_File)::DownCast(anInput); - Handle(Storage_IStream) aStream = Handle(Storage_IStream)::DownCast(anInput); if ( !aFile.IsNull() ) { TCollection_AsciiString aPath( aFile->Path() ); aRes = LDOMParser::parse( aPath.ToCString() ); } - else if ( !aStream.IsNull() && aStream->Stream() ) + else if ( !anInput.IsNull() && anInput->CanRead() ) { - aStream->Open(Storage_VSRead); - aRes = LDOMParser::parse( *aStream->Stream() ); - aStream->Close(); + Standard_Size aSize = 8000; + char* aBuf = (char*)malloc( aSize ); + anInput->Open(Storage_VSRead); + std::string aStr; + while ( !anInput->IsEnd() ) + { + Standard_Size aNum = anInput->Read( aBuf, aSize ); + aStr.append( aBuf, aNum ); + } + anInput->Close(); + free( aBuf ); + + Standard_SStream aStream( std::ios::in ); + aStream.str( aStr ); + + aRes = LDOMParser::parse( aStream ); } return aRes; } diff --git a/src/Storage/Storage_IStream.cdl b/src/Storage/Storage_IStream.cdl index 8f1419a1cf..a35c4a81df 100644 --- a/src/Storage/Storage_IStream.cdl +++ b/src/Storage/Storage_IStream.cdl @@ -21,6 +21,7 @@ uses Position from Storage, OpenMode from Storage, SeekMode from Storage, Error from Storage, + SStream from Standard, IStream from Standard, IStreamPtr from Standard, ExtendedString from TCollection @@ -35,8 +36,6 @@ is Delete (me: mutable) is redefined; - Stream(me) returns IStreamPtr from Standard; - Name (me) returns ExtendedString from TCollection is redefined; Open (me: mutable; theMode: OpenMode from Storage = Storage_VSWrite) returns Error from Storage; @@ -68,6 +67,10 @@ is returns OStream from Standard is redefined; ---C++: return & + fillBuffer(me: mutable) + is private; + fields + myBuffer: SStream from Standard; myStream: IStreamPtr from Standard; end; diff --git a/src/Storage/Storage_IStream.cxx b/src/Storage/Storage_IStream.cxx index 62b4594969..980b5d42c7 100644 --- a/src/Storage/Storage_IStream.cxx +++ b/src/Storage/Storage_IStream.cxx @@ -5,6 +5,8 @@ #include +#include + #include #include @@ -14,7 +16,8 @@ //======================================================================= Storage_IStream::Storage_IStream (Standard_IStream& theStream) : Storage_IODevice(), - myStream (&theStream) + myStream( &theStream ), + myBuffer( std::ios::in | std::ios::binary ) { } @@ -26,15 +29,6 @@ void Storage_IStream::Delete() { } -//======================================================================= -//function : Path -//purpose : -//======================================================================= -Standard_IStreamPtr Storage_IStream::Stream() const -{ - return myStream; -} - //======================================================================= //function : Name //purpose : @@ -59,17 +53,15 @@ Storage_Error Storage_IStream::Open (const Storage_OpenMode theMode) if (OpenMode() == Storage_VSNone) { - if (!myStream->good()) // not good for eof - { + if ( !myBuffer.good() ) // not good for eof anOpenResult = Storage_VSOpenError; - } else { SetOpenMode (theMode); - + // clear flags and set the position where the next character is to be inserted - myStream->clear(); - Seek(0); + myBuffer.clear(); + Seek( 0 ); } } else @@ -86,7 +78,7 @@ Storage_Error Storage_IStream::Open (const Storage_OpenMode theMode) //======================================================================= Standard_Boolean Storage_IStream::IsEnd() const { - return myStream->eof(); + return myBuffer.eof() && myStream->eof(); } //======================================================================= @@ -95,7 +87,7 @@ Standard_Boolean Storage_IStream::IsEnd() const //======================================================================= Storage_Position Storage_IStream::Tell() { - return Storage_Position (myStream->tellg()); + return Storage_Position( myBuffer.tellg() ); } //======================================================================= @@ -104,21 +96,37 @@ Storage_Position Storage_IStream::Tell() //======================================================================= Standard_Boolean Storage_IStream::Seek (const Storage_Position& thePos, const Storage_SeekMode aMode ) { - switch ( aMode ) + if ( aMode == Storage_SMEnd ) + { + fillBuffer(); + myBuffer.seekg( thePos, ios::end ); + } + else { - case Storage_SMEnd: - myStream->seekg(thePos, ios::end); - break; - case Storage_SMCur: - myStream->seekg(thePos, ios::cur); - break; - case Storage_SMBegin: - default: - myStream->seekg(thePos, ios::beg); - break; + Standard_Size aCur = myBuffer.tellg(); + Standard_Size aPos = aMode == Storage_SMBegin ? thePos : aCur + thePos; + if ( aPos > aCur ) + { + myBuffer.seekg( 0, ios::end ); + Standard_Size aLast = myBuffer.tellg(); + if ( aLast < aPos ) + { + Standard_Size aCount = aPos - aLast; + char* aBuf = (char*)malloc( aCount ); + myStream->read( aBuf, aCount ); + Standard_Size aNum = (Standard_Size)myStream->gcount(); + std::string& aStr = myBuffer.str(); + aStr.append( (char*)aBuf, aNum ); + myBuffer.str( aStr ); + free( aBuf ); + aPos = aLast + aNum; + } + } + if ( aPos != aCur ) + myBuffer.seekg( aPos ); } - return !myStream->fail(); + return !myBuffer.fail(); } //======================================================================= @@ -128,8 +136,7 @@ Standard_Boolean Storage_IStream::Seek (const Storage_Position& thePos, const St Standard_Boolean Storage_IStream::Close() { SetOpenMode( Storage_VSNone ); - myStream->clear(); - Seek(0); + myBuffer.clear(); return Standard_True; } @@ -140,7 +147,7 @@ Standard_Boolean Storage_IStream::Close() //======================================================================= Standard_Boolean Storage_IStream::CanRead() const { - return myStream->good(); + return myBuffer.good() || myStream->good(); } //======================================================================= @@ -156,10 +163,28 @@ Standard_Boolean Storage_IStream::CanWrite() const //function : Read //purpose : //======================================================================= -Standard_Size Storage_IStream::Read (const Standard_Address theBuffer, const Standard_Size theSize) +Standard_Size Storage_IStream::Read( const Standard_Address theBuffer, const Standard_Size theSize ) { - myStream->read((char*)theBuffer, theSize); - return (Standard_Size)myStream->gcount(); + myBuffer.read((char*)theBuffer, theSize); + Standard_Size aCount = (Standard_Size)myBuffer.gcount(); + if ( aCount < theSize ) + { + myStream->read((char*)theBuffer + aCount, theSize - aCount ); + Standard_Size aNum = (Standard_Size)myStream->gcount(); + + if ( aNum > 0 ) + { + std::string aStr = myBuffer.str(); + aStr.append( (char*)theBuffer + aCount, aNum ); + myBuffer.str( aStr ); + aCount += aNum; + + myBuffer.clear(); + myBuffer.seekg( 0, std::ios::end ); + } + } + + return aCount; } //======================================================================= @@ -188,3 +213,26 @@ Standard_OStream& Storage_IStream::Print (Standard_OStream& theOStream) const { return theOStream; } + +//======================================================================= +//function : fillBuffer +//purpose : +//======================================================================= +void Storage_IStream::fillBuffer() +{ + Standard_Size aCur = myBuffer.tellg(); + + Standard_Size aSize = 8000; + char* aBuf = (char*)malloc( aSize ); + while ( !myStream->eof() ) + { + myStream->read( aBuf, aSize ); + Standard_Size aNum = (Standard_Size)myStream->gcount(); + std::string aStr = myBuffer.str(); + aStr.append( (char*)aBuf, aNum ); + myBuffer.str( aStr ); + } + free( aBuf ); + + myBuffer.seekg( aCur ); +} diff --git a/src/Storage/Storage_OStream.cdl b/src/Storage/Storage_OStream.cdl index a3a364ea7a..a112de0964 100644 --- a/src/Storage/Storage_OStream.cdl +++ b/src/Storage/Storage_OStream.cdl @@ -23,6 +23,7 @@ uses Position from Storage, Error from Storage, OStream from Standard, OStreamPtr from Standard, + SStream from Standard, ExtendedString from TCollection raises StreamTypeMismatchError from Storage, @@ -35,8 +36,6 @@ is Delete (me: mutable) is redefined; - Stream (me) returns OStreamPtr from Standard; - Name (me) returns ExtendedString from TCollection is redefined; Open (me: mutable; theMode: OpenMode from Storage = Storage_VSWrite) returns Error from Storage; @@ -69,5 +68,6 @@ is ---C++: return & fields - myStream: OStreamPtr from Standard; + myBuffer : SStream from Standard; + myStream : OStreamPtr from Standard; end; diff --git a/src/Storage/Storage_OStream.cxx b/src/Storage/Storage_OStream.cxx index 62236cf47d..9da1bc87e1 100644 --- a/src/Storage/Storage_OStream.cxx +++ b/src/Storage/Storage_OStream.cxx @@ -5,6 +5,8 @@ #include +#include + #include #include @@ -12,9 +14,10 @@ //function : Storage_OStream //purpose : Constructor //======================================================================= -Storage_OStream::Storage_OStream (Standard_OStream& theStream) +Storage_OStream::Storage_OStream( Standard_OStream& theStream ) : Storage_IODevice(), - myStream (&theStream) + myStream( &theStream ), + myBuffer( std::ios::out | std::ios::binary ) { } @@ -26,15 +29,6 @@ void Storage_OStream::Delete() { } -//======================================================================= -//function : Stream -//purpose : -//======================================================================= -Standard_OStreamPtr Storage_OStream::Stream() const -{ - return myStream; -} - //======================================================================= //function : Name //purpose : @@ -50,7 +44,7 @@ TCollection_ExtendedString Storage_OStream::Name() const //======================================================================= Storage_Error Storage_OStream::Open (const Storage_OpenMode theMode) { - if (theMode != Storage_VSWrite || theMode != Storage_VSAppend) + if (theMode != Storage_VSWrite && theMode != Storage_VSAppend) { return Storage_VSOpenError; } @@ -68,11 +62,11 @@ Storage_Error Storage_OStream::Open (const Storage_OpenMode theMode) SetOpenMode (theMode); // clear flags and set the position where the next character is to be inserted - myStream->clear(); + myBuffer.clear(); if ( theMode == Storage_VSWrite ) - myStream->seekp(0, ios::beg); + myBuffer.seekp(0, ios::beg); else - myStream->seekp(0, ios::end); + myBuffer.seekp(0, ios::end); } } else @@ -89,7 +83,7 @@ Storage_Error Storage_OStream::Open (const Storage_OpenMode theMode) //======================================================================= Standard_Boolean Storage_OStream::IsEnd() const { - return myStream->eof(); + return myBuffer.eof(); } //======================================================================= @@ -98,7 +92,7 @@ Standard_Boolean Storage_OStream::IsEnd() const //======================================================================= Storage_Position Storage_OStream::Tell() { - return Storage_Position (myStream->tellp()); + return Storage_Position( myBuffer.tellp() ); } //======================================================================= @@ -110,18 +104,18 @@ Standard_Boolean Storage_OStream::Seek (const Storage_Position& thePos, const St switch ( aMode ) { case Storage_SMEnd: - myStream->seekp(thePos, ios::end); + myBuffer.seekp(thePos, ios::end); break; case Storage_SMCur: - myStream->seekp(thePos, ios::cur); + myBuffer.seekp(thePos, ios::cur); break; case Storage_SMBegin: default: - myStream->seekp(thePos, ios::beg); + myBuffer.seekp(thePos, ios::beg); break; } - return !myStream->fail(); + return !myBuffer.fail(); } //======================================================================= @@ -132,6 +126,10 @@ Standard_Boolean Storage_OStream::Close() { SetOpenMode( Storage_VSNone ); + std::string aStr = myBuffer.str(); + + myStream->write( aStr.c_str(), aStr.size() ); + return Standard_True; } @@ -150,7 +148,7 @@ Standard_Boolean Storage_OStream::CanRead() const //======================================================================= Standard_Boolean Storage_OStream::CanWrite() const { - return myStream->good(); + return myBuffer.good() && myStream->good(); } //======================================================================= @@ -168,7 +166,7 @@ Standard_Size Storage_OStream::Read( const Standard_Address /*theBuffer*/, const //======================================================================= Standard_Size Storage_OStream::Write (const Standard_Address theBuffer, const Standard_Size theSize) { - myStream->write((char*)theBuffer, theSize); + myBuffer.write((char*)theBuffer, theSize); return theSize; } diff --git a/src/XmlLDrivers/XmlLDrivers_DocumentRetrievalDriver.cxx b/src/XmlLDrivers/XmlLDrivers_DocumentRetrievalDriver.cxx index 95c9ce8e51..255e5444d1 100644 --- a/src/XmlLDrivers/XmlLDrivers_DocumentRetrievalDriver.cxx +++ b/src/XmlLDrivers/XmlLDrivers_DocumentRetrievalDriver.cxx @@ -199,16 +199,35 @@ void XmlLDrivers_DocumentRetrievalDriver::Read LDOMParser aParser; Standard_Boolean aRes = Standard_True; - Handle(Storage_File) aFile = Handle(Storage_File)::DownCast(theDevice); - Handle(Storage_IStream) aStream = Handle(Storage_IStream)::DownCast(theDevice); + Handle(Storage_File) aFile = Handle(Storage_File)::DownCast(myDevice); if ( !aFile.IsNull() ) { TCollection_AsciiString aPath( aFile->Path() ); aRes = aParser.parse( aPath.ToCString() ); } - else if ( !aStream.IsNull() && aStream->Stream() ) + else if ( !myDevice.IsNull() && myDevice->CanRead() ) { - aRes = aParser.parse( *aStream->Stream() ); + if ( myDevice->Open( Storage_VSRead ) == Storage_VSOk ) + { + Standard_Size aSize = 8000; + char* aBuf = (char*)malloc( aSize ); + std::string aStr; + while ( !myDevice->IsEnd() ) + { + Standard_Size aNum = myDevice->Read( aBuf, aSize ); + aStr.append( aBuf, aNum ); + } + free( aBuf ); + + myDevice->Close(); + + Standard_SStream aStream( std::ios::in ); + aStream.str( aStr ); + + aRes = aParser.parse( aStream ); + } + else + myReaderStatus = PCDM_RS_OpenError; } if (aRes) -- 2.39.5