sc/inc/formulacell.hxx | 1 sc/inc/formularesult.hxx | 1 sc/source/core/data/column2.cxx | 168 ++++++++++++++++++++++++++-------- sc/source/core/data/formulacell.cxx | 11 ++ sc/source/core/tool/formulagroup.cxx | 28 ++--- sc/source/core/tool/formularesult.cxx | 49 +++++++++ 6 files changed, 206 insertions(+), 52 deletions(-)
New commits: commit e6d9e1fce1ed92d8e36af4d542690ccc246083cd Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 20:39:17 2013 -0400 Eliminate (almost) duplicate code blocks. Change-Id: Ib5d0fae3efda6bde056f7e4990de57c8b3541549 diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 048402f..42c5469 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2050,6 +2050,26 @@ void ScColumn::FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nR namespace { +template<typename _Blk> +void getBlockIterators( + sc::CellStoreType::iterator it, size_t& rLenRemain, + typename _Blk::iterator& rData, typename _Blk::iterator& rDataEnd ) +{ + rData = _Blk::begin(*it->data); + if (rLenRemain >= it->size) + { + // Block is shorter than the remaining requested length. + rDataEnd = _Blk::end(*it->data); + rLenRemain -= it->size; + } + else + { + rDataEnd = rData; + std::advance(rDataEnd, rLenRemain); + rLenRemain = 0; + } +} + bool appendDouble( sc::FormulaGroupContext::NumArrayType& rArray, size_t nLen, sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd ) @@ -2064,20 +2084,8 @@ bool appendDouble( { case sc::element_type_numeric: { - sc::numeric_block::iterator itData = sc::numeric_block::begin(*it->data); - sc::numeric_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::numeric_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::numeric_block::iterator itData, itDataEnd; + getBlockIterators<sc::numeric_block>(it, nLenRemain, itData, itDataEnd); for (; itData != itDataEnd; ++itData) rArray.push_back(*itData); @@ -2085,20 +2093,8 @@ bool appendDouble( break; case sc::element_type_formula: { - sc::formula_block::iterator itData = sc::formula_block::begin(*it->data); - sc::formula_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::formula_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::formula_block::iterator itData, itDataEnd; + getBlockIterators<sc::formula_block>(it, nLenRemain, itData, itDataEnd); sal_uInt16 nErr; double fVal; @@ -2161,20 +2157,8 @@ bool appendStrings( { case sc::element_type_string: { - sc::string_block::iterator itData = sc::string_block::begin(*it->data); - sc::string_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::string_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::string_block::iterator itData, itDataEnd; + getBlockIterators<sc::string_block>(it, nLenRemain, itData, itDataEnd); for (; itData != itDataEnd; ++itData) rArray.push_back(rCxt.intern(*itData)); @@ -2182,20 +2166,8 @@ bool appendStrings( break; case sc::element_type_edittext: { - sc::edittext_block::iterator itData = sc::edittext_block::begin(*it->data); - sc::edittext_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::edittext_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::edittext_block::iterator itData, itDataEnd; + getBlockIterators<sc::edittext_block>(it, nLenRemain, itData, itDataEnd); for (; itData != itDataEnd; ++itData) { @@ -2206,20 +2178,8 @@ bool appendStrings( break; case sc::element_type_formula: { - sc::formula_block::iterator itData = sc::formula_block::begin(*it->data); - sc::formula_block::iterator itDataEnd; - if (nLenRemain >= it->size) - { - // Block is shorter than the remaining requested length. - itDataEnd = sc::formula_block::end(*it->data); - nLenRemain -= it->size; - } - else - { - itDataEnd = itData; - std::advance(itDataEnd, nLenRemain); - nLenRemain = 0; - } + sc::formula_block::iterator itData, itDataEnd; + getBlockIterators<sc::formula_block>(it, nLenRemain, itData, itDataEnd); sal_uInt16 nErr; OUString aStr; commit 6fc2ca3ccabca19bb87bc53fcbe074a2a61bdb46 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 19:36:30 2013 -0400 Support fetching string array that spans over multiple blocks. Change-Id: I543fca231e0be886159b8ddbd83ceffa1bf69c1b diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 835eb91..a494759 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -252,6 +252,7 @@ public: sal_uInt16 GetErrCode(); // interpret first if necessary sal_uInt16 GetRawError(); // don't interpret, just return code or result error bool GetErrorOrValue( sal_uInt16& rErr, double& rVal ); + bool GetErrorOrString( sal_uInt16& rErr, OUString& rStr ); sal_uInt8 GetMatrixFlag() const; ScTokenArray* GetCode(); const ScTokenArray* GetCode() const; diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx index f1f7b5d..2459bcf 100644 --- a/sc/inc/formularesult.hxx +++ b/sc/inc/formularesult.hxx @@ -135,6 +135,7 @@ public: bool IsMultiline() const; bool GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const; + bool GetErrorOrString( sal_uInt16& rErr, OUString& rStr ) const; /** Get error code if set or GetCellResultType() is formula::svError or svUnknown, else 0. */ diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 7a97972..048402f 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2148,6 +2148,138 @@ bool appendDouble( return false; } +bool appendStrings( + sc::FormulaGroupContext& rCxt, ScDocument* pDoc, + sc::FormulaGroupContext::StrArrayType& rArray, size_t nLen, + sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd ) +{ + size_t nLenRemain = nLen; + + for (; it != itEnd; ++it) + { + switch (it->type) + { + case sc::element_type_string: + { + sc::string_block::iterator itData = sc::string_block::begin(*it->data); + sc::string_block::iterator itDataEnd; + if (nLenRemain >= it->size) + { + // Block is shorter than the remaining requested length. + itDataEnd = sc::string_block::end(*it->data); + nLenRemain -= it->size; + } + else + { + itDataEnd = itData; + std::advance(itDataEnd, nLenRemain); + nLenRemain = 0; + } + + for (; itData != itDataEnd; ++itData) + rArray.push_back(rCxt.intern(*itData)); + } + break; + case sc::element_type_edittext: + { + sc::edittext_block::iterator itData = sc::edittext_block::begin(*it->data); + sc::edittext_block::iterator itDataEnd; + if (nLenRemain >= it->size) + { + // Block is shorter than the remaining requested length. + itDataEnd = sc::edittext_block::end(*it->data); + nLenRemain -= it->size; + } + else + { + itDataEnd = itData; + std::advance(itDataEnd, nLenRemain); + nLenRemain = 0; + } + + for (; itData != itDataEnd; ++itData) + { + OUString aStr = ScEditUtil::GetString(**itData, pDoc); + rArray.push_back(rCxt.intern(aStr)); + } + } + break; + case sc::element_type_formula: + { + sc::formula_block::iterator itData = sc::formula_block::begin(*it->data); + sc::formula_block::iterator itDataEnd; + if (nLenRemain >= it->size) + { + // Block is shorter than the remaining requested length. + itDataEnd = sc::formula_block::end(*it->data); + nLenRemain -= it->size; + } + else + { + itDataEnd = itData; + std::advance(itDataEnd, nLenRemain); + nLenRemain = 0; + } + + sal_uInt16 nErr; + OUString aStr; + for (; itData != itDataEnd; ++itData) + { + ScFormulaCell& rFC = **itData; + if (!rFC.GetErrorOrString(nErr, aStr) || nErr) + { + if (nErr == ScErrorCodes::errCircularReference) + { + // This cell needs to be recalculated on next visit. + rFC.SetErrCode(0); + rFC.SetDirtyVar(); + } + return false; + } + + rArray.push_back(rCxt.intern(aStr)); + } + } + break; + case sc::element_type_empty: + { + // Fill it with NULL pointers. + if (nLenRemain >= it->size) + { + rArray.resize(rArray.size() + it->size, NULL); + nLenRemain -= it->size; + } + else + { + rArray.resize(rArray.size() + nLenRemain, NULL); + nLenRemain = 0; + } + } + break; + case sc::element_type_numeric: + default: + return false; + } + + if (!nLenRemain) + return true; + } + + return false; +} + +void copyFirstBlock( sc::FormulaGroupContext& rCxt, size_t nLen, const sc::CellStoreType::position_type& rPos ) +{ + rCxt.maStrArrays.push_back(new sc::FormulaGroupContext::StrArrayType); + sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back(); + rArray.reserve(nLen); + + const OUString* p = &sc::string_block::at(*rPos.first->data, rPos.second); + const OUString* pEnd = p + nLen; + for (; p != pEnd; ++p) + rArray.push_back(rCxt.intern(*p)); +} + } formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 ) @@ -2256,20 +2388,20 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext& if (nLenRequested <= nLen) { // Requested length fits a single block. - rCxt.maStrArrays.push_back(new sc::FormulaGroupContext::StrArrayType); + copyFirstBlock(rCxt, nLenRequested, aPos); sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back(); - rArray.reserve(nLenRequested); - - const OUString* p = &sc::string_block::at(*aPos.first->data, aPos.second); - const OUString* pEnd = p + nLenRequested; - for (; p != pEnd; ++p) - rArray.push_back(rCxt.intern(*p)); - return formula::VectorRefArray(&rArray[0]); } - // TODO: handle cases where the requested length goes beyond the - // current block just like we do with numeric array. + copyFirstBlock(rCxt, nLen, aPos); + sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back(); + + // Fill the remaining array with values from the following blocks. + ++aPos.first; + if (!appendStrings(rCxt, pDocument, rArray, nLenRequested - nLen, aPos.first, maCells.end())) + return formula::VectorRefArray(); + + return formula::VectorRefArray(&rArray[0]); } break; case sc::element_type_empty: diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 143351e8..f8f344d 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2082,6 +2082,17 @@ bool ScFormulaCell::GetErrorOrValue( sal_uInt16& rErr, double& rVal ) return aResult.GetErrorOrDouble(rErr, rVal); } +bool ScFormulaCell::GetErrorOrString( sal_uInt16& rErr, OUString& rStr ) +{ + MaybeInterpret(); + + rErr = pCode->GetCodeError(); + if (rErr) + return true; + + return aResult.GetErrorOrString(rErr, rStr); +} + bool ScFormulaCell::HasOneReference( ScRange& r ) const { pCode->Reset(); diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx index 77de2ae..c232a31 100644 --- a/sc/source/core/tool/formularesult.cxx +++ b/sc/source/core/tool/formularesult.cxx @@ -255,6 +255,19 @@ inline bool isValue( formula::StackVar sv ) || sv == formula::svEmptyCell || sv == formula::svHybridValueCell; } +inline bool isString( formula::StackVar sv ) +{ + switch (sv) + { + case formula::svString: + case formula::svHybridCell: + case formula::svHybridValueCell: + return true; + } + + return false; +} + } bool ScFormulaResult::IsValue() const @@ -321,6 +334,42 @@ bool ScFormulaResult::GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const return true; } +bool ScFormulaResult::GetErrorOrString( sal_uInt16& rErr, OUString& rStr ) const +{ + if (mnError) + { + rErr = mnError; + return true; + } + + formula::StackVar sv = GetCellResultType(); + if (sv == formula::svError) + { + if (GetType() == formula::svMatrixCell) + { + // don't need to test for mpToken here, GetType() already did it + rErr = static_cast<const ScMatrixCellResultToken*>(mpToken)-> + GetUpperLeftToken()->GetError(); + } + else if (mpToken) + { + rErr = mpToken->GetError(); + } + } + + if (rErr) + return true; + + if (!mbToken) + return false; + + if (!isString(sv)) + return false; + + rStr = GetString(); + return true; +} + sal_uInt16 ScFormulaResult::GetResultError() const { if (mnError) commit d27053e92838bf68e0e8348f65d6d111b318824c Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Sep 9 18:53:33 2013 -0400 Move common code blocks to a function. Change-Id: I1b1aaa0b1dd8cc6e14fbac1981c67a8b63c92c2c diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index 0b37b97..5dff3d9 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -83,6 +83,18 @@ void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen ) } } +void flushSegment( + ScMatrix& rMat, size_t nCol, rtl_uString** pHead, rtl_uString** pCur, rtl_uString** pTop ) +{ + size_t nOffset = pHead - pTop; + std::vector<OUString> aStrs; + aStrs.reserve(pCur - pHead); + for (; pHead != pCur; ++pHead) + aStrs.push_back(OUString(*pHead)); + + rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); +} + void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) { rtl_uString** p = pStrs; @@ -102,13 +114,7 @@ void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) if (pHead) { // Flush this non-empty segment to the matrix. - size_t nOffset = pHead - pStrs; - std::vector<OUString> aStrs; - aStrs.reserve(p - pHead); - for (; pHead != p; ++pHead) - aStrs.push_back(OUString(*pHead)); - - rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); + flushSegment(rMat, nCol, pHead, p, pStrs); pHead = NULL; } } @@ -116,13 +122,7 @@ void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen ) if (pHead) { // Flush last non-empty segment to the matrix. - size_t nOffset = pHead - pStrs; - std::vector<OUString> aStrs; - aStrs.reserve(p - pHead); - for (; pHead != p; ++pHead) - aStrs.push_back(OUString(*pHead)); - - rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset); + flushSegment(rMat, nCol, pHead, p, pStrs); } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits