LCOV - code coverage report
Current view: top level - sc/source/core/tool - formularesult.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 244 291 83.8 %
Date: 2014-04-11 Functions: 35 38 92.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include "formularesult.hxx"
      11             : #include "scmatrix.hxx"
      12             : 
      13             : namespace sc {
      14             : 
      15           0 : FormulaResultValue::FormulaResultValue() : meType(Invalid), mfValue(0.0), mnError(0) {}
      16          51 : FormulaResultValue::FormulaResultValue( double fValue ) : meType(Value), mfValue(fValue), mnError(0) {}
      17          13 : FormulaResultValue::FormulaResultValue( const svl::SharedString& rStr ) : meType(String), mfValue(0.0), maString(rStr), mnError(0) {}
      18           0 : FormulaResultValue::FormulaResultValue( sal_uInt16 nErr ) : meType(Error), mfValue(0.0), mnError(nErr) {}
      19             : 
      20             : }
      21             : 
      22        5433 : ScFormulaResult::ScFormulaResult() :
      23             :     mpToken(NULL), mnError(0), mbToken(true),
      24             :     mbEmpty(false), mbEmptyDisplayedAsString(false),
      25        5433 :     meMultiline(MULTILINE_UNKNOWN) {}
      26             : 
      27         721 : ScFormulaResult::ScFormulaResult( const ScFormulaResult & r ) :
      28             :     mnError( r.mnError), mbToken( r.mbToken),
      29             :     mbEmpty( r.mbEmpty),
      30             :     mbEmptyDisplayedAsString( r.mbEmptyDisplayedAsString),
      31         721 :     meMultiline( r.meMultiline)
      32             : {
      33         721 :     if (mbToken)
      34             :     {
      35         518 :         mpToken = r.mpToken;
      36         518 :         if (mpToken)
      37             :         {
      38             :             // Since matrix dimension and
      39             :             // results are assigned to a matrix
      40             :             // cell formula token we have to
      41             :             // clone that instead of sharing it.
      42             :             const ScMatrixFormulaCellToken* pMatFormula =
      43          18 :                 r.GetMatrixFormulaCellToken();
      44          18 :             if (pMatFormula)
      45             :             {
      46           0 :                 mpToken = new ScMatrixFormulaCellToken( *pMatFormula);
      47           0 :                 mpToken->IncRef();
      48             :             }
      49             :             else
      50          18 :                 IncrementTokenRef( mpToken);
      51             :         }
      52             :     }
      53             :     else
      54         203 :         mfValue = r.mfValue;
      55         721 : }
      56             : 
      57        4011 : ScFormulaResult::ScFormulaResult( const formula::FormulaToken* p ) :
      58             :     mnError(0), mbToken(false), mbEmpty(false), mbEmptyDisplayedAsString(false),
      59        4011 :     meMultiline(MULTILINE_UNKNOWN)
      60             : {
      61        4011 :     SetToken( p);
      62        4011 : }
      63             : 
      64        9744 : ScFormulaResult::~ScFormulaResult()
      65             : {
      66        9744 :     if (mbToken && mpToken)
      67         313 :         mpToken->DecRef();
      68        9744 : }
      69             : 
      70             : 
      71       21494 : void ScFormulaResult::ResetToDefaults()
      72             : {
      73       21494 :     mnError = 0;
      74       21494 :     mbEmpty = false;
      75       21494 :     mbEmptyDisplayedAsString = false;
      76       21494 :     meMultiline = MULTILINE_UNKNOWN;
      77       21494 : }
      78             : 
      79        7494 : void ScFormulaResult::ResolveToken( const formula::FormulaToken * p )
      80             : {
      81        7494 :     ResetToDefaults();
      82        7494 :     if (!p)
      83             :     {
      84         838 :         mpToken = p;
      85         838 :         mbToken = true;
      86             :     }
      87             :     else
      88             :     {
      89        6656 :         switch (p->GetType())
      90             :         {
      91             :             case formula::svError:
      92         233 :                 mnError = p->GetError();
      93         233 :                 p->DecRef();
      94         233 :                 mbToken = false;
      95             :                 // set in case mnError is 0 now, which shouldn't happen but ...
      96         233 :                 mfValue = 0.0;
      97         233 :                 meMultiline = MULTILINE_FALSE;
      98         233 :                 break;
      99             :             case formula::svEmptyCell:
     100         723 :                 mbEmpty = true;
     101         723 :                 mbEmptyDisplayedAsString = static_cast<const ScEmptyCellToken*>(p)->IsDisplayedAsString();
     102         723 :                 p->DecRef();
     103         723 :                 mbToken = false;
     104         723 :                 meMultiline = MULTILINE_FALSE;
     105         723 :                 break;
     106             :             case formula::svDouble:
     107        5049 :                 mfValue = p->GetDouble();
     108        5049 :                 p->DecRef();
     109        5049 :                 mbToken = false;
     110        5049 :                 meMultiline = MULTILINE_FALSE;
     111        5049 :                 break;
     112             :             default:
     113         651 :                 mpToken = p;
     114         651 :                 mbToken = true;
     115             :         }
     116             :     }
     117        7494 : }
     118             : 
     119           3 : ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r )
     120             : {
     121           3 :     Assign( r);
     122           3 :     return *this;
     123             : }
     124             : 
     125        3708 : void ScFormulaResult::Assign( const ScFormulaResult & r )
     126             : {
     127        3708 :     if (this == &r)
     128        3708 :         return;
     129        3708 :     if (r.mbEmpty)
     130             :     {
     131         704 :         if (mbToken && mpToken)
     132           0 :             mpToken->DecRef();
     133         704 :         mbToken = false;
     134         704 :         mbEmpty = true;
     135         704 :         mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString;
     136         704 :         meMultiline = r.meMultiline;
     137             :     }
     138        3004 :     else if (r.mbToken)
     139             :     {
     140             :         // Matrix formula cell token must be cloned, see copy-ctor.
     141             :         const ScMatrixFormulaCellToken* pMatFormula =
     142          41 :             r.GetMatrixFormulaCellToken();
     143          41 :         if (pMatFormula)
     144           0 :             SetToken( new ScMatrixFormulaCellToken( *pMatFormula));
     145             :         else
     146          41 :             SetToken( r.mpToken);
     147             :     }
     148             :     else
     149        2963 :         SetDouble( r.mfValue);
     150             :     // If there was an error there will be an error, no matter what Set...()
     151             :     // methods did.
     152        3708 :     mnError = r.mnError;
     153             : }
     154             : 
     155        7536 : void ScFormulaResult::SetToken( const formula::FormulaToken* p )
     156             : {
     157        7536 :     ResetToDefaults();
     158        7536 :     IncrementTokenRef( p);
     159             :     // Handle a result obtained from the interpreter to be assigned to a matrix
     160             :     // formula cell's ScMatrixFormulaCellToken.
     161        7536 :     ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
     162        7536 :     if (pMatFormula)
     163             :     {
     164             :         const ScMatrixCellResultToken* pMatResult =
     165          42 :             (p && p->GetType() == formula::svMatrixCell ?
     166          64 :              dynamic_cast<const ScMatrixCellResultToken*>(p) : NULL);
     167          42 :         if (pMatResult)
     168             :         {
     169             :             const ScMatrixFormulaCellToken* pNewMatFormula =
     170          22 :                 dynamic_cast<const ScMatrixFormulaCellToken*>(pMatResult);
     171          22 :             if (pNewMatFormula)
     172             :             {
     173             :                 SAL_WARN( "sc", "ScFormulaResult::SetToken: pNewMatFormula and pMatFormula, overriding matrix formula dimension; intended?");
     174           0 :                 pMatFormula->SetMatColsRows( pNewMatFormula->GetMatCols(),
     175           0 :                         pNewMatFormula->GetMatRows());
     176             :             }
     177          22 :             pMatFormula->Assign( *pMatResult);
     178          22 :             p->DecRef();
     179             :         }
     180          20 :         else if (p)
     181             :         {
     182             :             // This may be the result of some constant expression like
     183             :             // {="string"} that doesn't result in a matrix but still would
     184             :             // display the result in all cells of this matrix formula.
     185          20 :             pMatFormula->Assign( *p);
     186          20 :             p->DecRef();
     187             :         }
     188             :         else
     189             :         {
     190             :             // NULL result? Well, if you say so ...
     191           0 :             pMatFormula->ResetResult();
     192             :         }
     193             :     }
     194             :     else
     195             :     {
     196        7494 :         if (mbToken && mpToken)
     197         433 :             mpToken->DecRef();
     198        7494 :         ResolveToken( p);
     199             :     }
     200        7536 : }
     201             : 
     202        5759 : void ScFormulaResult::SetDouble( double f )
     203             : {
     204        5759 :     ResetToDefaults();
     205             :     // Handle a result obtained from the interpreter to be assigned to a matrix
     206             :     // formula cell's ScMatrixFormulaCellToken.
     207        5759 :     ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
     208        5759 :     if (pMatFormula)
     209           9 :         pMatFormula->SetUpperLeftDouble( f);
     210             :     else
     211             :     {
     212        5750 :         if (mbToken && mpToken)
     213           0 :             mpToken->DecRef();
     214        5750 :         mfValue = f;
     215        5750 :         mbToken = false;
     216        5750 :         meMultiline = MULTILINE_FALSE;
     217             :     }
     218        5759 : }
     219             : 
     220       84976 : formula::StackVar ScFormulaResult::GetType() const
     221             : {
     222             :     // Order is significant.
     223       84976 :     if (mnError)
     224         838 :         return formula::svError;
     225       84138 :     if (mbEmpty)
     226        4315 :         return formula::svEmptyCell;
     227       79823 :     if (!mbToken)
     228       64180 :         return formula::svDouble;
     229       15643 :     if (mpToken)
     230        5625 :         return mpToken->GetType();
     231       10018 :     return formula::svUnknown;
     232             : }
     233             : 
     234       62462 : formula::StackVar ScFormulaResult::GetCellResultType() const
     235             : {
     236       62462 :     formula::StackVar sv = GetType();
     237       62462 :     if (sv == formula::svMatrixCell)
     238             :         // don't need to test for mpToken here, GetType() already did it
     239         503 :         sv = static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftType();
     240       62462 :     return sv;
     241             : }
     242             : 
     243        1379 : bool ScFormulaResult::IsEmptyDisplayedAsString() const
     244             : {
     245        1379 :     if (mbEmpty)
     246           7 :         return mbEmptyDisplayedAsString;
     247        1372 :     if (GetType() == formula::svMatrixCell)
     248             :     {
     249             :         // don't need to test for mpToken here, GetType() already did it
     250             :         const ScEmptyCellToken* p = dynamic_cast<const ScEmptyCellToken*>(
     251             :                 static_cast<const ScMatrixCellResultToken*>(
     252          13 :                     mpToken)->GetUpperLeftToken().get());
     253          13 :         if (p)
     254           0 :             return p->IsDisplayedAsString();
     255             :     }
     256        1372 :     return false;
     257             : }
     258             : 
     259             : namespace {
     260             : 
     261       25484 : inline bool isValue( formula::StackVar sv )
     262             : {
     263        4374 :     return sv == formula::svDouble || sv == formula::svError
     264       29254 :         || sv == formula::svEmptyCell || sv == formula::svHybridValueCell;
     265             : }
     266             : 
     267          13 : inline bool isString( formula::StackVar sv )
     268             : {
     269          13 :     switch (sv)
     270             :     {
     271             :         case formula::svString:
     272             :         case formula::svHybridCell:
     273             :         case formula::svHybridValueCell:
     274          13 :             return true;
     275             :         default:
     276           0 :             break;
     277             :     }
     278             : 
     279           0 :     return false;
     280             : }
     281             : 
     282             : }
     283             : 
     284       24687 : bool ScFormulaResult::IsValue() const
     285             : {
     286       24687 :     return isValue(GetCellResultType());
     287             : }
     288             : 
     289          16 : bool ScFormulaResult::IsValueNoError() const
     290             : {
     291          16 :     switch (GetCellResultType())
     292             :     {
     293             :         case formula::svDouble:
     294             :         case formula::svEmptyCell:
     295             :         case formula::svHybridValueCell:
     296          14 :             return true;
     297             :         default:
     298           2 :             return false;
     299             :     }
     300             : }
     301             : 
     302         112 : bool ScFormulaResult::IsMultiline() const
     303             : {
     304         112 :     if (meMultiline == MULTILINE_UNKNOWN)
     305             :     {
     306          25 :         svl::SharedString aStr = GetString();
     307          25 :         if (!aStr.isEmpty() && aStr.getString().indexOf('\n') != -1)
     308           0 :             const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_TRUE;
     309             :         else
     310          25 :             const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_FALSE;
     311             :     }
     312         112 :     return meMultiline == MULTILINE_TRUE;
     313             : }
     314             : 
     315         739 : bool ScFormulaResult::GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const
     316             : {
     317         739 :     if (mnError)
     318             :     {
     319           6 :         rErr = mnError;
     320           6 :         return true;
     321             :     }
     322             : 
     323         733 :     formula::StackVar sv = GetCellResultType();
     324         733 :     if (sv == formula::svError)
     325             :     {
     326           0 :         if (GetType() == formula::svMatrixCell)
     327             :         {
     328             :             // don't need to test for mpToken here, GetType() already did it
     329             :             rErr = static_cast<const ScMatrixCellResultToken*>(mpToken)->
     330           0 :                 GetUpperLeftToken()->GetError();
     331             :         }
     332           0 :         else if (mpToken)
     333             :         {
     334           0 :             rErr = mpToken->GetError();
     335             :         }
     336             :     }
     337             : 
     338         733 :     if (rErr)
     339           0 :         return true;
     340             : 
     341         733 :     if (!isValue(sv))
     342           0 :         return false;
     343             : 
     344         733 :     rVal = GetDouble();
     345         733 :     return true;
     346             : }
     347             : 
     348          64 : sc::FormulaResultValue ScFormulaResult::GetResult() const
     349             : {
     350          64 :     if (mnError)
     351           0 :         return sc::FormulaResultValue(mnError);
     352             : 
     353          64 :     formula::StackVar sv = GetCellResultType();
     354          64 :     sal_uInt16 nErr = 0;
     355          64 :     if (sv == formula::svError)
     356             :     {
     357           0 :         if (GetType() == formula::svMatrixCell)
     358             :         {
     359             :             // don't need to test for mpToken here, GetType() already did it
     360             :             nErr = static_cast<const ScMatrixCellResultToken*>(mpToken)->
     361           0 :                 GetUpperLeftToken()->GetError();
     362             :         }
     363           0 :         else if (mpToken)
     364             :         {
     365           0 :             nErr = mpToken->GetError();
     366             :         }
     367             :     }
     368             : 
     369          64 :     if (nErr)
     370           0 :         return sc::FormulaResultValue(nErr);
     371             : 
     372          64 :     if (isValue(sv))
     373          51 :         return sc::FormulaResultValue(GetDouble());
     374             : 
     375          13 :     if (!mbToken)
     376             :         // String result type needs token.
     377           0 :         return sc::FormulaResultValue();
     378             : 
     379          13 :     if (isString(sv))
     380          13 :         return sc::FormulaResultValue(GetString());
     381             : 
     382             :     // Invalid
     383           0 :     return sc::FormulaResultValue();
     384             : }
     385             : 
     386       28908 : sal_uInt16 ScFormulaResult::GetResultError() const
     387             : {
     388       28908 :     if (mnError)
     389         424 :         return mnError;
     390       28484 :     formula::StackVar sv = GetCellResultType();
     391       28484 :     if (sv == formula::svError)
     392             :     {
     393          16 :         if (GetType() == formula::svMatrixCell)
     394             :             // don't need to test for mpToken here, GetType() already did it
     395             :             return static_cast<const ScMatrixCellResultToken*>(mpToken)->
     396          16 :                 GetUpperLeftToken()->GetError();
     397           0 :         if (mpToken)
     398           0 :             return mpToken->GetError();
     399             :     }
     400       28468 :     return 0;
     401             : }
     402             : 
     403        6298 : void ScFormulaResult::SetResultError( sal_uInt16 nErr )
     404             : {
     405        6298 :     mnError = nErr;
     406        6298 : }
     407             : 
     408           0 : formula::FormulaConstTokenRef ScFormulaResult::GetToken() const
     409             : {
     410           0 :     if (mbToken)
     411           0 :         return mpToken;
     412           0 :     return NULL;
     413             : }
     414             : 
     415          16 : formula::FormulaConstTokenRef ScFormulaResult::GetCellResultToken() const
     416             : {
     417          16 :     if (GetType() == formula::svMatrixCell)
     418             :         // don't need to test for mpToken here, GetType() already did it
     419          16 :         return static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftToken();
     420           0 :     return GetToken();
     421             : }
     422             : 
     423       25933 : double ScFormulaResult::GetDouble() const
     424             : {
     425       25933 :     if (mbToken)
     426             :     {
     427             :         // Should really not be of type formula::svDouble here.
     428         615 :         if (mpToken)
     429             :         {
     430         498 :             switch (mpToken->GetType())
     431             :             {
     432             :                 case formula::svHybridCell:
     433             :                 case formula::svHybridValueCell:
     434           0 :                     return mpToken->GetDouble();
     435             :                 case formula::svMatrixCell:
     436             :                     {
     437             :                         const ScMatrixCellResultToken* p =
     438         156 :                             static_cast<const ScMatrixCellResultToken*>(mpToken);
     439         156 :                         if (p->GetUpperLeftType() == formula::svDouble)
     440         150 :                             return p->GetUpperLeftToken()->GetDouble();
     441             :                     }
     442           6 :                     break;
     443             :                 default:
     444             :                     ;   // nothing
     445             :             }
     446             :         }
     447         465 :         return 0.0;
     448             :     }
     449       25318 :     if (mbEmpty)
     450        1431 :         return 0.0;
     451       23887 :     return mfValue;
     452             : }
     453             : 
     454         488 : svl::SharedString ScFormulaResult::GetString() const
     455             : {
     456         488 :     if (mbToken && mpToken)
     457             :     {
     458         468 :         switch (mpToken->GetType())
     459             :         {
     460             :             case formula::svString:
     461             :             case formula::svHybridCell:
     462             :             case formula::svHybridValueCell:
     463         454 :                 return mpToken->GetString();
     464             :             case formula::svMatrixCell:
     465             :                 {
     466             :                     const ScMatrixCellResultToken* p =
     467          14 :                         static_cast<const ScMatrixCellResultToken*>(mpToken);
     468          14 :                     if (p->GetUpperLeftType() == formula::svString)
     469          14 :                         return p->GetUpperLeftToken()->GetString();
     470             :                 }
     471           0 :                 break;
     472             :             default:
     473             :                 ;   // nothing
     474             :         }
     475             :     }
     476          20 :     return svl::SharedString::getEmptyString();
     477             : }
     478             : 
     479        6505 : ScConstMatrixRef ScFormulaResult::GetMatrix() const
     480             : {
     481        6505 :     if (GetType() == formula::svMatrixCell)
     482         293 :         return static_cast<const ScToken*>(mpToken)->GetMatrix();
     483        6212 :     return NULL;
     484             : }
     485             : 
     486         113 : const OUString& ScFormulaResult::GetHybridFormula() const
     487             : {
     488         113 :     if (GetType() == formula::svHybridCell)
     489             :     {
     490           2 :         const ScHybridCellToken* p = dynamic_cast<const ScHybridCellToken*>(mpToken);
     491           2 :         if (p)
     492           2 :             return p->GetFormula();
     493             :     }
     494         111 :     return EMPTY_OUSTRING;
     495             : }
     496             : 
     497         569 : void ScFormulaResult::SetHybridDouble( double f )
     498             : {
     499         569 :     ResetToDefaults();
     500         569 :     if (mbToken && mpToken)
     501             :     {
     502           0 :         if(GetType() == formula::svMatrixCell)
     503           0 :             SetDouble(f);
     504             :         else
     505             :         {
     506           0 :             svl::SharedString aString = GetString();
     507           0 :             OUString aFormula( GetHybridFormula());
     508           0 :             mpToken->DecRef();
     509           0 :             mpToken = new ScHybridCellToken( f, aString, aFormula);
     510           0 :             mpToken->IncRef();
     511           0 :         }
     512             :     }
     513             :     else
     514             :     {
     515         569 :         mfValue = f;
     516         569 :         mbToken = false;
     517         569 :         meMultiline = MULTILINE_FALSE;
     518             :     }
     519         569 : }
     520             : 
     521         109 : void ScFormulaResult::SetHybridString( const OUString & rStr )
     522             : {
     523             :     // Obtain values before changing anything.
     524         109 :     double f = GetDouble();
     525         109 :     OUString aFormula( GetHybridFormula());
     526         109 :     ResetToDefaults();
     527         109 :     if (mbToken && mpToken)
     528           0 :         mpToken->DecRef();
     529         109 :     mpToken = new ScHybridCellToken( f, rStr, aFormula);
     530         109 :     mpToken->IncRef();
     531         109 :     mbToken = true;
     532         109 : }
     533             : 
     534           2 : void ScFormulaResult::SetHybridFormula( const OUString & rFormula )
     535             : {
     536             :     // Obtain values before changing anything.
     537           2 :     double f = GetDouble();
     538           2 :     svl::SharedString aStr = GetString();
     539           2 :     ResetToDefaults();
     540           2 :     if (mbToken && mpToken)
     541           0 :         mpToken->DecRef();
     542           2 :     mpToken = new ScHybridCellToken( f, aStr, rFormula);
     543           2 :     mpToken->IncRef();
     544           2 :     mbToken = true;
     545           2 : }
     546             : 
     547          25 : void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
     548             : {
     549          25 :     ResetToDefaults();
     550          25 :     if (mbToken && mpToken)
     551          25 :         mpToken->DecRef();
     552          25 :     mpToken = new ScMatrixFormulaCellToken(nCols, nRows, pMat, pUL);
     553          25 :     mpToken->IncRef();
     554          25 :     mbToken = true;
     555          25 : }
     556             : 
     557       13421 : const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const
     558             : {
     559       13421 :     return (GetType() == formula::svMatrixCell ?
     560       13421 :             dynamic_cast<const ScMatrixFormulaCellToken*>(mpToken) : NULL);
     561             : }
     562             : 
     563       13339 : ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
     564             : {
     565       13339 :     return const_cast<ScMatrixFormulaCellToken*>( GetMatrixFormulaCellToken());
     566             : }
     567             : 
     568             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10