sc/qa/unit/ucalc.cxx | 82 +++++++++++++++++++++--------------------- sc/source/core/tool/token.cxx | 40 ++++++++++++++++++-- 2 files changed, 78 insertions(+), 44 deletions(-)
New commits: commit f974be31a7881c4ad72d9c29b4db3c435bd99ba5 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Mon Mar 18 16:28:11 2013 -0400 Embed reference tokens in the generated hash values. Also make the test code a bit easier to extend. Change-Id: Ib4e381cc139231884999c9d0dc9f51201e11f807 diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index b6addd1..3e9a14d 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -1196,47 +1196,47 @@ void Test::testFormulaGrouping() ScAddress aPos1(0,0,0), aPos2(1,0,0); - // simplest cases. - m_pDoc->SetString(aPos1, "=1"); - size_t nHashVal1 = m_pDoc->GetFormulaHash(aPos1); - m_pDoc->SetString(aPos2, "=2"); - size_t nHashVal2 = m_pDoc->GetFormulaHash(aPos2); - CPPUNIT_ASSERT_MESSAGE("These hashes should differ.", nHashVal1 != nHashVal2); - - // different cell functions. - aPos1.IncRow(); - aPos2.IncRow(); - m_pDoc->SetString(aPos1, "=SUM(1;2;3;4;5)"); - m_pDoc->SetString(aPos2, "=AVERAGE(1;2;3;4;5)"); - nHashVal1 = m_pDoc->GetFormulaHash(aPos1); - nHashVal2 = m_pDoc->GetFormulaHash(aPos2); - CPPUNIT_ASSERT_MESSAGE("These hashes should differ.", nHashVal1 != nHashVal2); - - // same relative references. - aPos1.IncRow(); - aPos2.IncRow(); - m_pDoc->SetString(aPos1, "=A2*3"); - m_pDoc->SetString(aPos2, "=B2*3"); - nHashVal1 = m_pDoc->GetFormulaHash(aPos1); - nHashVal2 = m_pDoc->GetFormulaHash(aPos2); - CPPUNIT_ASSERT_MESSAGE("These hashes should be equal.", nHashVal1 == nHashVal2); - - m_pDoc->SetString(aPos2, "=B2*4"); // Change the constant. - nHashVal2 = m_pDoc->GetFormulaHash(aPos2); - CPPUNIT_ASSERT_MESSAGE("These hashes should differ.", nHashVal1 != nHashVal2); - - m_pDoc->SetString(aPos1, "=A2*4"); // Change the constant again to make it "equal". - nHashVal1 = m_pDoc->GetFormulaHash(aPos1); - CPPUNIT_ASSERT_MESSAGE("These hashes should be equal.", nHashVal1 == nHashVal2); - - // string constant vs numeric constant. - aPos1.IncRow(); - aPos2.IncRow(); - m_pDoc->SetString(aPos1, "=3*4*5"); - m_pDoc->SetString(aPos2, "=3*4*\"foo\""); - nHashVal1 = m_pDoc->GetFormulaHash(aPos1); - nHashVal2 = m_pDoc->GetFormulaHash(aPos2); - CPPUNIT_ASSERT_MESSAGE("These hashes should differ.", nHashVal1 != nHashVal2); + struct { + const char* pFormula1; const char* pFormula2; bool bEqual; + } aTests[] = { + { "=1", "=2", false }, // different constants + { "=SUM(1;2;3;4;5)", "=AVERAGE(1;2;3;4;5)", false }, // different functions + { "=C2*3", "=D2*3", true }, // relative references + { "=C2*3", "=D2*4", false }, // different constants + { "=C2*4", "=D2*4", true }, // relative references + { "=3*4*5", "=3*4*\"foo\"", false }, // numeric vs string constants + { "=$C3/2", "=$C3/2", true }, // absolute column references + { "=C$3/2", "=D$3/2", true }, // absolute row references + { "=$E$30/2", "=$E$30/2", true }, // absolute references + { "=X20", "=$X$20", false }, // absolute vs relative + { "=X20", "=X$20", false }, // absolute vs relative + { "=X20", "=$X20", false }, // absolute vs relative + { "=X$20", "=$X20", false }, // column absolute vs row absolute + }; + + for (size_t i = 0; i < SAL_N_ELEMENTS(aTests); ++i) + { + m_pDoc->SetString(aPos1, OUString::createFromAscii(aTests[i].pFormula1)); + m_pDoc->SetString(aPos2, OUString::createFromAscii(aTests[i].pFormula2)); + size_t nHashVal1 = m_pDoc->GetFormulaHash(aPos1); + size_t nHashVal2 = m_pDoc->GetFormulaHash(aPos2); + + std::ostringstream os; + os << "(expr1:" << aTests[i].pFormula1 << "; expr2:" << aTests[i].pFormula2 << ")"; + if (aTests[i].bEqual) + { + os << " Error: these hashes should be equal." << endl; + CPPUNIT_ASSERT_MESSAGE(os.str().c_str(), nHashVal1 == nHashVal2); + } + else + { + os << " Error: these hashes should differ." << endl; + CPPUNIT_ASSERT_MESSAGE(os.str().c_str(), nHashVal1 != nHashVal2); + } + + aPos1.IncRow(); + aPos2.IncRow(); + } m_pDoc->DeleteTab(0); } diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index b400f6d..a19f2e3 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -1274,6 +1274,26 @@ bool ScTokenArray::ImplGetReference( ScRange& rRange, bool bValidOnly ) const return bIs; } +namespace { + +size_t HashSingleRef( const ScSingleRefData& rRef ) +{ + SCsCOL nCol = rRef.Flags.bColRel ? rRef.nRelCol : rRef.nCol; + SCsROW nRow = rRef.Flags.bRowRel ? rRef.nRelRow : rRef.nRow; + SCsTAB nTab = rRef.Flags.bTabRel ? rRef.nRelTab : rRef.nTab; + size_t nVal = nCol; + nVal += (nRow << 8); + nVal += (nTab << 16); + + // Embed flag values too. + nVal += rRef.Flags.bColRel; + nVal += (rRef.Flags.bRowRel << 1); + nVal += (rRef.Flags.bTabRel << 2); + return nVal; +} + +} + size_t ScTokenArray::GetHash() const { static OUStringHash aHasher; @@ -1281,11 +1301,11 @@ size_t ScTokenArray::GetHash() const size_t nHash = 1; OpCode eOp; StackVar eType; - const FormulaToken* p; + const ScToken* p; sal_uInt16 n = std::min<sal_uInt16>(nLen, 20); for (sal_uInt16 i = 0; i < n; ++i) { - p = pCode[i]; + p = static_cast<const ScToken*>(pCode[i]); eOp = p->GetOpCode(); if (eOp == ocPush) { @@ -1314,8 +1334,22 @@ size_t ScTokenArray::GetHash() const nHash += (aHasher(rStr) << i); continue; } + case svSingleRef: + { + size_t nVal = HashSingleRef(p->GetSingleRef()); + nHash += (nVal << i); + continue; + } + case svDoubleRef: + { + const ScComplexRefData& rRef = p->GetDoubleRef(); + size_t nVal1 = HashSingleRef(rRef.Ref1); + size_t nVal2 = HashSingleRef(rRef.Ref2); + nHash += (nVal1 << i); + nHash += (nVal2 << i); + continue; + } default: - // TODO: Decide later if we should generate hash from references as well. ; } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits