LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/ods - ods_formula_node.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 683 953 71.7 %
Date: 2024-11-21 22:18:42 Functions: 33 35 94.3 %

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

Generated by: LCOV version 1.14