sc/inc/column.hxx | 2 sc/inc/document.hxx | 2 sc/inc/table.hxx | 2 sc/source/core/data/column2.cxx | 188 +++++++++++++++++++++++++++++++++--- sc/source/core/data/document.cxx | 2 sc/source/core/data/formulacell.cxx | 13 +- sc/source/core/data/table1.cxx | 2 7 files changed, 188 insertions(+), 23 deletions(-)
New commits: commit 49c16e6060b4323c79d33abfa163d4e5aae2bc15 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Fri Jun 28 11:29:14 2013 -0400 Have FetchDoubleArray() to optionally calculate dependent formula cells. Change-Id: Ide29df664ff002f9cd8fe3edbf9512dd0cbb9eb6 diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index b119d3d..4601ae2 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -471,7 +471,7 @@ public: formula::FormulaTokenRef ResolveStaticReference( SCROW nRow ); bool ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow1, SCROW nRow2 ); void FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nRow2 ) const; - const double* FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 ) const; + const double* FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 ); void SetFormulaResults( SCROW nRow, const double* pResults, size_t nLen ); void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index fd8f61f..8d942b7 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1973,7 +1973,7 @@ public: formula::FormulaTokenRef ResolveStaticReference( const ScRange& rRange ); const double* FetchDoubleArray( - sc::FormulaGroupContext& rCxt, const ScAddress& rPos, SCROW nLength ) const; + sc::FormulaGroupContext& rCxt, const ScAddress& rPos, SCROW nLength ); SvtBroadcaster* GetBroadcaster( const ScAddress& rPos ); const SvtBroadcaster* GetBroadcaster( const ScAddress& rPos ) const; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index bae3818..bda039f 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -842,7 +842,7 @@ public: formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol, SCROW nRow ); formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); const double* FetchDoubleArray( - sc::FormulaGroupContext& rCxt, SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const; + sc::FormulaGroupContext& rCxt, SCCOL nCol, SCROW nRow1, SCROW nRow2 ); ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow ); diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 3704c6d..82990ab 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2073,23 +2073,189 @@ void ScColumn::FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nR sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2); } -const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& /*rCxt*/, SCROW nRow1, SCROW nRow2 ) const +namespace { + +bool appendDouble( + sc::FormulaGroupContext::DoubleArrayType& rArray, size_t nLen, + sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd ) { - // TODO: I'll use the context object later. - if (nRow1 > nRow2) - return NULL; + size_t nLenRemain = nLen; + for (; it != itEnd; ++it) + { + switch (it->type) + { + 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; + } - std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1); - if (aPos.first->type != sc::element_type_numeric) - // This is not a numeric cell block. + for (; itData != itDataEnd; ++itData) + rArray.push_back(*itData); + } + 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; + } + + for (; itData != itDataEnd; ++itData) + { + ScFormulaCell& rFC = **itData; + rArray.push_back(rFC.GetValue()); + } + } + break; + case sc::element_type_empty: + { + // Fill it with 0's. + if (nLenRemain >= it->size) + { + rArray.resize(rArray.size() + it->size, 0); + nLenRemain -= it->size; + } + else + { + rArray.resize(rArray.size() + nLenRemain, 0); + nLenRemain = 0; + } + } + break; + case sc::element_type_string: + case sc::element_type_edittext: + default: + return false; + } + + if (!nLenRemain) + return true; + } + + return false; +} + +} + +const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 ) +{ + if (nRow1 > nRow2) return NULL; + size_t nLenRequested = nRow2 - nRow1 + 1; + sc::CellStoreType::position_type aPos = maCells.position(nRow1); size_t nLen = aPos.first->size - aPos.second; - if (static_cast<SCROW>(nLen) < nRow2 - nRow1 + 1) - // Array shorter than requested. - return NULL; + switch (aPos.first->type) + { + case sc::element_type_numeric: + { + // This is a numeric cell block. + if (nLenRequested <= nLen) + // Requested length fits a single block. + return &sc::numeric_block::at(*aPos.first->data, aPos.second); + + // Allocate a new array and copy the values to it. + sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aPos.first->data); + sc::numeric_block::const_iterator itEnd = sc::numeric_block::end(*aPos.first->data); + std::advance(it, aPos.second); + rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType(it, itEnd)); + sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back(); + rArray.reserve(nLenRequested); + + // Fill the remaining array with values from the following blocks. + ++aPos.first; + if (!appendDouble(rArray, nLenRequested - nLen, aPos.first, maCells.end())) + return NULL; + + return &rArray[0]; + } + break; + case sc::element_type_formula: + { + rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType); + sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back(); + rArray.reserve(nLenRequested); + + sc::formula_block::const_iterator it = sc::formula_block::begin(*aPos.first->data); + sc::formula_block::const_iterator itEnd; + if (nLenRequested <= nLen) + { + // Requested length is within a single block. + itEnd = it; + std::advance(itEnd, nLenRequested); + for (; it != itEnd; ++it) + { + ScFormulaCell& rCell = **it; + rArray.push_back(rCell.GetValue()); // the cell may be interpreted. + } + + return &rArray[0]; + } + + itEnd = sc::formula_block::end(*aPos.first->data); + std::advance(itEnd, nLenRequested); + for (; it != itEnd; ++it) + { + ScFormulaCell& rCell = **it; + rArray.push_back(rCell.GetValue()); // the cell may be interpreted. + } + + // Fill the remaining array with values from the following blocks. + ++aPos.first; + if (!appendDouble(rArray, nLenRequested - nLen, aPos.first, maCells.end())) + return NULL; + + return &rArray[0]; + } + break; + case sc::element_type_empty: + { + if (nLenRequested <= nLen) + { + // Fill the whole length with zero. + rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType(nLenRequested, 0.0)); + return &rCxt.maArrays.back()[0]; + } + + // Fill the array with zero for the length of the empty block. + rCxt.maArrays.push_back(new sc::FormulaGroupContext::DoubleArrayType(nLen, 0.0)); + sc::FormulaGroupContext::DoubleArrayType& rArray = rCxt.maArrays.back(); + rArray.reserve(nLenRequested); + + // Fill the remaining array with values from the following blocks. + ++aPos.first; + if (!appendDouble(rArray, nLenRequested - nLen, aPos.first, maCells.end())) + return NULL; + + return &rArray[0]; + } + default: + ; + } - return &sc::numeric_block::at(*aPos.first->data, aPos.second); + return NULL; } void ScColumn::SetFormulaResults( SCROW nRow, const double* pResults, size_t nLen ) diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 3ed67c3..3ce424f 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -1609,7 +1609,7 @@ formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScRange& rRan } const double* ScDocument::FetchDoubleArray( - sc::FormulaGroupContext& rCxt, const ScAddress& rPos, SCROW nLength ) const + sc::FormulaGroupContext& rCxt, const ScAddress& rPos, SCROW nLength ) { SCTAB nTab = rPos.Tab(); if (!TableExists(nTab)) diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 2ade13b..26d7ee5 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2941,13 +2941,13 @@ namespace { class GroupTokenConverter { - sc::FormulaGroupContext maCxt; + sc::FormulaGroupContext& mrCxt; ScTokenArray& mrGroupTokens; ScDocument& mrDoc; ScFormulaCell& mrCell; public: - GroupTokenConverter(ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell) : - mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell) {} + GroupTokenConverter(sc::FormulaGroupContext& rCxt, ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell) : + mrCxt(rCxt), mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell) {} bool convert(ScTokenArray& rCode) { @@ -2978,7 +2978,7 @@ public: // we finish cell storage rework, we'll support temporary // generation of a double array which is a combination of // multiple cell array segments. - const double* pArray = mrDoc.FetchDoubleArray(maCxt, aRefPos, mrCell.GetCellGroup()->mnLength); + const double* pArray = mrDoc.FetchDoubleArray(mrCxt, aRefPos, mrCell.GetCellGroup()->mnLength); if (!pArray) return false; @@ -3020,7 +3020,7 @@ public: for (SCCOL i = aRef.Ref1.nCol; i <= aRef.Ref2.nCol; ++i) { aRefPos.SetCol(i); - const double* pArray = mrDoc.FetchDoubleArray(maCxt, aRefPos, nArrayLength); + const double* pArray = mrDoc.FetchDoubleArray(mrCxt, aRefPos, nArrayLength); if (!pArray) return false; @@ -3108,9 +3108,8 @@ bool ScFormulaCell::InterpretFormulaGroup() return InterpretInvariantFormulaGroup(); sc::FormulaGroupContext aCxt; - ScTokenArray aCode; - GroupTokenConverter aConverter(aCode, *pDocument, *this); + GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this); if (!aConverter.convert(*pCode)) return false; return sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aPos, xGroup, aCode); diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 2d90fa9..dcd0344 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -2156,7 +2156,7 @@ formula::FormulaTokenRef ScTable::ResolveStaticReference( SCCOL nCol1, SCROW nRo } const double* ScTable::FetchDoubleArray( - sc::FormulaGroupContext& rCxt, SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const + sc::FormulaGroupContext& rCxt, SCCOL nCol, SCROW nRow1, SCROW nRow2 ) { if (nRow2 < nRow1) return NULL; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits