[Libreoffice-commits] core.git: Branch 'private/kohei/xlsx-import-speedup' - 2 commits - sc/qa sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Tue Nov 5 17:55:36 CET 2013


 sc/qa/unit/ucalc.hxx                   |    2 
 sc/qa/unit/ucalc_formula.cxx           |   56 +++++++++++++++++++++++++++
 sc/source/core/tool/address.cxx        |   67 +++++++++++++++++++++++++--------
 sc/source/filter/oox/formulabuffer.cxx |    2 
 4 files changed, 111 insertions(+), 16 deletions(-)

New commits:
commit 4d2666fa2b40b17673589e7b226907e9353f7e9d
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 11:55:57 2013 -0500

    Avoid using an extra buffer when the name doesn't contain double-quotes.
    
    Change-Id: Idc76ccad114e5964f80c5a3c8c8da2a64c1a2b86

diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 039b256..495c9a0 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -47,6 +47,44 @@ ScAddress::Details::Details ( const ScDocument* pDoc,
 {
 }
 
+namespace {
+
+const sal_Unicode* parseQuotedNameWithBuffer( const sal_Unicode* pStart, const sal_Unicode* p, OUString& rName )
+{
+    // The current character must be on the 2nd quote.
+
+    // Push all the characters up to the current, but skip the very first
+    // character which is the opening quote.
+    OUStringBuffer aBuf(OUString(pStart+1, p-pStart-1));
+
+    ++p; // Skip the 2nd quote.
+    sal_Unicode cPrev = 0;
+    for (; *p; ++p)
+    {
+        if (*p == '\'')
+        {
+            if (cPrev == '\'')
+            {
+                // double single-quote equals one single quote.
+                aBuf.append(*p);
+                cPrev = 0;
+                continue;
+            }
+        }
+        else if (cPrev == '\'')
+        {
+            // We are past the closing quote.  We're done!
+            rName = aBuf.makeStringAndClear();
+            return p;
+        }
+        else
+            aBuf.append(*p);
+        cPrev = *p;
+    }
+
+    return pStart;
+}
+
 /**
  * Parse from the opening single quote to the closing single quote.  Inside
  * the quotes, a single quote character is encoded by double single-quote
@@ -59,13 +97,11 @@ ScAddress::Details::Details ( const ScDocument* pDoc,
  * @return pointer to the character immediately after the closing single
  *         quote.
  */
-static const sal_Unicode* lcl_ParseQuotedName( const sal_Unicode* p, OUString& rName )
+const sal_Unicode* parseQuotedName( const sal_Unicode* p, OUString& rName )
 {
-    rName = "";
     if (*p != '\'')
         return p;
 
-    OUStringBuffer aBuf;
     const sal_Unicode* pStart = p;
     sal_Unicode cPrev = 0;
     for (++p; *p; ++p)
@@ -75,25 +111,26 @@ static const sal_Unicode* lcl_ParseQuotedName( const sal_Unicode* p, OUString& r
             if (cPrev == '\'')
             {
                 // double single-quote equals one single quote.
-                aBuf.append(*p);
-                cPrev = 0;
-                continue;
+                return parseQuotedNameWithBuffer(pStart, p, rName);
             }
         }
         else if (cPrev == '\'')
         {
-            // We are past the closing quote.  We're done!
-            rName = aBuf.makeStringAndClear();
+            // We are past the closing quote.  We're done!  Skip the opening
+            // and closing quotes.
+            rName = OUString(pStart+1, p - pStart-2);
             return p;
         }
-        else
-            aBuf.append(*p);
+
         cPrev = *p;
     }
 
+    rName = "";
     return pStart;
 }
 
+}
+
 static long int
 sal_Unicode_strtol ( const sal_Unicode*  p,
                      const sal_Unicode** pEnd )
@@ -265,7 +302,7 @@ lcl_XL_ParseSheetRef( const sal_Unicode* start,
     }
     else if( *p == '\'')
     {
-        p = lcl_ParseQuotedName(p, aTabName);
+        p = parseQuotedName(p, aTabName);
         if (aTabName.isEmpty())
             return NULL;
     }
@@ -415,7 +452,7 @@ const sal_Unicode* ScRange::Parse_XL_Header(
         // single quote text inside the quoted text.
         if (*p == '\'')
         {
-            p = lcl_ParseQuotedName(p, rExternDocName);
+            p = parseQuotedName(p, rExternDocName);
             if (!*p || *p != ']' || rExternDocName.isEmpty())
             {
                 rExternDocName = "";
@@ -447,7 +484,7 @@ const sal_Unicode* ScRange::Parse_XL_Header(
         // Excel does not allow [ and ] characters in sheet names though.
         // But, more sickness comes with MOOXML as there may be
         // '[1]Sheet 4'!$A$1  where [1] is the external doc's index.
-        p = lcl_ParseQuotedName(p, rExternDocName);
+        p = parseQuotedName(p, rExternDocName);
         if (!*p || *p != '!')
         {
             rExternDocName = "";
@@ -1003,7 +1040,7 @@ lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAdd
     {
         const sal_Unicode* pStart = p;
         OUString aTmp;
-        p = lcl_ParseQuotedName(p, aTmp);
+        p = parseQuotedName(p, aTmp);
         aDocName = aTmp;
         if (*p++ == SC_COMPILER_FILE_TAB_SEP)
             bExtDoc = true;
@@ -1036,7 +1073,7 @@ lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAdd
             // Tokens that start at ' can have anything in them until a final
             // ' but '' marks an escaped '.  We've earlier guaranteed that a
             // string containing '' will be surrounded by '.
-            p = lcl_ParseQuotedName(p, aTab);
+            p = parseQuotedName(p, aTab);
         }
         else
         {
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index bc074a2..68e1d2e 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -90,11 +90,11 @@ void FormulaBuffer::finalizeImport()
 void FormulaBuffer::applyCellFormulas( const std::vector< TokenAddressItem >& rVector )
 {
     ScDocumentImport& rDoc = getDocImport();
+    ScExternalRefManager::ApiGuard aExtRefGuard(&rDoc.getDoc());
     for ( std::vector< TokenAddressItem >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
     {
         ScAddress aPos;
         ScUnoConversion::FillScAddress(aPos, it->maCellAddress);
-        ScExternalRefManager::ApiGuard aExtRefGuard(&rDoc.getDoc());
         ScCompiler aCompiler(&rDoc.getDoc(), aPos);
         aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
         ScTokenArray* pCode = aCompiler.CompileString(it->maTokenStr);
commit e5f2c9f1c244f199ba0765e26161a7b674bee75d
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 11:00:05 2013 -0500

    Add new test for parsing OOo A1 style single references.
    
    Change-Id: I7644338bd536d16777d330a64764eb26ecda5da5

diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index b9c1d42..19c94d7 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -84,6 +84,7 @@ public:
     void testRangeList();
     void testInput();
 
+    void testFormulaParseReference();
     void testFetchVectorRefArray();
     void testFormulaHashAndTag();
     void testFormulaRefData();
@@ -292,6 +293,7 @@ public:
     CPPUNIT_TEST(testSharedStringPool);
     CPPUNIT_TEST(testRangeList);
     CPPUNIT_TEST(testInput);
+    CPPUNIT_TEST(testFormulaParseReference);
     CPPUNIT_TEST(testFetchVectorRefArray);
     CPPUNIT_TEST(testFormulaHashAndTag);
     CPPUNIT_TEST(testFormulaRefData);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 9f824e5..ce407e7 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -73,6 +73,62 @@ bool equals( const formula::VectorRefArray& rArray, size_t nPos, const OUString&
 
 }
 
+void Test::testFormulaParseReference()
+{
+    OUString aTab1("90's Music"), aTab2("90's and 70's"), aTab3("All Others"), aTab4("NoQuote");
+    m_pDoc->InsertTab(0, "Dummy"); // just to shift the sheet indices...
+    m_pDoc->InsertTab(1, aTab1); // name with a single quote.
+    m_pDoc->InsertTab(2, aTab2); // name with 2 single quotes.
+    m_pDoc->InsertTab(3, aTab3); // name without single quotes.
+    m_pDoc->InsertTab(4, aTab4); // name that doesn't require to be quoted.
+
+    OUString aTabName;
+    m_pDoc->GetName(1, aTabName);
+    CPPUNIT_ASSERT_EQUAL(aTab1, aTabName);
+    m_pDoc->GetName(2, aTabName);
+    CPPUNIT_ASSERT_EQUAL(aTab2, aTabName);
+    m_pDoc->GetName(3, aTabName);
+    CPPUNIT_ASSERT_EQUAL(aTab3, aTabName);
+    m_pDoc->GetName(4, aTabName);
+    CPPUNIT_ASSERT_EQUAL(aTab4, aTabName);
+
+    ScAddress aPos;
+    ScAddress::ExternalInfo aExtInfo;
+    sal_uInt16 nRes = aPos.Parse("'90''s Music'.D10", m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
+    CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & SCA_VALID) != 0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(1), aPos.Tab());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(3), aPos.Col());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), aPos.Row());
+    CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
+
+    nRes = aPos.Parse("'90''s and 70''s'.C100", m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
+    CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & SCA_VALID) != 0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(2), aPos.Tab());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(2), aPos.Col());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(99), aPos.Row());
+    CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
+
+    nRes = aPos.Parse("'All Others'.B3", m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
+    CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & SCA_VALID) != 0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(3), aPos.Tab());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), aPos.Col());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), aPos.Row());
+    CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
+
+    nRes = aPos.Parse("NoQuote.E13", m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
+    CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & SCA_VALID) != 0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(4), aPos.Tab());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(4), aPos.Col());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), aPos.Row());
+    CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
+
+    m_pDoc->DeleteTab(4);
+    m_pDoc->DeleteTab(3);
+    m_pDoc->DeleteTab(2);
+    m_pDoc->DeleteTab(1);
+    m_pDoc->DeleteTab(0);
+}
+
 void Test::testFetchVectorRefArray()
 {
     m_pDoc->InsertTab(0, "Test");


More information about the Libreoffice-commits mailing list