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);
 

Reply via email to