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 : }
|