• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GothenburgBitFactory / taskwarrior / 10152339701

29 Jul 2024 09:45PM UTC coverage: 84.437% (+0.07%) from 84.372%
10152339701

push

github

web-flow
Merge pull request #3566 from felixschurk/add-clang-format

Add clang-format to enforce style guide

12359 of 13760 new or added lines in 147 files covered. (89.82%)

123 existing lines in 42 files now uncovered.

19070 of 22585 relevant lines covered (84.44%)

19724.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.91
/src/Variant.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright 2013 - 2021, Tomas Babej, Paul Beckingham, Federico Hernandez.
4
//
5
// Permission is hereby granted, free of charge, to any person obtaining a copy
6
// of this software and associated documentation files (the "Software"), to deal
7
// in the Software without restriction, including without limitation the rights
8
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the Software is
10
// furnished to do so, subject to the following conditions:
11
//
12
// The above copyright notice and this permission notice shall be included
13
// in all copies or substantial portions of the Software.
14
//
15
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
// SOFTWARE.
22
//
23
// https://www.opensource.org/licenses/mit-license.php
24
//
25
////////////////////////////////////////////////////////////////////////////////
26

27
#include <cmake.h>
28
// cmake.h include header must come first
29

30
#include <Datetime.h>
31
#include <Duration.h>
32
#include <Lexer.h>
33
#include <RX.h>
34
#include <Variant.h>
35
#include <math.h>
36
#include <shared.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39

40
#include <algorithm>
41
#include <sstream>
42

43
// These are all error messages generated by the expression evaluator, and are
44
// mostly concerned with how various operators interact with the different
45
// data types.
46
#define STRING_VARIANT_TIME_T "Cannot instantiate this type with a time_t value."
47
#define STRING_VARIANT_EXP_BOOL "Cannot exponentiate Booleans"
48
#define STRING_VARIANT_EXP_NON_INT "Cannot exponentiate to a non-integer power"
49
#define STRING_VARIANT_EXP_STRING "Cannot exponentiate strings"
50
#define STRING_VARIANT_EXP_DATE "Cannot exponentiate dates"
51
#define STRING_VARIANT_EXP_DURATION "Cannot exponentiate durations"
52
#define STRING_VARIANT_SUB_BOOL "Cannot subtract from a Boolean value"
53
#define STRING_VARIANT_SUB_STRING "Cannot subtract strings"
54
#define STRING_VARIANT_SUB_DATE "Cannot subtract a date"
55
#define STRING_VARIANT_ADD_BOOL "Cannot add two Boolean values"
56
#define STRING_VARIANT_ADD_DATE "Cannot add two date values"
57
#define STRING_VARIANT_MUL_BOOL "Cannot multiply Boolean values"
58
#define STRING_VARIANT_MUL_DATE "Cannot multiply date values"
59
#define STRING_VARIANT_MUL_REAL_STR "Cannot multiply real numbers by strings"
60
#define STRING_VARIANT_MUL_STR_REAL "Cannot multiply strings by real numbers"
61
#define STRING_VARIANT_MUL_STR_STR "Cannot multiply strings by strings"
62
#define STRING_VARIANT_MUL_STR_DATE "Cannot multiply strings by dates"
63
#define STRING_VARIANT_MUL_STR_DUR "Cannot multiply strings by durations"
64
#define STRING_VARIANT_MUL_DUR_STR "Cannot multiply durations by strings"
65
#define STRING_VARIANT_MUL_DUR_DATE "Cannot multiply durations by dates"
66
#define STRING_VARIANT_MUL_DUR_DUR "Cannot multiply durations by durations"
67
#define STRING_VARIANT_DIV_BOOL "Cannot divide Boolean values"
68
#define STRING_VARIANT_DIV_INT_BOOL "Cannot divide integers by Boolean values"
69
#define STRING_VARIANT_DIV_ZERO "Cannot divide by zero"
70
#define STRING_VARIANT_DIV_INT_STR "Cannot divide integer by string"
71
#define STRING_VARIANT_DIV_INT_DATE "Cannot divide integer by date values"
72
#define STRING_VARIANT_DIV_REAL_BOOL "Cannot divide real by Boolean"
73
#define STRING_VARIANT_DIV_REAL_STR "Cannot divide real numbers by strings"
74
#define STRING_VARIANT_DIV_REAL_DATE "Cannot divide real numbers by dates"
75
#define STRING_VARIANT_DIV_DUR_BOOL "Cannot divide duration by Boolean"
76
#define STRING_VARIANT_DIV_DUR_STR "Cannot divide durations by strings"
77
#define STRING_VARIANT_DIV_DUR_DATE "Cannot divide durations by dates"
78
#define STRING_VARIANT_DIV_DUR_DUR "Cannot divide durations by durations"
79
#define STRING_VARIANT_MOD_BOOL "Cannot modulo Booleans"
80
#define STRING_VARIANT_MOD_DATE "Cannot modulo date values"
81
#define STRING_VARIANT_MOD_DUR "Cannot modulo duration values"
82
#define STRING_VARIANT_MOD_INT_BOOL "Cannot modulo integer by Boolean"
83
#define STRING_VARIANT_MOD_INT_DATE "Cannot modulo integer by date values"
84
#define STRING_VARIANT_MOD_INT_DUR "Cannot modulo integer by duration values"
85
#define STRING_VARIANT_MOD_INT_STR "Cannot modulo integer by string"
86
#define STRING_VARIANT_MOD_REAL_BOOL "Cannot modulo real by Boolean"
87
#define STRING_VARIANT_MOD_REAL_DUR "Cannot modulo real by duration values"
88
#define STRING_VARIANT_MOD_REAL_DATE "Cannot modulo real numbers by dates"
89
#define STRING_VARIANT_MOD_REAL_STR "Cannot modulo real numbers by strings"
90
#define STRING_VARIANT_MOD_STR "Cannot modulo string values"
91
#define STRING_VARIANT_MOD_ZERO "Cannot modulo zero"
92
#define STRING_VARIANT_SQRT_NEG "Cannot take the square root of a negative number."
93

94
std::string Variant::dateFormat = "";
95
bool Variant::searchCaseSensitive = true;
96
bool Variant::searchUsingRegex = true;
97

98
////////////////////////////////////////////////////////////////////////////////
99
Variant::Variant(const Variant& other) {
146,635✔
100
  _type = other._type;
146,635✔
101
  _bool = other._bool;
146,635✔
102
  _integer = other._integer;
146,635✔
103
  _real = other._real;
146,635✔
104
  _string = other._string;
146,635✔
105
  _date = other._date;
146,635✔
106
  _duration = other._duration;
146,635✔
107
  _source = other._source;
146,635✔
108
}
146,635✔
109

110
////////////////////////////////////////////////////////////////////////////////
111
Variant::Variant(const bool value) : _type(Variant::type_boolean), _bool(value) {}
23,366✔
112

113
////////////////////////////////////////////////////////////////////////////////
114
Variant::Variant(const int value) : _type(Variant::type_integer), _integer(value) {}
9,326✔
115

116
////////////////////////////////////////////////////////////////////////////////
117
Variant::Variant(const double value) : _type(Variant::type_real), _real(value) {}
119✔
118

119
////////////////////////////////////////////////////////////////////////////////
120
Variant::Variant(const std::string& value) : _type(Variant::type_string), _string(value) {}
39,015✔
121

122
////////////////////////////////////////////////////////////////////////////////
123
Variant::Variant(const char* value) : _type(Variant::type_string), _string(value) {}
178✔
124

125
////////////////////////////////////////////////////////////////////////////////
126
Variant::Variant(const time_t value, const enum type new_type) : _type(new_type) {
215✔
127
  switch (new_type) {
215✔
128
    case type_date:
171✔
129
      _date = value;
171✔
130
      break;
171✔
131
    case type_duration:
44✔
132
      _duration = value;
44✔
133
      break;
44✔
NEW
134
    default:
×
NEW
135
      throw std::string(STRING_VARIANT_TIME_T);
×
136
  }
137
}
215✔
138

139
////////////////////////////////////////////////////////////////////////////////
140
void Variant::source(const std::string& input) { _source = input; }
15,660✔
141

142
////////////////////////////////////////////////////////////////////////////////
143
const std::string& Variant::source() const { return _source; }
3,368✔
144

145
////////////////////////////////////////////////////////////////////////////////
146
Variant& Variant::operator=(const Variant& other) = default;
48,441✔
147

148
////////////////////////////////////////////////////////////////////////////////
149
bool Variant::operator&&(const Variant& other) const {
7,084✔
150
  Variant left(*this);
7,084✔
151
  Variant right(other);
7,084✔
152

153
  if (left._type == type_string) Lexer::dequote(left._string);
7,084✔
154

155
  if (right._type == type_string) Lexer::dequote(right._string);
7,084✔
156

157
  left.cast(type_boolean);
7,084✔
158
  right.cast(type_boolean);
7,084✔
159

160
  return left._bool && right._bool;
14,168✔
161
}
7,084✔
162

163
////////////////////////////////////////////////////////////////////////////////
164
bool Variant::operator||(const Variant& other) const {
197✔
165
  Variant left(*this);
197✔
166
  Variant right(other);
197✔
167

168
  if (left._type == type_string) Lexer::dequote(left._string);
197✔
169

170
  if (right._type == type_string) Lexer::dequote(right._string);
197✔
171

172
  left.cast(type_boolean);
197✔
173
  right.cast(type_boolean);
197✔
174

175
  return left._bool || right._bool;
394✔
176
}
197✔
177

178
////////////////////////////////////////////////////////////////////////////////
179
bool Variant::operator_xor(const Variant& other) const {
60✔
180
  Variant left(*this);
60✔
181
  Variant right(other);
60✔
182

183
  if (left._type == type_string) Lexer::dequote(left._string);
60✔
184

185
  if (right._type == type_string) Lexer::dequote(right._string);
60✔
186

187
  left.cast(type_boolean);
60✔
188
  right.cast(type_boolean);
60✔
189

190
  return (left._bool && !right._bool) || (!left._bool && right._bool);
120✔
191
}
60✔
192

193
////////////////////////////////////////////////////////////////////////////////
194
bool Variant::operator<(const Variant& other) const {
115✔
195
  Variant left(*this);
115✔
196
  Variant right(other);
115✔
197

198
  if (left._type == type_string) Lexer::dequote(left._string);
115✔
199

200
  if (right._type == type_string) Lexer::dequote(right._string);
115✔
201

202
  switch (left._type) {
115✔
203
    case type_boolean:
6✔
204
      switch (right._type) {
6✔
205
        case type_boolean:
1✔
206
          return !left._bool && right._bool;
1✔
207
        case type_integer:
1✔
208
          left.cast(type_integer);
1✔
209
          return left._integer < right._integer;
1✔
210
        case type_real:
1✔
211
          left.cast(type_real);
1✔
212
          return left._real < right._real;
1✔
213
        case type_string:
1✔
214
          left.cast(type_string);
1✔
215
          return left._string < right._string;
1✔
216
        case type_date:
1✔
217
          left.cast(type_date);
1✔
218
          return left._date < right._date;
1✔
219
        case type_duration:
1✔
220
          left.cast(type_duration);
1✔
221
          return left._duration < right._duration;
1✔
222
      }
NEW
223
      break;
×
224

225
    case type_integer:
6✔
226
      switch (right._type) {
6✔
227
        case type_boolean:
1✔
228
          right.cast(type_integer);
1✔
229
          return left._integer < right._integer;
1✔
230
        case type_integer:
1✔
231
          return left._integer < right._integer;
1✔
232
        case type_real:
1✔
233
          left.cast(type_real);
1✔
234
          return left._real < right._real;
1✔
235
        case type_string:
1✔
236
          left.cast(type_string);
1✔
237
          return left._string < right._string;
1✔
238
        case type_date:
1✔
239
          left.cast(type_date);
1✔
240
          return left._date < right._date;
1✔
241
        case type_duration:
1✔
242
          left.cast(type_duration);
1✔
243
          return left._duration < right._duration;
1✔
244
      }
NEW
245
      break;
×
246

247
    case type_real:
18✔
248
      switch (right._type) {
18✔
249
        case type_boolean:
1✔
250
          right.cast(type_real);
1✔
251
          return left._real < right._real;
1✔
252
        case type_integer:
3✔
253
          right.cast(type_real);
3✔
254
          return left._real < right._real;
3✔
255
        case type_real:
11✔
256
          return left._real < right._real;
11✔
257
        case type_string:
1✔
258
          left.cast(type_string);
1✔
259
          return left._string < right._string;
1✔
260
        case type_date:
1✔
261
          left.cast(type_date);
1✔
262
          return left._date < right._date;
1✔
263
        case type_duration:
1✔
264
          left.cast(type_duration);
1✔
265
          return left._duration < right._duration;
1✔
266
      }
NEW
267
      break;
×
268

269
    case type_string:
42✔
270
      switch (right._type) {
42✔
271
        case type_boolean:
3✔
272
        case type_integer:
273
        case type_real:
274
          right.cast(type_string);
3✔
275
          return left._string < right._string;
3✔
276

277
        case type_string: {
32✔
278
          if (left._string == right._string) return false;
32✔
279

280
          auto order = Task::customOrder.find(left.source());
25✔
281
          if (order != Task::customOrder.end()) {
25✔
282
            // Guaranteed to be found, because of ColUDA::validate ().
283
            auto posLeft = std::find(order->second.begin(), order->second.end(), left._string);
20✔
284
            auto posRight = std::find(order->second.begin(), order->second.end(), right._string);
20✔
285
            return posLeft < posRight;
20✔
286
          } else {
287
            if (left.trivial() || right.trivial()) return false;
5✔
288

289
            return left._string < right._string;
5✔
290
          }
291
        }
292

293
        case type_date:
5✔
294
          if (left.trivial() || right.trivial()) return false;
5✔
295

296
          left.cast(type_date);
1✔
297
          return left._date < right._date;
1✔
298

299
        case type_duration:
2✔
300
          if (left.trivial() || right.trivial()) return false;
2✔
301

302
          left.cast(type_duration);
1✔
303
          return left._duration < right._duration;
1✔
304
      }
NEW
305
      break;
×
306

307
    case type_date:
37✔
308
      switch (right._type) {
37✔
309
        case type_boolean:
37✔
310
        case type_integer:
311
        case type_real:
312
        case type_string:
313
        case type_date:
314
        case type_duration:
315
          if (left.trivial() || right.trivial()) return false;
37✔
316

317
          right.cast(type_date);
37✔
318
          return left._date < right._date;
37✔
319
      }
NEW
320
      break;
×
321

322
    case type_duration:
6✔
323
      switch (right._type) {
6✔
324
        case type_boolean:
6✔
325
        case type_integer:
326
        case type_real:
327
        case type_string:
328
        case type_date:
329
        case type_duration:
330
          if (left.trivial() || right.trivial()) return false;
6✔
331

332
          right.cast(type_duration);
6✔
333
          return left._duration < right._duration;
6✔
334
      }
NEW
335
      break;
×
336
  }
337

338
  return false;
×
339
}
115✔
340

341
////////////////////////////////////////////////////////////////////////////////
342
bool Variant::operator<=(const Variant& other) const {
3,894✔
343
  Variant left(*this);
3,894✔
344
  Variant right(other);
3,894✔
345

346
  if (left._type == type_string) Lexer::dequote(left._string);
3,894✔
347

348
  if (right._type == type_string) Lexer::dequote(right._string);
3,894✔
349

350
  switch (left._type) {
3,894✔
351
    case type_boolean:
6✔
352
      switch (right._type) {
6✔
353
        case type_boolean:
1✔
354
          return !left._bool || right._bool;
1✔
355
        case type_integer:
1✔
356
          left.cast(type_integer);
1✔
357
          return left._integer <= right._integer;
1✔
358
        case type_real:
1✔
359
          left.cast(type_real);
1✔
360
          return left._real <= right._real;
1✔
361
        case type_string:
1✔
362
          left.cast(type_string);
1✔
363
          return left._string <= right._string;
1✔
NEW
364
        case type_date:
×
NEW
365
          left.cast(type_date);
×
NEW
366
          return left._date <= right._date;
×
367
        case type_duration:
2✔
368
          left.cast(type_duration);
2✔
369
          return left._duration <= right._duration;
2✔
370
      }
NEW
371
      break;
×
372

373
    case type_integer:
3,841✔
374
      switch (right._type) {
3,841✔
375
        case type_boolean:
1✔
376
          right.cast(type_integer);
1✔
377
          return left._integer <= right._integer;
1✔
378
        case type_integer:
3,836✔
379
          return left._integer <= right._integer;
3,836✔
380
        case type_real:
1✔
381
          left.cast(type_real);
1✔
382
          return left._real <= right._real;
1✔
383
        case type_string:
1✔
384
          left.cast(type_string);
1✔
385
          return left._string <= right._string;
1✔
NEW
386
        case type_date:
×
NEW
387
          left.cast(type_date);
×
NEW
388
          return left._date <= right._date;
×
389
        case type_duration:
2✔
390
          left.cast(type_duration);
2✔
391
          return left._duration <= right._duration;
2✔
392
      }
NEW
393
      break;
×
394

395
    case type_real:
11✔
396
      switch (right._type) {
11✔
397
        case type_boolean:
1✔
398
          right.cast(type_real);
1✔
399
          return left._real <= right._real;
1✔
400
        case type_integer:
1✔
401
          right.cast(type_real);
1✔
402
          return left._real <= right._real;
1✔
403
        case type_real:
6✔
404
          return left._real <= right._real;
6✔
405
        case type_string:
1✔
406
          left.cast(type_string);
1✔
407
          return left._string <= right._string;
1✔
NEW
408
        case type_date:
×
NEW
409
          left.cast(type_date);
×
NEW
410
          return left._date <= right._date;
×
411
        case type_duration:
2✔
412
          left.cast(type_duration);
2✔
413
          return left._duration <= right._duration;
2✔
414
      }
NEW
415
      break;
×
416

417
    case type_string:
18✔
418
      switch (right._type) {
18✔
419
        case type_boolean:
3✔
420
        case type_integer:
421
        case type_real:
422
          right.cast(type_string);
3✔
423
          return left._string <= right._string;
3✔
424

425
        case type_string: {
11✔
426
          if (left._string == right._string) return true;
11✔
427

428
          auto order = Task::customOrder.find(left.source());
9✔
429
          if (order != Task::customOrder.end()) {
9✔
430
            // Guaranteed to be found, because of ColUDA::validate ().
431
            auto posLeft = std::find(order->second.begin(), order->second.end(), left._string);
4✔
432
            auto posRight = std::find(order->second.begin(), order->second.end(), right._string);
4✔
433
            return posLeft <= posRight;
4✔
434
          } else {
435
            if (left.trivial() || right.trivial()) return false;
5✔
436

437
            return left._string <= right._string;
5✔
438
          }
439
        }
440

441
        case type_date:
2✔
442
          if (left.trivial() || right.trivial()) return false;
2✔
443

NEW
444
          left.cast(type_date);
×
NEW
445
          return left._date <= right._date;
×
446

447
        case type_duration:
2✔
448
          if (left.trivial() || right.trivial()) return false;
2✔
449

450
          left.cast(type_duration);
2✔
451
          return left._duration <= right._duration;
2✔
452
      }
NEW
453
      break;
×
454

455
    case type_date:
6✔
456
      switch (right._type) {
6✔
457
        case type_boolean:
6✔
458
        case type_integer:
459
        case type_real:
460
        case type_string:
461
        case type_date:
462
        case type_duration:
463
          if (left.trivial() || right.trivial()) return false;
6✔
464

465
          right.cast(type_date);
6✔
466
          return left._date <= right._date;
6✔
467
      }
NEW
468
      break;
×
469

470
    case type_duration:
12✔
471
      switch (right._type) {
12✔
472
        case type_boolean:
12✔
473
        case type_integer:
474
        case type_real:
475
        case type_string:
476
        case type_date:
477
        case type_duration:
478
          if (left.trivial() || right.trivial()) return false;
12✔
479

480
          right.cast(type_duration);
12✔
481
          return left._duration <= right._duration;
12✔
482
      }
NEW
483
      break;
×
484
  }
485

486
  return false;
×
487
}
3,894✔
488

489
////////////////////////////////////////////////////////////////////////////////
490
bool Variant::operator>(const Variant& other) const {
140✔
491
  Variant left(*this);
140✔
492
  Variant right(other);
140✔
493

494
  if (left._type == type_string) Lexer::dequote(left._string);
140✔
495

496
  if (right._type == type_string) Lexer::dequote(right._string);
140✔
497

498
  switch (left._type) {
140✔
499
    case type_boolean:
6✔
500
      switch (right._type) {
6✔
501
        case type_boolean:
1✔
502
          return !left._bool && right._bool;
1✔
503
        case type_integer:
1✔
504
          left.cast(type_integer);
1✔
505
          return left._integer > right._integer;
1✔
506
        case type_real:
1✔
507
          left.cast(type_real);
1✔
508
          return left._real > right._real;
1✔
509
        case type_string:
1✔
510
          left.cast(type_string);
1✔
511
          return left._string > right._string;
1✔
512
        case type_date:
1✔
513
          left.cast(type_date);
1✔
514
          return left._date > right._date;
1✔
515
        case type_duration:
1✔
516
          left.cast(type_duration);
1✔
517
          return left._duration > right._duration;
1✔
518
      }
NEW
519
      break;
×
520

521
    case type_integer:
6✔
522
      switch (right._type) {
6✔
523
        case type_boolean:
1✔
524
          right.cast(type_integer);
1✔
525
          return left._integer > right._integer;
1✔
526
        case type_integer:
1✔
527
          return left._integer > right._integer;
1✔
528
        case type_real:
1✔
529
          left.cast(type_real);
1✔
530
          return left._real > right._real;
1✔
531
        case type_string:
1✔
532
          left.cast(type_string);
1✔
533
          return left._string > right._string;
1✔
534
        case type_date:
1✔
535
          left.cast(type_date);
1✔
536
          return left._date > right._date;
1✔
537
        case type_duration:
1✔
538
          left.cast(type_duration);
1✔
539
          return left._duration > right._duration;
1✔
540
      }
NEW
541
      break;
×
542

543
    case type_real:
16✔
544
      switch (right._type) {
16✔
545
        case type_boolean:
1✔
546
          right.cast(type_real);
1✔
547
          return left._real > right._real;
1✔
548
        case type_integer:
1✔
549
          right.cast(type_real);
1✔
550
          return left._real > right._real;
1✔
551
        case type_real:
11✔
552
          return left._real > right._real;
11✔
553
        case type_string:
1✔
554
          left.cast(type_string);
1✔
555
          return left._string > right._string;
1✔
556
        case type_date:
1✔
557
          left.cast(type_date);
1✔
558
          return left._date > right._date;
1✔
559
        case type_duration:
1✔
560
          left.cast(type_duration);
1✔
561
          return left._duration > right._duration;
1✔
562
      }
NEW
563
      break;
×
564

565
    case type_string:
63✔
566
      switch (right._type) {
63✔
567
        case type_boolean:
3✔
568
        case type_integer:
569
        case type_real:
570
          right.cast(type_string);
3✔
571
          return left._string > right._string;
3✔
572

573
        case type_string: {
32✔
574
          if (left._string == right._string) return false;
32✔
575

576
          auto order = Task::customOrder.find(left.source());
25✔
577
          if (order != Task::customOrder.end()) {
25✔
578
            // Guaranteed to be found, because of ColUDA::validate ().
579
            auto posLeft = std::find(order->second.begin(), order->second.end(), left._string);
20✔
580
            auto posRight = std::find(order->second.begin(), order->second.end(), right._string);
20✔
581
            return posLeft > posRight;
20✔
582
          } else {
583
            if (left.trivial() || right.trivial()) return false;
5✔
584

585
            return left._string > right._string;
5✔
586
          }
587
        }
588

589
        case type_date:
27✔
590
          if (left.trivial() || right.trivial()) return false;
27✔
591

592
          left.cast(type_date);
1✔
593
          return left._date > right._date;
1✔
594

595
        case type_duration:
1✔
596
          if (left.trivial() || right.trivial()) return false;
1✔
597

598
          left.cast(type_duration);
1✔
599
          return left._duration > right._duration;
1✔
600
      }
NEW
601
      break;
×
602

603
    case type_date:
43✔
604
      switch (right._type) {
43✔
605
        case type_boolean:
43✔
606
        case type_integer:
607
        case type_real:
608
        case type_string:
609
        case type_date:
610
        case type_duration:
611
          if (left.trivial() || right.trivial()) return false;
43✔
612

613
          right.cast(type_date);
43✔
614
          return left._date > right._date;
43✔
615
      }
NEW
616
      break;
×
617

618
    case type_duration:
6✔
619
      switch (right._type) {
6✔
620
        case type_boolean:
6✔
621
        case type_integer:
622
        case type_real:
623
        case type_string:
624
        case type_date:
625
        case type_duration:
626
          if (left.trivial() || right.trivial()) return false;
6✔
627

628
          right.cast(type_duration);
6✔
629
          return left._duration > right._duration;
6✔
630
      }
NEW
631
      break;
×
632
  }
633

634
  return false;
×
635
}
140✔
636

637
////////////////////////////////////////////////////////////////////////////////
638
bool Variant::operator>=(const Variant& other) const {
3,891✔
639
  Variant left(*this);
3,891✔
640
  Variant right(other);
3,891✔
641

642
  if (left._type == type_string) Lexer::dequote(left._string);
3,891✔
643

644
  if (right._type == type_string) Lexer::dequote(right._string);
3,891✔
645

646
  switch (left._type) {
3,891✔
647
    case type_boolean:
6✔
648
      switch (right._type) {
6✔
649
        case type_boolean:
1✔
650
          return left._bool || !right._bool;
1✔
651
        case type_integer:
1✔
652
          left.cast(type_integer);
1✔
653
          return left._integer >= right._integer;
1✔
654
        case type_real:
1✔
655
          left.cast(type_real);
1✔
656
          return left._real >= right._real;
1✔
657
        case type_string:
1✔
658
          left.cast(type_string);
1✔
659
          return left._string >= right._string;
1✔
660
        case type_date:
1✔
661
          left.cast(type_date);
1✔
662
          return left._date >= right._date;
1✔
663
        case type_duration:
1✔
664
          left.cast(type_duration);
1✔
665
          return left._duration >= right._duration;
1✔
666
      }
NEW
667
      break;
×
668

669
    case type_integer:
3,841✔
670
      switch (right._type) {
3,841✔
671
        case type_boolean:
1✔
672
          right.cast(type_integer);
1✔
673
          return left._integer >= right._integer;
1✔
674
        case type_integer:
3,836✔
675
          return left._integer >= right._integer;
3,836✔
676
        case type_real:
1✔
677
          left.cast(type_real);
1✔
678
          return left._real >= right._real;
1✔
679
        case type_string:
1✔
680
          left.cast(type_string);
1✔
681
          return left._string >= right._string;
1✔
682
        case type_date:
1✔
683
          left.cast(type_date);
1✔
684
          return left._date >= right._date;
1✔
685
        case type_duration:
1✔
686
          left.cast(type_duration);
1✔
687
          return left._duration >= right._duration;
1✔
688
      }
NEW
689
      break;
×
690

691
    case type_real:
11✔
692
      switch (right._type) {
11✔
693
        case type_boolean:
1✔
694
          right.cast(type_real);
1✔
695
          return left._real >= right._real;
1✔
696
        case type_integer:
1✔
697
          right.cast(type_real);
1✔
698
          return left._real >= right._real;
1✔
699
        case type_real:
6✔
700
          return left._real >= right._real;
6✔
701
        case type_string:
1✔
702
          left.cast(type_string);
1✔
703
          return left._string >= right._string;
1✔
704
        case type_date:
1✔
705
          left.cast(type_date);
1✔
706
          return left._date >= right._date;
1✔
707
        case type_duration:
1✔
708
          left.cast(type_duration);
1✔
709
          return left._duration >= right._duration;
1✔
710
      }
NEW
711
      break;
×
712

713
    case type_string:
18✔
714
      switch (right._type) {
18✔
715
        case type_boolean:
3✔
716
        case type_integer:
717
        case type_real:
718
          right.cast(type_string);
3✔
719
          return left._string >= right._string;
3✔
720

721
        case type_string: {
11✔
722
          if (left._string == right._string) return true;
11✔
723

724
          auto order = Task::customOrder.find(left.source());
9✔
725
          if (order != Task::customOrder.end()) {
9✔
726
            // Guaranteed to be found, because of ColUDA::validate ().
727
            auto posLeft = std::find(order->second.begin(), order->second.end(), left._string);
4✔
728
            auto posRight = std::find(order->second.begin(), order->second.end(), right._string);
4✔
729
            return posLeft >= posRight;
4✔
730
          } else {
731
            if (left.trivial() || right.trivial()) return false;
5✔
732

733
            return left._string >= right._string;
5✔
734
          }
735
        }
736

737
        case type_date:
3✔
738
          if (left.trivial() || right.trivial()) return false;
3✔
739

740
          left.cast(type_date);
1✔
741
          return left._date >= right._date;
1✔
742

743
        case type_duration:
1✔
744
          if (left.trivial() || right.trivial()) return false;
1✔
745

746
          left.cast(type_duration);
1✔
747
          return left._duration >= right._duration;
1✔
748
      }
NEW
749
      break;
×
750

751
    case type_date:
9✔
752
      switch (right._type) {
9✔
753
        case type_boolean:
9✔
754
        case type_integer:
755
        case type_real:
756
        case type_string:
757
        case type_date:
758
        case type_duration:
759
          if (left.trivial() || right.trivial()) return false;
9✔
760

761
          right.cast(type_date);
9✔
762
          return left._date >= right._date;
9✔
763
      }
NEW
764
      break;
×
765

766
    case type_duration:
6✔
767
      switch (right._type) {
6✔
768
        case type_boolean:
6✔
769
        case type_integer:
770
        case type_real:
771
        case type_string:
772
        case type_date:
773
        case type_duration:
774
          if (left.trivial() || right.trivial()) return false;
6✔
775

776
          right.cast(type_duration);
6✔
777
          return left._duration >= right._duration;
6✔
778
      }
NEW
779
      break;
×
780
  }
781

782
  return false;
×
783
}
3,891✔
784

785
////////////////////////////////////////////////////////////////////////////////
786
bool Variant::operator==(const Variant& other) const {
1,668✔
787
  Variant left(*this);
1,668✔
788
  Variant right(other);
1,668✔
789

790
  if (left._type == type_string) Lexer::dequote(left._string);
1,668✔
791

792
  if (right._type == type_string) Lexer::dequote(right._string);
1,668✔
793

794
  switch (left._type) {
1,668✔
795
    case type_boolean:
12✔
796
      switch (right._type) {
12✔
797
        case type_boolean:
2✔
798
          return left._bool == right._bool;
2✔
799
        case type_integer:
2✔
800
          left.cast(type_integer);
2✔
801
          return left._integer == right._integer;
2✔
802
        case type_real:
2✔
803
          left.cast(type_real);
2✔
804
          return left._real == right._real;
2✔
805
        case type_string:
2✔
806
          left.cast(type_string);
2✔
807
          return left._string == right._string;
2✔
808
        case type_date:
2✔
809
          left.cast(type_date);
2✔
810
          return left._date == right._date;
2✔
811
        case type_duration:
2✔
812
          left.cast(type_duration);
2✔
813
          return left._duration == right._duration;
2✔
814
      }
NEW
815
      break;
×
816

817
    case type_integer:
1,566✔
818
      switch (right._type) {
1,566✔
819
        case type_boolean:
2✔
820
          right.cast(type_integer);
2✔
821
          return left._integer == right._integer;
2✔
822
        case type_integer:
1,556✔
823
          return left._integer == right._integer;
1,556✔
824
        case type_real:
2✔
825
          left.cast(type_real);
2✔
826
          return left._real == right._real;
2✔
827
        case type_string:
2✔
828
          left.cast(type_string);
2✔
829
          return left._string == right._string;
2✔
830
        case type_date:
2✔
831
          left.cast(type_date);
2✔
832
          return left._date == right._date;
2✔
833
        case type_duration:
2✔
834
          left.cast(type_duration);
2✔
835
          return left._duration == right._duration;
2✔
836
      }
NEW
837
      break;
×
838

839
    case type_real:
12✔
840
      switch (right._type) {
12✔
841
        case type_boolean:
2✔
842
          right.cast(type_real);
2✔
843
          return left._real == right._real;
2✔
844
        case type_integer:
2✔
845
          right.cast(type_real);
2✔
846
          return left._real == right._real;
2✔
847
        case type_real:
2✔
848
          return left._real == right._real;
2✔
849
        case type_string:
2✔
850
          left.cast(type_string);
2✔
851
          return left._string == right._string;
2✔
852
        case type_date:
2✔
853
          left.cast(type_date);
2✔
854
          return left._date == right._date;
2✔
855
        case type_duration:
2✔
856
          left.cast(type_duration);
2✔
857
          return left._duration == right._duration;
2✔
858
      }
NEW
859
      break;
×
860

861
    case type_string:
50✔
862
      switch (right._type) {
50✔
863
        case type_boolean:
46✔
864
        case type_integer:
865
        case type_real:
866
        case type_string:
867
          right.cast(type_string);
46✔
868

869
          // Status is always compared caseless.
870
          if (left.source() == "status") return compare(left._string, right._string, false);
46✔
871

872
          return left._string == right._string;
46✔
873

874
        case type_date:
2✔
875
          if (left.trivial() || right.trivial()) return false;
2✔
876

877
          left.cast(type_date);
2✔
878
          return left._date == right._date;
2✔
879

880
        case type_duration:
2✔
881
          left.cast(type_duration);
2✔
882
          return left._duration == right._duration;
2✔
883
      }
NEW
884
      break;
×
885

886
    case type_date:
16✔
887
      switch (right._type) {
16✔
888
        case type_boolean:
16✔
889
        case type_integer:
890
        case type_real:
891
        case type_string:
892
        case type_date:
893
        case type_duration:
894
          if (left.trivial() || right.trivial()) return false;
16✔
895

896
          right.cast(type_date);
16✔
897
          return left._date == right._date;
16✔
898
      }
NEW
899
      break;
×
900

901
    case type_duration:
12✔
902
      switch (right._type) {
12✔
903
        case type_boolean:
12✔
904
        case type_integer:
905
        case type_real:
906
        case type_string:
907
        case type_date:
908
        case type_duration:
909
          right.cast(type_duration);
12✔
910
          return left._duration == right._duration;
12✔
911
      }
NEW
912
      break;
×
913
  }
914

915
  return false;
×
916
}
1,668✔
917

918
////////////////////////////////////////////////////////////////////////////////
919
bool Variant::operator!=(const Variant& other) const { return !(*this == other); }
70✔
920

921
////////////////////////////////////////////////////////////////////////////////
922
bool Variant::operator_match(const Variant& other, const Task& task) const {
897✔
923
  // Simple matching case first.
924
  Variant left(*this);
897✔
925
  Variant right(other);
897✔
926

927
  if (left._type == type_string) Lexer::dequote(left._string);
897✔
928

929
  if (right._type == type_string) Lexer::dequote(right._string);
897✔
930

931
  left.cast(type_string);
897✔
932
  right.cast(type_string);
897✔
933

934
  std::string pattern = right._string;
897✔
935
  Lexer::dequote(pattern);
897✔
936

937
  if (searchUsingRegex) {
897✔
938
    RX r(pattern, searchCaseSensitive);
885✔
939
    if (r.match(left._string)) return true;
885✔
940

941
    // If the above did not match, and the left source is "description", then
942
    // in the annotations.
943
    if (left.source() == "description") {
734✔
944
      for (auto& a : task.getAnnotations())
500✔
945
        if (r.match(a.second)) return true;
500✔
946
    }
947
  } else {
885✔
948
    // If pattern starts with '^', look for a leftmost compare only.
949
    if (pattern[0] == '^' && find(left._string, pattern.substr(1), searchCaseSensitive) == 0) {
12✔
950
      return true;
1✔
951
    }
952

953
    // If pattern ends with '$', look for a rightmost compare only.
954
    else if (pattern[pattern.length() - 1] == '$' &&
13✔
955
             find(left._string, pattern.substr(0, pattern.length() - 1), searchCaseSensitive) ==
13✔
956
                 (left._string.length() - pattern.length() + 1)) {
2✔
957
      return true;
1✔
958
    }
959

960
    else if (find(left._string, pattern, searchCaseSensitive) != std::string::npos)
10✔
961
      return true;
4✔
962

963
    // If the above did not match, and the left source is "description", then
964
    // in the annotations.
965
    if (left.source() == "description") {
6✔
966
      for (auto& a : task.getAnnotations())
6✔
967
        if (find(a.second, pattern, searchCaseSensitive) != std::string::npos) return true;
6✔
968
    }
969
  }
970

971
  return false;
733✔
972
}
897✔
973

974
////////////////////////////////////////////////////////////////////////////////
975
bool Variant::operator_nomatch(const Variant& other, const Task& task) const {
79✔
976
  return !operator_match(other, task);
79✔
977
}
978

979
////////////////////////////////////////////////////////////////////////////////
980
// Partial match is mostly a clone of operator==, but with some overrides:
981
//
982
//   date <partial> date     --> same day check
983
//   string <partial> string --> leftmost
984
//
985
bool Variant::operator_partial(const Variant& other) const {
2,611✔
986
  Variant left(*this);
2,611✔
987
  Variant right(other);
2,611✔
988

989
  if (left._type == type_string) Lexer::dequote(left._string);
2,611✔
990

991
  if (right._type == type_string) Lexer::dequote(right._string);
2,611✔
992

993
  switch (left._type) {
2,611✔
994
    case type_boolean:
6✔
995
      switch (right._type) {
6✔
996
        case type_boolean:
1✔
997
          return left._bool == right._bool;
1✔
998
        case type_integer:
1✔
999
          left.cast(type_integer);
1✔
1000
          return left._integer == right._integer;
1✔
1001
        case type_real:
1✔
1002
          left.cast(type_real);
1✔
1003
          return left._real == right._real;
1✔
1004
        case type_string:
1✔
1005
          left.cast(type_string);
1✔
1006
          return left._string == right._string;
1✔
1007

1008
        // Same-day comparison.
1009
        case type_date: {
1✔
1010
          left.cast(type_date);
1✔
1011
          Datetime left_date(left._date);
1✔
1012
          Datetime right_date(right._date);
1✔
1013
          return left_date.sameDay(right_date);
1✔
1014
        }
1015

1016
        case type_duration:
1✔
1017
          left.cast(type_duration);
1✔
1018
          return left._duration == right._duration;
1✔
1019
      }
NEW
1020
      break;
×
1021

1022
    case type_integer:
18✔
1023
      switch (right._type) {
18✔
1024
        case type_boolean:
1✔
1025
          right.cast(type_integer);
1✔
1026
          return left._integer == right._integer;
1✔
1027
        case type_integer:
13✔
1028
          return left._integer == right._integer;
13✔
1029
        case type_real:
1✔
1030
          left.cast(type_real);
1✔
1031
          return left._real == right._real;
1✔
1032
        case type_string:
1✔
1033
          left.cast(type_string);
1✔
1034
          return left._string == right._string;
1✔
1035

1036
        // Same-day comparison.
1037
        case type_date: {
1✔
1038
          left.cast(type_date);
1✔
1039
          Datetime left_date(left._date);
1✔
1040
          Datetime right_date(right._date);
1✔
1041
          return left_date.sameDay(right_date);
1✔
1042
        }
1043

1044
        case type_duration:
1✔
1045
          left.cast(type_duration);
1✔
1046
          return left._duration == right._duration;
1✔
1047
      }
NEW
1048
      break;
×
1049

1050
    case type_real:
7✔
1051
      switch (right._type) {
7✔
1052
        case type_boolean:
4✔
1053
        case type_integer:
1054
        case type_real:
1055
          right.cast(type_real);
4✔
1056
          return left._real == right._real;
4✔
1057

1058
        case type_string:
1✔
1059
          left.cast(type_string);
1✔
1060
          return left._string == right._string;
1✔
1061

1062
        // Same-day comparison.
1063
        case type_date: {
1✔
1064
          left.cast(type_date);
1✔
1065
          Datetime left_date(left._date);
1✔
1066
          Datetime right_date(right._date);
1✔
1067
          return left_date.sameDay(right_date);
1✔
1068
        }
1069

1070
        case type_duration:
1✔
1071
          left.cast(type_duration);
1✔
1072
          return left._duration == right._duration;
1✔
1073
      }
NEW
1074
      break;
×
1075

1076
    case type_string:
2,528✔
1077
      switch (right._type) {
2,528✔
1078
        case type_boolean:
2,514✔
1079
        case type_integer:
1080
        case type_real:
1081
        case type_string: {
1082
          right.cast(type_string);
2,514✔
1083

1084
          // Status is always compared caseless.
1085
          if (left.source() == "status") return compare(left._string, right._string, false);
2,514✔
1086

1087
          int left_len = left._string.length();
731✔
1088
          int right_len = right._string.length();
731✔
1089

1090
          if ((left_len == 0 && right_len != 0) || (left_len != 0 && right_len == 0)) return false;
731✔
1091

1092
          // Dodgy.
1093
          if (left._string.length() < right._string.length()) return false;
573✔
1094

1095
          return left._string.substr(0, right._string.length()) == right._string;
558✔
1096
        }
1097

1098
        // Same-day comparison.
1099
        case type_date: {
11✔
1100
          if (left.trivial() || right.trivial()) return false;
11✔
1101

1102
          left.cast(type_date);
2✔
1103
          Datetime left_date(left._date);
2✔
1104
          Datetime right_date(right._date);
2✔
1105
          return left_date.sameDay(right_date);
2✔
1106
        }
1107

1108
        case type_duration:
3✔
1109
          left.cast(type_duration);
3✔
1110
          return left._duration == right._duration;
3✔
1111
      }
NEW
1112
      break;
×
1113

1114
    case type_date:
37✔
1115
      switch (right._type) {
37✔
1116
        // Same-day comparison.
1117
        case type_string: {
2✔
1118
          if (left.trivial() || right.trivial()) return false;
2✔
1119

1120
          right.cast(type_date);
2✔
1121
          Datetime left_date(left._date);
2✔
1122
          Datetime right_date(right._date);
2✔
1123
          return left_date.sameDay(right_date);
2✔
1124
        }
1125

1126
        case type_boolean:
35✔
1127
        case type_integer:
1128
        case type_real:
1129
        case type_date:
1130
        case type_duration: {
1131
          right.cast(type_date);
35✔
1132
          Datetime left_date(left._date);
35✔
1133
          Datetime right_date(right._date);
35✔
1134
          return left_date.sameDay(right_date);
35✔
1135
        }
1136
      }
NEW
1137
      break;
×
1138

1139
    case type_duration:
15✔
1140
      switch (right._type) {
15✔
1141
        // Same-day comparison.
1142
        case type_boolean:
15✔
1143
        case type_integer:
1144
        case type_real:
1145
        case type_string:
1146
        case type_date:
1147
        case type_duration:
1148
          right.cast(type_duration);
15✔
1149
          return left._duration == right._duration;
15✔
1150
      }
NEW
1151
      break;
×
1152
  }
1153

1154
  return false;
×
1155
}
2,611✔
1156

1157
////////////////////////////////////////////////////////////////////////////////
1158
// Inverse of operator_partial.
1159
bool Variant::operator_nopartial(const Variant& other) const { return !operator_partial(other); }
41✔
1160

1161
////////////////////////////////////////////////////////////////////////////////
1162
bool Variant::operator_hastag(const Variant& other, const Task& task) const {
2,772✔
1163
  Variant right(other);
2,772✔
1164
  right.cast(type_string);
2,772✔
1165
  Lexer::dequote(right._string);
2,772✔
1166
  return task.hasTag(right._string);
5,544✔
1167
}
2,772✔
1168

1169
////////////////////////////////////////////////////////////////////////////////
1170
bool Variant::operator_notag(const Variant& other, const Task& task) const {
1,918✔
1171
  return !operator_hastag(other, task);
1,918✔
1172
}
1173

1174
////////////////////////////////////////////////////////////////////////////////
1175
bool Variant::operator!() const {
12✔
1176
  Variant left(*this);
12✔
1177

1178
  if (left._type == type_string) Lexer::dequote(left._string);
12✔
1179

1180
  left.cast(type_boolean);
12✔
1181
  return !left._bool;
12✔
1182
}
12✔
1183

1184
////////////////////////////////////////////////////////////////////////////////
1185
Variant& Variant::operator^=(const Variant& other) {
36✔
1186
  switch (_type) {
36✔
1187
    case type_boolean:
6✔
1188
      throw std::string(STRING_VARIANT_EXP_BOOL);
6✔
1189
      break;
1190

1191
    case type_integer:
6✔
1192
      switch (other._type) {
6✔
1193
        case type_boolean:
1✔
1194
          throw std::string(STRING_VARIANT_EXP_BOOL);
1✔
1195
        case type_integer:
1✔
1196
          _integer = (int)pow(static_cast<double>(_integer), static_cast<double>(other._integer));
1✔
1197
          break;
1✔
1198
        case type_real:
1✔
1199
          throw std::string(STRING_VARIANT_EXP_NON_INT);
1✔
1200
        case type_string:
1✔
1201
          throw std::string(STRING_VARIANT_EXP_STRING);
1✔
1202
        case type_date:
1✔
1203
          throw std::string(STRING_VARIANT_EXP_DATE);
1✔
1204
        case type_duration:
1✔
1205
          throw std::string(STRING_VARIANT_EXP_DURATION);
1✔
1206
      }
1207
      break;
1✔
1208

1209
    case type_real:
6✔
1210
      switch (other._type) {
6✔
1211
        case type_boolean:
1✔
1212
          throw std::string(STRING_VARIANT_EXP_BOOL);
1✔
1213
        case type_integer:
1✔
1214
          _real = pow(_real, static_cast<double>(other._integer));
1✔
1215
          break;
1✔
1216
        case type_real:
1✔
1217
          throw std::string(STRING_VARIANT_EXP_NON_INT);
1✔
1218
        case type_string:
1✔
1219
          throw std::string(STRING_VARIANT_EXP_STRING);
1✔
1220
        case type_date:
1✔
1221
          throw std::string(STRING_VARIANT_EXP_DATE);
1✔
1222
        case type_duration:
1✔
1223
          throw std::string(STRING_VARIANT_EXP_DURATION);
1✔
1224
      }
1225
      break;
1✔
1226

1227
    case type_string:
6✔
1228
      throw std::string(STRING_VARIANT_EXP_STRING);
6✔
1229
      break;
1230

1231
    case type_date:
6✔
1232
      throw std::string(STRING_VARIANT_EXP_DATE);
6✔
1233
      break;
1234

1235
    case type_duration:
6✔
1236
      throw std::string(STRING_VARIANT_EXP_DURATION);
6✔
1237
      break;
1238
  }
1239

1240
  return *this;
2✔
1241
}
1242

1243
////////////////////////////////////////////////////////////////////////////////
1244
Variant Variant::operator^(const Variant& other) const {
36✔
1245
  Variant left(*this);
36✔
1246
  left ^= other;
36✔
1247
  return left;
2✔
1248
}
34✔
1249

1250
////////////////////////////////////////////////////////////////////////////////
1251
Variant& Variant::operator-=(const Variant& other) {
252✔
1252
  Variant right(other);
252✔
1253

1254
  switch (_type) {
252✔
1255
    case type_boolean:
6✔
1256
      throw std::string(STRING_VARIANT_SUB_BOOL);
6✔
1257
      break;
1258

1259
    case type_integer:
67✔
1260
      switch (right._type) {
67✔
1261
        case type_boolean:
1✔
1262
          right.cast(type_integer);
1✔
1263
          _integer -= right._integer;
1✔
1264
          break;
1✔
1265
        case type_integer:
6✔
1266
          _integer -= right._integer;
6✔
1267
          break;
6✔
1268
        case type_real:
2✔
1269
          cast(type_real);
2✔
1270
          _real -= right._real;
2✔
1271
          break;
2✔
1272
        case type_string:
34✔
1273
          throw std::string(STRING_VARIANT_SUB_STRING);
34✔
1274
        case type_date:
1✔
1275
          cast(type_date);
1✔
1276
          _date -= right._date;
1✔
1277
          break;
1✔
1278
        case type_duration:
23✔
1279
          cast(type_duration);
23✔
1280
          _duration -= right._duration;
23✔
1281
          break;
23✔
1282
      }
1283
      break;
33✔
1284

1285
    case type_real:
5✔
1286
      switch (right._type) {
5✔
NEW
1287
        case type_string:
×
NEW
1288
          throw std::string(STRING_VARIANT_SUB_STRING);
×
1289

1290
        case type_boolean:
5✔
1291
        case type_integer:
1292
        case type_real:
1293
        case type_date:
1294
        case type_duration:
1295
          right.cast(type_real);
5✔
1296
          _real -= right._real;
5✔
1297
          break;
5✔
1298
      }
1299
      break;
5✔
1300

1301
    case type_string:
114✔
1302
      switch (right._type) {
114✔
1303
        case type_string:
17✔
1304
          cast(type_string);
17✔
1305
          _string += '-' + right._string;
17✔
1306
          break;
17✔
1307
        case type_boolean:
97✔
1308
        case type_integer:
1309
        case type_real:
1310
        case type_date:
1311
        case type_duration:
1312
          throw std::string(STRING_VARIANT_SUB_STRING);
97✔
1313
          break;
1314
      }
1315
      break;
17✔
1316

1317
    case type_date:
54✔
1318
      switch (right._type) {
54✔
1319
        case type_boolean:
1✔
1320
          right.cast(type_integer);
1✔
1321
          _date -= right._integer;
1✔
1322
          break;
1✔
1323
        case type_integer:
1✔
1324
          _date -= right._integer;
1✔
1325
          break;
1✔
1326
        case type_real:
1✔
1327
          _date -= (int)right._real;
1✔
1328
          break;
1✔
1329
        case type_string:
1✔
1330
          throw std::string(STRING_VARIANT_SUB_STRING);
1✔
1331
        case type_date:
1✔
1332
          _type = Variant::type_duration;
1✔
1333
          _duration = _date - right._date;
1✔
1334
          break;
1✔
1335
        case type_duration:
49✔
1336
          _date -= right._duration;
49✔
1337
          break;
49✔
1338
      }
1339
      break;
53✔
1340

1341
    case type_duration:
6✔
1342
      switch (right._type) {
6✔
1343
        case type_boolean:
1✔
1344
          right.cast(type_integer);
1✔
1345
          _duration -= right._integer;
1✔
1346
          break;
1✔
1347
        case type_integer:
1✔
1348
          _duration -= right._integer;
1✔
1349
          break;
1✔
1350
        case type_real:
1✔
1351
          _duration -= (int)right._real;
1✔
1352
          break;
1✔
1353
        case type_string:
1✔
1354
          throw std::string(STRING_VARIANT_SUB_STRING);
1✔
1355
        case type_date:
1✔
1356
          throw std::string(STRING_VARIANT_SUB_DATE);
1✔
1357
        case type_duration:
1✔
1358
          _duration -= right._duration;
1✔
1359
          break;
1✔
1360
      }
1361
      break;
4✔
1362
  }
1363

1364
  return *this;
112✔
1365
}
252✔
1366

1367
////////////////////////////////////////////////////////////////////////////////
1368
Variant Variant::operator-(const Variant& other) const {
226✔
1369
  Variant left(*this);
226✔
1370
  left -= other;
226✔
1371
  return left;
86✔
1372
}
140✔
1373

1374
////////////////////////////////////////////////////////////////////////////////
1375
Variant& Variant::operator+=(const Variant& other) {
99✔
1376
  Variant right(other);
99✔
1377

1378
  if (right._type == type_string) Lexer::dequote(right._string);
99✔
1379

1380
  switch (_type) {
99✔
1381
    case type_boolean:
6✔
1382
      switch (right._type) {
6✔
1383
        case type_boolean:
1✔
1384
          throw std::string(STRING_VARIANT_ADD_BOOL);
1✔
1385
        case type_integer:
1✔
1386
          cast(type_integer);
1✔
1387
          _integer += right._integer;
1✔
1388
          break;
1✔
1389
        case type_real:
1✔
1390
          cast(type_real);
1✔
1391
          _real += right._real;
1✔
1392
          break;
1✔
1393
        case type_string:
1✔
1394
          cast(type_string);
1✔
1395
          _string += right._string;
1✔
1396
          break;
1✔
1397
        case type_date:
1✔
1398
          cast(type_date);
1✔
1399
          _date += right._date;
1✔
1400
          break;
1✔
1401
        case type_duration:
1✔
1402
          cast(type_duration);
1✔
1403
          _duration += right._duration;
1✔
1404
          break;
1✔
1405
      }
1406
      break;
5✔
1407

1408
    case type_integer:
10✔
1409
      switch (right._type) {
10✔
1410
        case type_boolean:
1✔
1411
          right.cast(type_integer);
1✔
1412
          _integer += right._integer;
1✔
1413
          break;
1✔
1414
        case type_integer:
4✔
1415
          _integer += right._integer;
4✔
1416
          break;
4✔
1417
        case type_real:
2✔
1418
          cast(type_real);
2✔
1419
          _real += right._real;
2✔
1420
          break;
2✔
1421
        case type_string:
1✔
1422
          cast(type_string);
1✔
1423
          _string += right._string;
1✔
1424
          break;
1✔
1425
        case type_date:
1✔
1426
          cast(type_date);
1✔
1427
          _date += right._date;
1✔
1428
          break;
1✔
1429
        case type_duration:
1✔
1430
          cast(type_duration);
1✔
1431
          _duration += right._duration;
1✔
1432
          break;
1✔
1433
      }
1434
      break;
10✔
1435

1436
    case type_real:
6✔
1437
      switch (right._type) {
6✔
1438
        case type_boolean:
3✔
1439
        case type_integer:
1440
        case type_real:
1441
          right.cast(type_real);
3✔
1442
          _real += right._real;
3✔
1443
          break;
3✔
1444

1445
        case type_string:
1✔
1446
          cast(type_string);
1✔
1447
          _string += right._string;
1✔
1448
          break;
1✔
1449

1450
        case type_date:
1✔
1451
          _type = type_date;
1✔
1452
          _date = (unsigned)(int)_real + right._date;
1✔
1453
          break;
1✔
1454

1455
        case type_duration:
1✔
1456
          _type = type_duration;
1✔
1457
          _duration = (unsigned)(int)_real + right._duration;
1✔
1458
          break;
1✔
1459
      }
1460
      break;
6✔
1461

1462
    case type_string:
58✔
1463
      _string += (std::string)right;
58✔
1464
      break;
58✔
1465

1466
    case type_date:
12✔
1467
      switch (right._type) {
12✔
1468
        case type_boolean:
1✔
1469
          right.cast(type_date);
1✔
1470
          _date += right._date;
1✔
1471
          break;
1✔
1472
        case type_integer:
1✔
1473
          _date += right._integer;
1✔
1474
          break;
1✔
1475
        case type_real:
1✔
1476
          _date += (int)right._real;
1✔
1477
          break;
1✔
1478
        case type_string:
1✔
1479
          cast(type_string);
1✔
1480
          _string += right._string;
1✔
1481
          break;
1✔
1482
        case type_date:
1✔
1483
          throw std::string(STRING_VARIANT_ADD_DATE);
1✔
1484
        case type_duration:
7✔
1485
          _date += right._duration;
7✔
1486
          break;
7✔
1487
      }
1488
      break;
11✔
1489

1490
    case type_duration:
7✔
1491
      switch (right._type) {
7✔
1492
        case type_boolean:
1✔
1493
          right.cast(type_duration);
1✔
1494
          _duration += right._duration;
1✔
1495
          break;
1✔
1496
        case type_integer:
1✔
1497
          _duration += right._integer;
1✔
1498
          break;
1✔
1499
        case type_real:
1✔
1500
          _duration += (int)right._real;
1✔
1501
          break;
1✔
1502
        case type_string:
1✔
1503
          cast(type_string);
1✔
1504
          _string += right._string;
1✔
1505
          break;
1✔
1506
        case type_date:
1✔
1507
          _type = Variant::type_date;
1✔
1508
          _date += right._date + _duration;
1✔
1509
          break;
1✔
1510
        case type_duration:
2✔
1511
          _duration += right._duration;
2✔
1512
          break;
2✔
1513
      }
1514
      break;
7✔
1515
  }
1516

1517
  return *this;
97✔
1518
}
99✔
1519

1520
////////////////////////////////////////////////////////////////////////////////
1521
Variant Variant::operator+(const Variant& other) const {
99✔
1522
  Variant left(*this);
99✔
1523
  left += other;
99✔
1524
  return left;
97✔
1525
}
2✔
1526

1527
////////////////////////////////////////////////////////////////////////////////
1528
Variant& Variant::operator*=(const Variant& other) {
40✔
1529
  Variant right(other);
40✔
1530

1531
  if (right._type == type_string) Lexer::dequote(right._string);
40✔
1532

1533
  switch (_type) {
40✔
1534
    case type_boolean:
6✔
1535
      switch (right._type) {
6✔
1536
        case type_boolean:
1✔
1537
          throw std::string(STRING_VARIANT_MUL_BOOL);
1✔
1538
        case type_integer:
1✔
1539
          cast(type_integer);
1✔
1540
          _integer *= right._integer;
1✔
1541
          break;
1✔
1542
        case type_real:
1✔
1543
          cast(type_real);
1✔
1544
          _real *= right._real;
1✔
1545
          break;
1✔
1546
        case type_string:
1✔
1547
          _string = (_bool ? right._string : "");
1✔
1548
          _type = type_string;
1✔
1549
          break;
1✔
1550
        case type_date:
1✔
1551
          throw std::string(STRING_VARIANT_MUL_DATE);
1✔
1552
        case type_duration:
1✔
1553
          cast(type_duration);
1✔
1554
          _duration *= right._duration;
1✔
1555
          break;
1✔
1556
      }
1557
      break;
4✔
1558

1559
    case type_integer:
10✔
1560
      switch (right._type) {
10✔
1561
        case type_boolean:
1✔
1562
          right.cast(type_integer);
1✔
1563
          _integer *= right._integer;
1✔
1564
          break;
1✔
1565
        case type_integer:
5✔
1566
          _integer *= right._integer;
5✔
1567
          break;
5✔
1568
        case type_real:
1✔
1569
          cast(type_real);
1✔
1570
          _real *= right._real;
1✔
1571
          break;
1✔
1572
        case type_string: {
1✔
1573
          int limit = _integer;
1✔
1574
          // assert (limit < 128);
1575
          _type = type_string;
1✔
1576
          _string = "";
1✔
1577
          while (limit--) _string += right._string;
43✔
1578
        } break;
1✔
1579
        case type_date:
1✔
1580
          throw std::string(STRING_VARIANT_MUL_DATE);
1✔
1581
        case type_duration:
1✔
1582
          cast(type_duration);
1✔
1583
          _duration *= right._duration;
1✔
1584
          break;
1✔
1585
      }
1586
      break;
9✔
1587

1588
    case type_real:
6✔
1589
      switch (right._type) {
6✔
1590
        case type_boolean:
3✔
1591
        case type_integer:
1592
        case type_real:
1593
          right.cast(type_real);
3✔
1594
          _real *= right._real;
3✔
1595
          break;
3✔
1596

1597
        case type_string:
1✔
1598
          throw std::string(STRING_VARIANT_MUL_REAL_STR);
1✔
1599

1600
        case type_date:
1✔
1601
          throw std::string(STRING_VARIANT_MUL_DATE);
1✔
1602

1603
        case type_duration:
1✔
1604
          _type = type_duration;
1✔
1605
          _duration = (time_t)(unsigned)(int)(_real * static_cast<double>(right._duration));
1✔
1606
      }
1607
      break;
4✔
1608

1609
    case type_string:
6✔
1610
      switch (right._type) {
6✔
1611
        case type_boolean:
1✔
1612
          if (!right._bool) _string = "";
1✔
1613
          break;
1✔
1614
        case type_integer: {
1✔
1615
          int limit = right._integer - 1;
1✔
1616
          // assert (limit < 128);
1617
          std::string fragment = _string;
1✔
1618
          while (limit--) _string += fragment;
42✔
1619
        } break;
1✔
1620
        case type_real:
1✔
1621
          throw std::string(STRING_VARIANT_MUL_STR_REAL);
1✔
1622
        case type_string:
1✔
1623
          throw std::string(STRING_VARIANT_MUL_STR_STR);
1✔
1624
        case type_date:
1✔
1625
          throw std::string(STRING_VARIANT_MUL_STR_DATE);
1✔
1626
        case type_duration:
1✔
1627
          throw std::string(STRING_VARIANT_MUL_STR_DUR);
1✔
1628
      }
1629
      break;
2✔
1630

1631
    case type_date:
6✔
1632
      throw std::string(STRING_VARIANT_MUL_DATE);
6✔
1633

1634
    case type_duration:
6✔
1635
      switch (right._type) {
6✔
1636
        case type_boolean:
1✔
1637
          right.cast(type_duration);
1✔
1638
          _duration *= right._duration;
1✔
1639
          break;
1✔
1640
        case type_integer:
1✔
1641
          _duration *= right._integer;
1✔
1642
          break;
1✔
1643
        case type_real:
1✔
1644
          _duration = (time_t)(unsigned)(int)(static_cast<double>(_duration) * right._real);
1✔
1645
          break;
1✔
1646
        case type_string:
1✔
1647
          throw std::string(STRING_VARIANT_MUL_DUR_STR);
1✔
1648
        case type_date:
1✔
1649
          throw std::string(STRING_VARIANT_MUL_DUR_DATE);
1✔
1650
        case type_duration:
1✔
1651
          throw std::string(STRING_VARIANT_MUL_DUR_DUR);
1✔
1652
      }
1653
      break;
3✔
1654
  }
1655

1656
  return *this;
22✔
1657
}
40✔
1658

1659
////////////////////////////////////////////////////////////////////////////////
1660
Variant Variant::operator*(const Variant& other) const {
40✔
1661
  Variant left(*this);
40✔
1662
  left *= other;
40✔
1663
  return left;
22✔
1664
}
18✔
1665

1666
////////////////////////////////////////////////////////////////////////////////
1667
Variant& Variant::operator/=(const Variant& other) {
39✔
1668
  Variant right(other);
39✔
1669

1670
  switch (_type) {
39✔
1671
    case type_boolean:
6✔
1672
      throw std::string(STRING_VARIANT_DIV_BOOL);
6✔
1673
      break;
1674

1675
    case type_integer:
9✔
1676
      switch (right._type) {
9✔
1677
        case type_boolean:
1✔
1678
          throw std::string(STRING_VARIANT_DIV_INT_BOOL);
1✔
1679

1680
        case type_integer:
3✔
1681
          if (right._integer == 0) throw std::string(STRING_VARIANT_DIV_ZERO);
3✔
1682
          _integer /= right._integer;
3✔
1683
          break;
3✔
1684

1685
        case type_real:
2✔
1686
          if (right._real == 0.0) throw std::string(STRING_VARIANT_DIV_ZERO);
2✔
1687
          cast(type_real);
2✔
1688
          _real /= right._real;
2✔
1689
          break;
2✔
1690

1691
        case type_string:
1✔
1692
          throw std::string(STRING_VARIANT_DIV_INT_STR);
1✔
1693

1694
        case type_date:
1✔
1695
          throw std::string(STRING_VARIANT_DIV_INT_DATE);
1✔
1696

1697
        case type_duration:
1✔
1698
          if (right._duration == 0) throw std::string(STRING_VARIANT_DIV_ZERO);
1✔
1699
          _type = type_duration;
1✔
1700
          _duration = (time_t)(unsigned)(int)(_integer / right._duration);
1✔
1701
          break;
1✔
1702
      }
1703
      break;
6✔
1704

1705
    case type_real:
6✔
1706
      switch (right._type) {
6✔
1707
        case type_boolean:
1✔
1708
          throw std::string(STRING_VARIANT_DIV_REAL_BOOL);
1✔
1709

1710
        case type_integer:
1✔
1711
          if (right._integer == 0) throw std::string(STRING_VARIANT_DIV_ZERO);
1✔
1712
          _real /= static_cast<double>(right._integer);
1✔
1713
          break;
1✔
1714

1715
        case type_real:
1✔
1716
          if (right._real == 0) throw std::string(STRING_VARIANT_DIV_ZERO);
1✔
1717
          _real /= right._real;
1✔
1718
          break;
1✔
1719

1720
        case type_string:
1✔
1721
          throw std::string(STRING_VARIANT_DIV_REAL_STR);
1✔
1722

1723
        case type_date:
1✔
1724
          throw std::string(STRING_VARIANT_DIV_REAL_DATE);
1✔
1725

1726
        case type_duration:
1✔
1727
          if (right._duration == 0) throw std::string(STRING_VARIANT_DIV_ZERO);
1✔
1728
          _type = type_duration;
1✔
1729
          _duration = (time_t)(unsigned)(int)(_real / right._duration);
1✔
1730
          break;
1✔
1731
      }
1732
      break;
3✔
1733

1734
    case type_string:
6✔
1735
      throw std::string(STRING_VARIANT_DIV_REAL_STR);
6✔
1736
      break;
1737

1738
    case type_date:
6✔
1739
      throw std::string(STRING_VARIANT_DIV_REAL_DATE);
6✔
1740

1741
    case type_duration:
6✔
1742
      switch (right._type) {
6✔
1743
        case type_boolean:
1✔
1744
          throw std::string(STRING_VARIANT_DIV_DUR_BOOL);
1✔
1745

1746
        case type_integer:
1✔
1747
          if (right._integer == 0) throw std::string(STRING_VARIANT_DIV_ZERO);
1✔
1748
          _duration /= right._integer;
1✔
1749
          break;
1✔
1750

1751
        case type_real:
1✔
1752
          if (right._real == 0) throw std::string(STRING_VARIANT_DIV_ZERO);
1✔
1753
          _duration = (time_t)(unsigned)(int)(static_cast<double>(_duration) / right._real);
1✔
1754
          break;
1✔
1755

1756
        case type_string:
1✔
1757
          throw std::string(STRING_VARIANT_DIV_DUR_STR);
1✔
1758

1759
        case type_date:
1✔
1760
          throw std::string(STRING_VARIANT_DIV_DUR_DATE);
1✔
1761

1762
        case type_duration:
1✔
1763
          throw std::string(STRING_VARIANT_DIV_DUR_DUR);
1✔
1764
      }
1765
      break;
2✔
1766
  }
1767

1768
  return *this;
11✔
1769
}
39✔
1770

1771
////////////////////////////////////////////////////////////////////////////////
1772
Variant Variant::operator/(const Variant& other) const {
39✔
1773
  Variant left(*this);
39✔
1774
  left /= other;
39✔
1775
  return left;
11✔
1776
}
28✔
1777

1778
////////////////////////////////////////////////////////////////////////////////
1779
Variant& Variant::operator%=(const Variant& other) {
36✔
1780
  Variant right(other);
36✔
1781

1782
  switch (_type) {
36✔
1783
    case type_boolean:
6✔
1784
      throw std::string(STRING_VARIANT_MOD_BOOL);
6✔
1785
      break;
1786

1787
    case type_integer:
6✔
1788
      switch (right._type) {
6✔
1789
        case type_boolean:
1✔
1790
          throw std::string(STRING_VARIANT_MOD_INT_BOOL);
1✔
1791

1792
        case type_integer:
1✔
1793
          if (right._integer == 0) throw std::string(STRING_VARIANT_MOD_ZERO);
1✔
1794
          _integer %= right._integer;
1✔
1795
          break;
1✔
1796

1797
        case type_real:
1✔
1798
          if (right._real == 0.0) throw std::string(STRING_VARIANT_MOD_ZERO);
1✔
1799
          cast(type_real);
1✔
1800
          _real = fmod(_real, right._real);
1✔
1801
          break;
1✔
1802

1803
        case type_string:
1✔
1804
          throw std::string(STRING_VARIANT_MOD_INT_STR);
1✔
1805

1806
        case type_date:
1✔
1807
          throw std::string(STRING_VARIANT_MOD_INT_DATE);
1✔
1808

1809
        case type_duration:
1✔
1810
          throw std::string(STRING_VARIANT_MOD_INT_DUR);
1✔
1811
      }
1812
      break;
2✔
1813

1814
    case type_real:
6✔
1815
      switch (right._type) {
6✔
1816
        case type_boolean:
1✔
1817
          throw std::string(STRING_VARIANT_MOD_REAL_BOOL);
1✔
1818

1819
        case type_integer:
1✔
1820
          if (right._integer == 0) throw std::string(STRING_VARIANT_MOD_ZERO);
1✔
1821
          _real = fmod(_real, static_cast<double>(right._integer));
1✔
1822
          break;
1✔
1823

1824
        case type_real:
1✔
1825
          if (right._real == 0) throw std::string(STRING_VARIANT_MOD_ZERO);
1✔
1826
          _real = fmod(_real, right._real);
1✔
1827
          break;
1✔
1828

1829
        case type_string:
1✔
1830
          throw std::string(STRING_VARIANT_MOD_REAL_STR);
1✔
1831

1832
        case type_date:
1✔
1833
          throw std::string(STRING_VARIANT_MOD_REAL_DATE);
1✔
1834

1835
        case type_duration:
1✔
1836
          throw std::string(STRING_VARIANT_MOD_REAL_DUR);
1✔
1837
      }
1838
      break;
2✔
1839

1840
    case type_string:
6✔
1841
      throw std::string(STRING_VARIANT_MOD_STR);
6✔
1842

1843
    case type_date:
6✔
1844
      throw std::string(STRING_VARIANT_MOD_DATE);
6✔
1845

1846
    case type_duration:
6✔
1847
      throw std::string(STRING_VARIANT_MOD_DUR);
6✔
1848
  }
1849

1850
  return *this;
4✔
1851
}
36✔
1852

1853
////////////////////////////////////////////////////////////////////////////////
1854
Variant Variant::operator%(const Variant& other) const {
36✔
1855
  Variant left(*this);
36✔
1856
  left %= other;
36✔
1857
  return left;
4✔
1858
}
32✔
1859

1860
////////////////////////////////////////////////////////////////////////////////
1861
Variant::operator std::string() const {
853✔
1862
  switch (_type) {
853✔
1863
    case type_boolean:
13✔
1864
      return std::string(_bool ? "true" : "false");
13✔
1865

1866
    case type_integer: {
49✔
1867
      std::stringstream s;
49✔
1868
      s << _integer;
49✔
1869
      return s.str();
49✔
1870
    }
49✔
1871

1872
    case type_real: {
54✔
1873
      std::stringstream s;
54✔
1874
      s << _real;
54✔
1875
      return s.str();
54✔
1876
    }
54✔
1877

1878
    case type_string:
230✔
1879
      return _string;
230✔
1880

1881
    case type_date:
388✔
1882
      return Datetime(_date).toISOLocalExtended();
776✔
1883

1884
    case type_duration:
119✔
1885
      return Duration(_duration).formatISO();
238✔
1886
  }
1887

1888
  return "";
×
1889
}
1890

1891
////////////////////////////////////////////////////////////////////////////////
1892
void Variant::sqrt() {
1✔
1893
  if (_type == type_string) Lexer::dequote(_string);
1✔
1894

1895
  cast(type_real);
1✔
1896
  if (_real < 0.0) throw std::string(STRING_VARIANT_SQRT_NEG);
1✔
1897
  _real = ::sqrt(_real);
1✔
1898
}
1✔
1899

1900
////////////////////////////////////////////////////////////////////////////////
1901
void Variant::cast(const enum type new_type) {
33,219✔
1902
  // Short circuit.
1903
  if (_type == new_type) return;
33,219✔
1904

1905
  // From type_boolean
1906
  switch (_type) {
11,496✔
1907
    case type_boolean:
126✔
1908
      switch (new_type) {
126✔
NEW
1909
        case type_boolean:
×
NEW
1910
          break;
×
1911
        case type_integer:
22✔
1912
          _integer = _bool ? 1 : 0;
22✔
1913
          break;
22✔
1914
        case type_real:
20✔
1915
          _real = _bool ? 1.0 : 0.0;
20✔
1916
          break;
20✔
1917
        case type_string:
48✔
1918
          _string = _bool ? "true" : "false";
48✔
1919
          break;
48✔
1920
        case type_date:
15✔
1921
          _date = _bool ? 1 : 0;
15✔
1922
          break;
15✔
1923
        case type_duration:
21✔
1924
          _duration = _bool ? 1 : 0;
21✔
1925
          break;
21✔
1926
      }
1927
      break;
126✔
1928

1929
    case type_integer:
188✔
1930
      switch (new_type) {
188✔
1931
        case type_boolean:
43✔
1932
          _bool = _integer == 0 ? false : true;
43✔
1933
          break;
43✔
NEW
1934
        case type_integer:
×
NEW
1935
          break;
×
1936
        case type_real:
28✔
1937
          _real = static_cast<double>(_integer);
28✔
1938
          break;
28✔
1939
        case type_string: {
60✔
1940
          char temp[24];
1941
          snprintf(temp, 24, "%lld", _integer);
60✔
1942
          _string = temp;
60✔
1943
        } break;
60✔
1944
        case type_date:
15✔
1945
          _date = (time_t)_integer;
15✔
1946
          break;
15✔
1947
        case type_duration:
42✔
1948
          _duration = (time_t)_integer;
42✔
1949
          break;
42✔
1950
      }
1951
      break;
188✔
1952

1953
    case type_real:
130✔
1954
      switch (new_type) {
130✔
1955
        case type_boolean:
38✔
1956
          _bool = _real == 0.0 ? false : true;
38✔
1957
          break;
38✔
1958
        case type_integer:
1✔
1959
          _integer = (long long)_real;
1✔
1960
          break;
1✔
NEW
1961
        case type_real:
×
NEW
1962
          break;
×
1963
        case type_string: {
61✔
1964
          char temp[24];
1965
          snprintf(temp, 24, "%g", _real);
61✔
1966
          _string = temp;
61✔
1967
        } break;
61✔
1968
        case type_date:
13✔
1969
          _date = (time_t)(int)_real;
13✔
1970
          break;
13✔
1971
        case type_duration:
17✔
1972
          _duration = (time_t)(int)_real;
17✔
1973
          break;
17✔
1974
      }
1975
      break;
130✔
1976

1977
    case type_string:
10,817✔
1978
      Lexer::dequote(_string);
10,817✔
1979
      switch (new_type) {
10,817✔
1980
        case type_boolean:
262✔
1981
          _bool = (_string.length() == 0 || _string == "0" || _string == "0.0") ? false : true;
262✔
1982
          break;
262✔
1983
        case type_integer:
9,340✔
1984
          _integer =
9,340✔
1985
              (long long)strtol(_string.c_str(), nullptr, (_string.substr(0, 2) == "0x" ? 16 : 10));
9,340✔
1986
          break;
9,340✔
1987
        case type_real:
35✔
1988
          _real = strtod(_string.c_str(), nullptr);
35✔
1989
          break;
35✔
NEW
1990
        case type_string:
×
NEW
1991
          break;
×
1992
        case type_date: {
941✔
1993
          _date = 0;
941✔
1994
          Datetime iso;
941✔
1995
          std::string::size_type pos = 0;
941✔
1996
          if (iso.parse(_string, pos, dateFormat) && pos == _string.length()) {
941✔
1997
            _date = iso.toEpoch();
545✔
1998
            break;
545✔
1999
          }
2000

2001
          pos = 0;
396✔
2002
          Duration isop;
396✔
2003
          if (isop.parse(_string, pos) && pos == _string.length()) {
396✔
NEW
2004
            _date = Datetime().toEpoch() + isop.toTime_t();
×
NEW
2005
            break;
×
2006
          }
2007

2008
          if (dateFormat != "") {
396✔
2009
            _date = Datetime(_string, dateFormat).toEpoch();
384✔
NEW
2010
            break;
×
2011
          }
2012
        } break;
12✔
2013
        case type_duration: {
239✔
2014
          _duration = 0;
239✔
2015
          std::string::size_type pos = 0;
239✔
2016
          Duration iso;
239✔
2017
          if (iso.parse(_string, pos) && pos == _string.length()) {
239✔
2018
            _duration = iso.toTime_t();
221✔
2019
          }
2020
        } break;
239✔
2021
      }
2022
      break;
10,433✔
2023

2024
    case type_date:
82✔
2025
      switch (new_type) {
82✔
2026
        case type_boolean:
38✔
2027
          _bool = _date != 0 ? true : false;
38✔
2028
          break;
38✔
2029
        case type_integer:
1✔
2030
          _integer = (long long)_date;
1✔
2031
          break;
1✔
2032
        case type_real:
2✔
2033
          _real = static_cast<double>(_date);
2✔
2034
          break;
2✔
2035
        case type_string:
34✔
2036
          _string = (std::string) * this;
34✔
2037
          break;
34✔
NEW
2038
        case type_date:
×
NEW
2039
          break;
×
2040
        // TODO: Not exactly correct (should duration convert into date?), but
2041
        // currently needed for symmetry, which is assumed by operators.
2042
        case type_duration:
7✔
2043
          _duration = _date - time(nullptr);
7✔
2044
          break;
7✔
2045
      }
2046
      break;
82✔
2047

2048
    case type_duration:
153✔
2049
      switch (new_type) {
153✔
2050
        case type_boolean:
43✔
2051
          _bool = _duration != 0 ? true : false;
43✔
2052
          break;
43✔
2053
        case type_integer:
1✔
2054
          _integer = (long long)_duration;
1✔
2055
          break;
1✔
2056
        case type_real:
2✔
2057
          _real = static_cast<double>(_duration);
2✔
2058
          break;
2✔
2059
        case type_string:
34✔
2060
          _string = (std::string) * this;
34✔
2061
          break;
34✔
2062
        case type_date:
73✔
2063
          _date = time(nullptr) + _duration;
73✔
2064
          break;
73✔
NEW
2065
        case type_duration:
×
NEW
2066
          break;
×
2067
      }
2068
      break;
153✔
2069
  }
2070

2071
  _type = new_type;
11,112✔
2072
}
2073

2074
////////////////////////////////////////////////////////////////////////////////
2075
int Variant::type() { return _type; }
1,463✔
2076

2077
////////////////////////////////////////////////////////////////////////////////
2078
bool Variant::trivial() const {
394✔
2079
  return (_type == type_integer && _integer == 0) || (_type == type_real && _real == 0.0) ||
394✔
2080
         (_type == type_string && _string == "") || (_type == type_date && _date == 0) ||
1,138✔
2081
         (_type == type_duration && _duration == 0);
744✔
2082
}
2083

2084
////////////////////////////////////////////////////////////////////////////////
2085
bool Variant::get_bool() const { return _bool; }
9,123✔
2086

2087
////////////////////////////////////////////////////////////////////////////////
2088
long long Variant::get_integer() const { return _integer; }
28✔
2089

2090
////////////////////////////////////////////////////////////////////////////////
2091
double Variant::get_real() const { return _real; }
34✔
2092

2093
////////////////////////////////////////////////////////////////////////////////
2094
const std::string& Variant::get_string() const { return _string; }
45✔
2095

2096
////////////////////////////////////////////////////////////////////////////////
2097
time_t Variant::get_date() const { return _date; }
978✔
2098

2099
////////////////////////////////////////////////////////////////////////////////
2100
time_t Variant::get_duration() const { return _duration; }
94✔
2101

2102
////////////////////////////////////////////////////////////////////////////////
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc