LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/ods - ods_formula_node.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 784 593 75.6 %
Date: 2012-12-26 Functions: 43 34 79.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: ods_formula_node.cpp 25340 2012-12-21 20:30:21Z rouault $
       3                 :  *
       4                 :  * Component: ODS formula Engine
       5                 :  * Purpose: Implementation of the ods_formula_node class used to represent a
       6                 :  *          node in a ODS expression.
       7                 :  * Author: Even Rouault <even dot rouault at mines dash paris dot org>
       8                 :  * 
       9                 :  ******************************************************************************
      10                 :  * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
      11                 :  * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "cpl_conv.h"
      33                 : #include "ods_formula.h"
      34                 : 
      35                 : #ifndef PI
      36                 : #define PI  3.14159265358979323846
      37                 : #endif
      38                 : 
      39                 : /************************************************************************/
      40                 : /*                          ods_formula_node()                          */
      41                 : /************************************************************************/
      42                 : 
      43               6 : ods_formula_node::ods_formula_node()
      44                 : 
      45                 : {
      46               6 :     Initialize();
      47               6 : }
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                         ods_formula_node(int)                        */
      51                 : /************************************************************************/
      52                 : 
      53             110 : ods_formula_node::ods_formula_node( int nValueIn )
      54                 : 
      55                 : {
      56             110 :     Initialize();
      57                 : 
      58             110 :     field_type = ODS_FIELD_TYPE_INTEGER;
      59             110 :     int_value = nValueIn;
      60             110 : }
      61                 : 
      62                 : /************************************************************************/
      63                 : /*                      ods_formula_node(double)                        */
      64                 : /************************************************************************/
      65                 : 
      66              62 : ods_formula_node::ods_formula_node( double dfValueIn )
      67                 : 
      68                 : {
      69              62 :     Initialize();
      70                 : 
      71              62 :     field_type = ODS_FIELD_TYPE_FLOAT;
      72              62 :     float_value = dfValueIn;
      73              62 : }
      74                 : 
      75                 : /************************************************************************/
      76                 : /*                       ods_formula_node(const char*)                  */
      77                 : /************************************************************************/
      78                 : 
      79              97 : ods_formula_node::ods_formula_node( const char *pszValueIn,
      80                 :                                     ods_formula_field_type field_type_in )
      81                 : 
      82                 : {
      83              97 :     Initialize();
      84                 : 
      85              97 :     field_type = field_type_in;
      86              97 :     string_value = CPLStrdup( pszValueIn ? pszValueIn : "" );
      87              97 : }
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                        ods_formula_node(ods_formula_op)              */
      91                 : /************************************************************************/
      92                 : 
      93             167 : ods_formula_node::ods_formula_node( ods_formula_op eOpIn )
      94                 : 
      95                 : {
      96             167 :     Initialize();
      97                 : 
      98             167 :     eNodeType = SNT_OPERATION;
      99                 : 
     100             167 :     eOp = eOpIn;
     101             167 : }
     102                 : 
     103                 : /************************************************************************/
     104                 : /*              ods_formula_node(const ods_formula_node&)               */
     105                 : /************************************************************************/
     106                 : 
     107              61 : ods_formula_node::ods_formula_node( const ods_formula_node& other )
     108                 : {
     109              61 :     eNodeType = other.eNodeType;
     110              61 :     eOp = other.eOp;
     111              61 :     field_type = other.field_type;
     112              61 :     int_value = other.int_value;
     113              61 :     float_value = other.float_value;
     114              61 :     string_value = other.string_value ? CPLStrdup(other.string_value) : NULL;
     115              61 :     nSubExprCount = other.nSubExprCount;
     116              61 :     if (nSubExprCount)
     117                 :     {
     118                 :         papoSubExpr = (ods_formula_node **)
     119               0 :             CPLMalloc( sizeof(void*) * nSubExprCount );
     120               0 :         for(int i=0;i<nSubExprCount;i++)
     121                 :         {
     122               0 :             papoSubExpr[i] = new ods_formula_node( *(other.papoSubExpr[i]) );
     123                 :         }
     124                 :     }
     125                 :     else
     126              61 :         papoSubExpr = NULL;
     127              61 : }
     128                 : 
     129                 : /************************************************************************/
     130                 : /*                             Initialize()                             */
     131                 : /************************************************************************/
     132                 : 
     133             442 : void ods_formula_node::Initialize()
     134                 : 
     135                 : {
     136             442 :     eNodeType = SNT_CONSTANT;
     137             442 :     field_type = ODS_FIELD_TYPE_EMPTY;
     138             442 :     int_value = 0;
     139             442 :     float_value = 0;
     140             442 :     string_value = NULL;
     141             442 :     papoSubExpr = NULL;
     142             442 :     nSubExprCount = 0;
     143             442 : }
     144                 : 
     145                 : /************************************************************************/
     146                 : /*                          ~ods_formula_node()                         */
     147                 : /************************************************************************/
     148                 : 
     149             503 : ods_formula_node::~ods_formula_node()
     150                 : 
     151                 : {
     152             503 :     CPLFree( string_value );
     153             503 :     FreeSubExpr();
     154             503 : }
     155                 : 
     156                 : /************************************************************************/
     157                 : /*                         PushSubExpression()                          */
     158                 : /************************************************************************/
     159                 : 
     160             283 : void ods_formula_node::PushSubExpression( ods_formula_node *child )
     161                 : 
     162                 : {
     163             283 :     nSubExprCount++;
     164                 :     papoSubExpr = (ods_formula_node **)
     165             283 :         CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount );
     166                 : 
     167             283 :     papoSubExpr[nSubExprCount-1] = child;
     168             283 : }
     169                 : 
     170                 : /************************************************************************/
     171                 : /*                       ReverseSubExpressions()                        */
     172                 : /************************************************************************/
     173                 : 
     174              14 : void ods_formula_node::ReverseSubExpressions()
     175                 : 
     176                 : {
     177                 :     int i;
     178              23 :     for( i = 0; i < nSubExprCount / 2; i++ )
     179                 :     {
     180                 :         ods_formula_node *temp;
     181                 : 
     182               9 :         temp = papoSubExpr[i];
     183               9 :         papoSubExpr[i] = papoSubExpr[nSubExprCount - i - 1];
     184               9 :         papoSubExpr[nSubExprCount - i - 1] = temp;
     185                 :     }
     186              14 : }
     187                 : 
     188                 : /************************************************************************/
     189                 : /*                        GetOperatorName()                             */
     190                 : /************************************************************************/
     191                 : 
     192               0 : static const char* ODSGetOperatorName( ods_formula_op eOp )
     193                 : {
     194               0 :     switch (eOp)
     195                 :     {
     196               0 :         case ODS_OR : return "OR";
     197               0 :         case ODS_AND : return "AND";
     198               0 :         case ODS_NOT : return "NOT";
     199               0 :         case ODS_IF : return "IF";
     200                 : 
     201               0 :         case ODS_PI : return "PI";
     202                 : 
     203                 :         //case ODS_T : return "T";
     204               0 :         case ODS_LEN : return "LEN";
     205               0 :         case ODS_LEFT : return "LEFT";
     206               0 :         case ODS_RIGHT : return "RIGHT";
     207               0 :         case ODS_MID : return "MID";
     208                 : 
     209               0 :         case ODS_SUM : return "SUM";
     210               0 :         case ODS_AVERAGE : return "AVERAGE";
     211               0 :         case ODS_MIN : return "MIN";
     212               0 :         case ODS_MAX : return "MAX";
     213               0 :         case ODS_COUNT : return "COUNT";
     214               0 :         case ODS_COUNTA : return "COUNTA";
     215                 : 
     216               0 :         case ODS_EQ : return "=";
     217               0 :         case ODS_NE : return "<>";
     218               0 :         case ODS_GE : return ">=";
     219               0 :         case ODS_LE : return "<=";
     220               0 :         case ODS_LT : return "<";
     221               0 :         case ODS_GT : return ">";
     222                 : 
     223               0 :         case ODS_ADD : return "+";
     224               0 :         case ODS_SUBTRACT : return "-";
     225               0 :         case ODS_MULTIPLY : return "*";
     226               0 :         case ODS_DIVIDE : return "/";
     227               0 :         case ODS_MODULUS : return "MOD";
     228               0 :         case ODS_CONCAT : return "&";
     229                 : 
     230               0 :         case ODS_LIST : return "*list*";
     231               0 :         case ODS_CELL : return "*cell*";
     232               0 :         case ODS_CELL_RANGE : return "*cell_range*";
     233                 :         default:
     234                 :         {
     235               0 :             const SingleOpStruct* psSingleOp = ODSGetSingleOpEntry(eOp);
     236               0 :             if (psSingleOp != NULL)
     237               0 :                 return psSingleOp->pszName;
     238               0 :             return "*unknown*";
     239                 :         }
     240                 :     }
     241                 : }
     242                 : 
     243                 : /************************************************************************/
     244                 : /*                                Dump()                                */
     245                 : /************************************************************************/
     246                 : 
     247               0 : void ods_formula_node::Dump( FILE * fp, int depth )
     248                 : 
     249                 : {
     250                 :     char        spaces[60];
     251                 :     int         i;
     252                 : 
     253               0 :     for( i = 0; i < depth*2 && i < (int) sizeof(spaces); i++ )
     254               0 :         spaces[i] = ' ';
     255               0 :     spaces[i] = '\0';
     256                 : 
     257               0 :     if( eNodeType == SNT_CONSTANT )
     258                 :     {
     259               0 :         if( field_type == ODS_FIELD_TYPE_INTEGER )
     260               0 :             fprintf( fp, "%s  %d\n", spaces, int_value );
     261               0 :         else if( field_type == ODS_FIELD_TYPE_FLOAT )
     262               0 :             fprintf( fp, "%s  %.15g\n", spaces, float_value );
     263                 :         else
     264               0 :             fprintf( fp, "%s  \"%s\"\n", spaces, string_value );
     265               0 :         return;
     266                 :     }
     267                 : 
     268               0 :     CPLAssert( eNodeType == SNT_OPERATION );
     269                 : 
     270               0 :     fprintf( fp, "%s%s\n", spaces, ODSGetOperatorName(eOp) );
     271                 : 
     272               0 :     for( i = 0; i < nSubExprCount; i++ )
     273               0 :         papoSubExpr[i]->Dump( fp, depth+1 );
     274                 : }
     275                 : 
     276                 : /************************************************************************/
     277                 : /*                             FreeSubExpr()                            */
     278                 : /************************************************************************/
     279                 : 
     280             639 : void  ods_formula_node::FreeSubExpr()
     281                 : {
     282                 :     int i;
     283             922 :     for( i = 0; i < nSubExprCount; i++ )
     284             283 :         delete papoSubExpr[i];
     285             639 :     CPLFree( papoSubExpr );
     286                 : 
     287             639 :     nSubExprCount = 0;
     288             639 :     papoSubExpr = NULL;
     289             639 : }
     290                 : 
     291                 : /************************************************************************/
     292                 : /*                              Evaluate()                              */
     293                 : /************************************************************************/
     294                 : 
     295             339 : int ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
     296                 : {
     297             339 :     if (eNodeType == SNT_CONSTANT)
     298             192 :         return TRUE;
     299                 : 
     300             147 :     CPLAssert( eNodeType == SNT_OPERATION );
     301                 : 
     302             147 :     switch (eOp)
     303                 :     {
     304               4 :         case ODS_OR: return EvaluateOR(poEvaluator);
     305               4 :         case ODS_AND: return EvaluateAND(poEvaluator);
     306               2 :         case ODS_NOT: return EvaluateNOT(poEvaluator);
     307               4 :         case ODS_IF: return EvaluateIF(poEvaluator);
     308                 : 
     309                 :         case ODS_PI:
     310               1 :             eNodeType = SNT_CONSTANT;
     311               1 :             field_type = ODS_FIELD_TYPE_FLOAT;
     312               1 :             float_value = PI;
     313               1 :             return TRUE;
     314                 : 
     315               1 :         case ODS_LEN : return EvaluateLEN(poEvaluator);
     316               3 :         case ODS_LEFT : return EvaluateLEFT(poEvaluator);
     317               3 :         case ODS_RIGHT : return EvaluateRIGHT(poEvaluator);
     318               8 :         case ODS_MID : return EvaluateMID(poEvaluator);
     319                 : 
     320                 :         case ODS_SUM:
     321                 :         case ODS_AVERAGE:
     322                 :         case ODS_MIN:
     323                 :         case ODS_MAX:
     324                 :         case ODS_COUNT:
     325                 :         case ODS_COUNTA:
     326               6 :             return EvaluateListArgOp(poEvaluator);
     327                 : 
     328                 :         case ODS_ABS:
     329                 :         case ODS_SQRT:
     330                 :         case ODS_COS:
     331                 :         case ODS_SIN:
     332                 :         case ODS_TAN:
     333                 :         case ODS_ACOS:
     334                 :         case ODS_ASIN:
     335                 :         case ODS_ATAN:
     336                 :         case ODS_EXP:
     337                 :         case ODS_LN:
     338                 :         case ODS_LOG:
     339               9 :             return EvaluateSingleArgOp(poEvaluator);
     340                 : 
     341                 : 
     342              10 :         case ODS_EQ: return EvaluateEQ(poEvaluator);
     343              10 :         case ODS_NE: return EvaluateNE(poEvaluator);
     344              10 :         case ODS_LE: return EvaluateLE(poEvaluator);
     345              10 :         case ODS_GE: return EvaluateGE(poEvaluator);
     346              14 :         case ODS_LT: return EvaluateLT(poEvaluator);
     347              10 :         case ODS_GT: return EvaluateGT(poEvaluator);
     348                 : 
     349                 :         case ODS_ADD:
     350                 :         case ODS_SUBTRACT:
     351                 :         case ODS_MULTIPLY:
     352                 :         case ODS_DIVIDE:
     353                 :         case ODS_MODULUS:
     354               9 :             return EvaluateBinaryArithmetic(poEvaluator);
     355                 : 
     356               1 :         case ODS_CONCAT: return EvaluateCONCAT(poEvaluator);
     357                 : 
     358              28 :         case ODS_CELL: return EvaluateCELL(poEvaluator);
     359                 : 
     360                 :         default:
     361                 :         {
     362                 :             CPLError(CE_Failure, CPLE_AppDefined,
     363                 :                      "Unhandled case in Evaluate() for %s",
     364               0 :                      ODSGetOperatorName(eOp));
     365               0 :             return FALSE;
     366                 :         }
     367                 :     }
     368                 : }
     369                 : 
     370                 : /************************************************************************/
     371                 : /*                             EvaluateOR()                             */
     372                 : /************************************************************************/
     373                 : 
     374               4 : int ods_formula_node::EvaluateOR(IODSCellEvaluator* poEvaluator)
     375                 : {
     376               4 :     CPLAssert( eNodeType == SNT_OPERATION );
     377               4 :     CPLAssert( eOp == ODS_OR );
     378                 : 
     379               4 :     CPLAssert(nSubExprCount == 1);
     380               4 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_OPERATION );
     381               4 :     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
     382               4 :     int bVal = FALSE;
     383              12 :     for(int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
     384                 :     {
     385               8 :         if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
     386               0 :             return FALSE;
     387               8 :         CPLAssert(papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
     388               8 :         if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
     389                 :         {
     390               8 :             bVal |= (papoSubExpr[0]->papoSubExpr[i]->int_value != 0);
     391                 :         }
     392               0 :         else if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_FLOAT)
     393                 :         {
     394               0 :             bVal |= (papoSubExpr[0]->papoSubExpr[i]->float_value != 0);
     395                 :         }
     396                 :         else
     397                 :         {
     398                 :             CPLError(CE_Failure, CPLE_NotSupported,
     399               0 :                      "Bad argument type for %s", ODSGetOperatorName(eOp));
     400               0 :             return FALSE;
     401                 :         }
     402                 :     }
     403                 : 
     404               4 :     FreeSubExpr();
     405                 : 
     406               4 :     eNodeType = SNT_CONSTANT;
     407               4 :     field_type = ODS_FIELD_TYPE_INTEGER;
     408               4 :     int_value = bVal;
     409                 : 
     410               4 :     return TRUE;
     411                 : }
     412                 : 
     413                 : /************************************************************************/
     414                 : /*                            EvaluateAND()                             */
     415                 : /************************************************************************/
     416                 : 
     417               4 : int ods_formula_node::EvaluateAND(IODSCellEvaluator* poEvaluator)
     418                 : {
     419               4 :     CPLAssert( eNodeType == SNT_OPERATION );
     420               4 :     CPLAssert( eOp == ODS_AND );
     421                 : 
     422               4 :     CPLAssert(nSubExprCount == 1);
     423               4 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_OPERATION );
     424               4 :     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
     425               4 :     int bVal = TRUE;
     426              12 :     for(int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
     427                 :     {
     428               8 :         if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
     429               0 :             return FALSE;
     430               8 :         CPLAssert(papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
     431               8 :         if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
     432                 :         {
     433               8 :             bVal &= (papoSubExpr[0]->papoSubExpr[i]->int_value != 0);
     434                 :         }
     435               0 :         else if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_FLOAT)
     436                 :         {
     437               0 :             bVal &= (papoSubExpr[0]->papoSubExpr[i]->float_value != 0);
     438                 :         }
     439                 :         else
     440                 :         {
     441                 :             CPLError(CE_Failure, CPLE_NotSupported,
     442               0 :                      "Bad argument type for %s", ODSGetOperatorName(eOp));
     443               0 :             return FALSE;
     444                 :         }
     445                 :     }
     446                 : 
     447               4 :     FreeSubExpr();
     448                 : 
     449               4 :     eNodeType = SNT_CONSTANT;
     450               4 :     field_type = ODS_FIELD_TYPE_INTEGER;
     451               4 :     int_value = bVal;
     452                 : 
     453               4 :     return TRUE;
     454                 : }
     455                 : 
     456                 : /************************************************************************/
     457                 : /*                            EvaluateNOT()                             */
     458                 : /************************************************************************/
     459                 : 
     460               2 : int ods_formula_node::EvaluateNOT(IODSCellEvaluator* poEvaluator)
     461                 : {
     462               2 :     CPLAssert( eNodeType == SNT_OPERATION );
     463               2 :     CPLAssert( eOp == ODS_NOT );
     464                 : 
     465               2 :     CPLAssert(nSubExprCount == 1);
     466               2 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     467               0 :         return FALSE;
     468               2 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     469                 : 
     470               2 :     int bVal = FALSE;
     471               2 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     472                 :     {
     473               2 :         bVal = !(papoSubExpr[0]->int_value != 0);
     474                 :     }
     475               0 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     476                 :     {
     477               0 :         bVal = !(papoSubExpr[0]->float_value != 0);
     478                 :     }
     479                 :     else
     480                 :     {
     481                 :         CPLError(CE_Failure, CPLE_NotSupported,
     482               0 :                  "Bad argument type for %s", ODSGetOperatorName(eOp));
     483               0 :         return FALSE;
     484                 :     }
     485                 : 
     486               2 :     FreeSubExpr();
     487                 : 
     488               2 :     eNodeType = SNT_CONSTANT;
     489               2 :     field_type = ODS_FIELD_TYPE_INTEGER;
     490               2 :     int_value = bVal;
     491                 : 
     492               2 :     return TRUE;
     493                 : }
     494                 : 
     495                 : /************************************************************************/
     496                 : /*                            EvaluateIF()                              */
     497                 : /************************************************************************/
     498                 : 
     499               4 : int ods_formula_node::EvaluateIF(IODSCellEvaluator* poEvaluator)
     500                 : {
     501               4 :     CPLAssert( eNodeType == SNT_OPERATION );
     502               4 :     CPLAssert( eOp == ODS_IF );
     503                 : 
     504               4 :     CPLAssert(nSubExprCount == 2 || nSubExprCount == 3);
     505               4 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     506               0 :         return FALSE;
     507               4 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     508               0 :         return FALSE;
     509               4 :     if (nSubExprCount == 3 && !(papoSubExpr[2]->Evaluate(poEvaluator)))
     510               0 :         return FALSE;
     511                 : 
     512               4 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     513               4 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     514               4 :     if (nSubExprCount == 3)
     515               2 :         CPLAssert(papoSubExpr[2]->eNodeType == SNT_CONSTANT );
     516                 : 
     517               4 :     int bCond = FALSE;
     518               4 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     519                 :     {
     520               4 :         bCond = (papoSubExpr[0]->int_value != 0);
     521                 :     }
     522               0 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     523                 :     {
     524               0 :         bCond = (papoSubExpr[0]->float_value != 0);
     525                 :     }
     526                 :     else
     527                 :     {
     528                 :         CPLError(CE_Failure, CPLE_NotSupported,
     529               0 :                  "Bad argument type for %s", ODSGetOperatorName(eOp));
     530               0 :         return FALSE;
     531                 :     }
     532                 : 
     533               4 :     if (bCond)
     534                 :     {
     535               2 :         eNodeType = SNT_CONSTANT;
     536               2 :         field_type = papoSubExpr[1]->field_type;
     537               2 :         if (field_type == ODS_FIELD_TYPE_INTEGER)
     538               2 :             int_value = papoSubExpr[1]->int_value;
     539               0 :         else if (field_type == ODS_FIELD_TYPE_FLOAT)
     540               0 :             float_value = papoSubExpr[1]->float_value;
     541               0 :         else if (field_type == ODS_FIELD_TYPE_STRING)
     542                 :         {
     543               0 :             string_value = papoSubExpr[1]->string_value;
     544               0 :             papoSubExpr[1]->string_value = NULL;
     545                 :         }
     546                 :     }
     547               2 :     else if (nSubExprCount == 3)
     548                 :     {
     549               1 :         eNodeType = SNT_CONSTANT;
     550               1 :         field_type = papoSubExpr[2]->field_type;
     551               1 :         if (field_type == ODS_FIELD_TYPE_INTEGER)
     552               1 :             int_value = papoSubExpr[2]->int_value;
     553               0 :         else if (field_type == ODS_FIELD_TYPE_FLOAT)
     554               0 :             float_value = papoSubExpr[2]->float_value;
     555               0 :         else if (field_type == ODS_FIELD_TYPE_STRING)
     556                 :         {
     557               0 :             string_value = papoSubExpr[2]->string_value;
     558               0 :             papoSubExpr[2]->string_value = NULL;
     559                 :         }
     560                 :     }
     561                 :     else
     562                 :     {
     563               1 :         eNodeType = SNT_CONSTANT;
     564               1 :         field_type = ODS_FIELD_TYPE_INTEGER;
     565               1 :         int_value = FALSE;
     566                 :     }
     567                 : 
     568               4 :     FreeSubExpr();
     569                 : 
     570               4 :     return TRUE;
     571                 : }
     572                 : 
     573                 : /************************************************************************/
     574                 : /*                            EvaluateEQ()                              */
     575                 : /************************************************************************/
     576                 : 
     577              20 : int ods_formula_node::EvaluateEQ(IODSCellEvaluator* poEvaluator)
     578                 : {
     579              20 :     CPLAssert( eNodeType == SNT_OPERATION );
     580              20 :     CPLAssert( eOp == ODS_EQ );
     581                 : 
     582              20 :     CPLAssert(nSubExprCount == 2);
     583              20 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     584               0 :         return FALSE;
     585              20 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     586               0 :         return FALSE;
     587                 : 
     588              20 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     589              20 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     590                 : 
     591              20 :     int bVal = FALSE;
     592              20 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     593                 :     {
     594               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     595                 :         {
     596               4 :             bVal = (papoSubExpr[0]->int_value == papoSubExpr[1]->int_value);
     597                 :         }
     598               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     599                 :         {
     600               4 :             bVal = (papoSubExpr[0]->int_value == papoSubExpr[1]->float_value);
     601                 :         }
     602                 :     }
     603              12 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     604                 :     {
     605               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     606                 :         {
     607               4 :             bVal = (papoSubExpr[0]->float_value == papoSubExpr[1]->int_value);
     608                 :         }
     609               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     610                 :         {
     611               4 :             bVal = (papoSubExpr[0]->float_value == papoSubExpr[1]->float_value);
     612                 :         }
     613                 :     }
     614               4 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     615                 :     {
     616               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     617                 :         {
     618               4 :             bVal = (strcmp(papoSubExpr[0]->string_value,
     619               8 :                            papoSubExpr[1]->string_value) == 0);
     620                 :         }
     621                 :     }
     622                 :     else
     623                 :     {
     624                 :         CPLError(CE_Failure, CPLE_NotSupported,
     625               0 :                  "Bad argument type for %s", ODSGetOperatorName(eOp));
     626               0 :         return FALSE;
     627                 :     }
     628                 : 
     629              20 :     eNodeType = SNT_CONSTANT;
     630              20 :     field_type = ODS_FIELD_TYPE_INTEGER;
     631              20 :     int_value = bVal;
     632                 : 
     633              20 :     FreeSubExpr();
     634                 : 
     635              20 :     return TRUE;
     636                 : }
     637                 : 
     638                 : /************************************************************************/
     639                 : /*                           EvaluateNE()                               */
     640                 : /************************************************************************/
     641                 : 
     642              10 : int ods_formula_node::EvaluateNE(IODSCellEvaluator* poEvaluator)
     643                 : {
     644              10 :     CPLAssert( eNodeType == SNT_OPERATION );
     645              10 :     CPLAssert( eOp == ODS_NE );
     646                 : 
     647              10 :     eOp = ODS_EQ;
     648              10 :     if (!EvaluateEQ(poEvaluator))
     649               0 :         return FALSE;
     650                 : 
     651              10 :     int_value = !int_value;
     652              10 :     return TRUE;
     653                 : }
     654                 : 
     655                 : /************************************************************************/
     656                 : /*                              GetCase()                               */
     657                 : /************************************************************************/
     658                 : 
     659                 : typedef enum
     660                 : {
     661                 :     CASE_LOWER,
     662                 :     CASE_UPPER,
     663                 :     CASE_UNKNOWN,
     664                 : } CaseType;
     665                 : 
     666              24 : static CaseType GetCase(const char* pszStr)
     667                 : {
     668              24 :     int bInit = TRUE;
     669                 :     char ch;
     670              24 :     CaseType eCase = CASE_UNKNOWN;
     671              72 :     while((ch = *(pszStr++)) != '\0')
     672                 :     {
     673              24 :         if (bInit)
     674                 :         {
     675              28 :             if (ch >= 'a' && ch <= 'z')
     676               4 :                 eCase = CASE_LOWER;
     677              40 :             else if (ch >= 'A' && ch <= 'Z')
     678              20 :                 eCase = CASE_UPPER;
     679                 :             else
     680               0 :                 return CASE_UNKNOWN;
     681                 :         }
     682               0 :         else if (ch >= 'a' && ch <= 'z' && eCase == CASE_LOWER)
     683                 :             ;
     684               0 :         else if (ch >= 'A' && ch <= 'Z' && eCase == CASE_UPPER)
     685                 :             ;
     686                 :         else
     687               0 :             return CASE_UNKNOWN;
     688                 :     }
     689              24 :     return eCase;
     690                 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                            EvaluateLE()                              */
     694                 : /************************************************************************/
     695                 : 
     696              10 : int ods_formula_node::EvaluateLE(IODSCellEvaluator* poEvaluator)
     697                 : {
     698              10 :     CPLAssert( eNodeType == SNT_OPERATION );
     699              10 :     CPLAssert( eOp == ODS_LE );
     700                 : 
     701              10 :     CPLAssert(nSubExprCount == 2);
     702              10 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     703               0 :         return FALSE;
     704              10 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     705               0 :         return FALSE;
     706                 : 
     707              10 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     708              10 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     709                 : 
     710              10 :     int bVal = FALSE;
     711              10 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     712                 :     {
     713               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     714                 :         {
     715               2 :             bVal = (papoSubExpr[0]->int_value <= papoSubExpr[1]->int_value);
     716                 :         }
     717               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     718                 :         {
     719               2 :             bVal = (papoSubExpr[0]->int_value <= papoSubExpr[1]->float_value);
     720                 :         }
     721                 :         else
     722               0 :             bVal = TRUE;
     723                 :     }
     724               6 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     725                 :     {
     726               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     727                 :         {
     728               2 :             bVal = (papoSubExpr[0]->float_value <= papoSubExpr[1]->int_value);
     729                 :         }
     730               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     731                 :         {
     732               2 :             bVal = (papoSubExpr[0]->float_value <= papoSubExpr[1]->float_value);
     733                 :         }
     734                 :         else
     735               0 :             bVal = TRUE;
     736                 :     }
     737               2 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     738                 :     {
     739               2 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     740                 :         {
     741               4 :             if (GetCase(papoSubExpr[0]->string_value) ==
     742               2 :                 GetCase(papoSubExpr[1]->string_value))
     743               2 :                 bVal = (strcmp(papoSubExpr[0]->string_value,
     744               4 :                                papoSubExpr[1]->string_value) <= 0);
     745                 :             else
     746               0 :                 bVal = (strcasecmp(papoSubExpr[0]->string_value,
     747               0 :                                    papoSubExpr[1]->string_value) <= 0);
     748                 :         }
     749                 :     }
     750                 :     else
     751                 :     {
     752                 :         CPLError(CE_Failure, CPLE_NotSupported,
     753               0 :                  "Bad argument type for %s", ODSGetOperatorName(eOp));
     754               0 :         return FALSE;
     755                 :     }
     756                 : 
     757              10 :     eNodeType = SNT_CONSTANT;
     758              10 :     field_type = ODS_FIELD_TYPE_INTEGER;
     759              10 :     int_value = bVal;
     760                 : 
     761              10 :     FreeSubExpr();
     762                 : 
     763              10 :     return TRUE;
     764                 : }
     765                 : 
     766                 : /************************************************************************/
     767                 : /*                            EvaluateGE()                              */
     768                 : /************************************************************************/
     769                 : 
     770              10 : int ods_formula_node::EvaluateGE(IODSCellEvaluator* poEvaluator)
     771                 : {
     772              10 :     CPLAssert( eNodeType == SNT_OPERATION );
     773              10 :     CPLAssert( eOp == ODS_GE );
     774                 : 
     775              10 :     CPLAssert(nSubExprCount == 2);
     776              10 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     777               0 :         return FALSE;
     778              10 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     779               0 :         return FALSE;
     780                 : 
     781              10 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     782              10 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     783                 : 
     784              10 :     int bVal = FALSE;
     785              10 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     786                 :     {
     787               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     788                 :         {
     789               2 :             bVal = (papoSubExpr[0]->int_value >= papoSubExpr[1]->int_value);
     790                 :         }
     791               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     792                 :         {
     793               2 :             bVal = (papoSubExpr[0]->int_value >= papoSubExpr[1]->float_value);
     794                 :         }
     795                 :     }
     796               6 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     797                 :     {
     798               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     799                 :         {
     800               2 :             bVal = (papoSubExpr[0]->float_value >= papoSubExpr[1]->int_value);
     801                 :         }
     802               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     803                 :         {
     804               2 :             bVal = (papoSubExpr[0]->float_value >= papoSubExpr[1]->float_value);
     805                 :         }
     806                 :     }
     807               2 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     808                 :     {
     809               2 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     810                 :         {
     811               4 :             if (GetCase(papoSubExpr[0]->string_value) ==
     812               2 :                 GetCase(papoSubExpr[1]->string_value))
     813               2 :                 bVal = (strcmp(papoSubExpr[0]->string_value,
     814               4 :                                papoSubExpr[1]->string_value) >= 0);
     815                 :             else
     816               0 :                 bVal = (strcasecmp(papoSubExpr[0]->string_value,
     817               0 :                                    papoSubExpr[1]->string_value) >= 0);
     818                 :         }
     819                 :         else
     820               0 :             bVal = TRUE;
     821                 :     }
     822                 :     else
     823                 :     {
     824                 :         CPLError(CE_Failure, CPLE_NotSupported,
     825               0 :                  "Bad argument type for %s", ODSGetOperatorName(eOp));
     826               0 :         return FALSE;
     827                 :     }
     828                 : 
     829              10 :     eNodeType = SNT_CONSTANT;
     830              10 :     field_type = ODS_FIELD_TYPE_INTEGER;
     831              10 :     int_value = bVal;
     832                 : 
     833              10 :     FreeSubExpr();
     834                 : 
     835              10 :     return TRUE;
     836                 : }
     837                 : 
     838                 : /************************************************************************/
     839                 : /*                            EvaluateLT()                              */
     840                 : /************************************************************************/
     841                 : 
     842              14 : int ods_formula_node::EvaluateLT(IODSCellEvaluator* poEvaluator)
     843                 : {
     844              14 :     CPLAssert( eNodeType == SNT_OPERATION );
     845              14 :     CPLAssert( eOp == ODS_LT );
     846                 : 
     847              14 :     CPLAssert(nSubExprCount == 2);
     848              14 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     849               0 :         return FALSE;
     850              14 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     851               0 :         return FALSE;
     852                 : 
     853              14 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     854              14 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     855                 : 
     856              14 :     int bVal = FALSE;
     857              14 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     858                 :     {
     859               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     860                 :         {
     861               2 :             bVal = (papoSubExpr[0]->int_value < papoSubExpr[1]->int_value);
     862                 :         }
     863               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     864                 :         {
     865               2 :             bVal = (papoSubExpr[0]->int_value < papoSubExpr[1]->float_value);
     866                 :         }
     867                 :         else
     868               0 :             bVal = TRUE;
     869                 :     }
     870              10 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     871                 :     {
     872               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     873                 :         {
     874               2 :             bVal = (papoSubExpr[0]->float_value < papoSubExpr[1]->int_value);
     875                 :         }
     876               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     877                 :         {
     878               2 :             bVal = (papoSubExpr[0]->float_value < papoSubExpr[1]->float_value);
     879                 :         }
     880                 :         else
     881               0 :             bVal = TRUE;
     882                 :     }
     883               6 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     884                 :     {
     885               6 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     886                 :         {
     887              12 :             if (GetCase(papoSubExpr[0]->string_value) ==
     888               6 :                 GetCase(papoSubExpr[1]->string_value))
     889               2 :                 bVal = (strcmp(papoSubExpr[0]->string_value,
     890               4 :                                papoSubExpr[1]->string_value) < 0);
     891                 :             else
     892               4 :                 bVal = (strcasecmp(papoSubExpr[0]->string_value,
     893               8 :                                    papoSubExpr[1]->string_value) < 0);
     894                 :         }
     895                 :     }
     896                 :     else
     897                 :     {
     898                 :         CPLError(CE_Failure, CPLE_NotSupported,
     899               0 :                  "Bad argument type for %s", ODSGetOperatorName(eOp));
     900               0 :         return FALSE;
     901                 :     }
     902                 : 
     903              14 :     eNodeType = SNT_CONSTANT;
     904              14 :     field_type = ODS_FIELD_TYPE_INTEGER;
     905              14 :     int_value = bVal;
     906                 : 
     907              14 :     FreeSubExpr();
     908                 : 
     909              14 :     return TRUE;
     910                 : }
     911                 : 
     912                 : /************************************************************************/
     913                 : /*                            EvaluateGT()                              */
     914                 : /************************************************************************/
     915                 : 
     916              10 : int ods_formula_node::EvaluateGT(IODSCellEvaluator* poEvaluator)
     917                 : {
     918              10 :     CPLAssert( eNodeType == SNT_OPERATION );
     919              10 :     CPLAssert( eOp == ODS_GT );
     920                 : 
     921              10 :     CPLAssert(nSubExprCount == 2);
     922              10 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     923               0 :         return FALSE;
     924              10 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     925               0 :         return FALSE;
     926                 : 
     927              10 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     928              10 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     929                 : 
     930              10 :     int bVal = FALSE;
     931              10 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     932                 :     {
     933               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     934                 :         {
     935               2 :             bVal = (papoSubExpr[0]->int_value > papoSubExpr[1]->int_value);
     936                 :         }
     937               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     938                 :         {
     939               2 :             bVal = (papoSubExpr[0]->int_value > papoSubExpr[1]->float_value);
     940                 :         }
     941                 :     }
     942               6 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     943                 :     {
     944               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     945                 :         {
     946               2 :             bVal = (papoSubExpr[0]->float_value > papoSubExpr[1]->int_value);
     947                 :         }
     948               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     949                 :         {
     950               2 :             bVal = (papoSubExpr[0]->float_value > papoSubExpr[1]->float_value);
     951                 :         }
     952                 :     }
     953               2 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     954                 :     {
     955               2 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     956                 :         {
     957               4 :             if (GetCase(papoSubExpr[0]->string_value) ==
     958               2 :                 GetCase(papoSubExpr[1]->string_value))
     959               2 :                 bVal = (strcmp(papoSubExpr[0]->string_value,
     960               4 :                                papoSubExpr[1]->string_value) > 0);
     961                 :             else
     962               0 :                 bVal = (strcasecmp(papoSubExpr[0]->string_value,
     963               0 :                                    papoSubExpr[1]->string_value) > 0);
     964                 :         }
     965                 :         else
     966               0 :             bVal = TRUE;
     967                 :     }
     968                 :     else
     969                 :     {
     970                 :         CPLError(CE_Failure, CPLE_NotSupported,
     971               0 :                  "Bad argument type for %s", ODSGetOperatorName(eOp));
     972               0 :         return FALSE;
     973                 :     }
     974                 : 
     975              10 :     eNodeType = SNT_CONSTANT;
     976              10 :     field_type = ODS_FIELD_TYPE_INTEGER;
     977              10 :     int_value = bVal;
     978                 : 
     979              10 :     FreeSubExpr();
     980                 : 
     981              10 :     return TRUE;
     982                 : }
     983                 : 
     984                 : /************************************************************************/
     985                 : /*                         EvaluateSingleArgOp()                        */
     986                 : /************************************************************************/
     987                 : 
     988               9 : int ods_formula_node::EvaluateSingleArgOp(IODSCellEvaluator* poEvaluator)
     989                 : {
     990               9 :     CPLAssert( eNodeType == SNT_OPERATION );
     991                 : 
     992               9 :     const SingleOpStruct* psSingleOp = ODSGetSingleOpEntry(eOp);
     993               9 :     CPLAssert(psSingleOp);
     994                 : 
     995               9 :     CPLAssert(nSubExprCount == 1);
     996               9 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     997               0 :         return FALSE;
     998                 : 
     999               9 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1000               9 :     double dfVal = 0;
    1001                 : 
    1002               9 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
    1003                 :     {
    1004               1 :         dfVal = psSingleOp->pfnEval(papoSubExpr[0]->int_value);
    1005                 :     }
    1006               8 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
    1007                 :     {
    1008               8 :         dfVal = psSingleOp->pfnEval(papoSubExpr[0]->float_value);
    1009                 :     }
    1010                 :     else
    1011                 :     {
    1012                 :         CPLError(CE_Failure, CPLE_NotSupported, "Bad argument type for %s",
    1013               0 :                  psSingleOp->pszName);
    1014               0 :         return FALSE;
    1015                 :     }
    1016                 : 
    1017               9 :     eNodeType = SNT_CONSTANT;
    1018               9 :     field_type = ODS_FIELD_TYPE_FLOAT;
    1019               9 :     float_value = dfVal;
    1020                 : 
    1021               9 :     FreeSubExpr();
    1022                 : 
    1023               9 :     return TRUE;
    1024                 : }
    1025                 : 
    1026                 : /************************************************************************/
    1027                 : /*                       EvaluateBinaryArithmetic()                     */
    1028                 : /************************************************************************/
    1029                 : 
    1030               9 : int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
    1031                 : {
    1032               9 :     CPLAssert( eNodeType == SNT_OPERATION );
    1033               9 :     CPLAssert( eOp >= ODS_ADD && eOp<= ODS_MODULUS );
    1034                 : 
    1035               9 :     CPLAssert(nSubExprCount == 2);
    1036               9 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1037               0 :         return FALSE;
    1038               9 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1039               0 :         return FALSE;
    1040                 : 
    1041               9 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1042               9 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1043                 : 
    1044               9 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
    1045                 :     {
    1046               6 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
    1047                 :         {
    1048                 :             int nVal;
    1049               4 :             switch (eOp)
    1050                 :             {
    1051               1 :                 case ODS_ADD      : nVal = (papoSubExpr[0]->int_value + papoSubExpr[1]->int_value); break;
    1052               1 :                 case ODS_SUBTRACT : nVal = (papoSubExpr[0]->int_value - papoSubExpr[1]->int_value); break;
    1053               1 :                 case ODS_MULTIPLY : nVal = (papoSubExpr[0]->int_value * papoSubExpr[1]->int_value); break;
    1054                 :                 case ODS_DIVIDE   :
    1055               1 :                     if (papoSubExpr[1]->int_value != 0)
    1056               1 :                         nVal = (papoSubExpr[0]->int_value / papoSubExpr[1]->int_value);
    1057                 :                     else
    1058               0 :                         return FALSE;
    1059               1 :                     break;
    1060                 :                 case ODS_MODULUS  :
    1061               0 :                     if (papoSubExpr[1]->int_value != 0)
    1062               0 :                         nVal = (papoSubExpr[0]->int_value % papoSubExpr[1]->int_value);
    1063                 :                     else
    1064               0 :                         return FALSE;
    1065               0 :                     break;
    1066               0 :                 default: nVal = 0; CPLAssert(0);
    1067                 :             }
    1068                 : 
    1069               4 :             eNodeType = SNT_CONSTANT;
    1070               4 :             field_type = ODS_FIELD_TYPE_INTEGER;
    1071               4 :             int_value = nVal;
    1072                 : 
    1073               4 :             FreeSubExpr();
    1074                 : 
    1075               4 :             return TRUE;
    1076                 :         }
    1077               2 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
    1078                 :         {
    1079               2 :             papoSubExpr[0]->field_type = ODS_FIELD_TYPE_FLOAT;
    1080               2 :             papoSubExpr[0]->float_value = papoSubExpr[0]->int_value;
    1081                 :         }
    1082                 :         else
    1083                 :         {
    1084                 :             CPLError(CE_Failure, CPLE_NotSupported,
    1085               0 :                      "Bad argument type for %s", ODSGetOperatorName(eOp));
    1086               0 :             return FALSE;
    1087                 :         }
    1088                 :     }
    1089                 : 
    1090               5 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
    1091                 :     {
    1092               5 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
    1093                 :         {
    1094               2 :             papoSubExpr[1]->field_type = ODS_FIELD_TYPE_FLOAT;
    1095               2 :             papoSubExpr[1]->float_value = papoSubExpr[1]->int_value;
    1096                 :         }
    1097                 : 
    1098               5 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
    1099                 :         {
    1100                 :             float dfVal;
    1101               5 :             switch (eOp)
    1102                 :             {
    1103               0 :                 case ODS_ADD      : dfVal = (papoSubExpr[0]->float_value + papoSubExpr[1]->float_value); break;
    1104               0 :                 case ODS_SUBTRACT : dfVal = (papoSubExpr[0]->float_value - papoSubExpr[1]->float_value); break;
    1105               3 :                 case ODS_MULTIPLY : dfVal = (papoSubExpr[0]->float_value * papoSubExpr[1]->float_value); break;
    1106                 :                 case ODS_DIVIDE   :
    1107               1 :                     if (papoSubExpr[1]->float_value != 0)
    1108               1 :                         dfVal = (papoSubExpr[0]->float_value / papoSubExpr[1]->float_value);
    1109                 :                     else
    1110               0 :                         return FALSE;
    1111               1 :                     break;
    1112                 :                 case ODS_MODULUS  :
    1113               1 :                     if (papoSubExpr[1]->float_value != 0)
    1114               1 :                         dfVal = fmod(papoSubExpr[0]->float_value, papoSubExpr[1]->float_value);
    1115                 :                     else
    1116               0 :                         return FALSE;
    1117               1 :                     break;
    1118               0 :                 default: dfVal = 0.0; CPLAssert(0);
    1119                 :             }
    1120                 : 
    1121               5 :             eNodeType = SNT_CONSTANT;
    1122               5 :             field_type = ODS_FIELD_TYPE_FLOAT;
    1123               5 :             float_value = dfVal;
    1124                 : 
    1125               5 :             FreeSubExpr();
    1126                 : 
    1127               5 :             return TRUE;
    1128                 :         }
    1129                 :         else
    1130                 :         {
    1131                 :             CPLError(CE_Failure, CPLE_NotSupported,
    1132               0 :                      "Bad argument type for %s", ODSGetOperatorName(eOp));
    1133               0 :             return FALSE;
    1134                 :         }
    1135                 :     }
    1136                 :     else
    1137                 :     {
    1138                 :         CPLError(CE_Failure, CPLE_NotSupported,
    1139               0 :                  "Bad argument type for %s", ODSGetOperatorName(eOp));
    1140               0 :         return FALSE;
    1141                 :     }
    1142                 : }
    1143                 : 
    1144                 : 
    1145                 : /************************************************************************/
    1146                 : /*                         TransformToString()                          */
    1147                 : /************************************************************************/
    1148                 : 
    1149              17 : std::string ods_formula_node::TransformToString() const
    1150                 : {
    1151                 :     char szTmp[128];
    1152              17 :     if (field_type == ODS_FIELD_TYPE_INTEGER)
    1153                 :     {
    1154               0 :         snprintf(szTmp, sizeof(szTmp), "%d", int_value);
    1155               0 :         return szTmp;
    1156                 :     }
    1157              17 :     else if (field_type == ODS_FIELD_TYPE_FLOAT)
    1158                 :     {
    1159               0 :         snprintf(szTmp, sizeof(szTmp), "%.16g", float_value);
    1160               0 :         return szTmp;
    1161                 :     }
    1162              17 :     else if (field_type == ODS_FIELD_TYPE_STRING)
    1163                 :     {
    1164              17 :         return string_value;
    1165                 :     }
    1166                 :     else
    1167                 :     {
    1168               0 :         return "";
    1169                 :     }
    1170                 : }
    1171                 : 
    1172                 : /************************************************************************/
    1173                 : /*                           EvaluateCONCAT()                           */
    1174                 : /************************************************************************/
    1175                 : 
    1176               1 : int ods_formula_node::EvaluateCONCAT(IODSCellEvaluator* poEvaluator)
    1177                 : {
    1178               1 :     CPLAssert( eNodeType == SNT_OPERATION );
    1179               1 :     CPLAssert( eOp == ODS_CONCAT );
    1180                 : 
    1181               1 :     CPLAssert(nSubExprCount == 2);
    1182               1 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1183               0 :         return FALSE;
    1184               1 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1185               0 :         return FALSE;
    1186                 : 
    1187               1 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1188               1 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1189                 : 
    1190               1 :     std::string osLeft(papoSubExpr[0]->TransformToString());
    1191               1 :     std::string osRight(papoSubExpr[1]->TransformToString());
    1192                 : 
    1193               1 :     eNodeType = SNT_CONSTANT;
    1194               1 :     field_type = ODS_FIELD_TYPE_STRING;
    1195               1 :     string_value = CPLStrdup((osLeft + osRight).c_str());
    1196                 : 
    1197               1 :     FreeSubExpr();
    1198                 : 
    1199               1 :     return TRUE;
    1200                 : }
    1201                 : 
    1202                 : /************************************************************************/
    1203                 : /*                             GetRowCol()                              */
    1204                 : /************************************************************************/
    1205                 : 
    1206              40 : static int GetRowCol(const char* pszCell, int& nRow, int& nCol)
    1207                 : {
    1208                 :     int i;
    1209                 : 
    1210              40 :     if (pszCell[0] != '.')
    1211                 :     {
    1212                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1213               0 :                  "Invalid cell %s", pszCell);
    1214               0 :         return FALSE;
    1215                 :     }
    1216                 : 
    1217              40 :     nCol = 0;
    1218              80 :     for(i=1; pszCell[i]>='A' && pszCell[i]<='Z';i++)
    1219                 :     {
    1220              40 :         nCol = nCol * 26 + (pszCell[i] - 'A');
    1221                 :     }
    1222              40 :     nRow = atoi(pszCell + i) - 1;
    1223                 : 
    1224              40 :     return TRUE;
    1225                 : }
    1226                 : 
    1227                 : /************************************************************************/
    1228                 : /*                         EvaluateListArgOp()                          */
    1229                 : /************************************************************************/
    1230                 : 
    1231               6 : int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
    1232                 : {
    1233               6 :     CPLAssert( eNodeType == SNT_OPERATION );
    1234               6 :     CPLAssert( eOp >= ODS_SUM && eOp <= ODS_COUNTA );
    1235                 : 
    1236               6 :     CPLAssert(nSubExprCount == 1);
    1237               6 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_OPERATION );
    1238               6 :     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
    1239                 : 
    1240               6 :     std::vector<double> adfVal;
    1241                 :     int i;
    1242                 : 
    1243               6 :     int nCount = 0, nCountA = 0;
    1244                 : 
    1245              13 :     for(i=0;i<papoSubExpr[0]->nSubExprCount;i++)
    1246                 :     {
    1247              19 :         if (papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_OPERATION &&
    1248               6 :             papoSubExpr[0]->papoSubExpr[i]->eOp == ODS_CELL_RANGE)
    1249                 :         {
    1250               6 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->nSubExprCount == 2);
    1251               6 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[0]->eNodeType == SNT_CONSTANT);
    1252               6 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING);
    1253               6 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[1]->eNodeType == SNT_CONSTANT);
    1254               6 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING);
    1255                 : 
    1256               6 :             if (poEvaluator == NULL)
    1257                 :             {
    1258               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "No cell evaluator provided");
    1259               0 :                 return FALSE;
    1260                 :             }
    1261                 : 
    1262               6 :             const char* psz1 = papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[0]->string_value;
    1263               6 :             const char* psz2 = papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[1]->string_value;
    1264               6 :             int nRow1 = 0,nCol1 = 0;
    1265               6 :             if (!GetRowCol(psz1, nRow1, nCol1))
    1266               0 :                 return FALSE;
    1267               6 :             int nRow2 = 0,nCol2 = 0;
    1268               6 :             if (!GetRowCol(psz2, nRow2, nCol2))
    1269               0 :                 return FALSE;
    1270                 : 
    1271               6 :             std::vector<ods_formula_node> aoOutValues;
    1272               6 :             if (poEvaluator->EvaluateRange(nRow1, nCol1, nRow2, nCol2, aoOutValues))
    1273                 :             {
    1274              30 :                 for(size_t j = 0; j < aoOutValues.size(); j++)
    1275                 :                 {
    1276              24 :                     if (aoOutValues[j].eNodeType == SNT_CONSTANT)
    1277                 :                     {
    1278              24 :                         if (aoOutValues[j].field_type == ODS_FIELD_TYPE_INTEGER)
    1279                 :                         {
    1280               0 :                             adfVal.push_back(aoOutValues[j].int_value);
    1281               0 :                             nCount ++;
    1282               0 :                             nCountA ++;
    1283                 :                         }
    1284              24 :                         else if (aoOutValues[j].field_type == ODS_FIELD_TYPE_FLOAT)
    1285                 :                         {
    1286              12 :                             adfVal.push_back(aoOutValues[j].float_value);
    1287              12 :                             nCount ++;
    1288              12 :                             nCountA ++;
    1289                 :                         }
    1290              12 :                         else if (aoOutValues[j].field_type == ODS_FIELD_TYPE_STRING)
    1291                 :                         {
    1292               6 :                             nCountA ++;
    1293                 :                         }
    1294                 :                     }
    1295                 :                 }
    1296               6 :             }
    1297                 :         }
    1298                 :         else
    1299                 :         {
    1300               1 :             if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
    1301               0 :                 return FALSE;
    1302                 : 
    1303               1 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
    1304               1 :             if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
    1305                 :             {
    1306               1 :                 adfVal.push_back(papoSubExpr[0]->papoSubExpr[i]->int_value);
    1307               1 :                 nCount ++;
    1308               1 :                 nCountA ++;
    1309                 :             }
    1310               0 :             else if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_FLOAT)
    1311                 :             {
    1312               0 :                 adfVal.push_back(papoSubExpr[0]->papoSubExpr[i]->float_value);
    1313               0 :                 nCount ++;
    1314               0 :                 nCountA ++;
    1315                 :             }
    1316               0 :             else if (eOp == ODS_COUNT || eOp == ODS_COUNTA)
    1317                 :             {
    1318               0 :                 if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_STRING)
    1319               0 :                     nCountA ++;
    1320                 :             }
    1321                 :             else
    1322                 :             {
    1323                 : 
    1324                 :                 CPLError(CE_Failure, CPLE_NotSupported,
    1325               0 :                          "Bad argument type for %s", ODSGetOperatorName(eOp));
    1326               0 :                 return FALSE;
    1327                 :             }
    1328                 :         }
    1329                 :     }
    1330                 : 
    1331               6 :     if (eOp == ODS_COUNT)
    1332                 :     {
    1333               1 :         eNodeType = SNT_CONSTANT;
    1334               1 :         field_type = ODS_FIELD_TYPE_INTEGER;
    1335               1 :         int_value = nCount;
    1336                 : 
    1337               1 :         FreeSubExpr();
    1338               1 :         return TRUE;
    1339                 :     }
    1340                 : 
    1341               5 :     if (eOp == ODS_COUNTA)
    1342                 :     {
    1343               1 :         eNodeType = SNT_CONSTANT;
    1344               1 :         field_type = ODS_FIELD_TYPE_INTEGER;
    1345               1 :         int_value = nCountA;
    1346                 : 
    1347               1 :         FreeSubExpr();
    1348               1 :         return TRUE;
    1349                 :     }
    1350                 : 
    1351               4 :     double dfVal = 0;
    1352                 : 
    1353               4 :     switch(eOp)
    1354                 :     {
    1355                 :         case ODS_SUM:
    1356                 :         {
    1357               3 :             for(i=0;i<(int)adfVal.size();i++)
    1358                 :             {
    1359               2 :                 dfVal += adfVal[i];
    1360                 :             }
    1361               1 :             break;
    1362                 :         }
    1363                 : 
    1364                 :         case ODS_AVERAGE:
    1365                 :         {
    1366               3 :             for(i=0;i<(int)adfVal.size();i++)
    1367                 :             {
    1368               2 :                 dfVal += adfVal[i];
    1369                 :             }
    1370               1 :             dfVal /= adfVal.size();
    1371               1 :             break;
    1372                 :         }
    1373                 : 
    1374                 :         case ODS_MIN:
    1375                 :         {
    1376               1 :             dfVal = (adfVal.size() == 0) ? 0 :adfVal[0];
    1377               3 :             for(i=1;i<(int)adfVal.size();i++)
    1378                 :             {
    1379               2 :                 if (adfVal[i] < dfVal) dfVal = adfVal[i];
    1380                 :             }
    1381               1 :             break;
    1382                 :         }
    1383                 : 
    1384                 :         case ODS_MAX:
    1385                 :         {
    1386               1 :             dfVal = (adfVal.size() == 0) ? 0 :adfVal[0];
    1387               2 :             for(i=1;i<(int)adfVal.size();i++)
    1388                 :             {
    1389               1 :                 if (adfVal[i] > dfVal) dfVal = adfVal[i];
    1390                 :             }
    1391                 :             break;
    1392                 :         }
    1393                 : 
    1394                 :         default:
    1395                 :             break;
    1396                 :     }
    1397                 : 
    1398               4 :     eNodeType = SNT_CONSTANT;
    1399               4 :     field_type = ODS_FIELD_TYPE_FLOAT;
    1400               4 :     float_value = dfVal;
    1401                 : 
    1402               4 :     FreeSubExpr();
    1403                 : 
    1404               4 :     return TRUE;
    1405                 : }
    1406                 : 
    1407                 : /************************************************************************/
    1408                 : /*                           EvaluateCELL()                             */
    1409                 : /************************************************************************/
    1410                 : 
    1411              28 : int ods_formula_node::EvaluateCELL(IODSCellEvaluator* poEvaluator)
    1412                 : {
    1413              28 :     CPLAssert( eNodeType == SNT_OPERATION );
    1414              28 :     CPLAssert( eOp == ODS_CELL );
    1415                 : 
    1416              28 :     CPLAssert(nSubExprCount == 1);
    1417              28 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1418              28 :     CPLAssert(papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING );
    1419                 : 
    1420              28 :     if (poEvaluator == NULL)
    1421                 :     {
    1422               0 :         CPLError(CE_Failure, CPLE_AppDefined, "No cell evaluator provided");
    1423               0 :         return FALSE;
    1424                 :     }
    1425                 : 
    1426              28 :     int nRow = 0,nCol = 0;
    1427              28 :     if (!GetRowCol(papoSubExpr[0]->string_value, nRow, nCol))
    1428               0 :         return FALSE;
    1429                 : 
    1430              28 :     std::vector<ods_formula_node> aoOutValues;
    1431              28 :     if (poEvaluator->EvaluateRange(nRow, nCol, nRow, nCol, aoOutValues) &&
    1432                 :         aoOutValues.size() == 1)
    1433                 :     {
    1434              19 :         if (aoOutValues[0].eNodeType == SNT_CONSTANT)
    1435                 :         {
    1436              19 :             FreeSubExpr();
    1437                 : 
    1438              19 :             eNodeType = aoOutValues[0].eNodeType;
    1439              19 :             field_type = aoOutValues[0].field_type;
    1440              19 :             int_value = aoOutValues[0].int_value;
    1441              19 :             float_value = aoOutValues[0].float_value;
    1442              19 :             string_value = aoOutValues[0].string_value ? CPLStrdup(aoOutValues[0].string_value) : NULL;
    1443                 : 
    1444              19 :             return TRUE;
    1445                 :         }
    1446                 :     }
    1447                 : 
    1448               9 :     return FALSE;
    1449                 : }
    1450                 : 
    1451                 : /************************************************************************/
    1452                 : /*                           EvaluateLEN()                              */
    1453                 : /************************************************************************/
    1454                 : 
    1455               1 : int ods_formula_node::EvaluateLEN(IODSCellEvaluator* poEvaluator)
    1456                 : {
    1457               1 :     CPLAssert( eNodeType == SNT_OPERATION );
    1458                 : 
    1459               1 :     CPLAssert(nSubExprCount == 1);
    1460               1 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1461               0 :         return FALSE;
    1462                 : 
    1463               1 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1464                 : 
    1465               1 :     std::string osVal = papoSubExpr[0]->TransformToString();
    1466                 : 
    1467               1 :     eNodeType = SNT_CONSTANT;
    1468               1 :     field_type = ODS_FIELD_TYPE_INTEGER;
    1469               1 :     int_value = strlen(osVal.c_str()); // FIXME : UTF8 support
    1470                 : 
    1471               1 :     FreeSubExpr();
    1472                 : 
    1473               1 :     return TRUE;
    1474                 : }
    1475                 : 
    1476                 : /************************************************************************/
    1477                 : /*                           EvaluateLEFT()                             */
    1478                 : /************************************************************************/
    1479                 : 
    1480               3 : int ods_formula_node::EvaluateLEFT(IODSCellEvaluator* poEvaluator)
    1481                 : {
    1482               3 :     CPLAssert( eNodeType == SNT_OPERATION );
    1483                 : 
    1484               3 :     CPLAssert(nSubExprCount == 2);
    1485               3 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1486               0 :         return FALSE;
    1487               3 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1488               0 :         return FALSE;
    1489                 : 
    1490               3 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1491               3 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1492                 : 
    1493               3 :     std::string osVal = papoSubExpr[0]->TransformToString();
    1494                 : 
    1495               3 :     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
    1496               0 :         return FALSE;
    1497                 : 
    1498                 :     // FIXME : UTF8 support
    1499               3 :     int nVal = papoSubExpr[1]->int_value;
    1500               3 :     if (nVal < 0)
    1501               0 :         return FALSE;
    1502                 : 
    1503               3 :     osVal = osVal.substr(0,nVal);
    1504                 : 
    1505               3 :     eNodeType = SNT_CONSTANT;
    1506               3 :     field_type = ODS_FIELD_TYPE_STRING;
    1507               3 :     string_value = CPLStrdup(osVal.c_str());
    1508                 : 
    1509               3 :     FreeSubExpr();
    1510                 : 
    1511               3 :     return TRUE;
    1512                 : }
    1513                 : 
    1514                 : /************************************************************************/
    1515                 : /*                           EvaluateRIGHT()                            */
    1516                 : /************************************************************************/
    1517                 : 
    1518               3 : int ods_formula_node::EvaluateRIGHT(IODSCellEvaluator* poEvaluator)
    1519                 : {
    1520               3 :     CPLAssert( eNodeType == SNT_OPERATION );
    1521                 : 
    1522               3 :     CPLAssert(nSubExprCount == 2);
    1523               3 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1524               0 :         return FALSE;
    1525               3 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1526               0 :         return FALSE;
    1527                 : 
    1528               3 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1529               3 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1530                 : 
    1531               3 :     std::string osVal = papoSubExpr[0]->TransformToString();
    1532                 : 
    1533               3 :     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
    1534               0 :         return FALSE;
    1535                 : 
    1536                 :     // FIXME : UTF8 support
    1537               3 :     size_t nLen = osVal.size();
    1538               3 :     int nVal = papoSubExpr[1]->int_value;
    1539               3 :     if (nVal < 0)
    1540               0 :         return FALSE;
    1541                 : 
    1542               3 :     if (nLen > (size_t) nVal)
    1543               2 :         osVal = osVal.substr(nLen-nVal);
    1544                 : 
    1545               3 :     eNodeType = SNT_CONSTANT;
    1546               3 :     field_type = ODS_FIELD_TYPE_STRING;
    1547               3 :     string_value = CPLStrdup(osVal.c_str());
    1548                 : 
    1549               3 :     FreeSubExpr();
    1550                 : 
    1551               3 :     return TRUE;
    1552                 : }
    1553                 : 
    1554                 : /************************************************************************/
    1555                 : /*                           EvaluateMID()                             */
    1556                 : /************************************************************************/
    1557                 : 
    1558               8 : int ods_formula_node::EvaluateMID(IODSCellEvaluator* poEvaluator)
    1559                 : {
    1560               8 :     CPLAssert( eNodeType == SNT_OPERATION );
    1561                 : 
    1562               8 :     CPLAssert(nSubExprCount == 3);
    1563               8 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1564               0 :         return FALSE;
    1565               8 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1566               0 :         return FALSE;
    1567               8 :     if (!(papoSubExpr[2]->Evaluate(poEvaluator)))
    1568               0 :         return FALSE;
    1569                 : 
    1570               8 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1571               8 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1572               8 :     CPLAssert(papoSubExpr[2]->eNodeType == SNT_CONSTANT );
    1573                 : 
    1574               8 :     std::string osVal = papoSubExpr[0]->TransformToString();
    1575                 : 
    1576               8 :     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
    1577               0 :         return FALSE;
    1578                 : 
    1579               8 :     if (papoSubExpr[2]->field_type != ODS_FIELD_TYPE_INTEGER)
    1580               0 :         return FALSE;
    1581                 : 
    1582                 :     // FIXME : UTF8 support
    1583               8 :     size_t nLen = osVal.size();
    1584               8 :     int nStart = papoSubExpr[1]->int_value;
    1585               8 :     int nExtractLen = papoSubExpr[2]->int_value;
    1586               8 :     if (nStart <= 0)
    1587               1 :         return FALSE;
    1588               7 :     if (nExtractLen < 0)
    1589               0 :         return FALSE;
    1590                 : 
    1591               7 :     if ((size_t)nStart <= nLen)
    1592                 :     {
    1593               6 :         if (nStart-1 + nExtractLen >= (int)nLen)
    1594               3 :             osVal = osVal.substr(nStart - 1);
    1595                 :         else
    1596               3 :             osVal = osVal.substr(nStart - 1, nExtractLen);
    1597                 :     }
    1598                 :     else
    1599               1 :         osVal = "";
    1600                 : 
    1601               7 :     eNodeType = SNT_CONSTANT;
    1602               7 :     field_type = ODS_FIELD_TYPE_STRING;
    1603               7 :     string_value = CPLStrdup(osVal.c_str());
    1604                 : 
    1605               7 :     FreeSubExpr();
    1606                 : 
    1607               7 :     return TRUE;
    1608                 : }

Generated by: LCOV version 1.7