summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2016-05-27 18:05:01 +0200
committerEike Rathke <erack@redhat.com>2016-05-27 16:44:19 +0000
commitacb0f28e97874b22bd899e5cf04f2a8363a42e7a (patch)
tree48e6262f9902b5d3c27c589743323bd9027f5ca8
parent792337781f079d14679d05f08f4433a7dfa6fe9a (diff)
omit DCOUNT or DCOUNTA 2nd argument if 0 when writing ODFF or OOXML, tdf#70806
Change-Id: I2833a1005c6941e66a09172b337e23b0bf7f2002 (cherry picked from commit a88ee01b8683ded7d9da6dbcbf4d3e0c2ed4cadc) Reviewed-on: https://gerrit.libreoffice.org/25559 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Eike Rathke <erack@redhat.com>
-rw-r--r--formula/source/core/api/token.cxx50
-rw-r--r--include/formula/tokenarray.hxx2
2 files changed, 46 insertions, 6 deletions
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 8cbceb3e5e8d..b1a1f00ed4a8 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -1056,6 +1056,9 @@ inline bool MissingConventionODF::isRewriteNeeded( OpCode eOp ) const
case ocMissing:
case ocLog:
return isPODF(); // rewrite only for PODF
+ case ocDBCount:
+ case ocDBCount2:
+ return isODFF(); // rewrite only for ODFF
default:
return false;
}
@@ -1092,6 +1095,9 @@ inline bool MissingConventionOOXML::isRewriteNeeded( OpCode eOp )
case ocPoissonDist:
case ocNormDist:
case ocLogNormDist:
+
+ case ocDBCount:
+ case ocDBCount2:
return true;
default:
return false;
@@ -1379,15 +1385,26 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention &
{
const size_t nAlloc = 256;
FormulaMissingContext aCtx[ nAlloc ];
+
+ /* TODO: with some effort we might be able to merge the two almost
+ * identical function stacks into one and generalize things, otherwise
+ * adding yet another "omit argument" would be copypasta. */
+
int aOpCodeAddressStack[ nAlloc ]; // use of ADDRESS() function
const int nOmitAddressArg = 3; // ADDRESS() 4th parameter A1/R1C1
+
+ int aOpCodeDcountStack[ nAlloc ]; // use of DCOUNT()/DCOUNTA() function
+ const int nOmitDcountArg = 1; // DCOUNT() and DCOUNTA() 2nd parameter DatabaseField if 0
+
sal_uInt16 nTokens = GetLen() + 1;
FormulaMissingContext* pCtx = (nAlloc < nTokens ? new FormulaMissingContext[nTokens] : &aCtx[0]);
int* pOcas = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeAddressStack[0]);
+ int* pOcds = (nAlloc < nTokens ? new int[nTokens] : &aOpCodeDcountStack[0]);
// Never go below 0, never use 0, mpFunc always NULL.
pCtx[0].Clear();
int nFn = 0;
int nOcas = 0;
+ int nOcds = 0;
FormulaTokenArray *pNewArr = new FormulaTokenArray;
// At least ScRecalcMode::ALWAYS needs to be set.
@@ -1412,20 +1429,39 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention &
bAdd = false;
}
}
+ // Strip the 2nd argument (leaving empty) of DCOUNT() and DCOUNTA() if
+ // it is 0.
+ for (int i = nOcds; i-- > 0 && bAdd; )
+ {
+ if (pCtx[ pOcds[ i ] ].mnCurArg == nOmitDcountArg)
+ {
+ // Omit only a literal 0 value, nothing else.
+ if (pOcds[ i ] == nFn && pCur->GetOpCode() == ocPush && pCur->GetDouble() == 0.0)
+ bAdd = false;
+ }
+ }
switch ( pCur->GetOpCode() )
{
case ocOpen:
- ++nFn; // all following operations on _that_ function
- pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
- pCtx[ nFn ].mnCurArg = 0;
- if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
- pOcas[ nOcas++ ] = nFn; // entering ADDRESS() if PODF
- break;
+ {
+ ++nFn; // all following operations on _that_ function
+ pCtx[ nFn ].mpFunc = PeekPrevNoSpaces();
+ pCtx[ nFn ].mnCurArg = 0;
+ OpCode eOp;
+ if (rConv.isPODF() && pCtx[ nFn ].mpFunc && pCtx[ nFn ].mpFunc->GetOpCode() == ocAddress)
+ pOcas[ nOcas++ ] = nFn; // entering ADDRESS() if PODF
+ else if ((rConv.isODFF() || rConv.isOOXML()) && pCtx[ nFn ].mpFunc &&
+ ((eOp = pCtx[ nFn ].mpFunc->GetOpCode()) == ocDBCount || eOp == ocDBCount2))
+ pOcds[ nOcds++ ] = nFn; // entering DCOUNT() or DCOUNTA() if ODFF or OOXML
+ }
+ break;
case ocClose:
pCtx[ nFn ].AddMoreArgs( pNewArr, rConv );
SAL_WARN_IF(nFn <= 0, "formula.core", "FormulaTokenArray::RewriteMissing: underflow");
if (nOcas > 0 && pOcas[ nOcas-1 ] == nFn)
--nOcas; // leaving ADDRESS()
+ else if (nOcds > 0 && pOcds[ nOcds-1 ] == nFn)
+ --nOcds; // leaving DCOUNT() or DCOUNTA()
if (nFn > 0)
--nFn;
break;
@@ -1474,6 +1510,8 @@ FormulaTokenArray * FormulaTokenArray::RewriteMissing( const MissingConvention &
}
}
+ if (pOcds != &aOpCodeDcountStack[0])
+ delete [] pOcas;
if (pOcas != &aOpCodeAddressStack[0])
delete [] pOcas;
if (pCtx != &aCtx[0])
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index cd0f430f365c..3faadecb1325 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -72,6 +72,8 @@ public:
};
explicit MissingConvention( Convention eConvention ) : meConvention(eConvention) {}
inline bool isPODF() const { return meConvention == FORMULA_MISSING_CONVENTION_PODF; }
+ inline bool isODFF() const { return meConvention == FORMULA_MISSING_CONVENTION_ODFF; }
+ inline bool isOOXML() const { return meConvention == FORMULA_MISSING_CONVENTION_OOXML; }
inline Convention getConvention() const { return meConvention; }
private:
Convention meConvention;