diff options
author | Eike Rathke <erack@redhat.com> | 2016-05-27 18:05:01 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2016-05-27 16:44:19 +0000 |
commit | acb0f28e97874b22bd899e5cf04f2a8363a42e7a (patch) | |
tree | 48e6262f9902b5d3c27c589743323bd9027f5ca8 | |
parent | 792337781f079d14679d05f08f4433a7dfa6fe9a (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.cxx | 50 | ||||
-rw-r--r-- | include/formula/tokenarray.hxx | 2 |
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; |