[Libreoffice-commits] core.git: comphelper/source include/comphelper oox/source package/inc package/source

Kohei Yoshida kohei.yoshida at collabora.com
Sat Jan 14 17:30:51 UTC 2017


 comphelper/source/misc/storagehelper.cxx |   46 ++++++++----
 include/comphelper/storagehelper.hxx     |    6 +
 oox/source/helper/zipstorage.cxx         |    4 -
 package/inc/ZipFile.hxx                  |    5 +
 package/source/xstor/xfactory.cxx        |    4 -
 package/source/xstor/xstorage.cxx        |    3 
 package/source/zipapi/ZipFile.cxx        |  118 +++++++++++++++++++++++++++++--
 package/source/zippackage/ZipPackage.cxx |    6 +
 8 files changed, 166 insertions(+), 26 deletions(-)

New commits:
commit 4ae705d02df0ddf75b97d0e94add6994626f487e
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Jan 13 20:47:46 2017 -0500

    tdf#97597: Ensure that each parsing thread has its own buffer.
    
    Change-Id: I93077f954a49b3922930e4fc86c80228be0f4dd2
    Reviewed-on: https://gerrit.libreoffice.org/33069
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Kohei Yoshida <libreoffice at kohei.us>

diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx
index 4730794..394a0aa 100644
--- a/comphelper/source/misc/storagehelper.cxx
+++ b/comphelper/source/misc/storagehelper.cxx
@@ -317,17 +317,28 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStr
             const OUString& aFormat,
             const uno::Reference < io::XInputStream >& xStream,
             const uno::Reference< uno::XComponentContext >& rxContext,
-            bool bRepairStorage )
+            bool bRepairStorage, bool bUseBufferedStream )
         throw ( uno::Exception )
 {
     uno::Sequence< beans::PropertyValue > aProps( 1 );
-    aProps[0].Name = "StorageFormat";
-    aProps[0].Value <<= aFormat;
+    sal_Int32 nPos = 0;
+    aProps[nPos].Name = "StorageFormat";
+    aProps[nPos].Value <<= aFormat;
+    ++nPos;
     if ( bRepairStorage )
     {
-        aProps.realloc( 2 );
-        aProps[1].Name = "RepairPackage";
-        aProps[1].Value <<= bRepairStorage;
+        aProps.realloc(nPos+1);
+        aProps[nPos].Name = "RepairPackage";
+        aProps[nPos].Value <<= bRepairStorage;
+        ++nPos;
+    }
+
+    if (bUseBufferedStream)
+    {
+        aProps.realloc(nPos+1);
+        aProps[nPos].Name = "UseBufferedStream";
+        aProps[nPos].Value <<= bUseBufferedStream;
+        ++nPos;
     }
 
     uno::Sequence< uno::Any > aArgs( 3 );
@@ -349,17 +360,28 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream(
             const uno::Reference < io::XStream >& xStream,
             sal_Int32 nStorageMode,
             const uno::Reference< uno::XComponentContext >& rxContext,
-            bool bRepairStorage )
+            bool bRepairStorage, bool bUseBufferedStream )
         throw ( uno::Exception )
 {
     uno::Sequence< beans::PropertyValue > aProps( 1 );
-    aProps[0].Name = "StorageFormat";
-    aProps[0].Value <<= aFormat;
+    sal_Int32 nPos = 0;
+    aProps[nPos].Name = "StorageFormat";
+    aProps[nPos].Value <<= aFormat;
+    ++nPos;
     if ( bRepairStorage )
     {
-        aProps.realloc( 2 );
-        aProps[1].Name = "RepairPackage";
-        aProps[1].Value <<= bRepairStorage;
+        aProps.realloc(nPos+1);
+        aProps[nPos].Name = "RepairPackage";
+        aProps[nPos].Value <<= bRepairStorage;
+        ++nPos;
+    }
+
+    if (bUseBufferedStream)
+    {
+        aProps.realloc(nPos+1);
+        aProps[nPos].Name = "UseBufferedStream";
+        aProps[nPos].Value <<= bUseBufferedStream;
+        ++nPos;
     }
 
     uno::Sequence< uno::Any > aArgs( 3 );
diff --git a/include/comphelper/storagehelper.hxx b/include/comphelper/storagehelper.hxx
index d5655d4..6748198 100644
--- a/include/comphelper/storagehelper.hxx
+++ b/include/comphelper/storagehelper.hxx
@@ -154,7 +154,8 @@ public:
             const css::uno::Reference < css::io::XInputStream >& xStream,
             const css::uno::Reference< css::uno::XComponentContext >& rxContext
                             = css::uno::Reference< css::uno::XComponentContext >(),
-            bool bRepairStorage = false )
+            bool bRepairStorage = false,
+            bool bUseBufferedStream = false )
         throw ( css::uno::Exception );
 
     static css::uno::Reference< css::embed::XStorage >
@@ -164,7 +165,8 @@ public:
             sal_Int32 nStorageMode = css::embed::ElementModes::READWRITE,
             const css::uno::Reference< css::uno::XComponentContext >& rxContext
                             = css::uno::Reference< css::uno::XComponentContext >(),
-            bool bRepairStorage = false )
+            bool bRepairStorage = false,
+            bool bUseBufferedStream = false )
         throw ( css::uno::Exception );
 
     static css::uno::Sequence< css::beans::NamedValue >
diff --git a/oox/source/helper/zipstorage.cxx b/oox/source/helper/zipstorage.cxx
index 0673651..c0d454d 100644
--- a/oox/source/helper/zipstorage.cxx
+++ b/oox/source/helper/zipstorage.cxx
@@ -58,7 +58,7 @@ ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const R
             implementation of relations handling.
          */
         mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(
-            ZIP_STORAGE_FORMAT_STRING, rxInStream, rxContext );
+            ZIP_STORAGE_FORMAT_STRING, rxInStream, rxContext, false, true);
     }
     catch (Exception const& e)
     {
@@ -76,7 +76,7 @@ ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const R
     {
         const sal_Int32 nOpenMode = ElementModes::READWRITE | ElementModes::TRUNCATE;
         mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream(
-            OFOPXML_STORAGE_FORMAT_STRING, rxStream, nOpenMode, rxContext, true );
+            OFOPXML_STORAGE_FORMAT_STRING, rxStream, nOpenMode, rxContext, true, true);
     }
     catch (Exception const& e)
     {
diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx
index 9d1a6da..e84ace2 100644
--- a/package/inc/ZipFile.hxx
+++ b/package/inc/ZipFile.hxx
@@ -64,9 +64,10 @@ class ZipFile
     const css::uno::Reference < css::uno::XComponentContext > m_xContext;
 
     bool bRecoveryMode;
+    bool mbUseBufferedStream;
 
     // aMediaType parameter is used only for raw stream header creation
-    css::uno::Reference < css::io::XInputStream >  createUnbufferedStream(
+    css::uno::Reference < css::io::XInputStream >  createStreamForZipEntry(
             const rtl::Reference<SotMutexHolder>& aMutexHolder,
             ZipEntry & rEntry,
             const ::rtl::Reference < EncryptionData > &rData,
@@ -102,6 +103,8 @@ public:
 
     EntryHash& GetEntryHash() { return aEntries; }
 
+    void setUseBufferedStream( bool b );
+
     void setInputStream ( const css::uno::Reference < css::io::XInputStream >& xNewStream );
     css::uno::Reference< css::io::XInputStream > getRawData(
             ZipEntry& rEntry,
diff --git a/package/source/xstor/xfactory.cxx b/package/source/xstor/xfactory.cxx
index 95bb21a..d5031b4 100644
--- a/package/source/xstor/xfactory.cxx
+++ b/package/source/xstor/xfactory.cxx
@@ -193,8 +193,8 @@ uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstanceWithAr
                 if ( aDescr[nInd].Name == "InteractionHandler"
                   || aDescr[nInd].Name == "Password"
                   || aDescr[nInd].Name == "RepairPackage"
-                  || aDescr[nInd].Name == "StatusIndicator" )
-                  // || aDescr[nInd].Name == "Unpacked" ) // TODO:
+                  || aDescr[nInd].Name == "StatusIndicator"
+                  || aDescr[nInd].Name == "UseBufferedStream" )
                 {
                     aPropsToSet.realloc( ++nNumArgs );
                     aPropsToSet[nNumArgs-1].Name = aDescr[nInd].Name;
diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx
index 29155de..68f47a8 100644
--- a/package/source/xstor/xstorage.cxx
+++ b/package/source/xstor/xstorage.cxx
@@ -467,7 +467,8 @@ void OStorage_Impl::OpenOwnPackage()
             for ( sal_Int32 aInd = 0; aInd < m_xProperties.getLength(); aInd++ )
             {
                 if ( m_xProperties[aInd].Name == "RepairPackage"
-                  || m_xProperties[aInd].Name == "ProgressHandler" )
+                  || m_xProperties[aInd].Name == "ProgressHandler"
+                  || m_xProperties[aInd].Name == "UseBufferedStream" )
                 {
                     beans::NamedValue aNamedValue( m_xProperties[aInd].Name,
                                                     m_xProperties[aInd].Value );
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx
index 08d862a..0f436ab 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -74,6 +74,7 @@ ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference
 , xStream(xInput)
 , m_xContext ( rxContext )
 , bRecoveryMode( false )
+, mbUseBufferedStream(false)
 {
     if (bInitialise)
     {
@@ -91,6 +92,7 @@ ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference
 , xStream(xInput)
 , m_xContext ( rxContext )
 , bRecoveryMode( bForceRecovery )
+, mbUseBufferedStream(false)
 {
     if (bInitialise)
     {
@@ -111,6 +113,11 @@ ZipFile::~ZipFile()
     aEntries.clear();
 }
 
+void ZipFile::setUseBufferedStream( bool b )
+{
+    mbUseBufferedStream = b;
+}
+
 void ZipFile::setInputStream ( const uno::Reference < XInputStream >& xNewStream )
 {
     ::osl::MutexGuard aGuard( m_aMutex );
@@ -504,7 +511,99 @@ bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ::rtl::Reference< Encr
     return bRet;
 }
 
-uno::Reference< XInputStream > ZipFile::createUnbufferedStream(
+namespace {
+
+class XBufferedStream : public cppu::WeakImplHelper<css::io::XInputStream>
+{
+    std::vector<sal_Int8> maBytes;
+    size_t mnPos;
+
+    size_t remainingSize() const
+    {
+        return maBytes.size() - mnPos;
+    }
+
+    bool hasBytes() const
+    {
+        return mnPos < maBytes.size();
+    }
+
+public:
+    XBufferedStream( const uno::Reference<XInputStream>& xSrcStream ) : mnPos(0)
+    {
+        const sal_Int32 nBufSize = 8192;
+
+        sal_Int32 nRemaining = xSrcStream->available();
+        maBytes.reserve(nRemaining);
+        uno::Sequence<sal_Int8> aBuf(nBufSize);
+
+        auto readAndCopy = [&]( sal_Int32 nReadSize ) -> sal_Int32
+        {
+            sal_Int32 nBytes = xSrcStream->readBytes(aBuf, nReadSize);
+            const sal_Int8* p = aBuf.getArray();
+            const sal_Int8* pEnd = p + nBytes;
+            std::copy(p, pEnd, std::back_inserter(maBytes));
+            return nBytes;
+        };
+
+        while (nRemaining > nBufSize)
+            nRemaining -= readAndCopy(nBufSize);
+
+        if (nRemaining)
+            readAndCopy(nRemaining);
+    }
+
+    virtual sal_Int32 SAL_CALL readBytes( uno::Sequence<sal_Int8>& rData, sal_Int32 nBytesToRead )
+        throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override
+    {
+        if (!hasBytes())
+            return 0;
+
+        sal_Int32 nReadSize = std::min<sal_Int32>(nBytesToRead, remainingSize());
+        rData.realloc(nReadSize);
+        std::vector<sal_Int8>::const_iterator it = maBytes.cbegin();
+        std::advance(it, mnPos);
+        for (sal_Int32 i = 0; i < nReadSize; ++i, ++it)
+            rData[i] = *it;
+
+        mnPos += nReadSize;
+
+        return nReadSize;
+    }
+
+    virtual sal_Int32 SAL_CALL readSomeBytes( ::css::uno::Sequence<sal_Int8>& rData, sal_Int32 nMaxBytesToRead )
+        throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override
+    {
+        return readBytes(rData, nMaxBytesToRead);
+    }
+
+    virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+        throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override
+    {
+        if (!hasBytes())
+            return;
+
+        mnPos += nBytesToSkip;
+    }
+
+    virtual sal_Int32 SAL_CALL available()
+        throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override
+    {
+        if (!hasBytes())
+            return 0;
+
+        return remainingSize();
+    }
+
+    virtual void SAL_CALL closeInput()
+        throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override
+    {
+    }
+};
+
+}
+
+uno::Reference< XInputStream > ZipFile::createStreamForZipEntry(
             const rtl::Reference<SotMutexHolder>& aMutexHolder,
             ZipEntry & rEntry,
             const ::rtl::Reference< EncryptionData > &rData,
@@ -514,7 +613,14 @@ uno::Reference< XInputStream > ZipFile::createUnbufferedStream(
 {
     ::osl::MutexGuard aGuard( m_aMutex );
 
-    return new XUnbufferedStream ( m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode );
+    uno::Reference<io::XInputStream> xSrcStream = new XUnbufferedStream(
+        m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode);
+
+    if (!mbUseBufferedStream)
+        return xSrcStream;
+
+    uno::Reference<io::XInputStream> xBufStream(new XBufferedStream(xSrcStream));
+    return xBufStream;
 }
 
 std::unique_ptr<ZipEnumeration> ZipFile::entries()
@@ -542,7 +648,7 @@ uno::Reference< XInputStream > ZipFile::getInputStream( ZipEntry& rEntry,
     if ( bIsEncrypted && rData.is() && rData->m_aDigest.getLength() )
         bNeedRawStream = !hasValidPassword ( rEntry, rData );
 
-    return createUnbufferedStream ( aMutexHolder,
+    return createStreamForZipEntry ( aMutexHolder,
                                     rEntry,
                                     rData,
                                     bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA,
@@ -578,7 +684,7 @@ uno::Reference< XInputStream > ZipFile::getDataStream( ZipEntry& rEntry,
     else
         bNeedRawStream = ( rEntry.nMethod == STORED );
 
-    return createUnbufferedStream ( aMutexHolder,
+    return createStreamForZipEntry ( aMutexHolder,
                                     rEntry,
                                     rData,
                                     bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA,
@@ -595,7 +701,7 @@ uno::Reference< XInputStream > ZipFile::getRawData( ZipEntry& rEntry,
     if ( rEntry.nOffset <= 0 )
         readLOC( rEntry );
 
-    return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted );
+    return createStreamForZipEntry ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted );
 }
 
 uno::Reference< XInputStream > ZipFile::getWrappedRawStream(
@@ -612,7 +718,7 @@ uno::Reference< XInputStream > ZipFile::getWrappedRawStream(
     if ( rEntry.nOffset <= 0 )
         readLOC( rEntry );
 
-    return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, true, aMediaType );
+    return createStreamForZipEntry ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, true, aMediaType );
 }
 
 bool ZipFile::readLOC( ZipEntry &rEntry )
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index cb2e618..83b3a82 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -563,6 +563,7 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments )
     if ( aArguments.getLength() )
     {
         bool bHaveZipFile = true;
+        bool bUseBufferedStream = false;
 
         for( int ind = 0; ind < aArguments.getLength(); ind++ )
         {
@@ -690,6 +691,10 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments )
                     aNamedValue.Value >>= m_bAllowRemoveOnInsert;
                     m_xRootFolder->setRemoveOnInsertMode_Impl( m_bAllowRemoveOnInsert );
                 }
+                else if (aNamedValue.Name == "UseBufferedStream")
+                {
+                    aNamedValue.Value >>= bUseBufferedStream;
+                }
 
                 // for now the progress handler is not used, probably it will never be
                 // if ( aNamedValue.Name == "ProgressHandler" )
@@ -733,6 +738,7 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments )
             try
             {
                 m_pZipFile = o3tl::make_unique<ZipFile>(m_xContentStream, m_xContext, true, m_bForceRecovery);
+                m_pZipFile->setUseBufferedStream(bUseBufferedStream);
                 getZipFileContents();
             }
             catch ( IOException & e )


More information about the Libreoffice-commits mailing list