include/unotools/tempfile.hxx                    |   53 +++++
 package/inc/ZipOutputEntry.hxx                   |    3 
 package/source/xstor/owriteablestream.cxx        |    2 
 package/source/xstor/switchpersistencestream.cxx |    3 
 package/source/xstor/xfactory.cxx                |    5 
 package/source/xstor/xstorage.cxx                |   27 +-
 package/source/zipapi/ByteGrabber.cxx            |    3 
 package/source/zipapi/ZipFile.cxx                |   11 -
 package/source/zipapi/ZipOutputEntry.cxx         |    4 
 package/source/zipapi/ZipOutputStream.cxx        |    1 
 package/source/zippackage/ZipPackage.cxx         |    7 
 package/source/zippackage/ZipPackageStream.cxx   |   24 --
 unotools/source/ucbhelper/tempfile.cxx           |  229 +++++++++++++++++++++++
 13 files changed, 317 insertions(+), 55 deletions(-)

New commits:
commit 848f9b2c56ce4c4620f62f1fbf9d12d84ec4da96
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Thu Oct 20 17:47:21 2022 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Fri Oct 21 12:01:05 2022 +0200

    tdf#133767 new service TempFileFastService
    
    to use in places where we know we can use the TempFileFast mechanism.
    
    Speeds up export to EPUB from 43s to 17s on my windows machine.
    
    This is essentially a copy of OTempFileService, but it does not
    implement XTempFile (because these temp files have no name on Windows).
    
    Also remove a couple of calls to Flush() (which is not necessary now),
    and TellEnd(), which is a little slow on Windows.
    
    Change-Id: Iced300bf8121eae08c7a011d62ec68b93330d84c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141598
    Tested-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/include/unotools/tempfile.hxx b/include/unotools/tempfile.hxx
index 460f13b96e90..168659d26359 100644
--- a/include/unotools/tempfile.hxx
+++ b/include/unotools/tempfile.hxx
@@ -19,8 +19,16 @@
 #pragma once
 
 #include <unotools/unotoolsdllapi.h>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <cppuhelper/implbase.hxx>
 #include <tools/stream.hxx>
 #include <memory>
+#include <mutex>
+#include <optional>
 
 namespace utl
 {
@@ -182,6 +190,51 @@ public:
 
 };
 
+
+typedef ::cppu::WeakImplHelper<
+     css::io::XStream
+    , css::io::XSeekable
+    , css::io::XInputStream
+    , css::io::XOutputStream
+    , css::io::XTruncate> TempFileFastService_Base;
+class UNOTOOLS_DLLPUBLIC TempFileFastService : public TempFileFastService_Base
+{
+    std::optional<utl::TempFileFast> mpTempFile;
+    std::mutex maMutex;
+    SvStream* mpStream;
+    bool mbInClosed;
+    bool mbOutClosed;
+
+    void checkError () const;
+    void checkConnected ();
+
+public:
+    explicit TempFileFastService ();
+    virtual ~TempFileFastService () override;
+
+    // XInputStream
+    virtual ::sal_Int32 SAL_CALL readBytes( css::uno::Sequence< ::sal_Int8 >& 
aData, ::sal_Int32 nBytesToRead ) override;
+    virtual ::sal_Int32 SAL_CALL readSomeBytes( css::uno::Sequence< ::sal_Int8 
>& aData, ::sal_Int32 nMaxBytesToRead ) override;
+    virtual void SAL_CALL skipBytes( ::sal_Int32 nBytesToSkip ) override;
+    virtual ::sal_Int32 SAL_CALL available(  ) override;
+    virtual void SAL_CALL closeInput(  ) override;
+    // XOutputStream
+    virtual void SAL_CALL writeBytes( const css::uno::Sequence< ::sal_Int8 >& 
aData ) override;
+    virtual void SAL_CALL flush(  ) override;
+    virtual void SAL_CALL closeOutput(  ) override;
+    // XSeekable
+    virtual void SAL_CALL seek( sal_Int64 location ) override;
+    virtual sal_Int64 SAL_CALL getPosition(  ) override;
+    virtual sal_Int64 SAL_CALL getLength(  ) override;
+    // XStream
+    virtual css::uno::Reference< css::io::XInputStream > SAL_CALL 
getInputStream(  ) override;
+    virtual css::uno::Reference< css::io::XOutputStream > SAL_CALL 
getOutputStream(  ) override;
+    // XTruncate
+    virtual void SAL_CALL truncate() override;
+
+};
+
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/inc/ZipOutputEntry.hxx b/package/inc/ZipOutputEntry.hxx
index 678a073c6746..fcf25dcadf81 100644
--- a/package/inc/ZipOutputEntry.hxx
+++ b/package/inc/ZipOutputEntry.hxx
@@ -28,6 +28,7 @@
 
 #include <package/Deflater.hxx>
 #include <comphelper/threadpool.hxx>
+#include <unotools/tempfile.hxx>
 #include "CRC32.hxx"
 #include <atomic>
 
@@ -110,7 +111,7 @@ protected:
 class ZipOutputEntryInThread final : public ZipOutputEntry
 {
     class Task;
-    css::uno::Reference<css::io::XTempFile> m_xTempFile;
+    rtl::Reference<utl::TempFileFastService> m_xTempFile;
     std::exception_ptr m_aParallelDeflateException;
     std::atomic<bool>   m_bFinished;
 
diff --git a/package/source/xstor/owriteablestream.cxx 
b/package/source/xstor/owriteablestream.cxx
index 3437df46f2fd..2d6bda378d34 100644
--- a/package/source/xstor/owriteablestream.cxx
+++ b/package/source/xstor/owriteablestream.cxx
@@ -1320,7 +1320,7 @@ void OWriteStream_Impl::CreateReadonlyCopyBasedOnData( 
const uno::Reference< io:
 {
     uno::Reference < io::XStream > xTempFile;
     if ( !xTargetStream.is() )
-        xTempFile = io::TempFile::create(m_xContext);
+        xTempFile = new utl::TempFileFastService;
     else
         xTempFile = xTargetStream;
 
diff --git a/package/source/xstor/switchpersistencestream.cxx 
b/package/source/xstor/switchpersistencestream.cxx
index f4ccd452b8f9..f27dce18edc5 100644
--- a/package/source/xstor/switchpersistencestream.cxx
+++ b/package/source/xstor/switchpersistencestream.cxx
@@ -22,6 +22,7 @@
 #include <com/sun/star/io/NotConnectedException.hpp>
 #include <com/sun/star/io/TempFile.hpp>
 #include <comphelper/storagehelper.hxx>
+#include <unotools/tempfile.hxx>
 #include <utility>
 #include "switchpersistencestream.hxx"
 
@@ -157,7 +158,7 @@ void 
SwitchablePersistenceStream::CopyAndSwitchPersistenceTo( const uno::Referen
 
     if ( !xTargetStream.is() )
     {
-        xTargetStream.set( io::TempFile::create(m_xContext), 
uno::UNO_QUERY_THROW );
+        xTargetStream.set( new utl::TempFileFastService );
         xTargetSeek.set( xTargetStream, uno::UNO_QUERY_THROW );
     }
     else
diff --git a/package/source/xstor/xfactory.cxx 
b/package/source/xstor/xfactory.cxx
index 38c8d4df29df..0ee4ae0cc51d 100644
--- a/package/source/xstor/xfactory.cxx
+++ b/package/source/xstor/xfactory.cxx
@@ -33,6 +33,7 @@
 #include <cppuhelper/supportsservice.hxx>
 #include <cppuhelper/weak.hxx>
 #include <osl/diagnose.h>
+#include <unotools/tempfile.hxx>
 
 #include "xfactory.hxx"
 #include "xstorage.hxx"
@@ -71,9 +72,7 @@ static bool CheckPackageSignature_Impl( const uno::Reference< 
io::XInputStream >
 uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstance()
 {
     // TODO: reimplement TempStream service to support XStream interface
-    uno::Reference < io::XStream > xTempStream(
-                        io::TempFile::create(m_xContext),
-                        uno::UNO_QUERY_THROW );
+    uno::Reference < io::XStream > xTempStream(new utl::TempFileFastService);
 
     return static_cast<OWeakObject*>(new OStorage(xTempStream, 
embed::ElementModes::READWRITE,
                                                   
uno::Sequence<beans::PropertyValue>(), m_xContext,
diff --git a/package/source/xstor/xstorage.cxx 
b/package/source/xstor/xstorage.cxx
index e18c398436b2..5ac7f0618b7d 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -112,10 +112,9 @@ void OStorage_Impl::completeStorageStreamCopy_Impl(
             xDestProps->setPropertyValue( rPropName, 
xSourceProps->getPropertyValue( rPropName ) );
 }
 
-static uno::Reference< io::XInputStream > GetSeekableTempCopy( const 
uno::Reference< io::XInputStream >& xInStream,
-                                                        const uno::Reference< 
uno::XComponentContext >& xContext )
+static uno::Reference< io::XInputStream > GetSeekableTempCopy( const 
uno::Reference< io::XInputStream >& xInStream )
 {
-    uno::Reference < io::XTempFile > xTempFile = 
io::TempFile::create(xContext);
+    rtl::Reference < utl::TempFileFastService > xTempFile = new 
utl::TempFileFastService;
     uno::Reference < io::XOutputStream > xTempOut = 
xTempFile->getOutputStream();
     uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();
 
@@ -1318,7 +1317,7 @@ void OStorage_Impl::InsertRawStream( const OUString& 
aName, const uno::Reference
 
     uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
     uno::Reference< io::XInputStream > xInStrToInsert = xSeek.is() ? xInStream 
:
-                                                                     
GetSeekableTempCopy( xInStream, m_xContext );
+                                                                     
GetSeekableTempCopy( xInStream );
 
     uno::Sequence< uno::Any > aSeq{ uno::Any(false) };
     uno::Reference< lang::XUnoTunnel > xNewElement( 
m_xPackage->createInstanceWithArguments( aSeq ),
@@ -3299,18 +3298,17 @@ uno::Reference< io::XInputStream > SAL_CALL 
OStorage::getPlainRawStreamElement(
         if ( !xRawInStream.is() )
             throw io::IOException( THROW_WHERE );
 
-        uno::Reference < io::XTempFile > xTempFile = io::TempFile::create( 
m_pImpl->m_xContext );
+        rtl::Reference < utl::TempFileFastService > xTempFile = new 
utl::TempFileFastService;
         uno::Reference < io::XOutputStream > xTempOut = 
xTempFile->getOutputStream();
         xTempIn = xTempFile->getInputStream();
-        uno::Reference < io::XSeekable > xSeek( xTempOut, uno::UNO_QUERY );
 
-        if ( !xTempOut.is() || !xTempIn.is() || !xSeek.is() )
+        if ( !xTempOut.is() || !xTempIn.is() )
             throw io::IOException( THROW_WHERE );
 
         // Copy temporary file to a new one
         ::comphelper::OStorageHelper::CopyInputToOutput( xRawInStream, 
xTempOut );
         xTempOut->closeOutput();
-        xSeek->seek( 0 );
+        xTempFile->seek( 0 );
     }
     catch( const embed::InvalidStorageException& )
     {
@@ -3393,18 +3391,17 @@ uno::Reference< io::XInputStream > SAL_CALL 
OStorage::getRawEncrStreamElement(
         if ( !xRawInStream.is() )
             throw io::IOException( THROW_WHERE );
 
-        uno::Reference < io::XTempFile > xTempFile = 
io::TempFile::create(m_pImpl->m_xContext);
-        uno::Reference < io::XOutputStream > xTempOut = 
xTempFile->getOutputStream();
-        xTempIn = xTempFile->getInputStream();
-        uno::Reference < io::XSeekable > xSeek( xTempOut, uno::UNO_QUERY );
+        rtl::Reference < utl::TempFileFastService > xTempFile = new 
utl::TempFileFastService;
+        uno::Reference < io::XOutputStream > xTempOut = xTempFile;
+        xTempIn = xTempFile;
 
-        if ( !xTempOut.is() || !xTempIn.is() || !xSeek.is() )
+        if ( !xTempFile )
             throw io::IOException( THROW_WHERE );
 
         // Copy temporary file to a new one
         ::comphelper::OStorageHelper::CopyInputToOutput( xRawInStream, 
xTempOut );
-        xTempOut->closeOutput();
-        xSeek->seek( 0 );
+        xTempFile->closeOutput();
+        xTempFile->seek( 0 );
 
     }
     catch( const embed::InvalidStorageException& )
diff --git a/package/source/zipapi/ByteGrabber.cxx 
b/package/source/zipapi/ByteGrabber.cxx
index b58a7087f468..5a491de6509b 100644
--- a/package/source/zipapi/ByteGrabber.cxx
+++ b/package/source/zipapi/ByteGrabber.cxx
@@ -70,9 +70,6 @@ void ByteGrabber::seek( sal_Int64 location )
     if (!xSeek.is() )
         throw io::IOException(THROW_WHERE );
 
-    sal_Int64 nLen = xSeek->getLength();
-    if ( location < 0 || location > nLen )
-        throw lang::IllegalArgumentException(THROW_WHERE, uno::Reference< 
uno::XInterface >(), 1 );
     xSeek->seek( location );
 }
 
diff --git a/package/source/zipapi/ZipFile.cxx 
b/package/source/zipapi/ZipFile.cxx
index 63ba823e240e..c59035919bb8 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -820,16 +820,9 @@ void ZipFile::readLOC( ZipEntry &rEntry )
 
     try
     {
-        sal_Int16 nPathLenToRead = nPathLen;
-        const sal_Int64 nBytesAvailable = aGrabber.getLength() - 
aGrabber.getPosition();
-        if (nPathLenToRead > nBytesAvailable)
-            nPathLenToRead = nBytesAvailable;
-        else if (nPathLenToRead < 0)
-            nPathLenToRead = 0;
-
         // read always in UTF8, some tools seem not to set UTF8 bit
-        uno::Sequence<sal_Int8> aNameBuffer(nPathLenToRead);
-        sal_Int32 nRead = aGrabber.readBytes(aNameBuffer, nPathLenToRead);
+        uno::Sequence<sal_Int8> aNameBuffer(nPathLen);
+        sal_Int32 nRead = aGrabber.readBytes(aNameBuffer, nPathLen);
         if (nRead < aNameBuffer.getLength())
             aNameBuffer.realloc(nRead);
 
diff --git a/package/source/zipapi/ZipOutputEntry.cxx 
b/package/source/zipapi/ZipOutputEntry.cxx
index 2eb5f9db4391..86c8a9782df7 100644
--- a/package/source/zipapi/ZipOutputEntry.cxx
+++ b/package/source/zipapi/ZipOutputEntry.cxx
@@ -250,9 +250,7 @@ void ZipOutputEntryInThread::createBufferFile()
 {
     assert(!m_xOutStream && !m_xTempFile &&
            "should only be called in the threaded mode where there is no 
existing stream yet");
-    m_xTempFile.set(
-            io::TempFile::create(m_xContext),
-            uno::UNO_SET_THROW );
+    m_xTempFile = new utl::TempFileFastService;
     m_xOutStream = m_xTempFile->getOutputStream();
 }
 
diff --git a/package/source/zipapi/ZipOutputStream.cxx 
b/package/source/zipapi/ZipOutputStream.cxx
index 33321627b6f9..9b582c4691e8 100644
--- a/package/source/zipapi/ZipOutputStream.cxx
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -178,7 +178,6 @@ void ZipOutputStream::finish()
         delete p;
     }
     writeEND( nOffset, static_cast < sal_Int32 > (m_aChucker.GetPosition()) - 
nOffset);
-    m_xStream->flush();
     m_aZipList.clear();
 
     if (m_aDeflateException)
diff --git a/package/source/zippackage/ZipPackage.cxx 
b/package/source/zippackage/ZipPackage.cxx
index 0d9d66970ffd..6316498ef0b8 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -61,6 +61,7 @@
 #include <o3tl/string_view.hxx>
 #include <osl/diagnose.h>
 #include <sal/log.hxx>
+#include <unotools/tempfile.hxx>
 #include <com/sun/star/io/XAsyncOutputMonitor.hpp>
 
 #include <string_view>
@@ -1196,9 +1197,9 @@ uno::Reference< io::XInputStream > 
ZipPackage::writeTempFile()
     if( bUseTemp )
     {
         // create temporary file
-        uno::Reference < io::XTempFile > xTempFile( 
io::TempFile::create(m_xContext) );
-        xTempOut.set( xTempFile->getOutputStream(), UNO_SET_THROW );
-        xTempIn.set( xTempFile->getInputStream(), UNO_SET_THROW );
+        rtl::Reference < utl::TempFileFastService > xTempFile( new 
utl::TempFileFastService );
+        xTempOut.set( xTempFile );
+        xTempIn.set( xTempFile );
     }
 
     // Hand it to the ZipOutputStream:
diff --git a/package/source/zippackage/ZipPackageStream.cxx 
b/package/source/zippackage/ZipPackageStream.cxx
index 368d687e2886..a63683c771cd 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -49,6 +49,7 @@
 #include <comphelper/servicehelper.hxx>
 #include <comphelper/storagehelper.hxx>
 #include <cppuhelper/supportsservice.hxx>
+#include <unotools/tempfile.hxx>
 
 #include <rtl/random.h>
 #include <sal/log.hxx>
@@ -173,15 +174,13 @@ uno::Reference< io::XInputStream > 
ZipPackageStream::GetRawEncrStreamNoHeaderCop
                     m_xBaseEncryptionData->m_aSalt.getLength() + 
m_xBaseEncryptionData->m_aDigest.getLength() );
 
     // create temporary stream
-    uno::Reference < io::XTempFile > xTempFile = 
io::TempFile::create(m_xContext);
-    uno::Reference < io::XOutputStream > xTempOut = 
xTempFile->getOutputStream();
+    rtl::Reference < utl::TempFileFastService > xTempFile = new 
utl::TempFileFastService;
     uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();
-    uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
 
     // copy the raw stream to the temporary file starting from the current 
position
-    ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), 
xTempOut );
-    xTempOut->closeOutput();
-    xTempSeek->seek( 0 );
+    ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), 
xTempFile );
+    xTempFile->closeOutput();
+    xTempFile->seek( 0 );
 
     return xTempIn;
 }
@@ -276,9 +275,7 @@ uno::Reference< io::XInputStream > 
ZipPackageStream::TryToGetRawFromDataStream(
     try
     {
         // create temporary file
-        uno::Reference < io::XStream > xTempStream(
-                            io::TempFile::create(m_xContext),
-                            uno::UNO_QUERY_THROW );
+        uno::Reference < io::XStream > xTempStream(new 
utl::TempFileFastService);
 
         // create a package based on it
         rtl::Reference<ZipPackage> pPackage = new ZipPackage( m_xContext );
@@ -322,16 +319,13 @@ uno::Reference< io::XInputStream > 
ZipPackageStream::TryToGetRawFromDataStream(
             xInRaw = xNewPackStream->getPlainRawStream();
 
         // create another temporary file
-        uno::Reference < io::XOutputStream > xTempOut(
-                            io::TempFile::create(m_xContext),
-                            uno::UNO_QUERY_THROW );
-        uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY_THROW 
);
-        uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW 
);
+        rtl::Reference < utl::TempFileFastService > xTempOut = new 
utl::TempFileFastService;
+        uno::Reference < io::XInputStream > xTempIn( xTempOut );
 
         // copy the raw stream to the temporary file
         ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw, xTempOut );
         xTempOut->closeOutput();
-        xTempSeek->seek( 0 );
+        xTempOut->seek( 0 );
 
         // close raw stream, package stream and folder
         xInRaw.clear();
diff --git a/unotools/source/ucbhelper/tempfile.cxx 
b/unotools/source/ucbhelper/tempfile.cxx
index 406f08130dbd..09e3eda62e22 100644
--- a/unotools/source/ucbhelper/tempfile.cxx
+++ b/unotools/source/ucbhelper/tempfile.cxx
@@ -22,8 +22,12 @@
 #include <cassert>
 #include <utility>
 
+#include <com/sun/star/io/BufferSizeExceededException.hpp>
+#include <com/sun/star/io/NotConnectedException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
 #include <unotools/tempfile.hxx>
 #include <rtl/ustring.hxx>
+#include <o3tl/safeint.hxx>
 #include <osl/mutex.hxx>
 #include <osl/detail/file.h>
 #include <osl/file.hxx>
@@ -534,6 +538,231 @@ OUString GetTempNameBaseDirectory()
     return ConstructTempDir_Impl(nullptr, false);
 }
 
+
+TempFileFastService::TempFileFastService()
+: mbInClosed( false )
+, mbOutClosed( false )
+{
+    mpTempFile.emplace();
+    mpStream = mpTempFile->GetStream(StreamMode::READWRITE);
+}
+
+TempFileFastService::~TempFileFastService ()
+{
+}
+
+// XInputStream
+
+sal_Int32 SAL_CALL TempFileFastService::readBytes( css::uno::Sequence< 
sal_Int8 >& aData, sal_Int32 nBytesToRead )
+{
+    std::unique_lock aGuard( maMutex );
+    if ( mbInClosed )
+        throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+
+    checkConnected();
+    if (nBytesToRead < 0)
+        throw css::io::BufferSizeExceededException( OUString(), static_cast< 
css::uno::XWeak * >(this));
+
+    if (aData.getLength() < nBytesToRead)
+        aData.realloc(nBytesToRead);
+
+    sal_uInt32 nRead = 
mpStream->ReadBytes(static_cast<void*>(aData.getArray()), nBytesToRead);
+    checkError();
+
+    if (nRead < o3tl::make_unsigned(aData.getLength()))
+        aData.realloc( nRead );
+
+    return nRead;
+}
+
+sal_Int32 SAL_CALL TempFileFastService::readSomeBytes( css::uno::Sequence< 
sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+{
+    {
+        std::unique_lock aGuard( maMutex );
+        if ( mbInClosed )
+            throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+
+        checkConnected();
+        checkError();
+
+        if (nMaxBytesToRead < 0)
+            throw css::io::BufferSizeExceededException( OUString(), 
static_cast < css::uno::XWeak * >( this ) );
+
+        if (mpStream->eof())
+        {
+            aData.realloc(0);
+            return 0;
+        }
+    }
+    return readBytes(aData, nMaxBytesToRead);
+}
+
+void SAL_CALL TempFileFastService::skipBytes( sal_Int32 nBytesToSkip )
+{
+    std::unique_lock aGuard( maMutex );
+    if ( mbInClosed )
+        throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+
+    checkConnected();
+    checkError();
+    mpStream->SeekRel(nBytesToSkip);
+    checkError();
+}
+
+sal_Int32 SAL_CALL TempFileFastService::available()
+{
+    std::unique_lock aGuard( maMutex );
+    if ( mbInClosed )
+        throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+
+    checkConnected();
+
+    sal_Int64 nAvailable = mpStream->remainingSize();
+    checkError();
+
+    return std::min<sal_Int64>(SAL_MAX_INT32, nAvailable);
+}
+
+void SAL_CALL TempFileFastService::closeInput()
+{
+    std::unique_lock aGuard( maMutex );
+    if ( mbInClosed )
+        throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+
+    mbInClosed = true;
+
+    if ( mbOutClosed )
+    {
+        // stream will be deleted by TempFile implementation
+        mpStream = nullptr;
+        mpTempFile.reset();
+    }
+}
+
+// XOutputStream
+
+void SAL_CALL TempFileFastService::writeBytes( const css::uno::Sequence< 
sal_Int8 >& aData )
+{
+    std::unique_lock aGuard( maMutex );
+    if ( mbOutClosed )
+        throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+
+    checkConnected();
+    sal_uInt32 nWritten = mpStream->WriteBytes(aData.getConstArray(), 
aData.getLength());
+    checkError();
+    if  ( nWritten != static_cast<sal_uInt32>(aData.getLength()))
+        throw css::io::BufferSizeExceededException( OUString(),static_cast < 
css::uno::XWeak * > ( this ) );
+}
+
+void SAL_CALL TempFileFastService::flush()
+{
+    std::unique_lock aGuard( maMutex );
+    if ( mbOutClosed )
+        throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+
+    checkConnected();
+    mpStream->Flush();
+    checkError();
+}
+
+void SAL_CALL TempFileFastService::closeOutput()
+{
+    std::unique_lock aGuard( maMutex );
+    if ( mbOutClosed )
+        throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+
+    mbOutClosed = true;
+    if (mpStream)
+    {
+        // so that if you then open the InputStream, you can read the content
+        mpStream->FlushBuffer();
+        mpStream->Seek(0);
+    }
+
+    if ( mbInClosed )
+    {
+        // stream will be deleted by TempFile implementation
+        mpStream = nullptr;
+        mpTempFile.reset();
+    }
+}
+
+void TempFileFastService::checkError() const
+{
+    if (!mpStream || mpStream->SvStream::GetError () != ERRCODE_NONE )
+        throw css::io::NotConnectedException ( OUString(), const_cast < 
css::uno::XWeak * > ( static_cast < const css::uno::XWeak * > (this ) ) );
+}
+
+void TempFileFastService::checkConnected()
+{
+    if (!mpStream)
+        throw css::io::NotConnectedException ( OUString(), static_cast < 
css::uno::XWeak * > (this ) );
+}
+
+// XSeekable
+
+void SAL_CALL TempFileFastService::seek( sal_Int64 nLocation )
+{
+    std::unique_lock aGuard( maMutex );
+    checkConnected();
+    checkError();
+    if ( nLocation < 0 )
+        throw css::lang::IllegalArgumentException();
+
+    sal_Int64 nNewLoc = mpStream->Seek(static_cast<sal_uInt32>(nLocation) );
+    if ( nNewLoc != nLocation )
+        throw css::lang::IllegalArgumentException();
+    checkError();
+}
+
+sal_Int64 SAL_CALL TempFileFastService::getPosition()
+{
+    std::unique_lock aGuard( maMutex );
+    checkConnected();
+
+    sal_uInt32 nPos = mpStream->Tell();
+    checkError();
+    return static_cast<sal_Int64>(nPos);
+}
+
+sal_Int64 SAL_CALL TempFileFastService::getLength()
+{
+    std::unique_lock aGuard( maMutex );
+    checkConnected();
+
+    checkError();
+
+    sal_Int64 nEndPos = mpStream->TellEnd();
+
+    return nEndPos;
+}
+
+// XStream
+
+css::uno::Reference< css::io::XInputStream > SAL_CALL 
TempFileFastService::getInputStream()
+{
+    return css::uno::Reference< css::io::XInputStream >( *this, 
css::uno::UNO_QUERY );
+}
+
+css::uno::Reference< css::io::XOutputStream > SAL_CALL 
TempFileFastService::getOutputStream()
+{
+    return css::uno::Reference< css::io::XOutputStream >( this );
+}
+
+// XTruncate
+
+void SAL_CALL TempFileFastService::truncate()
+{
+    std::unique_lock aGuard( maMutex );
+    checkConnected();
+    // SetStreamSize() call does not change the position
+    mpStream->Seek( 0 );
+    mpStream->SetStreamSize( 0 );
+    checkError();
+}
+
+
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to