[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - sc/inc sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Fri Jun 28 08:32:20 PDT 2013
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.yoshida at 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;
More information about the Libreoffice-commits
mailing list