[Libreoffice-commits] core.git: writerfilter/source

Miklos Vajna vmiklos at collabora.co.uk
Tue Mar 25 01:47:43 PDT 2014


 writerfilter/source/ooxml/OOXMLStreamImpl.cxx |   43 +++++++++++++++++++++++---
 writerfilter/source/ooxml/OOXMLStreamImpl.hxx |    5 +++
 2 files changed, 44 insertions(+), 4 deletions(-)

New commits:
commit f5ae42f9344a523e586fdcca4f0e670ee2a4d821
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Tue Mar 25 09:40:27 2014 +0100

    fdo#76563 DOCX import: speed up importing lots of hyperlinks
    
    The problem was that in
    writerfilter::ooxml::OOXMLStreamImpl::lcl_getTarget(), we went over the
    list of all hyperlinks for each request. Instead, let's do it once, and
    in the remaining cases just look up the result from a map.
    
    Numbers before on my machine (ms, load time):
    
    2215, 2243, 2205
    
    After:
    
    1362, 1358, 1358
    
    So that causes about 39% speedup for a non-debug build.
    
    Change-Id: Ib4718abbe834c5ba49a85469148b656e3c808041

diff --git a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
index 6f639e6..284d369 100644
--- a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
+++ b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
@@ -93,6 +93,42 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
                                     const OUString & rId,
                                     OUString & rDocumentTarget)
 {
+    static OUString sId("Id");
+    static OUString sTarget("Target");
+    static OUString sTargetMode("TargetMode");
+    static OUString sExternal("External");
+    if (maIdCache.empty())
+    {
+        // Cache is empty? Then let's build it!
+        uno::Sequence< uno::Sequence<beans::StringPair> >aSeqs = xRelationshipAccess->getAllRelationships();
+        for (sal_Int32 i = 0; i < aSeqs.getLength(); ++i)
+        {
+            const uno::Sequence<beans::StringPair>& rSeq = aSeqs[i];
+            OUString aId;
+            OUString aTarget;
+            bool bExternal = false;
+            for (sal_Int32 j = 0; j < rSeq.getLength(); ++j)
+            {
+                const beans::StringPair& rPair = rSeq[j];
+                if (rPair.First == sId)
+                    aId = rPair.Second;
+                else if (rPair.First == sTarget)
+                    aTarget = rPair.Second;
+                else if (rPair.First == sTargetMode && rPair.Second == sExternal)
+                    bExternal = true;
+            }
+            // Only cache external targets, internal ones are more complex (see below)
+            if (bExternal)
+                maIdCache[aId] = aTarget;
+        }
+    }
+
+    if (maIdCache.find(rId) != maIdCache.end())
+    {
+        rDocumentTarget = maIdCache[rId];
+        return true;
+    }
+
     bool bFound = false;
     static uno::Reference< com::sun::star::uri::XUriReferenceFactory > xFac =  ::com::sun::star::uri::UriReferenceFactory::create( mxContext );
     // use '/' to representent the root of the zip package ( and provide a 'file' scheme to
@@ -101,7 +137,6 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
     uno::Reference< com::sun::star::uri::XUriReference > xBase = xFac->parse( OUString( "file:///"  ) + msPath );
 
     static OUString sType("Type");
-    static OUString sId("Id");
     static OUString sDocumentType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument");
     static OUString sStylesType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles");
     static OUString sNumberingType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering");
@@ -142,9 +177,6 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
     static OUString sFootersTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/footer");
     static OUString sHeaderTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/header");
     static OUString sOleObjectTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/oleObject");
-    static OUString sTarget("Target");
-    static OUString sTargetMode("TargetMode");
-    static OUString sExternal("External");
     static OUString sVBAProjectType("http://schemas.microsoft.com/office/2006/relationships/vbaProject");
 
     OUString sStreamType;
@@ -348,6 +380,9 @@ void OOXMLStreamImpl::init()
                           openStreamElementByHierarchicalName
                           (msTarget, embed::ElementModes::SEEKABLEREAD));
             aAny >>= mxDocumentStream;
+            // Non-cached ID lookup works by accessing mxDocumentStream as an embed::XRelationshipAccess.
+            // So when it changes, we should empty the cache.
+            maIdCache.clear();
         }
     }
 }
diff --git a/writerfilter/source/ooxml/OOXMLStreamImpl.hxx b/writerfilter/source/ooxml/OOXMLStreamImpl.hxx
index 4db03a2..2230944 100644
--- a/writerfilter/source/ooxml/OOXMLStreamImpl.hxx
+++ b/writerfilter/source/ooxml/OOXMLStreamImpl.hxx
@@ -19,6 +19,8 @@
 #ifndef INCLUDED_OOXML_STREAM_IMPL_HXX
 #define INCLUDED_OOXML_STREAM_IMPL_HXX
 
+#include <map>
+
 #include <ooxml/OOXMLDocument.hxx>
 #include <comphelper/storagehelper.hxx>
 #include <com/sun/star/embed/XRelationshipAccess.hpp>
@@ -51,6 +53,9 @@ class OOXMLStreamImpl : public OOXMLStream
     OUString msPath;
     OUString msTarget;
 
+    /// Cache holding an Id <-> Target map of external relations.
+    std::map<OUString, OUString> maIdCache;
+
     bool lcl_getTarget(uno::Reference<embed::XRelationshipAccess>
                        xRelationshipAccess,
                        StreamType_t nStreamType,


More information about the Libreoffice-commits mailing list