From c56c2e28ff4252aa858826416a8a57cb8c2bf100 Mon Sep 17 00:00:00 2001 From: Fridrich Štrba Date: Fri, 20 Dec 2013 14:49:06 +0100 Subject: Buffered WPXSvInputStream Change-Id: I8bb2632cb018093d02e21090e77bb48364f99268 Reviewed-on: https://gerrit.libreoffice.org/7146 Reviewed-by: David Tardon Tested-by: David Tardon --- writerperfect/source/common/WPXSvStream.cxx | 157 ++++++++++++++++++++++------ 1 file changed, 125 insertions(+), 32 deletions(-) (limited to 'writerperfect') diff --git a/writerperfect/source/common/WPXSvStream.cxx b/writerperfect/source/common/WPXSvStream.cxx index dd353119953f..c8036327791b 100644 --- a/writerperfect/source/common/WPXSvStream.cxx +++ b/writerperfect/source/common/WPXSvStream.cxx @@ -37,7 +37,7 @@ typedef struct SotStorageStreamRef ref; } SotStorageStreamRefWrapper; -class WPXSvInputStreamImpl : public WPXInputStream +class WPXSvInputStreamImpl { public : WPXSvInputStreamImpl( ::com::sun::star::uno::Reference< @@ -48,27 +48,35 @@ public : WPXInputStream * getDocumentOLEStream(const char *name); const unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead); - int seek(long offset, WPX_SEEK_TYPE seekType); + int seek(long offset); long tell(); bool atEOS(); + void invalidateReadBuffer(); private: ::std::vector< SotStorageRefWrapper > mxChildrenStorages; ::std::vector< SotStorageStreamRefWrapper > mxChildrenStreams; ::com::sun::star::uno::Reference< - ::com::sun::star::io::XInputStream > mxStream; + ::com::sun::star::io::XInputStream > mxStream; ::com::sun::star::uno::Reference< - ::com::sun::star::io::XSeekable > mxSeekable; + ::com::sun::star::io::XSeekable > mxSeekable; ::com::sun::star::uno::Sequence< sal_Int8 > maData; +public: sal_Int64 mnLength; + unsigned char *mpReadBuffer; + unsigned long mnReadBufferLength; + unsigned long mnReadBufferPos; }; WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference< XInputStream > xStream ) : - WPXInputStream(), mxChildrenStorages(), mxChildrenStreams(), mxStream(xStream), mxSeekable(xStream, UNO_QUERY), - maData(0) + maData(0), + mnLength(0), + mpReadBuffer(0), + mnReadBufferLength(0), + mnReadBufferPos(0) { if (!xStream.is() || !mxStream.is()) mnLength = 0; @@ -93,6 +101,8 @@ WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference< XInputStream > xStream ) WPXSvInputStreamImpl::~WPXSvInputStreamImpl() { + if (mpReadBuffer) + delete [] mpReadBuffer; } const unsigned char *WPXSvInputStreamImpl::read(unsigned long numBytes, unsigned long &numBytesRead) @@ -122,7 +132,7 @@ long WPXSvInputStreamImpl::tell() } } -int WPXSvInputStreamImpl::seek(long offset, WPX_SEEK_TYPE seekType) +int WPXSvInputStreamImpl::seek(long offset) { if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) return -1; @@ -131,28 +141,10 @@ int WPXSvInputStreamImpl::seek(long offset, WPX_SEEK_TYPE seekType) if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits::max)())) return -1; - sal_Int64 tmpOffset = offset; - if (seekType == WPX_SEEK_CUR) - tmpOffset += tmpPosition; - if (seekType == WPX_SEEK_END) - tmpOffset += mnLength; - - int retVal = 0; - if (tmpOffset < 0) - { - tmpOffset = 0; - retVal = -1; - } - if (tmpOffset > mnLength) - { - tmpOffset = mnLength; - retVal = -1; - } - try { - mxSeekable->seek(tmpOffset); - return retVal; + mxSeekable->seek(offset); + return 0; } catch (...) { @@ -255,6 +247,18 @@ WPXInputStream *WPXSvInputStreamImpl::getDocumentOLEStream(const char *name) } +void WPXSvInputStreamImpl::invalidateReadBuffer() +{ + if (mpReadBuffer) + { + seek((long) tell() + (long)mnReadBufferPos - (long)mnReadBufferLength); + delete [] mpReadBuffer; + mpReadBuffer = 0; + mnReadBufferPos = 0; + mnReadBufferLength = 0; + } +} + WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) : mpImpl(new WPXSvInputStreamImpl(xStream)) { @@ -262,36 +266,125 @@ WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) : WPXSvInputStream::~WPXSvInputStream() { - delete mpImpl; + if (mpImpl) + delete mpImpl; } +#define BUFFER_MAX 65536 + const unsigned char *WPXSvInputStream::read(unsigned long numBytes, unsigned long &numBytesRead) { - return mpImpl->read(numBytes, numBytesRead); + numBytesRead = 0; + + if (numBytes == 0 || numBytes > (std::numeric_limits::max)()/2) + return 0; + + if (mpImpl->mpReadBuffer) + { + if ((mpImpl->mnReadBufferPos + numBytes > mpImpl->mnReadBufferPos) && (mpImpl->mnReadBufferPos + numBytes <= mpImpl->mnReadBufferLength)) + { + const unsigned char *pTmp = mpImpl->mpReadBuffer + mpImpl->mnReadBufferPos; + mpImpl->mnReadBufferPos += numBytes; + numBytesRead = numBytes; + return pTmp; + } + + mpImpl->invalidateReadBuffer(); + } + + unsigned long curpos = (unsigned long) mpImpl->tell(); + if (curpos == (unsigned long)-1) // returned ERROR + return 0; + + if ((curpos + numBytes < curpos) /*overflow*/ || + (curpos + numBytes >= (sal_uInt64)mpImpl->mnLength)) /*reading more than available*/ + { + numBytes = mpImpl->mnLength - curpos; + } + + if (numBytes < BUFFER_MAX) + { + if (BUFFER_MAX < mpImpl->mnLength - curpos) + mpImpl->mnReadBufferLength = BUFFER_MAX; + else /* BUFFER_MAX >= mpImpl->mnLength - curpos */ + mpImpl->mnReadBufferLength = mpImpl->mnLength - curpos; + } + else + mpImpl->mnReadBufferLength = numBytes; + + mpImpl->seek((long) curpos); + + mpImpl->mpReadBuffer = new unsigned char[mpImpl->mnReadBufferLength]; + unsigned long tmpNumBytes(0); + const unsigned char *pTmp = mpImpl->read(mpImpl->mnReadBufferLength, tmpNumBytes); + if (tmpNumBytes != mpImpl->mnReadBufferLength) + mpImpl->mnReadBufferLength = tmpNumBytes; + + mpImpl->mnReadBufferPos = 0; + if (!mpImpl->mnReadBufferLength) + return 0; + + numBytesRead = numBytes; + + mpImpl->mnReadBufferPos += numBytesRead; + memcpy(mpImpl->mpReadBuffer, pTmp, mpImpl->mnReadBufferLength); + return const_cast(mpImpl->mpReadBuffer); } long WPXSvInputStream::tell() { - return mpImpl->tell(); + long retVal = mpImpl->tell(); + return retVal - (long)mpImpl->mnReadBufferLength + (long)mpImpl->mnReadBufferPos; } int WPXSvInputStream::seek(long offset, WPX_SEEK_TYPE seekType) { - return mpImpl->seek(offset, seekType); + sal_Int64 tmpOffset = offset; + if (seekType == WPX_SEEK_CUR) + tmpOffset += tell(); + if (seekType == WPX_SEEK_END) + tmpOffset += mpImpl->mnLength; + + int retVal = 0; + if (tmpOffset < 0) + { + tmpOffset = 0; + retVal = -1; + } + if (tmpOffset > mpImpl->mnLength) + { + tmpOffset = mpImpl->mnLength; + retVal = -1; + } + + if (tmpOffset < mpImpl->tell() && (unsigned long)tmpOffset >= (unsigned long)mpImpl->tell() - mpImpl->mnReadBufferLength) + { + mpImpl->mnReadBufferPos = (unsigned long)(tmpOffset + (long) mpImpl->mnReadBufferLength - (long) mpImpl->tell()); + return 0; + } + + mpImpl->invalidateReadBuffer(); + + int retVal2 = mpImpl->seek(tmpOffset); + if (retVal) + return retVal; + return retVal2; } bool WPXSvInputStream::atEOS() { - return mpImpl->atEOS(); + return mpImpl->atEOS() && mpImpl->mnReadBufferPos == mpImpl->mnReadBufferLength; } bool WPXSvInputStream::isOLEStream() { + mpImpl->invalidateReadBuffer(); return mpImpl->isOLEStream(); } WPXInputStream *WPXSvInputStream::getDocumentOLEStream(const char *name) { + mpImpl->invalidateReadBuffer(); return mpImpl->getDocumentOLEStream(name); } -- cgit v1.2.3