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

GothenburgBitFactory / taskwarrior / 13821480083

12 Mar 2025 09:03PM UTC coverage: 85.245% (+0.09%) from 85.153%
13821480083

Pull #3811

github

web-flow
Merge ba1cc9043 into f73b42d23
Pull Request #3811: Release 3.4.0

6 of 6 new or added lines in 1 file covered. (100.0%)

61 existing lines in 4 files now uncovered.

19556 of 22941 relevant lines covered (85.24%)

23391.9 hits per line

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

94.92
/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_MOD_BOOL "Cannot modulo Booleans"
79
#define STRING_VARIANT_MOD_DATE "Cannot modulo date values"
80
#define STRING_VARIANT_MOD_DUR "Cannot modulo duration values"
81
#define STRING_VARIANT_MOD_INT_BOOL "Cannot modulo integer by Boolean"
82
#define STRING_VARIANT_MOD_INT_DATE "Cannot modulo integer by date values"
83
#define STRING_VARIANT_MOD_INT_DUR "Cannot modulo integer by duration values"
84
#define STRING_VARIANT_MOD_INT_STR "Cannot modulo integer by string"
85
#define STRING_VARIANT_MOD_REAL_BOOL "Cannot modulo real by Boolean"
86
#define STRING_VARIANT_MOD_REAL_DUR "Cannot modulo real by duration values"
87
#define STRING_VARIANT_MOD_REAL_DATE "Cannot modulo real numbers by dates"
88
#define STRING_VARIANT_MOD_REAL_STR "Cannot modulo real numbers by strings"
89
#define STRING_VARIANT_MOD_STR "Cannot modulo string values"
90
#define STRING_VARIANT_MOD_ZERO "Cannot modulo zero"
91
#define STRING_VARIANT_SQRT_NEG "Cannot take the square root of a negative number."
92

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

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

109
////////////////////////////////////////////////////////////////////////////////
110
Variant::Variant(const bool value) : _type(Variant::type_boolean), _bool(value) {}
117,945✔
111

112
////////////////////////////////////////////////////////////////////////////////
113
Variant::Variant(const int value) : _type(Variant::type_integer), _integer(value) {}
46,790✔
114

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

118
////////////////////////////////////////////////////////////////////////////////
119
Variant::Variant(const std::string& value) : _type(Variant::type_string), _string(value) {}
118,542✔
120

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

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

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

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

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

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

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

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

156
  left.cast(type_boolean);
7,140✔
157
  right.cast(type_boolean);
7,140✔
158

159
  return left._bool && right._bool;
14,280✔
160
}
7,140✔
161

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

167
  if (left._type == type_string) Lexer::dequote(left._string);
209✔
168

169
  if (right._type == type_string) Lexer::dequote(right._string);
209✔
170

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

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

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

182
  if (left._type == type_string) Lexer::dequote(left._string);
72✔
183

184
  if (right._type == type_string) Lexer::dequote(right._string);
72✔
185

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

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

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

197
  if (left._type == type_string) Lexer::dequote(left._string);
215✔
198

199
  if (right._type == type_string) Lexer::dequote(right._string);
197✔
200

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

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

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

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

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

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

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

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

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

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

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

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

316
          right.cast(type_date);
41✔
317
          return left._date < right._date;
41✔
318
      }
UNCOV
319
      break;
×
320

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

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

UNCOV
337
  return false;
×
338
}
123✔
339

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

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

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

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

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

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

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

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

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

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

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

UNCOV
443
          left.cast(type_date);
×
444
          return left._date <= right._date;
×
445

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

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

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

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

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

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

UNCOV
485
  return false;
×
486
}
3,904✔
487

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

493
  if (left._type == type_string) Lexer::dequote(left._string);
266✔
494

495
  if (right._type == type_string) Lexer::dequote(right._string);
214✔
496

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

UNCOV
633
  return false;
×
634
}
140✔
635

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

UNCOV
781
  return false;
×
782
}
3,901✔
783

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

UNCOV
914
  return false;
×
915
}
1,678✔
916

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

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

926
  if (left._type == type_string) Lexer::dequote(left._string);
2,550✔
927

928
  if (right._type == type_string) Lexer::dequote(right._string);
2,518✔
929

930
  left.cast(type_string);
906✔
931
  right.cast(type_string);
906✔
932

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

936
  if (searchUsingRegex) {
906✔
937
    RX r(pattern, searchCaseSensitive);
894✔
938
    if (r.match(left._string)) return true;
894✔
939

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

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

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

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

970
  return false;
737✔
971
}
906✔
972

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

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

988
  if (left._type == type_string) Lexer::dequote(left._string);
7,844✔
989

990
  if (right._type == type_string) Lexer::dequote(right._string);
7,836✔
991

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

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

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

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

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

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

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

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

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

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

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

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

1086
          int left_len = left._string.length();
762✔
1087
          int right_len = right._string.length();
762✔
1088

1089
          if ((left_len == 0 && right_len != 0) || (left_len != 0 && right_len == 0)) return false;
762✔
1090

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

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

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

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

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

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

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

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

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

UNCOV
1153
  return false;
×
1154
}
2,670✔
1155

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

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

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

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

1177
  if (left._type == type_string) Lexer::dequote(left._string);
14✔
1178

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

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

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

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

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

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

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

1239
  return *this;
2✔
1240
}
1241

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

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

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

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

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

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

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

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

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

1363
  return *this;
113✔
1364
}
253✔
1365

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

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

1377
  if (right._type == type_string) Lexer::dequote(right._string);
118✔
1378

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

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

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

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

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

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

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

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

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

1516
  return *this;
104✔
1517
}
106✔
1518

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

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

1530
  if (right._type == type_string) Lexer::dequote(right._string);
52✔
1531

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1761
        case type_duration:
2✔
1762
          _type = type_real;
2✔
1763
          _real = static_cast<double>(_duration) / static_cast<double>(right._duration);
2✔
1764
          break;
2✔
1765
      }
1766
      break;
4✔
1767
  }
1768

1769
  return *this;
13✔
1770
}
40✔
1771

1772
////////////////////////////////////////////////////////////////////////////////
1773
Variant Variant::operator/(const Variant& other) const {
40✔
1774
  Variant left(*this);
40✔
1775
  left /= other;
40✔
1776
  return left;
13✔
1777
}
27✔
1778

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1861
////////////////////////////////////////////////////////////////////////////////
1862
Variant::operator std::string() const {
888✔
1863
  switch (_type) {
888✔
1864
    case type_boolean:
16✔
1865
      return std::string(_bool ? "true" : "false");
32✔
1866

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

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

1879
    case type_string:
246✔
1880
      return _string;
246✔
1881

1882
    case type_date:
400✔
1883
      return Datetime(_date).toISOLocalExtended();
400✔
1884

1885
    case type_duration:
121✔
1886
      return Duration(_duration).formatISO();
121✔
1887
  }
1888

UNCOV
1889
  return "";
×
1890
}
1891

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

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

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

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

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

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

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

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

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

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

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

2072
  _type = new_type;
11,187✔
2073
}
2074

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

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

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

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

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

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

2097
////////////////////////////////////////////////////////////////////////////////
2098
time_t Variant::get_date() const { return _date; }
1,012✔
2099

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

2103
////////////////////////////////////////////////////////////////////////////////
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

© 2026 Coveralls, Inc