summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2022-05-19 13:46:40 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2022-05-19 21:04:48 +0200
commit62531ec1091c7b3f6a3577889a18234790ec716d (patch)
tree72766dd4a58bbf61e2a56adc870d1a73307a9043
parent5eb25f6a7ecb215f7bc81116cd930c1dec645e8d (diff)
add ByteWriter to reduce memory copying when writing data
similarly to ByteReader move both of them down to comphelper, since we want to use it from comphelper, and comphelper is "below" unotools in the module dependency graph Change-Id: Ic98fa2268e125fd8e4378fb899ad5f97de721713 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134645 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
-rw-r--r--comphelper/source/misc/storagehelper.cxx48
-rw-r--r--comphelper/source/streaming/basicio.cxx18
-rw-r--r--comphelper/source/streaming/seqstream.cxx24
-rw-r--r--include/comphelper/bytereader.hxx (renamed from include/unotools/bytereader.hxx)19
-rw-r--r--include/comphelper/seqstream.hxx11
-rw-r--r--include/unotools/streamwrap.hxx4
-rw-r--r--package/source/xstor/owriteablestream.cxx82
-rw-r--r--package/source/xstor/owriteablestream.hxx10
-rw-r--r--ucb/source/ucp/file/filstr.cxx4
-rw-r--r--ucb/source/ucp/file/filstr.hxx4
-rw-r--r--unotools/source/streaming/streamhelper.cxx10
-rw-r--r--unotools/source/streaming/streamwrap.cxx4
-rw-r--r--unotools/source/ucbhelper/ucblockbytes.cxx6
13 files changed, 209 insertions, 35 deletions
diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx
index 8e08612b0699..5f8527bcf273 100644
--- a/comphelper/source/misc/storagehelper.cxx
+++ b/comphelper/source/misc/storagehelper.cxx
@@ -27,6 +27,7 @@
#include <com/sun/star/embed/FileSystemStorageFactory.hpp>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
@@ -48,6 +49,7 @@
#include <ucbhelper/content.hxx>
+#include <comphelper/bytereader.hxx>
#include <comphelper/fileformat.h>
#include <comphelper/hash.hxx>
#include <comphelper/processfactory.hxx>
@@ -173,21 +175,47 @@ void OStorageHelper::CopyInputToOutput(
{
static const sal_Int32 nConstBufferSize = 32000;
- sal_Int32 nRead;
- uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
+ uno::Reference< css::lang::XUnoTunnel > xInputTunnel( xInput, uno::UNO_QUERY );
+ comphelper::ByteReader* pByteReader = nullptr;
+ comphelper::ByteWriter* pByteWriter = nullptr;
+ if (xInputTunnel)
+ pByteReader = reinterpret_cast< comphelper::ByteReader* >( xInputTunnel->getSomething( comphelper::ByteReader::getUnoTunnelId() ) );
+ if (pByteReader)
+ {
+ uno::Reference< css::lang::XUnoTunnel > xOutputTunnel( xOutput, uno::UNO_QUERY );
+ if (xOutputTunnel)
+ pByteWriter = reinterpret_cast< comphelper::ByteWriter* >( xOutputTunnel->getSomething( comphelper::ByteWriter::getUnoTunnelId() ) );
+ }
- do
+ if (pByteWriter)
{
- nRead = xInput->readBytes ( aSequence, nConstBufferSize );
- if ( nRead < nConstBufferSize )
+ sal_Int32 nRead;
+ sal_Int8 aTempBuf[ nConstBufferSize ];
+ do
{
- uno::Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
- xOutput->writeBytes ( aTempBuf );
+ nRead = pByteReader->readSomeBytes ( aTempBuf, nConstBufferSize );
+ pByteWriter->writeSomeBytes ( aTempBuf, nRead );
}
- else
- xOutput->writeBytes ( aSequence );
+ while ( nRead == nConstBufferSize );
+ }
+ else
+ {
+ sal_Int32 nRead;
+ uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize );
+
+ do
+ {
+ nRead = xInput->readBytes ( aSequence, nConstBufferSize );
+ if ( nRead < nConstBufferSize )
+ {
+ uno::Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
+ xOutput->writeBytes ( aTempBuf );
+ }
+ else
+ xOutput->writeBytes ( aSequence );
+ }
+ while ( nRead == nConstBufferSize );
}
- while ( nRead == nConstBufferSize );
}
diff --git a/comphelper/source/streaming/basicio.cxx b/comphelper/source/streaming/basicio.cxx
index d86427b7de81..b8c0c96e2cfa 100644
--- a/comphelper/source/streaming/basicio.cxx
+++ b/comphelper/source/streaming/basicio.cxx
@@ -18,6 +18,8 @@
*/
#include <comphelper/basicio.hxx>
+#include <comphelper/bytereader.hxx>
+#include <comphelper/servicehelper.hxx>
#include <com/sun/star/awt/FontDescriptor.hpp>
namespace comphelper
@@ -157,6 +159,22 @@ const css::uno::Reference<css::io::XObjectOutputStream>& operator << (const css:
return _rxOutStream;
}
+ByteReader::~ByteReader() {}
+
+const css::uno::Sequence< sal_Int8 > & ByteReader::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+}
+
+ByteWriter::~ByteWriter() {}
+
+const css::uno::Sequence< sal_Int8 > & ByteWriter::getUnoTunnelId()
+{
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+}
+
} // namespace comphelper
diff --git a/comphelper/source/streaming/seqstream.cxx b/comphelper/source/streaming/seqstream.cxx
index db39a1dc30e8..1f37a7967b04 100644
--- a/comphelper/source/streaming/seqstream.cxx
+++ b/comphelper/source/streaming/seqstream.cxx
@@ -74,6 +74,30 @@ sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sa
return nBytesToRead;
}
+sal_Int32 SequenceInputStream::readSomeBytes( sal_Int8* pData, sal_Int32 nBytesToRead )
+{
+ if (nBytesToRead < 0)
+ throw BufferSizeExceededException(OUString(),*this);
+
+ std::scoped_lock aGuard( m_aMutex );
+
+ sal_Int32 nAvail = avail();
+
+ if (nAvail < nBytesToRead)
+ nBytesToRead = nAvail;
+
+ memcpy(pData, m_aData.getConstArray() + m_nPos, nBytesToRead);
+ m_nPos += nBytesToRead;
+
+ return nBytesToRead;
+}
+
+sal_Int64 SAL_CALL SequenceInputStream::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
+{
+ if (rIdentifier == comphelper::ByteReader::getUnoTunnelId())
+ return reinterpret_cast<sal_Int64>(static_cast<comphelper::ByteReader*>(this));
+ return 0;
+}
sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead )
{
diff --git a/include/unotools/bytereader.hxx b/include/comphelper/bytereader.hxx
index 8edf19929eea..a7e899098846 100644
--- a/include/unotools/bytereader.hxx
+++ b/include/comphelper/bytereader.hxx
@@ -8,16 +8,16 @@
*/
#pragma once
-#include <unotools/unotoolsdllapi.h>
+#include <comphelper/comphelperdllapi.h>
#include <com/sun/star/uno/Sequence.hxx>
-namespace utl
+namespace comphelper
{
/**
* Interface that we can cast to, to bypass the inefficiency of using Sequence<sal_Int8>
* when reading via XInputStream.
*/
-class UNOTOOLS_DLLPUBLIC ByteReader
+class COMPHELPER_DLLPUBLIC ByteReader
{
public:
virtual ~ByteReader();
@@ -26,6 +26,19 @@ public:
static const css::uno::Sequence<sal_Int8>& getUnoTunnelId();
};
+/**
+ * Interface that we can cast to, to bypass the inefficiency of using Sequence<sal_Int8>
+ * when writing via XOutputStream.
+ */
+class COMPHELPER_DLLPUBLIC ByteWriter
+{
+public:
+ virtual ~ByteWriter();
+ virtual sal_Int32 writeSomeBytes(const sal_Int8* aData, sal_Int32 nBytesToWrite) = 0;
+
+ static const css::uno::Sequence<sal_Int8>& getUnoTunnelId();
+};
+
} // namespace utl
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/include/comphelper/seqstream.hxx b/include/comphelper/seqstream.hxx
index 6cf22fdb6ebb..c2ba3913432b 100644
--- a/include/comphelper/seqstream.hxx
+++ b/include/comphelper/seqstream.hxx
@@ -24,8 +24,10 @@
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <cppuhelper/implbase.hxx>
#include <comphelper/comphelperdllapi.h>
+#include <comphelper/bytereader.hxx>
#include <mutex>
namespace comphelper
@@ -37,7 +39,8 @@ namespace comphelper
class COMPHELPER_DLLPUBLIC SequenceInputStream final
- : public ::cppu::WeakImplHelper< css::io::XInputStream, css::io::XSeekable >
+ : public ::cppu::WeakImplHelper< css::io::XInputStream, css::io::XSeekable, css::lang::XUnoTunnel >,
+ public comphelper::ByteReader
{
std::mutex m_aMutex;
css::uno::Sequence<sal_Int8> const m_aData;
@@ -61,6 +64,12 @@ public:
virtual sal_Int64 SAL_CALL getPosition( ) override;
virtual sal_Int64 SAL_CALL getLength( ) override;
+// css::lang::XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+
+// comphelper::ByteReader
+ virtual sal_Int32 readSomeBytes( sal_Int8* pData, sal_Int32 nBytesToRead ) override;
+
private:
sal_Int32 avail();
};
diff --git a/include/unotools/streamwrap.hxx b/include/unotools/streamwrap.hxx
index 15e729f156f3..dc4c51807189 100644
--- a/include/unotools/streamwrap.hxx
+++ b/include/unotools/streamwrap.hxx
@@ -27,9 +27,9 @@
#include <com/sun/star/io/XTruncate.hpp>
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <comphelper/bytereader.hxx>
#include <cppuhelper/implbase.hxx>
#include <cppuhelper/implbase1.hxx>
-#include <unotools/bytereader.hxx>
#include <memory>
#include <mutex>
@@ -42,7 +42,7 @@ namespace utl
class SAL_DLLPUBLIC_TEMPLATE OInputStreamWrapper_Base : public cppu::WeakImplHelper< css::io::XInputStream, css::lang::XUnoTunnel > {};
/// helper class for wrapping an SvStream into a com.sun.star.io::XInputStream
-class UNOTOOLS_DLLPUBLIC OInputStreamWrapper : public OInputStreamWrapper_Base, public ByteReader
+class UNOTOOLS_DLLPUBLIC OInputStreamWrapper : public OInputStreamWrapper_Base, public comphelper::ByteReader
{
protected:
std::mutex m_aMutex;
diff --git a/package/source/xstor/owriteablestream.cxx b/package/source/xstor/owriteablestream.cxx
index 8f9a93a2cc11..19707a5d4ee5 100644
--- a/package/source/xstor/owriteablestream.cxx
+++ b/package/source/xstor/owriteablestream.cxx
@@ -2137,6 +2137,88 @@ void SAL_CALL OWriteStream::writeBytes( const uno::Sequence< sal_Int8 >& aData )
ModifyParentUnlockMutex_Impl( aGuard );
}
+sal_Int32 OWriteStream::writeSomeBytes( const sal_Int8* pData, sal_Int32 nBytesToWrite )
+{
+ osl::ClearableMutexGuard aGuard(m_pData->m_xSharedMutex->GetMutex());
+
+ // the write method makes initialization itself, since it depends from the aData length
+ // NO CheckInitOnDemand()!
+
+ if ( !m_pImpl )
+ {
+ SAL_INFO("package.xstor", "Disposed!");
+ throw lang::DisposedException();
+ }
+
+ if ( !m_bInitOnDemand )
+ {
+ if ( !m_xOutStream.is() || !m_xSeekable.is())
+ throw io::NotConnectedException();
+
+ if ( m_pImpl->m_xCacheStream.is() )
+ {
+ // check whether the cache should be turned off
+ sal_Int64 nPos = m_xSeekable->getPosition();
+ if ( nPos + nBytesToWrite > MAX_STORCACHE_SIZE )
+ {
+ // disconnect the cache and copy the data to the temporary file
+ m_xSeekable->seek( 0 );
+
+ // it is enough to copy the cached stream, the cache should already contain everything
+ if ( !m_pImpl->GetFilledTempFileIfNo( m_xInStream ).isEmpty() )
+ {
+ DeInit();
+ // the last position is known and it is differs from the current stream position
+ m_nInitPosition = nPos;
+ }
+ }
+ }
+ }
+
+ if ( m_bInitOnDemand )
+ {
+ SAL_INFO( "package.xstor", "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" );
+ uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream();
+ if ( xStream.is() )
+ {
+ m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW );
+ m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW );
+ m_xSeekable.set( xStream, uno::UNO_QUERY_THROW );
+ m_xSeekable->seek( m_nInitPosition );
+
+ m_nInitPosition = 0;
+ m_bInitOnDemand = false;
+ }
+ }
+
+ if ( !m_xOutStream.is() )
+ throw io::NotConnectedException();
+
+ uno::Reference< css::lang::XUnoTunnel > xOutputTunnel( m_xOutStream, uno::UNO_QUERY );
+ comphelper::ByteWriter* pByteWriter = nullptr;
+ if (xOutputTunnel)
+ pByteWriter = reinterpret_cast< comphelper::ByteWriter* >( xOutputTunnel->getSomething( comphelper::ByteWriter::getUnoTunnelId() ) );
+ if (pByteWriter)
+ nBytesToWrite = pByteWriter->writeSomeBytes(pData, nBytesToWrite);
+ else
+ {
+ uno::Sequence<sal_Int8> aData(pData, nBytesToWrite);
+ m_xOutStream->writeBytes( aData );
+ }
+ m_pImpl->m_bHasDataToFlush = true;
+
+ ModifyParentUnlockMutex_Impl( aGuard );
+
+ return nBytesToWrite;
+}
+
+sal_Int64 SAL_CALL OWriteStream::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
+{
+ if (rIdentifier == comphelper::ByteWriter::getUnoTunnelId())
+ return reinterpret_cast<sal_Int64>(static_cast<comphelper::ByteWriter*>(this));
+ return 0;
+}
+
void SAL_CALL OWriteStream::flush()
{
// In case stream is flushed its current version becomes visible
diff --git a/package/source/xstor/owriteablestream.hxx b/package/source/xstor/owriteablestream.hxx
index 5e87aa3e3047..6c2b657e3160 100644
--- a/package/source/xstor/owriteablestream.hxx
+++ b/package/source/xstor/owriteablestream.hxx
@@ -28,6 +28,7 @@
#include <com/sun/star/packages/XDataSinkEncrSupport.hpp>
#include <com/sun/star/lang/XEventListener.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/XRelationshipAccess.hpp>
@@ -39,6 +40,7 @@
#include <cppuhelper/weak.hxx>
+#include <comphelper/bytereader.hxx>
#include <comphelper/refcountedmutex.hxx>
#include <comphelper/sequenceashashmap.hxx>
@@ -229,7 +231,9 @@ class OWriteStream : public css::lang::XTypeProvider
, public css::embed::XTransactedObject
, public css::embed::XTransactionBroadcaster
, public css::beans::XPropertySet
+ , public css::lang::XUnoTunnel
, public ::cppu::OWeakObject
+ , public comphelper::ByteWriter
{
friend struct OWriteStream_Impl;
@@ -342,6 +346,12 @@ public:
virtual void SAL_CALL removeTransactionListener(
const css::uno::Reference< css::embed::XTransactionListener >& aListener ) override;
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override;
+
+ // comphelper::ByteWriter
+ virtual sal_Int32 writeSomeBytes(const sal_Int8* aData, sal_Int32 nBytesToWrite) override;
+
};
#endif
diff --git a/ucb/source/ucp/file/filstr.cxx b/ucb/source/ucp/file/filstr.cxx
index 8e605f7f1cc6..8c88b9fc2e54 100644
--- a/ucb/source/ucp/file/filstr.cxx
+++ b/ucb/source/ucp/file/filstr.cxx
@@ -167,8 +167,8 @@ XStream_impl::readSomeBytes(
sal_Int64 SAL_CALL XStream_impl::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
{
- if (rIdentifier == utl::ByteReader::getUnoTunnelId())
- return reinterpret_cast<sal_Int64>(static_cast<utl::ByteReader*>(this));
+ if (rIdentifier == comphelper::ByteReader::getUnoTunnelId())
+ return reinterpret_cast<sal_Int64>(static_cast<comphelper::ByteReader*>(this));
return 0;
}
diff --git a/ucb/source/ucp/file/filstr.hxx b/ucb/source/ucp/file/filstr.hxx
index 65cf4369ce75..7ba43753f261 100644
--- a/ucb/source/ucp/file/filstr.hxx
+++ b/ucb/source/ucp/file/filstr.hxx
@@ -26,8 +26,8 @@
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/io/XAsyncOutputMonitor.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <comphelper/bytereader.hxx>
#include <cppuhelper/implbase.hxx>
-#include <unotools/bytereader.hxx>
#include <mutex>
#include "filrec.hxx"
@@ -45,7 +45,7 @@ class XStream_impl : public cppu::WeakImplHelper<
css::io::XTruncate,
css::io::XAsyncOutputMonitor,
css::lang::XUnoTunnel >,
- public utl::ByteReader
+ public comphelper::ByteReader
{
public:
diff --git a/unotools/source/streaming/streamhelper.cxx b/unotools/source/streaming/streamhelper.cxx
index 39585ec5f369..b5f07e6a6a7f 100644
--- a/unotools/source/streaming/streamhelper.cxx
+++ b/unotools/source/streaming/streamhelper.cxx
@@ -22,10 +22,8 @@
#include <com/sun/star/io/BufferSizeExceededException.hpp>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/io/NotConnectedException.hpp>
-#include <comphelper/servicehelper.hxx>
#include <o3tl/safeint.hxx>
#include <unotools/streamhelper.hxx>
-#include <unotools/bytereader.hxx>
namespace utl
{
@@ -120,14 +118,6 @@ void SAL_CALL OInputStreamHelper::acquire() SAL_NOEXCEPT
cppu::WeakImplHelper<css::io::XInputStream, css::io::XSeekable>::acquire();
}
-ByteReader::~ByteReader() {}
-
-const css::uno::Sequence< sal_Int8 > & ByteReader::getUnoTunnelId()
-{
- static const comphelper::UnoIdInit implId;
- return implId.getSeq();
-}
-
} // namespace utl
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/unotools/source/streaming/streamwrap.cxx b/unotools/source/streaming/streamwrap.cxx
index 0ed933b530e3..6a6cbbd20142 100644
--- a/unotools/source/streaming/streamwrap.cxx
+++ b/unotools/source/streaming/streamwrap.cxx
@@ -158,8 +158,8 @@ void OInputStreamWrapper::checkError() const
sal_Int64 SAL_CALL OInputStreamWrapper::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
{
- if (rIdentifier == utl::ByteReader::getUnoTunnelId())
- return reinterpret_cast<sal_Int64>(static_cast<utl::ByteReader*>(this));
+ if (rIdentifier == comphelper::ByteReader::getUnoTunnelId())
+ return reinterpret_cast<sal_Int64>(static_cast<comphelper::ByteReader*>(this));
return 0;
}
diff --git a/unotools/source/ucbhelper/ucblockbytes.cxx b/unotools/source/ucbhelper/ucblockbytes.cxx
index b40be28f2225..9cbee8ef6b95 100644
--- a/unotools/source/ucbhelper/ucblockbytes.cxx
+++ b/unotools/source/ucbhelper/ucblockbytes.cxx
@@ -56,9 +56,9 @@
#include <com/sun/star/io/XTruncate.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <comphelper/bytereader.hxx>
#include <comphelper/storagehelper.hxx>
#include <ucbhelper/content.hxx>
-#include <unotools/bytereader.hxx>
#include <mutex>
using namespace ::com::sun::star::uno;
@@ -1110,9 +1110,9 @@ ErrCode UcbLockBytes::ReadAt(sal_uInt64 const nPos,
}
Reference< css::lang::XUnoTunnel > xTunnel( xStream, UNO_QUERY );
- utl::ByteReader* pByteReader = nullptr;
+ comphelper::ByteReader* pByteReader = nullptr;
if (xTunnel)
- pByteReader = reinterpret_cast< utl::ByteReader* >( xTunnel->getSomething( utl::ByteReader::getUnoTunnelId() ) );
+ pByteReader = reinterpret_cast< comphelper::ByteReader* >( xTunnel->getSomething( comphelper::ByteReader::getUnoTunnelId() ) );
if (pByteReader)
{