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-04-28 Functions: 43 34 79.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: ods_formula_node.cpp 23831 2012-01-30 23:12:23Z 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              12 : ods_formula_node::ods_formula_node()
      44                 : 
      45                 : {
      46              12 :     Initialize();
      47              12 : }
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                         ods_formula_node(int)                        */
      51                 : /************************************************************************/
      52                 : 
      53             220 : ods_formula_node::ods_formula_node( int nValueIn )
      54                 : 
      55                 : {
      56             220 :     Initialize();
      57                 : 
      58             220 :     field_type = ODS_FIELD_TYPE_INTEGER;
      59             220 :     int_value = nValueIn;
      60             220 : }
      61                 : 
      62                 : /************************************************************************/
      63                 : /*                      ods_formula_node(double)                        */
      64                 : /************************************************************************/
      65                 : 
      66             124 : ods_formula_node::ods_formula_node( double dfValueIn )
      67                 : 
      68                 : {
      69             124 :     Initialize();
      70                 : 
      71             124 :     field_type = ODS_FIELD_TYPE_FLOAT;
      72             124 :     float_value = dfValueIn;
      73             124 : }
      74                 : 
      75                 : /************************************************************************/
      76                 : /*                       ods_formula_node(const char*)                  */
      77                 : /************************************************************************/
      78                 : 
      79             194 : ods_formula_node::ods_formula_node( const char *pszValueIn,
      80                 :                                     ods_formula_field_type field_type_in )
      81                 : 
      82                 : {
      83             194 :     Initialize();
      84                 : 
      85             194 :     field_type = field_type_in;
      86             194 :     string_value = CPLStrdup( pszValueIn ? pszValueIn : "" );
      87             194 : }
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                        ods_formula_node(ods_formula_op)              */
      91                 : /************************************************************************/
      92                 : 
      93             334 : ods_formula_node::ods_formula_node( ods_formula_op eOpIn )
      94                 : 
      95                 : {
      96             334 :     Initialize();
      97                 : 
      98             334 :     eNodeType = SNT_OPERATION;
      99                 : 
     100             334 :     eOp = eOpIn;
     101             334 : }
     102                 : 
     103                 : /************************************************************************/
     104                 : /*              ods_formula_node(const ods_formula_node&)               */
     105                 : /************************************************************************/
     106                 : 
     107             122 : ods_formula_node::ods_formula_node( const ods_formula_node& other )
     108                 : {
     109             122 :     eNodeType = other.eNodeType;
     110             122 :     eOp = other.eOp;
     111             122 :     field_type = other.field_type;
     112             122 :     int_value = other.int_value;
     113             122 :     float_value = other.float_value;
     114             122 :     string_value = other.string_value ? CPLStrdup(other.string_value) : NULL;
     115             122 :     nSubExprCount = other.nSubExprCount;
     116             122 :     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             122 :         papoSubExpr = NULL;
     127             122 : }
     128                 : 
     129                 : /************************************************************************/
     130                 : /*                             Initialize()                             */
     131                 : /************************************************************************/
     132                 : 
     133             884 : void ods_formula_node::Initialize()
     134                 : 
     135                 : {
     136             884 :     eNodeType = SNT_CONSTANT;
     137             884 :     field_type = ODS_FIELD_TYPE_EMPTY;
     138             884 :     int_value = 0;
     139             884 :     float_value = 0;
     140             884 :     string_value = NULL;
     141             884 :     papoSubExpr = NULL;
     142             884 :     nSubExprCount = 0;
     143             884 : }
     144                 : 
     145                 : /************************************************************************/
     146                 : /*                          ~ods_formula_node()                         */
     147                 : /************************************************************************/
     148                 : 
     149            1006 : ods_formula_node::~ods_formula_node()
     150                 : 
     151                 : {
     152            1006 :     CPLFree( string_value );
     153            1006 :     FreeSubExpr();
     154            1006 : }
     155                 : 
     156                 : /************************************************************************/
     157                 : /*                         PushSubExpression()                          */
     158                 : /************************************************************************/
     159                 : 
     160             566 : void ods_formula_node::PushSubExpression( ods_formula_node *child )
     161                 : 
     162                 : {
     163             566 :     nSubExprCount++;
     164                 :     papoSubExpr = (ods_formula_node **)
     165             566 :         CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount );
     166                 : 
     167             566 :     papoSubExpr[nSubExprCount-1] = child;
     168             566 : }
     169                 : 
     170                 : /************************************************************************/
     171                 : /*                       ReverseSubExpressions()                        */
     172                 : /************************************************************************/
     173                 : 
     174              28 : void ods_formula_node::ReverseSubExpressions()
     175                 : 
     176                 : {
     177                 :     int i;
     178              46 :     for( i = 0; i < nSubExprCount / 2; i++ )
     179                 :     {
     180                 :         ods_formula_node *temp;
     181                 : 
     182              18 :         temp = papoSubExpr[i];
     183              18 :         papoSubExpr[i] = papoSubExpr[nSubExprCount - i - 1];
     184              18 :         papoSubExpr[nSubExprCount - i - 1] = temp;
     185                 :     }
     186              28 : }
     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            1278 : void  ods_formula_node::FreeSubExpr()
     281                 : {
     282                 :     int i;
     283            1844 :     for( i = 0; i < nSubExprCount; i++ )
     284             566 :         delete papoSubExpr[i];
     285            1278 :     CPLFree( papoSubExpr );
     286                 : 
     287            1278 :     nSubExprCount = 0;
     288            1278 :     papoSubExpr = NULL;
     289            1278 : }
     290                 : 
     291                 : /************************************************************************/
     292                 : /*                              Evaluate()                              */
     293                 : /************************************************************************/
     294                 : 
     295             678 : int ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
     296                 : {
     297             678 :     if (eNodeType == SNT_CONSTANT)
     298             384 :         return TRUE;
     299                 : 
     300             294 :     CPLAssert( eNodeType == SNT_OPERATION );
     301                 : 
     302             294 :     switch (eOp)
     303                 :     {
     304               8 :         case ODS_OR: return EvaluateOR(poEvaluator);
     305               8 :         case ODS_AND: return EvaluateAND(poEvaluator);
     306               4 :         case ODS_NOT: return EvaluateNOT(poEvaluator);
     307               8 :         case ODS_IF: return EvaluateIF(poEvaluator);
     308                 : 
     309                 :         case ODS_PI:
     310               2 :             eNodeType = SNT_CONSTANT;
     311               2 :             field_type = ODS_FIELD_TYPE_FLOAT;
     312               2 :             float_value = PI;
     313               2 :             return TRUE;
     314                 : 
     315               2 :         case ODS_LEN : return EvaluateLEN(poEvaluator);
     316               6 :         case ODS_LEFT : return EvaluateLEFT(poEvaluator);
     317               6 :         case ODS_RIGHT : return EvaluateRIGHT(poEvaluator);
     318              16 :         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              12 :             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              18 :             return EvaluateSingleArgOp(poEvaluator);
     340                 : 
     341                 : 
     342              20 :         case ODS_EQ: return EvaluateEQ(poEvaluator);
     343              20 :         case ODS_NE: return EvaluateNE(poEvaluator);
     344              20 :         case ODS_LE: return EvaluateLE(poEvaluator);
     345              20 :         case ODS_GE: return EvaluateGE(poEvaluator);
     346              28 :         case ODS_LT: return EvaluateLT(poEvaluator);
     347              20 :         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              18 :             return EvaluateBinaryArithmetic(poEvaluator);
     355                 : 
     356               2 :         case ODS_CONCAT: return EvaluateCONCAT(poEvaluator);
     357                 : 
     358              56 :         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               8 : int ods_formula_node::EvaluateOR(IODSCellEvaluator* poEvaluator)
     375                 : {
     376               8 :     CPLAssert( eNodeType == SNT_OPERATION );
     377               8 :     CPLAssert( eOp == ODS_OR );
     378                 : 
     379               8 :     CPLAssert(nSubExprCount == 1);
     380               8 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_OPERATION );
     381               8 :     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
     382               8 :     int bVal = FALSE;
     383              24 :     for(int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
     384                 :     {
     385              16 :         if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
     386               0 :             return FALSE;
     387              16 :         CPLAssert(papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
     388              16 :         if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
     389                 :         {
     390              16 :             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               8 :     FreeSubExpr();
     405                 : 
     406               8 :     eNodeType = SNT_CONSTANT;
     407               8 :     field_type = ODS_FIELD_TYPE_INTEGER;
     408               8 :     int_value = bVal;
     409                 : 
     410               8 :     return TRUE;
     411                 : }
     412                 : 
     413                 : /************************************************************************/
     414                 : /*                            EvaluateAND()                             */
     415                 : /************************************************************************/
     416                 : 
     417               8 : int ods_formula_node::EvaluateAND(IODSCellEvaluator* poEvaluator)
     418                 : {
     419               8 :     CPLAssert( eNodeType == SNT_OPERATION );
     420               8 :     CPLAssert( eOp == ODS_AND );
     421                 : 
     422               8 :     CPLAssert(nSubExprCount == 1);
     423               8 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_OPERATION );
     424               8 :     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
     425               8 :     int bVal = TRUE;
     426              24 :     for(int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
     427                 :     {
     428              16 :         if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
     429               0 :             return FALSE;
     430              16 :         CPLAssert(papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
     431              16 :         if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
     432                 :         {
     433              16 :             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               8 :     FreeSubExpr();
     448                 : 
     449               8 :     eNodeType = SNT_CONSTANT;
     450               8 :     field_type = ODS_FIELD_TYPE_INTEGER;
     451               8 :     int_value = bVal;
     452                 : 
     453               8 :     return TRUE;
     454                 : }
     455                 : 
     456                 : /************************************************************************/
     457                 : /*                            EvaluateNOT()                             */
     458                 : /************************************************************************/
     459                 : 
     460               4 : int ods_formula_node::EvaluateNOT(IODSCellEvaluator* poEvaluator)
     461                 : {
     462               4 :     CPLAssert( eNodeType == SNT_OPERATION );
     463               4 :     CPLAssert( eOp == ODS_NOT );
     464                 : 
     465               4 :     CPLAssert(nSubExprCount == 1);
     466               4 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     467               0 :         return FALSE;
     468               4 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     469                 : 
     470               4 :     int bVal = FALSE;
     471               4 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     472                 :     {
     473               4 :         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               4 :     FreeSubExpr();
     487                 : 
     488               4 :     eNodeType = SNT_CONSTANT;
     489               4 :     field_type = ODS_FIELD_TYPE_INTEGER;
     490               4 :     int_value = bVal;
     491                 : 
     492               4 :     return TRUE;
     493                 : }
     494                 : 
     495                 : /************************************************************************/
     496                 : /*                            EvaluateIF()                              */
     497                 : /************************************************************************/
     498                 : 
     499               8 : int ods_formula_node::EvaluateIF(IODSCellEvaluator* poEvaluator)
     500                 : {
     501               8 :     CPLAssert( eNodeType == SNT_OPERATION );
     502               8 :     CPLAssert( eOp == ODS_IF );
     503                 : 
     504               8 :     CPLAssert(nSubExprCount == 2 || nSubExprCount == 3);
     505               8 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     506               0 :         return FALSE;
     507               8 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     508               0 :         return FALSE;
     509               8 :     if (nSubExprCount == 3 && !(papoSubExpr[2]->Evaluate(poEvaluator)))
     510               0 :         return FALSE;
     511                 : 
     512               8 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     513               8 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     514               8 :     if (nSubExprCount == 3)
     515               4 :         CPLAssert(papoSubExpr[2]->eNodeType == SNT_CONSTANT );
     516                 : 
     517               8 :     int bCond = FALSE;
     518               8 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     519                 :     {
     520               8 :         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               8 :     if (bCond)
     534                 :     {
     535               4 :         eNodeType = SNT_CONSTANT;
     536               4 :         field_type = papoSubExpr[1]->field_type;
     537               4 :         if (field_type == ODS_FIELD_TYPE_INTEGER)
     538               4 :             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               4 :     else if (nSubExprCount == 3)
     548                 :     {
     549               2 :         eNodeType = SNT_CONSTANT;
     550               2 :         field_type = papoSubExpr[2]->field_type;
     551               2 :         if (field_type == ODS_FIELD_TYPE_INTEGER)
     552               2 :             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               2 :         eNodeType = SNT_CONSTANT;
     564               2 :         field_type = ODS_FIELD_TYPE_INTEGER;
     565               2 :         int_value = FALSE;
     566                 :     }
     567                 : 
     568               8 :     FreeSubExpr();
     569                 : 
     570               8 :     return TRUE;
     571                 : }
     572                 : 
     573                 : /************************************************************************/
     574                 : /*                            EvaluateEQ()                              */
     575                 : /************************************************************************/
     576                 : 
     577              40 : int ods_formula_node::EvaluateEQ(IODSCellEvaluator* poEvaluator)
     578                 : {
     579              40 :     CPLAssert( eNodeType == SNT_OPERATION );
     580              40 :     CPLAssert( eOp == ODS_EQ );
     581                 : 
     582              40 :     CPLAssert(nSubExprCount == 2);
     583              40 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     584               0 :         return FALSE;
     585              40 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     586               0 :         return FALSE;
     587                 : 
     588              40 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     589              40 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     590                 : 
     591              40 :     int bVal = FALSE;
     592              40 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     593                 :     {
     594              16 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     595                 :         {
     596               8 :             bVal = (papoSubExpr[0]->int_value == papoSubExpr[1]->int_value);
     597                 :         }
     598               8 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     599                 :         {
     600               8 :             bVal = (papoSubExpr[0]->int_value == papoSubExpr[1]->float_value);
     601                 :         }
     602                 :     }
     603              24 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     604                 :     {
     605              16 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     606                 :         {
     607               8 :             bVal = (papoSubExpr[0]->float_value == papoSubExpr[1]->int_value);
     608                 :         }
     609               8 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     610                 :         {
     611               8 :             bVal = (papoSubExpr[0]->float_value == papoSubExpr[1]->float_value);
     612                 :         }
     613                 :     }
     614               8 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     615                 :     {
     616               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     617                 :         {
     618               8 :             bVal = (strcmp(papoSubExpr[0]->string_value,
     619              16 :                            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              40 :     eNodeType = SNT_CONSTANT;
     630              40 :     field_type = ODS_FIELD_TYPE_INTEGER;
     631              40 :     int_value = bVal;
     632                 : 
     633              40 :     FreeSubExpr();
     634                 : 
     635              40 :     return TRUE;
     636                 : }
     637                 : 
     638                 : /************************************************************************/
     639                 : /*                           EvaluateNE()                               */
     640                 : /************************************************************************/
     641                 : 
     642              20 : int ods_formula_node::EvaluateNE(IODSCellEvaluator* poEvaluator)
     643                 : {
     644              20 :     CPLAssert( eNodeType == SNT_OPERATION );
     645              20 :     CPLAssert( eOp == ODS_NE );
     646                 : 
     647              20 :     eOp = ODS_EQ;
     648              20 :     if (!EvaluateEQ(poEvaluator))
     649               0 :         return FALSE;
     650                 : 
     651              20 :     int_value = !int_value;
     652              20 :     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              48 : static CaseType GetCase(const char* pszStr)
     667                 : {
     668              48 :     int bInit = TRUE;
     669                 :     char ch;
     670              48 :     CaseType eCase = CASE_UNKNOWN;
     671             144 :     while((ch = *(pszStr++)) != '\0')
     672                 :     {
     673              48 :         if (bInit)
     674                 :         {
     675              56 :             if (ch >= 'a' && ch <= 'z')
     676               8 :                 eCase = CASE_LOWER;
     677              80 :             else if (ch >= 'A' && ch <= 'Z')
     678              40 :                 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              48 :     return eCase;
     690                 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                            EvaluateLE()                              */
     694                 : /************************************************************************/
     695                 : 
     696              20 : int ods_formula_node::EvaluateLE(IODSCellEvaluator* poEvaluator)
     697                 : {
     698              20 :     CPLAssert( eNodeType == SNT_OPERATION );
     699              20 :     CPLAssert( eOp == ODS_LE );
     700                 : 
     701              20 :     CPLAssert(nSubExprCount == 2);
     702              20 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     703               0 :         return FALSE;
     704              20 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     705               0 :         return FALSE;
     706                 : 
     707              20 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     708              20 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     709                 : 
     710              20 :     int bVal = FALSE;
     711              20 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     712                 :     {
     713               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     714                 :         {
     715               4 :             bVal = (papoSubExpr[0]->int_value <= papoSubExpr[1]->int_value);
     716                 :         }
     717               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     718                 :         {
     719               4 :             bVal = (papoSubExpr[0]->int_value <= papoSubExpr[1]->float_value);
     720                 :         }
     721                 :         else
     722               0 :             bVal = TRUE;
     723                 :     }
     724              12 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     725                 :     {
     726               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     727                 :         {
     728               4 :             bVal = (papoSubExpr[0]->float_value <= papoSubExpr[1]->int_value);
     729                 :         }
     730               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     731                 :         {
     732               4 :             bVal = (papoSubExpr[0]->float_value <= papoSubExpr[1]->float_value);
     733                 :         }
     734                 :         else
     735               0 :             bVal = TRUE;
     736                 :     }
     737               4 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     738                 :     {
     739               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     740                 :         {
     741               8 :             if (GetCase(papoSubExpr[0]->string_value) ==
     742               4 :                 GetCase(papoSubExpr[1]->string_value))
     743               4 :                 bVal = (strcmp(papoSubExpr[0]->string_value,
     744               8 :                                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              20 :     eNodeType = SNT_CONSTANT;
     758              20 :     field_type = ODS_FIELD_TYPE_INTEGER;
     759              20 :     int_value = bVal;
     760                 : 
     761              20 :     FreeSubExpr();
     762                 : 
     763              20 :     return TRUE;
     764                 : }
     765                 : 
     766                 : /************************************************************************/
     767                 : /*                            EvaluateGE()                              */
     768                 : /************************************************************************/
     769                 : 
     770              20 : int ods_formula_node::EvaluateGE(IODSCellEvaluator* poEvaluator)
     771                 : {
     772              20 :     CPLAssert( eNodeType == SNT_OPERATION );
     773              20 :     CPLAssert( eOp == ODS_GE );
     774                 : 
     775              20 :     CPLAssert(nSubExprCount == 2);
     776              20 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     777               0 :         return FALSE;
     778              20 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     779               0 :         return FALSE;
     780                 : 
     781              20 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     782              20 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     783                 : 
     784              20 :     int bVal = FALSE;
     785              20 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     786                 :     {
     787               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     788                 :         {
     789               4 :             bVal = (papoSubExpr[0]->int_value >= papoSubExpr[1]->int_value);
     790                 :         }
     791               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     792                 :         {
     793               4 :             bVal = (papoSubExpr[0]->int_value >= papoSubExpr[1]->float_value);
     794                 :         }
     795                 :     }
     796              12 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     797                 :     {
     798               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     799                 :         {
     800               4 :             bVal = (papoSubExpr[0]->float_value >= papoSubExpr[1]->int_value);
     801                 :         }
     802               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     803                 :         {
     804               4 :             bVal = (papoSubExpr[0]->float_value >= papoSubExpr[1]->float_value);
     805                 :         }
     806                 :     }
     807               4 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     808                 :     {
     809               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     810                 :         {
     811               8 :             if (GetCase(papoSubExpr[0]->string_value) ==
     812               4 :                 GetCase(papoSubExpr[1]->string_value))
     813               4 :                 bVal = (strcmp(papoSubExpr[0]->string_value,
     814               8 :                                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              20 :     eNodeType = SNT_CONSTANT;
     830              20 :     field_type = ODS_FIELD_TYPE_INTEGER;
     831              20 :     int_value = bVal;
     832                 : 
     833              20 :     FreeSubExpr();
     834                 : 
     835              20 :     return TRUE;
     836                 : }
     837                 : 
     838                 : /************************************************************************/
     839                 : /*                            EvaluateLT()                              */
     840                 : /************************************************************************/
     841                 : 
     842              28 : int ods_formula_node::EvaluateLT(IODSCellEvaluator* poEvaluator)
     843                 : {
     844              28 :     CPLAssert( eNodeType == SNT_OPERATION );
     845              28 :     CPLAssert( eOp == ODS_LT );
     846                 : 
     847              28 :     CPLAssert(nSubExprCount == 2);
     848              28 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     849               0 :         return FALSE;
     850              28 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     851               0 :         return FALSE;
     852                 : 
     853              28 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     854              28 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     855                 : 
     856              28 :     int bVal = FALSE;
     857              28 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     858                 :     {
     859               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     860                 :         {
     861               4 :             bVal = (papoSubExpr[0]->int_value < papoSubExpr[1]->int_value);
     862                 :         }
     863               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     864                 :         {
     865               4 :             bVal = (papoSubExpr[0]->int_value < papoSubExpr[1]->float_value);
     866                 :         }
     867                 :         else
     868               0 :             bVal = TRUE;
     869                 :     }
     870              20 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     871                 :     {
     872               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     873                 :         {
     874               4 :             bVal = (papoSubExpr[0]->float_value < papoSubExpr[1]->int_value);
     875                 :         }
     876               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     877                 :         {
     878               4 :             bVal = (papoSubExpr[0]->float_value < papoSubExpr[1]->float_value);
     879                 :         }
     880                 :         else
     881               0 :             bVal = TRUE;
     882                 :     }
     883              12 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     884                 :     {
     885              12 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     886                 :         {
     887              24 :             if (GetCase(papoSubExpr[0]->string_value) ==
     888              12 :                 GetCase(papoSubExpr[1]->string_value))
     889               4 :                 bVal = (strcmp(papoSubExpr[0]->string_value,
     890               8 :                                papoSubExpr[1]->string_value) < 0);
     891                 :             else
     892               8 :                 bVal = (strcasecmp(papoSubExpr[0]->string_value,
     893              16 :                                    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              28 :     eNodeType = SNT_CONSTANT;
     904              28 :     field_type = ODS_FIELD_TYPE_INTEGER;
     905              28 :     int_value = bVal;
     906                 : 
     907              28 :     FreeSubExpr();
     908                 : 
     909              28 :     return TRUE;
     910                 : }
     911                 : 
     912                 : /************************************************************************/
     913                 : /*                            EvaluateGT()                              */
     914                 : /************************************************************************/
     915                 : 
     916              20 : int ods_formula_node::EvaluateGT(IODSCellEvaluator* poEvaluator)
     917                 : {
     918              20 :     CPLAssert( eNodeType == SNT_OPERATION );
     919              20 :     CPLAssert( eOp == ODS_GT );
     920                 : 
     921              20 :     CPLAssert(nSubExprCount == 2);
     922              20 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     923               0 :         return FALSE;
     924              20 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
     925               0 :         return FALSE;
     926                 : 
     927              20 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     928              20 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
     929                 : 
     930              20 :     int bVal = FALSE;
     931              20 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
     932                 :     {
     933               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     934                 :         {
     935               4 :             bVal = (papoSubExpr[0]->int_value > papoSubExpr[1]->int_value);
     936                 :         }
     937               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     938                 :         {
     939               4 :             bVal = (papoSubExpr[0]->int_value > papoSubExpr[1]->float_value);
     940                 :         }
     941                 :     }
     942              12 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
     943                 :     {
     944               8 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
     945                 :         {
     946               4 :             bVal = (papoSubExpr[0]->float_value > papoSubExpr[1]->int_value);
     947                 :         }
     948               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
     949                 :         {
     950               4 :             bVal = (papoSubExpr[0]->float_value > papoSubExpr[1]->float_value);
     951                 :         }
     952                 :     }
     953               4 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING)
     954                 :     {
     955               4 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING)
     956                 :         {
     957               8 :             if (GetCase(papoSubExpr[0]->string_value) ==
     958               4 :                 GetCase(papoSubExpr[1]->string_value))
     959               4 :                 bVal = (strcmp(papoSubExpr[0]->string_value,
     960               8 :                                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              20 :     eNodeType = SNT_CONSTANT;
     976              20 :     field_type = ODS_FIELD_TYPE_INTEGER;
     977              20 :     int_value = bVal;
     978                 : 
     979              20 :     FreeSubExpr();
     980                 : 
     981              20 :     return TRUE;
     982                 : }
     983                 : 
     984                 : /************************************************************************/
     985                 : /*                         EvaluateSingleArgOp()                        */
     986                 : /************************************************************************/
     987                 : 
     988              18 : int ods_formula_node::EvaluateSingleArgOp(IODSCellEvaluator* poEvaluator)
     989                 : {
     990              18 :     CPLAssert( eNodeType == SNT_OPERATION );
     991                 : 
     992              18 :     const SingleOpStruct* psSingleOp = ODSGetSingleOpEntry(eOp);
     993              18 :     CPLAssert(psSingleOp);
     994                 : 
     995              18 :     CPLAssert(nSubExprCount == 1);
     996              18 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
     997               0 :         return FALSE;
     998                 : 
     999              18 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1000              18 :     double dfVal = 0;
    1001                 : 
    1002              18 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
    1003                 :     {
    1004               2 :         dfVal = psSingleOp->pfnEval(papoSubExpr[0]->int_value);
    1005                 :     }
    1006              16 :     else if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
    1007                 :     {
    1008              16 :         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              18 :     eNodeType = SNT_CONSTANT;
    1018              18 :     field_type = ODS_FIELD_TYPE_FLOAT;
    1019              18 :     float_value = dfVal;
    1020                 : 
    1021              18 :     FreeSubExpr();
    1022                 : 
    1023              18 :     return TRUE;
    1024                 : }
    1025                 : 
    1026                 : /************************************************************************/
    1027                 : /*                       EvaluateBinaryArithmetic()                     */
    1028                 : /************************************************************************/
    1029                 : 
    1030              18 : int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
    1031                 : {
    1032              18 :     CPLAssert( eNodeType == SNT_OPERATION );
    1033              18 :     CPLAssert( eOp >= ODS_ADD && eOp<= ODS_MODULUS );
    1034                 : 
    1035              18 :     CPLAssert(nSubExprCount == 2);
    1036              18 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1037               0 :         return FALSE;
    1038              18 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1039               0 :         return FALSE;
    1040                 : 
    1041              18 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1042              18 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1043                 : 
    1044              18 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_INTEGER)
    1045                 :     {
    1046              12 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
    1047                 :         {
    1048                 :             int nVal;
    1049               8 :             switch (eOp)
    1050                 :             {
    1051               2 :                 case ODS_ADD      : nVal = (papoSubExpr[0]->int_value + papoSubExpr[1]->int_value); break;
    1052               2 :                 case ODS_SUBTRACT : nVal = (papoSubExpr[0]->int_value - papoSubExpr[1]->int_value); break;
    1053               2 :                 case ODS_MULTIPLY : nVal = (papoSubExpr[0]->int_value * papoSubExpr[1]->int_value); break;
    1054                 :                 case ODS_DIVIDE   :
    1055               2 :                     if (papoSubExpr[1]->int_value != 0)
    1056               2 :                         nVal = (papoSubExpr[0]->int_value / papoSubExpr[1]->int_value);
    1057                 :                     else
    1058               0 :                         return FALSE;
    1059               2 :                     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: CPLAssert(0);
    1067                 :             }
    1068                 : 
    1069               8 :             eNodeType = SNT_CONSTANT;
    1070               8 :             field_type = ODS_FIELD_TYPE_INTEGER;
    1071               8 :             int_value = nVal;
    1072                 : 
    1073               8 :             FreeSubExpr();
    1074                 : 
    1075               8 :             return TRUE;
    1076                 :         }
    1077               4 :         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
    1078                 :         {
    1079               4 :             papoSubExpr[0]->field_type = ODS_FIELD_TYPE_FLOAT;
    1080               4 :             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              10 :     if (papoSubExpr[0]->field_type == ODS_FIELD_TYPE_FLOAT)
    1091                 :     {
    1092              10 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_INTEGER)
    1093                 :         {
    1094               4 :             papoSubExpr[1]->field_type = ODS_FIELD_TYPE_FLOAT;
    1095               4 :             papoSubExpr[1]->float_value = papoSubExpr[1]->int_value;
    1096                 :         }
    1097                 : 
    1098              10 :         if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
    1099                 :         {
    1100                 :             float dfVal;
    1101              10 :             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               6 :                 case ODS_MULTIPLY : dfVal = (papoSubExpr[0]->float_value * papoSubExpr[1]->float_value); break;
    1106                 :                 case ODS_DIVIDE   :
    1107               2 :                     if (papoSubExpr[1]->float_value != 0)
    1108               2 :                         dfVal = (papoSubExpr[0]->float_value / papoSubExpr[1]->float_value);
    1109                 :                     else
    1110               0 :                         return FALSE;
    1111               2 :                     break;
    1112                 :                 case ODS_MODULUS  :
    1113               2 :                     if (papoSubExpr[1]->float_value != 0)
    1114               2 :                         dfVal = fmod(papoSubExpr[0]->float_value, papoSubExpr[1]->float_value);
    1115                 :                     else
    1116               0 :                         return FALSE;
    1117               2 :                     break;
    1118               0 :                 default: CPLAssert(0);
    1119                 :             }
    1120                 : 
    1121              10 :             eNodeType = SNT_CONSTANT;
    1122              10 :             field_type = ODS_FIELD_TYPE_FLOAT;
    1123              10 :             float_value = dfVal;
    1124                 : 
    1125              10 :             FreeSubExpr();
    1126                 : 
    1127              10 :             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              34 : std::string ods_formula_node::TransformToString() const
    1150                 : {
    1151                 :     char szTmp[128];
    1152              34 :     if (field_type == ODS_FIELD_TYPE_INTEGER)
    1153                 :     {
    1154               0 :         snprintf(szTmp, sizeof(szTmp), "%d", int_value);
    1155               0 :         return szTmp;
    1156                 :     }
    1157              34 :     else if (field_type == ODS_FIELD_TYPE_FLOAT)
    1158                 :     {
    1159               0 :         snprintf(szTmp, sizeof(szTmp), "%.16g", float_value);
    1160               0 :         return szTmp;
    1161                 :     }
    1162              34 :     else if (field_type == ODS_FIELD_TYPE_STRING)
    1163                 :     {
    1164              34 :         return string_value;
    1165                 :     }
    1166                 :     else
    1167                 :     {
    1168               0 :         return "";
    1169                 :     }
    1170                 : }
    1171                 : 
    1172                 : /************************************************************************/
    1173                 : /*                           EvaluateCONCAT()                           */
    1174                 : /************************************************************************/
    1175                 : 
    1176               2 : int ods_formula_node::EvaluateCONCAT(IODSCellEvaluator* poEvaluator)
    1177                 : {
    1178               2 :     CPLAssert( eNodeType == SNT_OPERATION );
    1179               2 :     CPLAssert( eOp == ODS_CONCAT );
    1180                 : 
    1181               2 :     CPLAssert(nSubExprCount == 2);
    1182               2 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1183               0 :         return FALSE;
    1184               2 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1185               0 :         return FALSE;
    1186                 : 
    1187               2 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1188               2 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1189                 : 
    1190               2 :     std::string osLeft(papoSubExpr[0]->TransformToString());
    1191               2 :     std::string osRight(papoSubExpr[1]->TransformToString());
    1192                 : 
    1193               2 :     eNodeType = SNT_CONSTANT;
    1194               2 :     field_type = ODS_FIELD_TYPE_STRING;
    1195               2 :     string_value = CPLStrdup((osLeft + osRight).c_str());
    1196                 : 
    1197               2 :     FreeSubExpr();
    1198                 : 
    1199               2 :     return TRUE;
    1200                 : }
    1201                 : 
    1202                 : /************************************************************************/
    1203                 : /*                             GetRowCol()                              */
    1204                 : /************************************************************************/
    1205                 : 
    1206              80 : static int GetRowCol(const char* pszCell, int& nRow, int& nCol)
    1207                 : {
    1208                 :     int i;
    1209                 : 
    1210              80 :     if (pszCell[0] != '.')
    1211                 :     {
    1212                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1213               0 :                  "Invalid cell %s", pszCell);
    1214               0 :         return FALSE;
    1215                 :     }
    1216                 : 
    1217              80 :     nCol = 0;
    1218             160 :     for(i=1; pszCell[i]>='A' && pszCell[i]<='Z';i++)
    1219                 :     {
    1220              80 :         nCol = nCol * 26 + (pszCell[i] - 'A');
    1221                 :     }
    1222              80 :     nRow = atoi(pszCell + i) - 1;
    1223                 : 
    1224              80 :     return TRUE;
    1225                 : }
    1226                 : 
    1227                 : /************************************************************************/
    1228                 : /*                         EvaluateListArgOp()                          */
    1229                 : /************************************************************************/
    1230                 : 
    1231              12 : int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
    1232                 : {
    1233              12 :     CPLAssert( eNodeType == SNT_OPERATION );
    1234              12 :     CPLAssert( eOp >= ODS_SUM && eOp <= ODS_COUNTA );
    1235                 : 
    1236              12 :     CPLAssert(nSubExprCount == 1);
    1237              12 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_OPERATION );
    1238              12 :     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
    1239                 : 
    1240              12 :     std::vector<double> adfVal;
    1241                 :     int i;
    1242                 : 
    1243              12 :     int nCount = 0, nCountA = 0;
    1244                 : 
    1245              26 :     for(i=0;i<papoSubExpr[0]->nSubExprCount;i++)
    1246                 :     {
    1247              38 :         if (papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_OPERATION &&
    1248              12 :             papoSubExpr[0]->papoSubExpr[i]->eOp == ODS_CELL_RANGE)
    1249                 :         {
    1250              12 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->nSubExprCount == 2);
    1251              12 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[0]->eNodeType == SNT_CONSTANT);
    1252              12 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING);
    1253              12 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[1]->eNodeType == SNT_CONSTANT);
    1254              12 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[1]->field_type == ODS_FIELD_TYPE_STRING);
    1255                 : 
    1256              12 :             if (poEvaluator == NULL)
    1257                 :             {
    1258               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "No cell evaluator provided");
    1259               0 :                 return FALSE;
    1260                 :             }
    1261                 : 
    1262              12 :             const char* psz1 = papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[0]->string_value;
    1263              12 :             const char* psz2 = papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[1]->string_value;
    1264              12 :             int nRow1 = 0,nCol1 = 0;
    1265              12 :             if (!GetRowCol(psz1, nRow1, nCol1))
    1266               0 :                 return FALSE;
    1267              12 :             int nRow2 = 0,nCol2 = 0;
    1268              12 :             if (!GetRowCol(psz2, nRow2, nCol2))
    1269               0 :                 return FALSE;
    1270                 : 
    1271              12 :             std::vector<ods_formula_node> aoOutValues;
    1272              12 :             if (poEvaluator->EvaluateRange(nRow1, nCol1, nRow2, nCol2, aoOutValues))
    1273                 :             {
    1274              60 :                 for(size_t j = 0; j < aoOutValues.size(); j++)
    1275                 :                 {
    1276              48 :                     if (aoOutValues[j].eNodeType == SNT_CONSTANT)
    1277                 :                     {
    1278              48 :                         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              48 :                         else if (aoOutValues[j].field_type == ODS_FIELD_TYPE_FLOAT)
    1285                 :                         {
    1286              24 :                             adfVal.push_back(aoOutValues[j].float_value);
    1287              24 :                             nCount ++;
    1288              24 :                             nCountA ++;
    1289                 :                         }
    1290              24 :                         else if (aoOutValues[j].field_type == ODS_FIELD_TYPE_STRING)
    1291                 :                         {
    1292              12 :                             nCountA ++;
    1293                 :                         }
    1294                 :                     }
    1295                 :                 }
    1296              12 :             }
    1297                 :         }
    1298                 :         else
    1299                 :         {
    1300               2 :             if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
    1301               0 :                 return FALSE;
    1302                 : 
    1303               2 :             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
    1304               2 :             if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
    1305                 :             {
    1306               2 :                 adfVal.push_back(papoSubExpr[0]->papoSubExpr[i]->int_value);
    1307               2 :                 nCount ++;
    1308               2 :                 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              12 :     if (eOp == ODS_COUNT)
    1332                 :     {
    1333               2 :         eNodeType = SNT_CONSTANT;
    1334               2 :         field_type = ODS_FIELD_TYPE_INTEGER;
    1335               2 :         int_value = nCount;
    1336                 : 
    1337               2 :         FreeSubExpr();
    1338               2 :         return TRUE;
    1339                 :     }
    1340                 : 
    1341              10 :     if (eOp == ODS_COUNTA)
    1342                 :     {
    1343               2 :         eNodeType = SNT_CONSTANT;
    1344               2 :         field_type = ODS_FIELD_TYPE_INTEGER;
    1345               2 :         int_value = nCountA;
    1346                 : 
    1347               2 :         FreeSubExpr();
    1348               2 :         return TRUE;
    1349                 :     }
    1350                 : 
    1351               8 :     double dfVal = 0;
    1352                 : 
    1353               8 :     switch(eOp)
    1354                 :     {
    1355                 :         case ODS_SUM:
    1356                 :         {
    1357               6 :             for(i=0;i<(int)adfVal.size();i++)
    1358                 :             {
    1359               4 :                 dfVal += adfVal[i];
    1360                 :             }
    1361               2 :             break;
    1362                 :         }
    1363                 : 
    1364                 :         case ODS_AVERAGE:
    1365                 :         {
    1366               6 :             for(i=0;i<(int)adfVal.size();i++)
    1367                 :             {
    1368               4 :                 dfVal += adfVal[i];
    1369                 :             }
    1370               2 :             dfVal /= adfVal.size();
    1371               2 :             break;
    1372                 :         }
    1373                 : 
    1374                 :         case ODS_MIN:
    1375                 :         {
    1376               2 :             dfVal = (adfVal.size() == 0) ? 0 :adfVal[0];
    1377               6 :             for(i=1;i<(int)adfVal.size();i++)
    1378                 :             {
    1379               4 :                 if (adfVal[i] < dfVal) dfVal = adfVal[i];
    1380                 :             }
    1381               2 :             break;
    1382                 :         }
    1383                 : 
    1384                 :         case ODS_MAX:
    1385                 :         {
    1386               2 :             dfVal = (adfVal.size() == 0) ? 0 :adfVal[0];
    1387               4 :             for(i=1;i<(int)adfVal.size();i++)
    1388                 :             {
    1389               2 :                 if (adfVal[i] > dfVal) dfVal = adfVal[i];
    1390                 :             }
    1391                 :             break;
    1392                 :         }
    1393                 : 
    1394                 :         default:
    1395                 :             break;
    1396                 :     }
    1397                 : 
    1398               8 :     eNodeType = SNT_CONSTANT;
    1399               8 :     field_type = ODS_FIELD_TYPE_FLOAT;
    1400               8 :     float_value = dfVal;
    1401                 : 
    1402               8 :     FreeSubExpr();
    1403                 : 
    1404               8 :     return TRUE;
    1405                 : }
    1406                 : 
    1407                 : /************************************************************************/
    1408                 : /*                           EvaluateCELL()                             */
    1409                 : /************************************************************************/
    1410                 : 
    1411              56 : int ods_formula_node::EvaluateCELL(IODSCellEvaluator* poEvaluator)
    1412                 : {
    1413              56 :     CPLAssert( eNodeType == SNT_OPERATION );
    1414              56 :     CPLAssert( eOp == ODS_CELL );
    1415                 : 
    1416              56 :     CPLAssert(nSubExprCount == 1);
    1417              56 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1418              56 :     CPLAssert(papoSubExpr[0]->field_type == ODS_FIELD_TYPE_STRING );
    1419                 : 
    1420              56 :     if (poEvaluator == NULL)
    1421                 :     {
    1422               0 :         CPLError(CE_Failure, CPLE_AppDefined, "No cell evaluator provided");
    1423               0 :         return FALSE;
    1424                 :     }
    1425                 : 
    1426              56 :     int nRow = 0,nCol = 0;
    1427              56 :     if (!GetRowCol(papoSubExpr[0]->string_value, nRow, nCol))
    1428               0 :         return FALSE;
    1429                 : 
    1430              56 :     std::vector<ods_formula_node> aoOutValues;
    1431              56 :     if (poEvaluator->EvaluateRange(nRow, nCol, nRow, nCol, aoOutValues) &&
    1432                 :         aoOutValues.size() == 1)
    1433                 :     {
    1434              38 :         if (aoOutValues[0].eNodeType == SNT_CONSTANT)
    1435                 :         {
    1436              38 :             FreeSubExpr();
    1437                 : 
    1438              38 :             eNodeType = aoOutValues[0].eNodeType;
    1439              38 :             field_type = aoOutValues[0].field_type;
    1440              38 :             int_value = aoOutValues[0].int_value;
    1441              38 :             float_value = aoOutValues[0].float_value;
    1442              38 :             string_value = aoOutValues[0].string_value ? CPLStrdup(aoOutValues[0].string_value) : NULL;
    1443                 : 
    1444              38 :             return TRUE;
    1445                 :         }
    1446                 :     }
    1447                 : 
    1448              18 :     return FALSE;
    1449                 : }
    1450                 : 
    1451                 : /************************************************************************/
    1452                 : /*                           EvaluateLEN()                              */
    1453                 : /************************************************************************/
    1454                 : 
    1455               2 : int ods_formula_node::EvaluateLEN(IODSCellEvaluator* poEvaluator)
    1456                 : {
    1457               2 :     CPLAssert( eNodeType == SNT_OPERATION );
    1458                 : 
    1459               2 :     CPLAssert(nSubExprCount == 1);
    1460               2 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1461               0 :         return FALSE;
    1462                 : 
    1463               2 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1464                 : 
    1465               2 :     std::string osVal = papoSubExpr[0]->TransformToString();
    1466                 : 
    1467               2 :     eNodeType = SNT_CONSTANT;
    1468               2 :     field_type = ODS_FIELD_TYPE_INTEGER;
    1469               2 :     int_value = strlen(osVal.c_str()); // FIXME : UTF8 support
    1470                 : 
    1471               2 :     FreeSubExpr();
    1472                 : 
    1473               2 :     return TRUE;
    1474                 : }
    1475                 : 
    1476                 : /************************************************************************/
    1477                 : /*                           EvaluateLEFT()                             */
    1478                 : /************************************************************************/
    1479                 : 
    1480               6 : int ods_formula_node::EvaluateLEFT(IODSCellEvaluator* poEvaluator)
    1481                 : {
    1482               6 :     CPLAssert( eNodeType == SNT_OPERATION );
    1483                 : 
    1484               6 :     CPLAssert(nSubExprCount == 2);
    1485               6 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1486               0 :         return FALSE;
    1487               6 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1488               0 :         return FALSE;
    1489                 : 
    1490               6 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1491               6 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1492                 : 
    1493               6 :     std::string osVal = papoSubExpr[0]->TransformToString();
    1494                 : 
    1495               6 :     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
    1496               0 :         return FALSE;
    1497                 : 
    1498                 :     // FIXME : UTF8 support
    1499               6 :     int nVal = papoSubExpr[1]->int_value;
    1500               6 :     if (nVal < 0)
    1501               0 :         return FALSE;
    1502                 : 
    1503               6 :     osVal = osVal.substr(0,nVal);
    1504                 : 
    1505               6 :     eNodeType = SNT_CONSTANT;
    1506               6 :     field_type = ODS_FIELD_TYPE_STRING;
    1507               6 :     string_value = CPLStrdup(osVal.c_str());
    1508                 : 
    1509               6 :     FreeSubExpr();
    1510                 : 
    1511               6 :     return TRUE;
    1512                 : }
    1513                 : 
    1514                 : /************************************************************************/
    1515                 : /*                           EvaluateRIGHT()                            */
    1516                 : /************************************************************************/
    1517                 : 
    1518               6 : int ods_formula_node::EvaluateRIGHT(IODSCellEvaluator* poEvaluator)
    1519                 : {
    1520               6 :     CPLAssert( eNodeType == SNT_OPERATION );
    1521                 : 
    1522               6 :     CPLAssert(nSubExprCount == 2);
    1523               6 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1524               0 :         return FALSE;
    1525               6 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1526               0 :         return FALSE;
    1527                 : 
    1528               6 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1529               6 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1530                 : 
    1531               6 :     std::string osVal = papoSubExpr[0]->TransformToString();
    1532                 : 
    1533               6 :     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
    1534               0 :         return FALSE;
    1535                 : 
    1536                 :     // FIXME : UTF8 support
    1537               6 :     size_t nLen = osVal.size();
    1538               6 :     int nVal = papoSubExpr[1]->int_value;
    1539               6 :     if (nVal < 0)
    1540               0 :         return FALSE;
    1541                 : 
    1542               6 :     if (nLen > (size_t) nVal)
    1543               4 :         osVal = osVal.substr(nLen-nVal);
    1544                 : 
    1545               6 :     eNodeType = SNT_CONSTANT;
    1546               6 :     field_type = ODS_FIELD_TYPE_STRING;
    1547               6 :     string_value = CPLStrdup(osVal.c_str());
    1548                 : 
    1549               6 :     FreeSubExpr();
    1550                 : 
    1551               6 :     return TRUE;
    1552                 : }
    1553                 : 
    1554                 : /************************************************************************/
    1555                 : /*                           EvaluateMID()                             */
    1556                 : /************************************************************************/
    1557                 : 
    1558              16 : int ods_formula_node::EvaluateMID(IODSCellEvaluator* poEvaluator)
    1559                 : {
    1560              16 :     CPLAssert( eNodeType == SNT_OPERATION );
    1561                 : 
    1562              16 :     CPLAssert(nSubExprCount == 3);
    1563              16 :     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
    1564               0 :         return FALSE;
    1565              16 :     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
    1566               0 :         return FALSE;
    1567              16 :     if (!(papoSubExpr[2]->Evaluate(poEvaluator)))
    1568               0 :         return FALSE;
    1569                 : 
    1570              16 :     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
    1571              16 :     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
    1572              16 :     CPLAssert(papoSubExpr[2]->eNodeType == SNT_CONSTANT );
    1573                 : 
    1574              16 :     std::string osVal = papoSubExpr[0]->TransformToString();
    1575                 : 
    1576              16 :     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
    1577               0 :         return FALSE;
    1578                 : 
    1579              16 :     if (papoSubExpr[2]->field_type != ODS_FIELD_TYPE_INTEGER)
    1580               0 :         return FALSE;
    1581                 : 
    1582                 :     // FIXME : UTF8 support
    1583              16 :     size_t nLen = osVal.size();
    1584              16 :     int nStart = papoSubExpr[1]->int_value;
    1585              16 :     int nExtractLen = papoSubExpr[2]->int_value;
    1586              16 :     if (nStart <= 0)
    1587               2 :         return FALSE;
    1588              14 :     if (nExtractLen < 0)
    1589               0 :         return FALSE;
    1590                 : 
    1591              14 :     if ((size_t)nStart <= nLen)
    1592                 :     {
    1593              12 :         if (nStart-1 + nExtractLen >= (int)nLen)
    1594               6 :             osVal = osVal.substr(nStart - 1);
    1595                 :         else
    1596               6 :             osVal = osVal.substr(nStart - 1, nExtractLen);
    1597                 :     }
    1598                 :     else
    1599               2 :         osVal = "";
    1600                 : 
    1601              14 :     eNodeType = SNT_CONSTANT;
    1602              14 :     field_type = ODS_FIELD_TYPE_STRING;
    1603              14 :     string_value = CPLStrdup(osVal.c_str());
    1604                 : 
    1605              14 :     FreeSubExpr();
    1606                 : 
    1607              14 :     return TRUE;
    1608                 : }

Generated by: LCOV version 1.7