include/unotools/bytereader.hxx | 31 +++++++++++++++++++++++++++++ include/unotools/streamwrap.hxx | 12 +++++++++-- ucb/Library_ucpfile1.mk | 1 ucb/source/ucp/file/filstr.cxx | 23 +++++++++++++++++++++ ucb/source/ucp/file/filstr.hxx | 15 +++++++++++++- unotools/source/streaming/streamhelper.cxx | 10 +++++++++ unotools/source/streaming/streamwrap.cxx | 23 +++++++++++++++++++++ unotools/source/ucbhelper/ucblockbytes.cxx | 20 +++++++++++++++--- 8 files changed, 129 insertions(+), 6 deletions(-)
New commits: commit d1dc27fef899ff6cd70873cd945d5312a53e1b3a Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Sun May 15 13:03:18 2022 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Thu May 19 09:29:14 2022 +0200 add utl::ByteReader pure class which lets us skip the inefficiency of needing an extra buffer when reading via XInputStream Change-Id: Ic5334b7d11ea6a57bc1800f508fc69611a053af1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134348 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/include/unotools/bytereader.hxx b/include/unotools/bytereader.hxx new file mode 100644 index 000000000000..8edf19929eea --- /dev/null +++ b/include/unotools/bytereader.hxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include <unotools/unotoolsdllapi.h> +#include <com/sun/star/uno/Sequence.hxx> + +namespace utl +{ +/** + * Interface that we can cast to, to bypass the inefficiency of using Sequence<sal_Int8> + * when reading via XInputStream. + */ +class UNOTOOLS_DLLPUBLIC ByteReader +{ +public: + virtual ~ByteReader(); + virtual sal_Int32 readSomeBytes(sal_Int8* aData, sal_Int32 nBytesToRead) = 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/unotools/streamwrap.hxx b/include/unotools/streamwrap.hxx index 4993ffd92f7c..15e729f156f3 100644 --- a/include/unotools/streamwrap.hxx +++ b/include/unotools/streamwrap.hxx @@ -26,8 +26,10 @@ #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/io/XTruncate.hpp> #include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> #include <cppuhelper/implbase.hxx> #include <cppuhelper/implbase1.hxx> +#include <unotools/bytereader.hxx> #include <memory> #include <mutex> @@ -37,10 +39,10 @@ namespace utl { // workaround for incremental linking bugs in MSVC2015 -class SAL_DLLPUBLIC_TEMPLATE OInputStreamWrapper_Base : public cppu::WeakImplHelper< css::io::XInputStream > {}; +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 +class UNOTOOLS_DLLPUBLIC OInputStreamWrapper : public OInputStreamWrapper_Base, public ByteReader { protected: std::mutex m_aMutex; @@ -64,6 +66,12 @@ public: virtual sal_Int32 SAL_CALL available() override; virtual void SAL_CALL closeInput() override; +// css::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& _rIdentifier ) override; + +// utl::ByteReader + virtual sal_Int32 readSomeBytes( sal_Int8* aData, sal_Int32 nMaxBytesToRead ) final override; + protected: /// throws a NotConnectedException if the object is not connected anymore void checkConnected() const; diff --git a/ucb/Library_ucpfile1.mk b/ucb/Library_ucpfile1.mk index 2f9684955ec5..f67c69b78b28 100644 --- a/ucb/Library_ucpfile1.mk +++ b/ucb/Library_ucpfile1.mk @@ -23,6 +23,7 @@ $(eval $(call gb_Library_use_libraries,ucpfile1,\ sal \ tl \ ucbhelper \ + utl \ )) $(eval $(call gb_Library_add_exception_objects,ucpfile1,\ diff --git a/ucb/source/ucp/file/filstr.cxx b/ucb/source/ucp/file/filstr.cxx index 8b4274cb60e0..8e605f7f1cc6 100644 --- a/ucb/source/ucp/file/filstr.cxx +++ b/ucb/source/ucp/file/filstr.cxx @@ -148,6 +148,29 @@ XStream_impl::readBytes( return static_cast<sal_Int32>(nrc); } +sal_Int32 +XStream_impl::readSomeBytes( + sal_Int8* pData, + sal_Int32 nBytesToRead ) +{ + if( ! m_nIsOpen ) + throw io::IOException( THROW_WHERE ); + + sal_uInt64 nrc(0); + if(m_aFile.read( pData, sal_uInt64(nBytesToRead), nrc ) + != osl::FileBase::E_None) + { + throw io::IOException( THROW_WHERE ); + } + return static_cast<sal_Int32>(nrc); +} + +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)); + return 0; +} sal_Int32 SAL_CALL XStream_impl::readSomeBytes( diff --git a/ucb/source/ucp/file/filstr.hxx b/ucb/source/ucp/file/filstr.hxx index ad6c39964448..65cf4369ce75 100644 --- a/ucb/source/ucp/file/filstr.hxx +++ b/ucb/source/ucp/file/filstr.hxx @@ -25,7 +25,9 @@ #include <com/sun/star/io/XOutputStream.hpp> #include <com/sun/star/io/XStream.hpp> #include <com/sun/star/io/XAsyncOutputMonitor.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> #include <cppuhelper/implbase.hxx> +#include <unotools/bytereader.hxx> #include <mutex> #include "filrec.hxx" @@ -41,7 +43,9 @@ class XStream_impl : public cppu::WeakImplHelper< css::io::XInputStream, css::io::XOutputStream, css::io::XTruncate, - css::io::XAsyncOutputMonitor > + css::io::XAsyncOutputMonitor, + css::lang::XUnoTunnel >, + public utl::ByteReader { public: @@ -120,6 +124,15 @@ class XStream_impl : public cppu::WeakImplHelper< virtual void SAL_CALL waitForCompletion() override; + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& _rIdentifier ) override; + + // utl::ByteReader + virtual sal_Int32 + readSomeBytes( + sal_Int8* aData, + sal_Int32 nMaxBytesToRead ) override; + private: std::mutex m_aMutex; diff --git a/unotools/source/streaming/streamhelper.cxx b/unotools/source/streaming/streamhelper.cxx index b5f07e6a6a7f..39585ec5f369 100644 --- a/unotools/source/streaming/streamhelper.cxx +++ b/unotools/source/streaming/streamhelper.cxx @@ -22,8 +22,10 @@ #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 { @@ -118,6 +120,14 @@ 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 ccd9b5033d2a..0ed933b530e3 100644 --- a/unotools/source/streaming/streamwrap.cxx +++ b/unotools/source/streaming/streamwrap.cxx @@ -78,6 +78,21 @@ sal_Int32 SAL_CALL OInputStreamWrapper::readBytes(css::uno::Sequence< sal_Int8 > return nRead; } +sal_Int32 OInputStreamWrapper::readSomeBytes(sal_Int8* pData, sal_Int32 nBytesToRead) +{ + checkConnected(); + + if (nBytesToRead < 0) + throw css::io::BufferSizeExceededException(OUString(),static_cast<css::uno::XWeak*>(this)); + + std::scoped_lock aGuard( m_aMutex ); + + sal_uInt32 nRead = m_pSvStream->ReadBytes(static_cast<void*>(pData), nBytesToRead); + checkError(); + + return nRead; +} + sal_Int32 SAL_CALL OInputStreamWrapper::readSomeBytes(css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) { checkError(); @@ -141,6 +156,14 @@ void OInputStreamWrapper::checkError() const throw css::io::NotConnectedException("utl::OInputStreamWrapper error " + e.toHexString(), const_cast<css::uno::XWeak*>(static_cast<const css::uno::XWeak*>(this))); } +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)); + return 0; +} + + //= OSeekableInputStreamWrapper OSeekableInputStreamWrapper::~OSeekableInputStreamWrapper() = default; diff --git a/unotools/source/ucbhelper/ucblockbytes.cxx b/unotools/source/ucbhelper/ucblockbytes.cxx index 2d716f571586..b40be28f2225 100644 --- a/unotools/source/ucbhelper/ucblockbytes.cxx +++ b/unotools/source/ucbhelper/ucblockbytes.cxx @@ -27,6 +27,7 @@ #include <tools/urlobj.hxx> #include <tools/solar.h> #include <ucbhelper/interactionrequest.hxx> +#include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/task/XInteractionAbort.hpp> #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> #include <com/sun/star/ucb/CommandFailedException.hpp> @@ -57,6 +58,7 @@ #include <comphelper/storagehelper.hxx> #include <ucbhelper/content.hxx> +#include <unotools/bytereader.hxx> #include <mutex> using namespace ::com::sun::star::uno; @@ -1092,7 +1094,6 @@ ErrCode UcbLockBytes::ReadAt(sal_uInt64 const nPos, return ERRCODE_IO_CANTSEEK; } - Sequence<sal_Int8> aData; sal_Int32 nSize; if(nCount > 0x7FFFFFFF) @@ -1108,14 +1109,27 @@ ErrCode UcbLockBytes::ReadAt(sal_uInt64 const nPos, return ERRCODE_IO_PENDING; } - nSize = xStream->readBytes( aData, sal_Int32(nCount) ); + Reference< css::lang::XUnoTunnel > xTunnel( xStream, UNO_QUERY ); + utl::ByteReader* pByteReader = nullptr; + if (xTunnel) + pByteReader = reinterpret_cast< utl::ByteReader* >( xTunnel->getSomething( utl::ByteReader::getUnoTunnelId() ) ); + + if (pByteReader) + { + nSize = pByteReader->readSomeBytes( static_cast<sal_Int8*>(pBuffer), sal_Int32(nCount) ); + } + else + { + Sequence<sal_Int8> aData; + nSize = xStream->readBytes( aData, sal_Int32(nCount) ); + memcpy (pBuffer, aData.getConstArray(), nSize); + } } catch (const IOException&) { return ERRCODE_IO_CANTREAD; } - memcpy (pBuffer, aData.getConstArray(), nSize); if (pRead) *pRead = static_cast<std::size_t>(nSize);