diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2024-08-17 13:19:54 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2024-08-27 09:10:04 +0200 |
commit | a6ad198d097fb4a503c8d5831d484ff46721134b (patch) | |
tree | e82ca01e800c5f50ce8db7bd8eb610790ee13c8d | |
parent | 03b31a8ad48e3b8a9e54203ff3856702557757b5 (diff) |
tdf#158556 use more comphelper::ByteReader
which avoids a ton of temporary uno::Sequence being created
Change-Id: I237bb69395f692bb0272ca0daec05b81af828e01
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171968
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Tested-by: Jenkins
27 files changed, 476 insertions, 92 deletions
diff --git a/comphelper/source/streaming/memorystream.cxx b/comphelper/source/streaming/memorystream.cxx index b457f4b42ca8..39ae66b51d07 100644 --- a/comphelper/source/streaming/memorystream.cxx +++ b/comphelper/source/streaming/memorystream.cxx @@ -55,7 +55,7 @@ namespace { class UNOMemoryStream : public WeakImplHelper<XServiceInfo, XStream, XSeekableInputStream, XOutputStream, XTruncate>, - public comphelper::ByteWriter + public comphelper::ByteWriter, public comphelper::ByteReader { public: UNOMemoryStream(); @@ -92,6 +92,9 @@ public: // comphelper::ByteWriter virtual void writeBytes(const sal_Int8* aData, sal_Int32 nBytesToWrite) override; + // comphelper::ByteReader + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; + private: std::vector< sal_Int8, boost::noinit_adaptor<std::allocator<sal_Int8>> > maData; sal_Int32 mnCursor; @@ -153,6 +156,26 @@ sal_Int32 SAL_CALL UNOMemoryStream::readBytes( Sequence< sal_Int8 >& aData, sal_ return nBytesToRead; } +// ByteReader +sal_Int32 UNOMemoryStream::readSomeBytes( sal_Int8* aData, sal_Int32 nBytesToRead ) +{ + if( nBytesToRead < 0 ) + throw IOException(u"nBytesToRead < 0"_ustr); + + nBytesToRead = std::min( nBytesToRead, available() ); + + if( nBytesToRead ) + { + sal_Int8* pData = &(*maData.begin()); + sal_Int8* pCursor = &(pData[mnCursor]); + memcpy( aData, pCursor, nBytesToRead ); + + mnCursor += nBytesToRead; + } + + return nBytesToRead; +} + sal_Int32 SAL_CALL UNOMemoryStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) { return readBytes( aData, nMaxBytesToRead ); diff --git a/comphelper/source/streaming/seekableinput.cxx b/comphelper/source/streaming/seekableinput.cxx index 6fd418df36ca..dceb16824c58 100644 --- a/comphelper/source/streaming/seekableinput.cxx +++ b/comphelper/source/streaming/seekableinput.cxx @@ -107,7 +107,11 @@ void OSeekableInputWrapper::PrepareCopy_Impl() xTempSeek->seek( 0 ); m_xCopyInput.set( xTempOut, uno::UNO_QUERY ); if ( m_xCopyInput.is() ) + { m_xCopySeek = xTempSeek; + m_pCopyByteReader = dynamic_cast<comphelper::ByteReader*>(xTempOut.get()); + assert(m_pCopyByteReader); + } } } @@ -142,6 +146,18 @@ sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 return m_xCopyInput->readSomeBytes( aData, nMaxBytesToRead ); } +sal_Int32 OSeekableInputWrapper::readSomeBytes( sal_Int8* aData, sal_Int32 nMaxBytesToRead ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_pCopyByteReader->readSomeBytes( aData, nMaxBytesToRead ); +} + void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) { @@ -186,6 +202,7 @@ void SAL_CALL OSeekableInputWrapper::closeInput() } m_xCopySeek.clear(); + m_pCopyByteReader = nullptr; } diff --git a/include/comphelper/seekableinput.hxx b/include/comphelper/seekableinput.hxx index 0c2092f7b849..2287b506e9e2 100644 --- a/include/comphelper/seekableinput.hxx +++ b/include/comphelper/seekableinput.hxx @@ -23,6 +23,7 @@ #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/XSeekable.hpp> #include <cppuhelper/implbase.hxx> +#include <comphelper/bytereader.hxx> #include <comphelper/comphelperdllapi.h> #include <mutex> @@ -37,7 +38,7 @@ class SAL_DLLPUBLIC_TEMPLATE OSeekableInputWrapper_BASE {}; class COMPHELPER_DLLPUBLIC OSeekableInputWrapper final - : public OSeekableInputWrapper_BASE + : public OSeekableInputWrapper_BASE, public comphelper::ByteReader { std::mutex m_aMutex; @@ -47,6 +48,7 @@ class COMPHELPER_DLLPUBLIC OSeekableInputWrapper final css::uno::Reference< css::io::XInputStream > m_xCopyInput; css::uno::Reference< css::io::XSeekable > m_xCopySeek; + comphelper::ByteReader* m_pCopyByteReader { nullptr }; private: COMPHELPER_DLLPRIVATE void PrepareCopy_Impl(); @@ -74,6 +76,8 @@ public: virtual sal_Int64 SAL_CALL getPosition() override; virtual sal_Int64 SAL_CALL getLength() override; +// comphelper::ByteReader + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; }; } // namespace comphelper diff --git a/include/package/Inflater.hxx b/include/package/Inflater.hxx index e0d44d21d6f6..d59d220acfc4 100644 --- a/include/package/Inflater.hxx +++ b/include/package/Inflater.hxx @@ -51,6 +51,28 @@ public: sal_Int32 getLastInflateError() const { return nLastInflateError; } }; +class UNLESS_MERGELIBS(DLLPUBLIC_PACKAGE) InflaterBytes final +{ + typedef struct z_stream_s z_stream; + + bool bFinished, bNeedDict; + sal_Int32 nOffset, nLength, nLastInflateError; + std::unique_ptr<z_stream> pStream; + const sal_Int8* sInBuffer; + sal_Int32 doInflateBytes (sal_Int8* pOutBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength); + +public: + InflaterBytes(bool bNoWrap); + ~InflaterBytes(); + void setInput( const sal_Int8* pBuffer, sal_Int32 nLen ); + bool needsDictionary() const { return bNeedDict; } + bool finished() const { return bFinished; } + sal_Int32 doInflateSegment( sal_Int8* pOutBuffer, sal_Int32 nBufLen, sal_Int32 nNewOffset, sal_Int32 nNewLength ); + void end( ); + + sal_Int32 getLastInflateError() const { return nLastInflateError; } +}; + } #endif diff --git a/package/inc/ByteGrabber.hxx b/package/inc/ByteGrabber.hxx index 04a5b35f3547..8a695338563e 100644 --- a/package/inc/ByteGrabber.hxx +++ b/package/inc/ByteGrabber.hxx @@ -21,6 +21,8 @@ #include <com/sun/star/uno/Sequence.h> #include <com/sun/star/uno/Reference.h> +#include <comphelper/bytereader.hxx> +#include <array> namespace com::sun::star { namespace io { class XSeekable; class XInputStream; } @@ -29,8 +31,8 @@ class ByteGrabber final { css::uno::Reference < css::io::XInputStream > xStream; css::uno::Reference < css::io::XSeekable > xSeek; - css::uno::Sequence < sal_Int8 > aSequence; - const sal_Int8 *pSequence; + comphelper::ByteReader* mpByteReader; + std::array<sal_Int8, 8> maBuffer; public: ByteGrabber (css::uno::Reference < css::io::XInputStream > const & xIstream); @@ -43,6 +45,7 @@ public: /// @throws css::io::IOException /// @throws css::uno::RuntimeException sal_Int32 readBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ); + sal_Int32 readBytes( sal_Int8* aData, sal_Int32 nBytesToRead ); // XSeekable /// @throws css::lang::IllegalArgumentException /// @throws css::io::IOException diff --git a/package/inc/CRC32.hxx b/package/inc/CRC32.hxx index a2ca1b435e0e..c96a48a00f60 100644 --- a/package/inc/CRC32.hxx +++ b/package/inc/CRC32.hxx @@ -35,6 +35,7 @@ public: sal_Int64 updateStream (css::uno::Reference < css::io::XInputStream > const & xStream); /// @throws css::uno::RuntimeException void updateSegment(const css::uno::Sequence< sal_Int8 > &b, sal_Int32 len); + void updateSegment(const sal_Int8* b, sal_Int32 len); /// @throws css::uno::RuntimeException void update(const css::uno::Sequence< sal_Int8 > &b); /// @throws css::uno::RuntimeException diff --git a/package/source/xstor/ocompinstream.cxx b/package/source/xstor/ocompinstream.cxx index 8a23169f6814..b71b8ef99697 100644 --- a/package/source/xstor/ocompinstream.cxx +++ b/package/source/xstor/ocompinstream.cxx @@ -38,6 +38,7 @@ OInputCompStream::OInputCompStream( OWriteStream_Impl& aImpl, : m_pImpl( &aImpl ) , m_xMutex( m_pImpl->m_xMutex ) , m_xStream(std::move( xStream )) +, m_pByteReader( dynamic_cast<comphelper::ByteReader*>(m_xStream.get()) ) , m_aProperties( aProps ) , m_bDisposed( false ) , m_nStorageType( nStorageType ) @@ -47,6 +48,7 @@ OInputCompStream::OInputCompStream( OWriteStream_Impl& aImpl, throw uno::RuntimeException(); // just a disaster assert(m_xStream.is()); + assert(m_pByteReader); } OInputCompStream::OInputCompStream( uno::Reference < io::XInputStream > xStream, @@ -55,11 +57,13 @@ OInputCompStream::OInputCompStream( uno::Reference < io::XInputStream > xStream, : m_pImpl( nullptr ) , m_xMutex( new comphelper::RefCountedMutex ) , m_xStream(std::move( xStream )) +, m_pByteReader( dynamic_cast<comphelper::ByteReader*>(m_xStream.get()) ) , m_aProperties( aProps ) , m_bDisposed( false ) , m_nStorageType( nStorageType ) { assert(m_xStream.is()); + assert(m_pByteReader); } OInputCompStream::~OInputCompStream() @@ -125,6 +129,19 @@ sal_Int32 SAL_CALL OInputCompStream::readSomeBytes( uno::Sequence< sal_Int8 >& a } +sal_Int32 OInputCompStream::readSomeBytes( sal_Int8* aData, sal_Int32 nMaxBytesToRead ) +{ + ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ); + if ( m_bDisposed ) + { + SAL_INFO("package.xstor", "Disposed!"); + throw lang::DisposedException(); + } + + return m_pByteReader->readSomeBytes( aData, nMaxBytesToRead ); + +} + void SAL_CALL OInputCompStream::skipBytes( sal_Int32 nBytesToSkip ) { ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ); diff --git a/package/source/xstor/ocompinstream.hxx b/package/source/xstor/ocompinstream.hxx index effbc4be2fb8..54fc7dc19308 100644 --- a/package/source/xstor/ocompinstream.hxx +++ b/package/source/xstor/ocompinstream.hxx @@ -28,6 +28,7 @@ #include <cppuhelper/implbase.hxx> #include <comphelper/interfacecontainer3.hxx> #include <comphelper/refcountedmutex.hxx> +#include <comphelper/bytereader.hxx> #include <rtl/ref.hxx> #include <memory> @@ -37,12 +38,14 @@ struct OWriteStream_Impl; class OInputCompStream : public cppu::WeakImplHelper < css::io::XInputStream ,css::embed::XExtendedStorageStream ,css::embed::XRelationshipAccess - ,css::beans::XPropertySet > + ,css::beans::XPropertySet >, + public comphelper::ByteReader { protected: OWriteStream_Impl* m_pImpl; rtl::Reference<comphelper::RefCountedMutex> m_xMutex; css::uno::Reference < css::io::XInputStream > m_xStream; + comphelper::ByteReader* m_pByteReader; std::unique_ptr<::comphelper::OInterfaceContainerHelper3<css::lang::XEventListener>> m_pInterfaceContainer; css::uno::Sequence < css::beans::PropertyValue > m_aProperties; bool m_bDisposed; @@ -102,6 +105,8 @@ public: virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener ) override; + // comphelper::ByteReader + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; }; #endif diff --git a/package/source/xstor/selfterminatefilestream.cxx b/package/source/xstor/selfterminatefilestream.cxx index f3fe79439781..80d21dd3bee5 100644 --- a/package/source/xstor/selfterminatefilestream.cxx +++ b/package/source/xstor/selfterminatefilestream.cxx @@ -62,6 +62,11 @@ sal_Int32 SAL_CALL OSelfTerminateFileStream::readSomeBytes( uno::Sequence< sal_I return m_xStreamWrapper->readSomeBytes( aData, nMaxBytesToRead ); } +sal_Int32 OSelfTerminateFileStream::readSomeBytes( sal_Int8* aData, sal_Int32 nMaxBytesToRead ) +{ + return m_xStreamWrapper->readSomeBytes( aData, nMaxBytesToRead ); +} + void SAL_CALL OSelfTerminateFileStream::skipBytes( sal_Int32 nBytesToSkip ) { return m_xStreamWrapper->skipBytes( nBytesToSkip ); diff --git a/package/source/xstor/selfterminatefilestream.hxx b/package/source/xstor/selfterminatefilestream.hxx index f8cedcb64c46..4520552956c5 100644 --- a/package/source/xstor/selfterminatefilestream.hxx +++ b/package/source/xstor/selfterminatefilestream.hxx @@ -24,6 +24,7 @@ #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/ucb/XSimpleFileAccess3.hpp> #include <com/sun/star/uno/XComponentContext.hpp> +#include <comphelper/bytereader.hxx> #include <cppuhelper/implbase.hxx> #include <unotools/streamwrap.hxx> #include <unotools/tempfile.hxx> @@ -33,7 +34,8 @@ struct OWriteStream_Impl; class OSelfTerminateFileStream final : public cppu::WeakImplHelper< css::io::XInputStream, - css::io::XSeekable > + css::io::XSeekable >, + public comphelper::ByteReader { std::optional<utl::TempFileFast> m_oTempFile; rtl::Reference< utl::OSeekableInputStreamWrapper > m_xStreamWrapper; @@ -57,6 +59,8 @@ public: virtual sal_Int64 SAL_CALL getPosition() override; virtual sal_Int64 SAL_CALL getLength() override; + // comphelper::ByteReader + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; }; #endif diff --git a/package/source/xstor/switchpersistencestream.cxx b/package/source/xstor/switchpersistencestream.cxx index ef07966f09d0..6613b8b046b1 100644 --- a/package/source/xstor/switchpersistencestream.cxx +++ b/package/source/xstor/switchpersistencestream.cxx @@ -39,6 +39,7 @@ struct SPStreamData_Impl uno::Reference< io::XSeekable > m_xOrigSeekable; uno::Reference< io::XInputStream > m_xOrigInStream; uno::Reference< io::XOutputStream > m_xOrigOutStream; + comphelper::ByteReader* m_pByteReader; bool m_bInOpen; bool m_bOutOpen; @@ -56,6 +57,7 @@ struct SPStreamData_Impl , m_xOrigSeekable(std::move( xOrigSeekable )) , m_xOrigInStream(std::move( xOrigInStream )) , m_xOrigOutStream(std::move( xOrigOutStream )) + , m_pByteReader(dynamic_cast<comphelper::ByteReader*>(m_xOrigInStream.get())) , m_bInOpen( bInOpen ) , m_bOutOpen( bOutOpen ) { @@ -243,6 +245,20 @@ uno::Reference< io::XOutputStream > SAL_CALL SwitchablePersistenceStream::getOut return m_pStreamData->m_xOrigInStream->readBytes( aData, nMaxBytesToRead ); } +::sal_Int32 SwitchablePersistenceStream::readSomeBytes( sal_Int8* aData, sal_Int32 nBytesToRead) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigInStream.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_pByteReader->readSomeBytes( aData, nBytesToRead ); +} + void SAL_CALL SwitchablePersistenceStream::skipBytes( ::sal_Int32 nBytesToSkip ) { std::scoped_lock aGuard( m_aMutex ); diff --git a/package/source/xstor/switchpersistencestream.hxx b/package/source/xstor/switchpersistencestream.hxx index 64d4e37fd025..657ed3e98949 100644 --- a/package/source/xstor/switchpersistencestream.hxx +++ b/package/source/xstor/switchpersistencestream.hxx @@ -29,6 +29,7 @@ #include <com/sun/star/io/XStream.hpp> #include <com/sun/star/io/XAsyncOutputMonitor.hpp> #include <mutex> +#include <comphelper/bytereader.hxx> #include <cppuhelper/implbase.hxx> // SwitchablePersistenceStream @@ -45,7 +46,8 @@ class SwitchablePersistenceStream css::io::XOutputStream, css::io::XTruncate, css::io::XSeekable, - css::io::XAsyncOutputMonitor > + css::io::XAsyncOutputMonitor >, + public comphelper::ByteReader { std::mutex m_aMutex; @@ -96,6 +98,8 @@ public: // css::io::XAsyncOutputMonitor virtual void SAL_CALL waitForCompletion( ) override; + // comphelper::ByteReader + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; }; #endif // INCLUDED_PACKAGE_SOURCE_XSTOR_SWITCHPERSISTENCESTREAM_HXX diff --git a/package/source/zipapi/ByteGrabber.cxx b/package/source/zipapi/ByteGrabber.cxx index 50083b4dafc2..cd9e201dba0b 100644 --- a/package/source/zipapi/ByteGrabber.cxx +++ b/package/source/zipapi/ByteGrabber.cxx @@ -39,9 +39,9 @@ using namespace ::com::sun::star; ByteGrabber::ByteGrabber(uno::Reference < io::XInputStream > const & xIstream) : xStream(xIstream) , xSeek (xIstream, uno::UNO_QUERY ) -, aSequence ( 4 ) { - pSequence = aSequence.getArray(); + mpByteReader = dynamic_cast<comphelper::ByteReader*>(xStream.get()); + assert(mpByteReader); } ByteGrabber::~ByteGrabber() @@ -52,6 +52,8 @@ void ByteGrabber::setInputStream (const uno::Reference < io::XInputStream >& xNe { xStream = xNewStream; xSeek.set(xNewStream, uno::UNO_QUERY); + mpByteReader = dynamic_cast<comphelper::ByteReader*>(xStream.get()); + assert(mpByteReader); } // XInputStream chained @@ -61,6 +63,12 @@ sal_Int32 ByteGrabber::readBytes( uno::Sequence< sal_Int8 >& aData, return xStream->readBytes(aData, nBytesToRead ); } +sal_Int32 ByteGrabber::readBytes( sal_Int8* aData, + sal_Int32 nBytesToRead ) +{ + return mpByteReader->readSomeBytes(aData, nBytesToRead ); +} + // XSeekable chained... void ByteGrabber::seek( sal_Int64 location ) { @@ -88,42 +96,39 @@ sal_Int64 ByteGrabber::getLength( ) sal_uInt16 ByteGrabber::ReadUInt16() { - if (xStream->readBytes(aSequence, 2) != 2) + if (mpByteReader->readSomeBytes(maBuffer.data(), 2) != 2) return 0; - pSequence = aSequence.getConstArray(); return static_cast <sal_uInt16> - ( (pSequence[0] & 0xFF) - | (pSequence[1] & 0xFF) << 8); + ( (maBuffer[0] & 0xFF) + | (maBuffer[1] & 0xFF) << 8); } sal_uInt32 ByteGrabber::ReadUInt32() { - if (xStream->readBytes(aSequence, 4) != 4) + if (mpByteReader->readSomeBytes(maBuffer.data(), 4) != 4) return 0; - pSequence = aSequence.getConstArray(); return static_cast < sal_uInt32 > - ( (pSequence[0] & 0xFF) - | ( pSequence[1] & 0xFF ) << 8 - | ( pSequence[2] & 0xFF ) << 16 - | ( pSequence[3] & 0xFF ) << 24 ); + ( (maBuffer[0] & 0xFF) + | ( maBuffer[1] & 0xFF ) << 8 + | ( maBuffer[2] & 0xFF ) << 16 + | ( maBuffer[3] & 0xFF ) << 24 ); } sal_uInt64 ByteGrabber::ReadUInt64() { - if (xStream->readBytes(aSequence, 8) != 8) + if (mpByteReader->readSomeBytes(maBuffer.data(), 8) != 8) return 0; - pSequence = aSequence.getConstArray(); - return static_cast<sal_uInt64>(pSequence[0] & 0xFF) - | static_cast<sal_uInt64>(pSequence[1] & 0xFF) << 8 - | static_cast<sal_uInt64>(pSequence[2] & 0xFF) << 16 - | static_cast<sal_uInt64>(pSequence[3] & 0xFF) << 24 - | static_cast<sal_uInt64>(pSequence[4] & 0xFF) << 32 - | static_cast<sal_uInt64>(pSequence[5] & 0xFF) << 40 - | static_cast<sal_uInt64>(pSequence[6] & 0xFF) << 48 - | static_cast<sal_uInt64>(pSequence[7] & 0xFF) << 56; + return static_cast<sal_uInt64>(maBuffer[0] & 0xFF) + | static_cast<sal_uInt64>(maBuffer[1] & 0xFF) << 8 + | static_cast<sal_uInt64>(maBuffer[2] & 0xFF) << 16 + | static_cast<sal_uInt64>(maBuffer[3] & 0xFF) << 24 + | static_cast<sal_uInt64>(maBuffer[4] & 0xFF) << 32 + | static_cast<sal_uInt64>(maBuffer[5] & 0xFF) << 40 + | static_cast<sal_uInt64>(maBuffer[6] & 0xFF) << 48 + | static_cast<sal_uInt64>(maBuffer[7] & 0xFF) << 56; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/CRC32.cxx b/package/source/zipapi/CRC32.cxx index bd06822486b3..b6415efbf2f8 100644 --- a/package/source/zipapi/CRC32.cxx +++ b/package/source/zipapi/CRC32.cxx @@ -46,6 +46,10 @@ void CRC32::updateSegment(const Sequence< sal_Int8 > &b, sal_Int32 len) { nCRC = rtl_crc32(nCRC, b.getConstArray(), len ); } +void CRC32::updateSegment(const sal_Int8* b, sal_Int32 len) +{ + nCRC = rtl_crc32(nCRC, b, len ); +} /** Update CRC32 with specified sequence of bytes */ void CRC32::update(const Sequence< sal_Int8 > &b) diff --git a/package/source/zipapi/Inflater.cxx b/package/source/zipapi/Inflater.cxx index d03fed8c0968..7867259aa764 100644 --- a/package/source/zipapi/Inflater.cxx +++ b/package/source/zipapi/Inflater.cxx @@ -134,4 +134,112 @@ sal_Int32 Inflater::doInflateBytes (Sequence < sal_Int8 > &rBuffer, sal_Int32 n return 0; } +InflaterBytes::InflaterBytes(bool bNoWrap) +: bFinished(false), + bNeedDict(false), + nOffset(0), + nLength(0), + nLastInflateError(0) +{ + pStream.reset(new z_stream); + /* memset to 0 to set zalloc/opaque etc */ + memset (pStream.get(), 0, sizeof(*pStream)); + sal_Int32 nRes; + nRes = inflateInit2(pStream.get(), bNoWrap ? -MAX_WBITS : MAX_WBITS); + switch (nRes) + { + case Z_OK: + break; + case Z_MEM_ERROR: + pStream.reset(); + break; + case Z_STREAM_ERROR: + pStream.reset(); + break; + default: + break; + } +} + +InflaterBytes::~InflaterBytes() +{ + end(); +} + +void InflaterBytes::setInput( const sal_Int8* rBuffer, sal_Int32 nBufLen ) +{ + sInBuffer = rBuffer; + nOffset = 0; + nLength = nBufLen; +} + + +sal_Int32 InflaterBytes::doInflateSegment( sal_Int8* pOutBuffer, sal_Int32 nBufLen, sal_Int32 nNewOffset, sal_Int32 nNewLength ) +{ + if (nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > nBufLen) + { + // do error handling + } + return doInflateBytes(pOutBuffer, nNewOffset, nNewLength); +} + +void InflaterBytes::end( ) +{ + if (pStream) + { +#if !defined Z_PREFIX + inflateEnd(pStream.get()); +#else + z_inflateEnd(pStream.get()); +#endif + pStream.reset(); + } +} + +sal_Int32 InflaterBytes::doInflateBytes (sal_Int8* pOutBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength) +{ + if ( !pStream ) + { + nLastInflateError = Z_STREAM_ERROR; + return 0; + } + + nLastInflateError = 0; + + pStream->next_in = reinterpret_cast<const unsigned char*>( sInBuffer + nOffset ); + pStream->avail_in = nLength; + pStream->next_out = reinterpret_cast < unsigned char* > ( pOutBuffer + nNewOffset ); + pStream->avail_out = nNewLength; + +#if !defined Z_PREFIX + sal_Int32 nResult = ::inflate(pStream.get(), Z_PARTIAL_FLUSH); +#else + sal_Int32 nResult = ::z_inflate(pStream.get(), Z_PARTIAL_FLUSH); +#endif + + switch (nResult) + { + case Z_STREAM_END: + bFinished = true; + [[fallthrough]]; + case Z_OK: + nOffset += nLength - pStream->avail_in; + nLength = pStream->avail_in; + return nNewLength - pStream->avail_out; + + case Z_NEED_DICT: + bNeedDict = true; + nOffset += nLength - pStream->avail_in; + nLength = pStream->avail_in; + return 0; + + default: + // it is no error, if there is no input or no output + if ( nLength && nNewLength ) + nLastInflateError = nResult; + } + + return 0; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/MemoryByteGrabber.hxx b/package/source/zipapi/MemoryByteGrabber.hxx index dd876d66ebfa..f9076067cd91 100644 --- a/package/source/zipapi/MemoryByteGrabber.hxx +++ b/package/source/zipapi/MemoryByteGrabber.hxx @@ -32,6 +32,12 @@ public: , mnEnd ( rBuffer.getLength() ) { } + MemoryByteGrabber ( const sal_Int8* pBuffer, sal_Int32 nBufLen ) + : mpBuffer ( pBuffer ) + , mnCurrent ( 0 ) + , mnEnd ( nBufLen ) + { + } MemoryByteGrabber(css::uno::Sequence<sal_Int8> &&) = delete; const sal_Int8 * getCurrentPos () const { return mpBuffer + mnCurrent; } diff --git a/package/source/zipapi/XBufferedThreadedStream.cxx b/package/source/zipapi/XBufferedThreadedStream.cxx index d3bf995d9073..ea7c270ebea6 100644 --- a/package/source/zipapi/XBufferedThreadedStream.cxx +++ b/package/source/zipapi/XBufferedThreadedStream.cxx @@ -158,6 +158,32 @@ sal_Int32 SAL_CALL XBufferedThreadedStream::readBytes( Sequence< sal_Int8 >& rDa return nAvailableSize; } +sal_Int32 XBufferedThreadedStream::readSomeBytes( sal_Int8* pData, sal_Int32 nBytesToRead ) +{ + if( !hasBytes() ) + return 0; + + const sal_Int32 nAvailableSize = static_cast< sal_Int32 > ( std::min< sal_Int64 >( nBytesToRead, remainingSize() ) ); + sal_Int32 i = 0, nPendingBytes = nAvailableSize; + + while( nPendingBytes ) + { + const Buffer &pBuffer = getNextBlock(); + if( !pBuffer.hasElements() ) + return nAvailableSize - nPendingBytes; + const sal_Int32 limit = std::min<sal_Int32>( nPendingBytes, pBuffer.getLength() - mnOffset ); + + memcpy( &pData[i], &pBuffer[mnOffset], limit ); + + nPendingBytes -= limit; + mnOffset += limit; + mnPos += limit; + i += limit; + } + + return nAvailableSize; +} + sal_Int32 SAL_CALL XBufferedThreadedStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) { return readBytes( aData, nMaxBytesToRead ); diff --git a/package/source/zipapi/XBufferedThreadedStream.hxx b/package/source/zipapi/XBufferedThreadedStream.hxx index beb1cd33c700..c3243f4f1326 100644 --- a/package/source/zipapi/XBufferedThreadedStream.hxx +++ b/package/source/zipapi/XBufferedThreadedStream.hxx @@ -12,6 +12,7 @@ #include <com/sun/star/io/XInputStream.hpp> +#include <comphelper/bytereader.hxx> #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> #include <salhelper/thread.hxx> @@ -23,7 +24,8 @@ typedef css::uno::Sequence< sal_Int8 > Buffer; -class XBufferedThreadedStream : public cppu::WeakImplHelper< css::io::XInputStream > +class XBufferedThreadedStream : public cppu::WeakImplHelper< css::io::XInputStream >, + public comphelper::ByteReader { private: const css::uno::Reference<XInputStream> mxSrcStream; @@ -78,6 +80,9 @@ public: virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override; virtual sal_Int32 SAL_CALL available( ) override; virtual void SAL_CALL closeInput( ) override; + + // comphelper::ByteReader + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; }; #endif diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index 2d8d69c853c7..37907647711b 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -590,7 +590,8 @@ uno::Reference<io::XInputStream> ZipFile::checkValidPassword( namespace { -class XBufferedStream : public cppu::WeakImplHelper<css::io::XInputStream, css::io::XSeekable> +class XBufferedStream : public cppu::WeakImplHelper<css::io::XInputStream, css::io::XSeekable>, + public comphelper::ByteReader { std::vector<sal_Int8> maBytes; size_t mnPos; @@ -655,6 +656,22 @@ public: return nReadSize; } + virtual sal_Int32 readSomeBytes(sal_Int8* pData, sal_Int32 nBytesToRead) override + { + if (!hasBytes()) + return 0; + + sal_Int32 nReadSize = std::min<sal_Int32>(nBytesToRead, remainingSize()); + std::vector<sal_Int8>::const_iterator it = maBytes.cbegin(); + std::advance(it, mnPos); + for (sal_Int32 i = 0; i < nReadSize; ++i, ++it) + pData[i] = *it; + + mnPos += nReadSize; + + return nReadSize; + } + virtual sal_Int32 SAL_CALL readSomeBytes( ::css::uno::Sequence<sal_Int8>& rData, sal_Int32 nMaxBytesToRead ) override { return readBytes(rData, nMaxBytesToRead); @@ -918,7 +935,12 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry) sal_Int64 nPos = -rEntry.nOffset; aGrabber.seek(nPos); - sal_Int32 nTestSig = aGrabber.ReadInt32(); + std::array<sal_Int8, 30> aHeader; + if (aGrabber.readBytes(aHeader.data(), 30) != 30) + throw new uno::RuntimeException(); + MemoryByteGrabber headerMemGrabber(aHeader.data(), 30); + + sal_Int32 nTestSig = headerMemGrabber.ReadInt32(); if (nTestSig != LOCSIG) throw ZipIOException(u"Invalid LOC header (bad signature)"_ustr ); @@ -927,18 +949,18 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry) // Just verify the path and calculate the data offset and otherwise // rely on the central directory info. - aGrabber.ReadInt16(); // version - ignore any mismatch (Maven created JARs) - sal_uInt16 const nLocFlag = aGrabber.ReadUInt16(); // general purpose bit flag - sal_uInt16 const nLocMethod = aGrabber.ReadUInt16(); // compression method + headerMemGrabber.ReadInt16(); // version - ignore any mismatch (Maven created JARs) + sal_uInt16 const nLocFlag = headerMemGrabber.ReadUInt16(); // general purpose bit flag + sal_uInt16 const nLocMethod = headerMemGrabber.ReadUInt16(); // compression method // Do *not* compare timestamps, since MSO 2010 can produce documents // with timestamp difference in the central directory entry and local // file header. - aGrabber.ReadInt32(); //time - sal_uInt32 nLocCrc = aGrabber.ReadUInt32(); //crc - sal_uInt64 nLocCompressedSize = aGrabber.ReadUInt32(); //compressed size - sal_uInt64 nLocSize = aGrabber.ReadUInt32(); //size - sal_Int16 nPathLen = aGrabber.ReadInt16(); - sal_Int16 nExtraLen = aGrabber.ReadInt16(); + headerMemGrabber.ReadInt32(); //time + sal_uInt32 nLocCrc = headerMemGrabber.ReadUInt32(); //crc + sal_uInt64 nLocCompressedSize = headerMemGrabber.ReadUInt32(); //compressed size + sal_uInt64 nLocSize = headerMemGrabber.ReadUInt32(); //size + sal_Int16 nPathLen = headerMemGrabber.ReadInt16(); + sal_Int16 nExtraLen = headerMemGrabber.ReadInt16(); if (nPathLen < 0) { @@ -955,13 +977,13 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry) { // read always in UTF8, some tools seem not to set UTF8 bit // coverity[tainted_data] - we've checked negative lens, and up to max short is ok here - uno::Sequence<sal_Int8> aNameBuffer(nPathLen); - sal_Int32 nRead = aGrabber.readBytes(aNameBuffer, nPathLen); - if (nRead < aNameBuffer.getLength()) - aNameBuffer.realloc(nRead); + std::vector<sal_Int8> aNameBuffer(nPathLen); + sal_Int32 nRead = aGrabber.readBytes(aNameBuffer.data(), nPathLen); + if (nRead < nPathLen) + aNameBuffer.resize(nRead); - OUString sLOCPath( reinterpret_cast<const char *>(aNameBuffer.getConstArray()), - aNameBuffer.getLength(), + OUString sLOCPath( reinterpret_cast<const char *>(aNameBuffer.data()), + nRead, RTL_TEXTENCODING_UTF8 ); if ( rEntry.nPathLen == -1 ) // the file was created @@ -980,9 +1002,9 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry) ::std::optional<sal_uInt64> oOffset64; if (nExtraLen != 0) { - Sequence<sal_Int8> aExtraBuffer; - aGrabber.readBytes(aExtraBuffer, nExtraLen); - MemoryByteGrabber extraMemGrabber(aExtraBuffer); + std::vector<sal_Int8> aExtraBuffer(nExtraLen); + aGrabber.readBytes(aExtraBuffer.data(), nExtraLen); + MemoryByteGrabber extraMemGrabber(aExtraBuffer.data(), nExtraLen); isZip64 = readExtraFields(extraMemGrabber, nExtraLen, nLocSize, nLocCompressedSize, oOffset64, &sLOCPath); @@ -1116,7 +1138,7 @@ sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry) std::tuple<sal_Int64, sal_Int64, sal_Int64> ZipFile::findCentralDirectory() { // this method is called in constructor only, no need for mutex - Sequence < sal_Int8 > aBuffer; + std::vector < sal_Int8 > aBuffer; try { sal_Int64 const nLength = aGrabber.getLength(); @@ -1130,10 +1152,11 @@ std::tuple<sal_Int64, sal_Int64, sal_Int64> ZipFile::findCentralDirectory() aGrabber.seek( nEnd ); auto nSize = nLength - nEnd; - if (nSize != aGrabber.readBytes(aBuffer, nSize)) + aBuffer.reserve(nSize); + if (nSize != aGrabber.readBytes(aBuffer.data(), nSize)) throw ZipException(u"Zip END signature not found!"_ustr ); - const sal_Int8 *pBuffer = aBuffer.getConstArray(); + const sal_Int8 *pBuffer = aBuffer.data(); sal_Int64 nEndPos = {}; nPos = nSize - ENDHDR; @@ -1176,9 +1199,10 @@ std::tuple<sal_Int64, sal_Int64, sal_Int64> ZipFile::findCentralDirectory() if (20 <= nEndPos) { aGrabber.seek(nEndPos - 20); - Sequence<sal_Int8> aZip64EndLocator; - aGrabber.readBytes(aZip64EndLocator, 20); - MemoryByteGrabber loc64Grabber(aZip64EndLocator); + std::array<sal_Int8, 20> aZip64EndLocator; + if (20 != aGrabber.readBytes(aZip64EndLocator.data(), 20)) + throw uno::RuntimeException(); + MemoryByteGrabber loc64Grabber(aZip64EndLocator.data(), 20); if (loc64Grabber.ReadUInt8() == 'P' && loc64Grabber.ReadUInt8() == 'K' && loc64Grabber.ReadUInt8() == 6 @@ -1201,9 +1225,9 @@ std::tuple<sal_Int64, sal_Int64, sal_Int64> ZipFile::findCentralDirectory() throw ZipException(u"invalid Zip64 end locator (number of disks)"_ustr); } aGrabber.seek(nLoc64End64Offset); - Sequence<sal_Int8> aZip64EndDirectory; - aGrabber.readBytes(aZip64EndDirectory, nEndPos - 20 - nLoc64End64Offset); - MemoryByteGrabber end64Grabber(aZip64EndDirectory); + std::vector<sal_Int8> aZip64EndDirectory(nEndPos - 20 - nLoc64End64Offset); + aGrabber.readBytes(aZip64EndDirectory.data(), nEndPos - 20 - nLoc64End64Offset); + MemoryByteGrabber end64Grabber(aZip64EndDirectory.data(), nEndPos - 20 - nLoc64End64Offset); if (end64Grabber.ReadUInt8() != 'P' || end64Grabber.ReadUInt8() != 'K' || end64Grabber.ReadUInt8() != 6 @@ -1309,12 +1333,12 @@ sal_Int32 ZipFile::readCEN() throw ZipException(u"central directory too big"_ustr); aGrabber.seek(nCenPos); - Sequence<sal_Int8> aCENBuffer(nCenLen); - sal_Int64 nRead = aGrabber.readBytes ( aCENBuffer, nCenLen ); + std::vector<sal_Int8> aCENBuffer(nCenLen); + sal_Int64 nRead = aGrabber.readBytes ( aCENBuffer.data(), nCenLen ); if (nCenLen != nRead) throw ZipException (u"Error reading CEN into memory buffer!"_ustr ); - MemoryByteGrabber aMemGrabber(aCENBuffer); + MemoryByteGrabber aMemGrabber(aCENBuffer.data(), nCenLen); ZipEntry aEntry; sal_Int16 nCommentLen; @@ -1590,29 +1614,30 @@ void ZipFile::HandlePK34(std::span<const sal_Int8> data, sal_Int64 dataOffset, s RTL_TEXTENCODING_UTF8); else { - Sequence<sal_Int8> aFileName; + std::vector<sal_Int8> aFileName(aEntry.nPathLen); aGrabber.seek(dataOffset + 30); - aGrabber.readBytes(aFileName, aEntry.nPathLen); - aEntry.sPath = OUString(reinterpret_cast<const char*>(aFileName.getConstArray()), - aFileName.getLength(), RTL_TEXTENCODING_UTF8); - aEntry.nPathLen = static_cast<sal_Int16>(aFileName.getLength()); + aGrabber.readBytes(aFileName.data(), aEntry.nPathLen); + aEntry.sPath = OUString(reinterpret_cast<const char*>(aFileName.data()), + aEntry.nPathLen, RTL_TEXTENCODING_UTF8); + aEntry.nPathLen = aEntry.nPathLen; } aEntry.sPath = aEntry.sPath.replace('\\', '/'); // read 64bit header if (aEntry.nExtraLen > 0) { - Sequence<sal_Int8> aExtraBuffer; + std::vector<sal_Int8> aExtraBuffer(aEntry.nExtraLen); if (o3tl::make_unsigned(30 + aEntry.nPathLen) + aEntry.nExtraLen <= data.size()) { - aExtraBuffer = Sequence<sal_Int8>(data.data() + 30 + aEntry.nPathLen, aEntry.nExtraLen); + auto it = data.begin() + 30 + aEntry.nPathLen; + std::copy(it, it + aEntry.nExtraLen, aExtraBuffer.begin()); } else { aGrabber.seek(dataOffset + 30 + aEntry.nExtraLen); - aGrabber.readBytes(aExtraBuffer, aEntry.nExtraLen); + aGrabber.readBytes(aExtraBuffer.data(), aEntry.nExtraLen); } - MemoryByteGrabber aMemGrabberExtra(aExtraBuffer); + MemoryByteGrabber aMemGrabberExtra(aExtraBuffer.data(), aEntry.nExtraLen); if (aEntry.nExtraLen > 0) { ::std::optional<sal_uInt64> oOffset64; @@ -1743,7 +1768,9 @@ void ZipFile::recover() { ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() ); - Sequence < sal_Int8 > aBuffer; + std::vector < sal_Int8 > aBuffer; + const sal_Int64 nToRead = 32000; + aBuffer.reserve(nToRead); try { @@ -1753,11 +1780,11 @@ void ZipFile::recover() aGrabber.seek( 0 ); - const sal_Int64 nToRead = 32000; - for( sal_Int64 nGenPos = 0; aGrabber.readBytes( aBuffer, nToRead ) && aBuffer.getLength() > 16; ) + sal_Int32 nRead; + for( sal_Int64 nGenPos = 0; (nRead = aGrabber.readBytes( aBuffer.data(), nToRead )) && nRead > 16; ) { - const sal_Int8 *pBuffer = aBuffer.getConstArray(); - const sal_Int32 nBufSize = aBuffer.getLength(); + const sal_Int8 *pBuffer = aBuffer.data(); + const sal_Int32 nBufSize = nRead; sal_Int64 nPos = 0; // the buffer should contain at least one header, @@ -1822,17 +1849,18 @@ sal_Int32 ZipFile::getCRC( sal_Int64 nOffset, sal_Int64 nSize ) { ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() ); - Sequence < sal_Int8 > aBuffer; CRC32 aCRC; sal_Int64 nBlockSize = ::std::min(nSize, static_cast< sal_Int64 >(32000)); + std::vector < sal_Int8 > aBuffer; + aBuffer.reserve(nBlockSize); aGrabber.seek( nOffset ); + sal_Int32 nRead; for (sal_Int64 ind = 0; - aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nSize; + (nRead = aGrabber.readBytes( aBuffer.data(), nBlockSize )) && ind * nBlockSize < nSize; ++ind) { - sal_Int64 nLen = ::std::min(nBlockSize, nSize - ind * nBlockSize); - aCRC.updateSegment(aBuffer, static_cast<sal_Int32>(nLen)); + aCRC.updateSegment(aBuffer.data(), nRead); } return aCRC.getValue(); @@ -1842,26 +1870,29 @@ void ZipFile::getSizeAndCRC( sal_Int64 nOffset, sal_Int64 nCompressedSize, sal_I { ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() ); - Sequence < sal_Int8 > aBuffer; CRC32 aCRC; sal_Int64 nRealSize = 0; - Inflater aInflaterLocal( true ); + ZipUtils::InflaterBytes aInflaterLocal( true ); sal_Int32 nBlockSize = static_cast< sal_Int32 > (::std::min( nCompressedSize, static_cast< sal_Int64 >( 32000 ) ) ); + std::vector < sal_Int8 > aBuffer(nBlockSize); + std::vector< sal_Int8 > aData( nBlockSize ); aGrabber.seek( nOffset ); + sal_Int32 nRead; for ( sal_Int64 ind = 0; - !aInflaterLocal.finished() && aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nCompressedSize; + !aInflaterLocal.finished() + && (nRead = aGrabber.readBytes( aBuffer.data(), nBlockSize )) + && ind * nBlockSize < nCompressedSize; ind++ ) { - Sequence < sal_Int8 > aData( nBlockSize ); sal_Int32 nLastInflated = 0; sal_Int64 nInBlock = 0; - aInflaterLocal.setInput( aBuffer ); + aInflaterLocal.setInput( aBuffer.data(), nRead ); do { - nLastInflated = aInflaterLocal.doInflateSegment( aData, 0, nBlockSize ); - aCRC.updateSegment( aData, nLastInflated ); + nLastInflated = aInflaterLocal.doInflateSegment( aData.data(), nBlockSize, 0, nBlockSize ); + aCRC.updateSegment( aData.data(), nLastInflated ); nInBlock += nLastInflated; } while( !aInflater.finished() && nLastInflated ); diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx index 1b129362b4a4..0b6b1ee0503f 100644 --- a/package/source/zippackage/ZipPackage.cxx +++ b/package/source/zippackage/ZipPackage.cxx @@ -1241,6 +1241,7 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const std::vector< void ZipPackage::ConnectTo( const uno::Reference< io::XInputStream >& xInStream ) { + assert(dynamic_cast<comphelper::ByteReader*>(xInStream.get())); m_xContentSeek.set( xInStream, uno::UNO_QUERY_THROW ); m_xContentStream = xInStream; diff --git a/package/source/zippackage/wrapstreamforshare.cxx b/package/source/zippackage/wrapstreamforshare.cxx index 250ccb4ba5ce..026aee989b01 100644 --- a/package/source/zippackage/wrapstreamforshare.cxx +++ b/package/source/zippackage/wrapstreamforshare.cxx @@ -46,6 +46,8 @@ WrapStreamForShare::WrapStreamForShare( uno::Reference< io::XInputStream > xInSt throw uno::RuntimeException(THROW_WHERE ); } m_xSeekable.set( m_xInStream, uno::UNO_QUERY_THROW ); + mpByteReader = dynamic_cast<comphelper::ByteReader*>(m_xInStream.get()); + assert(mpByteReader); } WrapStreamForShare::~WrapStreamForShare() @@ -79,6 +81,19 @@ sal_Int32 SAL_CALL WrapStreamForShare::readSomeBytes( uno::Sequence< sal_Int8 >& return nRead; } +sal_Int32 WrapStreamForShare::readSomeBytes( sal_Int8* aData, sal_Int32 nMaxBytesToRead ) +{ + if ( !m_xInStream.is() ) + throw io::IOException(THROW_WHERE ); + + m_xSeekable->seek( m_nCurPos ); + + sal_Int32 nRead = mpByteReader->readSomeBytes( aData, nMaxBytesToRead ); + m_nCurPos += nRead; + + return nRead; +} + void SAL_CALL WrapStreamForShare::skipBytes( sal_Int32 nBytesToSkip ) { ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ); @@ -113,6 +128,7 @@ void SAL_CALL WrapStreamForShare::closeInput() // m_xInStream->closeInput(); m_xInStream.clear(); m_xSeekable.clear(); + mpByteReader = nullptr; } // XSeekable diff --git a/package/source/zippackage/wrapstreamforshare.hxx b/package/source/zippackage/wrapstreamforshare.hxx index ac8de258842f..adc57862d4ea 100644 --- a/package/source/zippackage/wrapstreamforshare.hxx +++ b/package/source/zippackage/wrapstreamforshare.hxx @@ -22,15 +22,18 @@ #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/XSeekable.hpp> +#include <comphelper/bytereader.hxx> #include <comphelper/refcountedmutex.hxx> #include <cppuhelper/implbase.hxx> #include <rtl/ref.hxx> class WrapStreamForShare final : public cppu::WeakImplHelper < css::io::XInputStream - , css::io::XSeekable > + , css::io::XSeekable >, + public comphelper::ByteReader { rtl::Reference< comphelper::RefCountedMutex > m_xMutex; css::uno::Reference < css::io::XInputStream > m_xInStream; + comphelper::ByteReader* mpByteReader; css::uno::Reference < css::io::XSeekable > m_xSeekable; sal_Int64 m_nCurPos; @@ -52,6 +55,8 @@ public: virtual sal_Int64 SAL_CALL getPosition() override; virtual sal_Int64 SAL_CALL getLength() override; + // comphelper::ByteReader + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; }; #endif diff --git a/sot/source/sdstor/ucbstorage.cxx b/sot/source/sdstor/ucbstorage.cxx index a6aa800e2436..51c43bb290e3 100644 --- a/sot/source/sdstor/ucbstorage.cxx +++ b/sot/source/sdstor/ucbstorage.cxx @@ -87,7 +87,7 @@ typedef ::cppu::WeakImplHelper < XInputStream, XSeekable > FileInputStreamWrappe namespace { -class FileStreamWrapper_Impl : public FileInputStreamWrapper_Base +class FileStreamWrapper_Impl : public FileInputStreamWrapper_Base, public comphelper::ByteReader { protected: std::mutex m_aMutex; @@ -107,6 +107,8 @@ public: virtual sal_Int32 SAL_CALL available() override; virtual void SAL_CALL closeInput() override; + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; + protected: void checkConnected(); void checkError(); @@ -164,6 +166,23 @@ sal_Int32 SAL_CALL FileStreamWrapper_Impl::readBytes(Sequence< sal_Int8 >& aData return nRead; } +sal_Int32 FileStreamWrapper_Impl::readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) +{ + if ( m_aURL.isEmpty() ) + return 0; + + checkConnected(); + + if (nBytesToRead < 0) + throw BufferSizeExceededException(OUString(), getXWeak()); + + std::scoped_lock aGuard( m_aMutex ); + + sal_uInt32 nRead = m_pSvStream->ReadBytes(static_cast<void*>(aData), nBytesToRead); + checkError(); + + return nRead; +} sal_Int32 SAL_CALL FileStreamWrapper_Impl::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) { diff --git a/ucb/source/ucp/file/filinpstr.cxx b/ucb/source/ucp/file/filinpstr.cxx index 70e80e384d2b..33cbf32d1df6 100644 --- a/ucb/source/ucp/file/filinpstr.cxx +++ b/ucb/source/ucp/file/filinpstr.cxx @@ -99,6 +99,24 @@ XInputStream_impl::readBytes( return static_cast<sal_Int32>(nrc); } +sal_Int32 +XInputStream_impl::readSomeBytes( + sal_Int8* aData, + sal_Int32 nBytesToRead ) +{ + if( ! m_nIsOpen ) throw io::IOException( THROW_WHERE ); + + //TODO! translate memory exhaustion (if it were detectable...) into + // io::BufferSizeExceededException + + sal_uInt64 nrc(0); + if(m_aFile.read( aData, sal_uInt64(nBytesToRead),nrc ) + != osl::FileBase::E_None) + throw io::IOException( THROW_WHERE ); + + return static_cast<sal_Int32>(nrc); +} + sal_Int32 SAL_CALL XInputStream_impl::readSomeBytes( uno::Sequence< sal_Int8 >& aData, diff --git a/ucb/source/ucp/file/filinpstr.hxx b/ucb/source/ucp/file/filinpstr.hxx index f62fe4741170..d43cd2871bd6 100644 --- a/ucb/source/ucp/file/filinpstr.hxx +++ b/ucb/source/ucp/file/filinpstr.hxx @@ -22,7 +22,7 @@ #include <cppuhelper/implbase.hxx> #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/io/XInputStream.hpp> - +#include <comphelper/bytereader.hxx> #include "filrec.hxx" enum class TaskHandlerErr; @@ -32,7 +32,8 @@ namespace fileaccess { class TaskManager; class XInputStream_impl final - : public cppu::WeakImplHelper<css::io::XInputStream, css::io::XSeekable> + : public cppu::WeakImplHelper<css::io::XInputStream, css::io::XSeekable>, + public comphelper::ByteReader { public: @@ -75,6 +76,8 @@ namespace fileaccess { virtual sal_Int64 SAL_CALL getLength() override; + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; + private: bool m_nIsOpen; diff --git a/unotools/source/ucbhelper/XTempFile.hxx b/unotools/source/ucbhelper/XTempFile.hxx index 2b0ec33cb42a..456dd7da186e 100644 --- a/unotools/source/ucbhelper/XTempFile.hxx +++ b/unotools/source/ucbhelper/XTempFile.hxx @@ -46,7 +46,7 @@ typedef ::cppu::WeakImplHelper< css::io::XTempFile , css::beans::XPropertyAccess , css::lang::XServiceInfo> OTempFileBase; -class OTempFileService : public OTempFileBase +class OTempFileService : public OTempFileBase, public comphelper::ByteReader { std::optional<utl::TempFileNamed> mpTempFile; std::mutex maMutex; @@ -112,6 +112,7 @@ public: virtual ::css::uno::Sequence< ::css::beans::PropertyValue > SAL_CALL getPropertyValues() override; virtual void SAL_CALL setPropertyValues( const ::css::uno::Sequence< ::css::beans::PropertyValue >& aProps ) override; + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) override; virtual ~OTempFileService () override; }; diff --git a/unotools/source/ucbhelper/xtempfile.cxx b/unotools/source/ucbhelper/xtempfile.cxx index 35462587ff84..7e27b7f4d24f 100644 --- a/unotools/source/ucbhelper/xtempfile.cxx +++ b/unotools/source/ucbhelper/xtempfile.cxx @@ -147,6 +147,21 @@ sal_Int32 SAL_CALL OTempFileService::readSomeBytes( css::uno::Sequence< sal_Int8 } return readBytes(aData, nMaxBytesToRead); } +sal_Int32 OTempFileService::readSomeBytes( sal_Int8* aData, sal_Int32 nBytesToRead ) +{ + std::unique_lock aGuard( maMutex ); + if ( mbInClosed ) + throw css::io::NotConnectedException ( OUString(), getXWeak() ); + + checkConnected(); + if (nBytesToRead < 0) + throw css::io::BufferSizeExceededException( OUString(), getXWeak()); + + sal_uInt32 nRead = mpStream->ReadBytes(static_cast<void*>(aData), nBytesToRead); + checkError(); + + return nRead; +} void SAL_CALL OTempFileService::skipBytes( sal_Int32 nBytesToSkip ) { std::unique_lock aGuard( maMutex ); |