diff options
author | Eike Rathke <erack@redhat.com> | 2014-12-22 21:14:11 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2015-01-07 13:27:55 +0000 |
commit | 007bede69824b2caee948d21acefc2f5b0f63b3a (patch) | |
tree | 26b305205aa201564cf06ef807dfa97b8c4cfbbf | |
parent | 11724301fb690cbd58581e468f3cd80e7becc07d (diff) |
fdo#85258 differentiate between empty cell and empty result in matrix
Change-Id: I79259224e411f9c1a6e852623d9d49cf89a03c27
(cherry picked from commit 069698de192ef7e8d3582398e4542c175cabb987)
Reviewed-on: https://gerrit.libreoffice.org/13617
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | sc/inc/scmatrix.hxx | 6 | ||||
-rw-r--r-- | sc/source/core/data/column2.cxx | 27 | ||||
-rw-r--r-- | sc/source/core/tool/interpr1.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/tool/scmatrix.cxx | 77 |
4 files changed, 93 insertions, 21 deletions
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx index 1e4c74ff99b3..851caa474373 100644 --- a/sc/inc/scmatrix.hxx +++ b/sc/inc/scmatrix.hxx @@ -278,6 +278,9 @@ public: /** Put a column vector of empties, starting at row nR, must fit into dimensions. */ void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ); + /** Put a column vector of empty results, starting at row nR, must fit into dimensions. */ + void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ); + /** Put a column vector of empty paths, starting at row nR, must fit into dimensions. */ void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ); @@ -322,6 +325,9 @@ public: /// @return <TRUE/> if empty or empty path. bool IsEmpty( SCSIZE nC, SCSIZE nR ) const; + /// @return <TRUE/> if empty, not empty result or empty path. + bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const; + /// @return <TRUE/> if empty path. bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const; diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 08a00c014359..06ee75a02797 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2065,16 +2065,23 @@ namespace { struct CellBucket { + SCSIZE mnEmpValStart; SCSIZE mnNumValStart; SCSIZE mnStrValStart; + SCSIZE mnEmpValCount; std::vector<double> maNumVals; std::vector<svl::SharedString> maStrVals; - CellBucket() : mnNumValStart(0), mnStrValStart(0) {} + CellBucket() : mnEmpValStart(0), mnNumValStart(0), mnStrValStart(0), mnEmpValCount(0) {} void flush(ScMatrix& rMat, SCSIZE nCol) { - if (!maNumVals.empty()) + if (mnEmpValCount) + { + rMat.PutEmptyResultVector(mnEmpValCount, nCol, mnEmpValStart); + reset(); + } + else if (!maNumVals.empty()) { const double* p = &maNumVals[0]; rMat.PutDouble(p, maNumVals.size(), nCol, mnNumValStart); @@ -2090,7 +2097,8 @@ struct CellBucket void reset() { - mnNumValStart = mnStrValStart = 0; + mnEmpValStart = mnNumValStart = mnStrValStart = 0; + mnEmpValCount = 0; maNumVals.clear(); maStrVals.clear(); } @@ -2162,7 +2170,18 @@ public: if (rCell.IsEmpty()) { - aBucket.flush(mrMat, mnMatCol); + if (aBucket.mnEmpValCount && nThisRow == nPrevRow + 1) + { + // Secondary empty results. + ++aBucket.mnEmpValCount; + } + else + { + // First empty result. + aBucket.flush(mrMat, mnMatCol); + aBucket.mnEmpValStart = nThisRow - mnTopRow; + ++aBucket.mnEmpValCount; + } continue; } diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 493080a272cd..4a63f1426396 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -1893,14 +1893,14 @@ void ScInterpreter::ScIsEmpty() if ( !pMat ) ; // nothing else if ( !pJumpMatrix ) - nRes = pMat->IsEmpty( 0, 0) ? 1 : 0; + nRes = pMat->IsEmptyCell( 0, 0) ? 1 : 0; else { SCSIZE nCols, nRows, nC, nR; pMat->GetDimensions( nCols, nRows); pJumpMatrix->GetPos( nC, nR); if ( nC < nCols && nR < nRows ) - nRes = pMat->IsEmpty( nC, nR) ? 1 : 0; + nRes = pMat->IsEmptyCell( nC, nR) ? 1 : 0; // else: false, not empty (which is what Xcl does) } } diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx index 19f65dd0757e..b71cc1dd6e28 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -194,6 +194,13 @@ _Comp CompareMatrixElemFunc<_Comp>::maComp; } +/* TODO: it would be good if mdds had get/set<sal_uInt8> additionally to + * get/set<bool>, we're abusing double here. */ +typedef double TMatFlag; +const TMatFlag SC_MATFLAG_EMPTYCELL = 0.0; +const TMatFlag SC_MATFLAG_EMPTYRESULT = 1.0; +const TMatFlag SC_MATFLAG_EMPTYPATH = 2.0; + class ScMatrixImpl: private boost::noncopyable { MatrixImplType maMat; @@ -246,6 +253,7 @@ public: bool IsString( SCSIZE nIndex ) const; bool IsString( SCSIZE nC, SCSIZE nR ) const; bool IsEmpty( SCSIZE nC, SCSIZE nR ) const; + bool IsEmptyCell( SCSIZE nC, SCSIZE nR ) const; bool IsEmptyPath( SCSIZE nC, SCSIZE nR ) const; bool IsValue( SCSIZE nIndex ) const; bool IsValue( SCSIZE nC, SCSIZE nR ) const; @@ -259,6 +267,7 @@ public: void PutDoubleVector( const ::std::vector< double > & rVec, SCSIZE nC, SCSIZE nR ); void PutStringVector( const ::std::vector< svl::SharedString > & rVec, SCSIZE nC, SCSIZE nR ); void PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ); + void PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ); void PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ); void CompareEqual(); void CompareNotEqual(); @@ -295,7 +304,7 @@ private: }; ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR) : - maMat(nR, nC), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {} + maMat(nR, nC), maMatFlag(nR, nC, SC_MATFLAG_EMPTYCELL), pErrorInterpreter(NULL), mbCloneIfConst(true) {} ScMatrixImpl::ScMatrixImpl(SCSIZE nC, SCSIZE nR, double fInitVal) : maMat(nR, nC, fInitVal), maMatFlag(nR, nC), pErrorInterpreter(NULL), mbCloneIfConst(true) {} @@ -454,7 +463,7 @@ void ScMatrixImpl::PutEmpty(SCSIZE nC, SCSIZE nR) if (ValidColRow( nC, nR)) { maMat.set_empty(nR, nC); - maMatFlag.set(nR, nC, false); // zero flag to indicate that this is 'empty', not 'empty path'. + maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYCELL); } else { @@ -467,7 +476,7 @@ void ScMatrixImpl::PutEmptyPath(SCSIZE nC, SCSIZE nR) if (ValidColRow( nC, nR)) { maMat.set_empty(nR, nC); - maMatFlag.set(nR, nC, true); // non-zero flag to indicate empty 'path'. + maMatFlag.set(nR, nC, SC_MATFLAG_EMPTYPATH); } else { @@ -582,7 +591,7 @@ svl::SharedString ScMatrixImpl::GetString( SvNumberFormatter& rFormatter, SCSIZE return maMat.get_string(aPos).getString(); case mdds::mtm::element_empty: { - if (!maMatFlag.get<bool>(nR, nC)) + if (maMatFlag.get<TMatFlag>(nR, nC) != SC_MATFLAG_EMPTYPATH) // not an empty path. return svl::SharedString::getEmptyString(); @@ -638,8 +647,10 @@ ScMatrixValue ScMatrixImpl::Get(SCSIZE nC, SCSIZE nR) const aVal.aStr = maMat.get_string(aPos); break; case mdds::mtm::element_empty: - // Empty path equals empty plus flag. - aVal.nType = maMatFlag.get<bool>(nR, nC) ? SC_MATVAL_EMPTYPATH : SC_MATVAL_EMPTY; + /* TODO: do we need to pass the differentiation of 'empty' and + * 'empty result' to the outer world anywhere? */ + aVal.nType = maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYPATH ? SC_MATVAL_EMPTYPATH : + SC_MATVAL_EMPTY; aVal.fVal = 0.0; default: ; @@ -675,17 +686,28 @@ bool ScMatrixImpl::IsString( SCSIZE nC, SCSIZE nR ) const bool ScMatrixImpl::IsEmpty( SCSIZE nC, SCSIZE nR ) const { - // Flag must be zero for this to be an empty element, instead of being an - // empty path element. + // Flag must indicate an empty element instead of an + // 'empty path' element. + ValidColRowReplicated( nC, nR ); + return maMat.get_type(nR, nC) == mdds::mtm::element_empty && + maMatFlag.get<TMatFlag>(nR, nC) != SC_MATFLAG_EMPTYPATH; +} + +bool ScMatrixImpl::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const +{ + // Flag must indicate an 'empty' element instead of an + // 'empty result' or 'empty path' element. ValidColRowReplicated( nC, nR ); - return maMat.get_type(nR, nC) == mdds::mtm::element_empty && !maMatFlag.get<bool>(nR, nC); + return maMat.get_type(nR, nC) == mdds::mtm::element_empty && + maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYCELL; } bool ScMatrixImpl::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const { - // 'Empty path' is empty plus non-zero flag. + // Flag must indicate an 'empty path' element. if (ValidColRowOrReplicated( nC, nR )) - return maMat.get_type(nR, nC) == mdds::mtm::element_empty && maMatFlag.get<bool>(nR, nC); + return maMat.get_type(nR, nC) == mdds::mtm::element_empty && + maMatFlag.get<TMatFlag>(nR, nC) == SC_MATFLAG_EMPTYPATH; else return true; } @@ -801,8 +823,8 @@ void ScMatrixImpl::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1)) { maMat.set_empty(nR, nC, nCount); - // zero flag to indicate that this is 'empty', not 'empty path'. - std::vector<bool> aVals(nCount, false); + // Flag to indicate that this is 'empty', not 'empty result' or 'empty path'. + std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYCELL); maMatFlag.set(nR, nC, aVals.begin(), aVals.end()); } else @@ -811,13 +833,28 @@ void ScMatrixImpl::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) } } +void ScMatrixImpl::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) +{ + if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1)) + { + maMat.set_empty(nR, nC, nCount); + // Flag to indicate that this is 'empty result', not 'empty' or 'empty path'. + std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYRESULT); + maMatFlag.set(nR, nC, aVals.begin(), aVals.end()); + } + else + { + OSL_FAIL("ScMatrixImpl::PutEmptyResultVector: dimension error"); + } +} + void ScMatrixImpl::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) { if (nCount && ValidColRow( nC, nR) && ValidColRow( nC, nR + nCount - 1)) { maMat.set_empty(nR, nC, nCount); - // non-zero flag to indicate empty 'path'. - std::vector<bool> aVals(nCount, true); + // Flag to indicate 'empty path'. + std::vector<TMatFlag> aVals(nCount, SC_MATFLAG_EMPTYPATH); maMatFlag.set(nR, nC, aVals.begin(), aVals.end()); } else @@ -2075,6 +2112,11 @@ bool ScMatrix::IsEmpty( SCSIZE nC, SCSIZE nR ) const return pImpl->IsEmpty(nC, nR); } +bool ScMatrix::IsEmptyCell( SCSIZE nC, SCSIZE nR ) const +{ + return pImpl->IsEmptyCell(nC, nR); +} + bool ScMatrix::IsEmptyPath( SCSIZE nC, SCSIZE nR ) const { return pImpl->IsEmptyPath(nC, nR); @@ -2135,6 +2177,11 @@ void ScMatrix::PutEmptyVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) pImpl->PutEmptyVector(nCount, nC, nR); } +void ScMatrix::PutEmptyResultVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) +{ + pImpl->PutEmptyResultVector(nCount, nC, nR); +} + void ScMatrix::PutEmptyPathVector( SCSIZE nCount, SCSIZE nC, SCSIZE nR ) { pImpl->PutEmptyPathVector(nCount, nC, nR); |