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 <[email protected]> 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 <[email protected]> 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"); _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
