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 <vmik...@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,
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to