]> granicus.if.org Git - icinga2/blob - lib/base/value-operators.cpp
Merge pull request #7185 from Icinga/bugfix/gelfwriter-wrong-log-facility
[icinga2] / lib / base / value-operators.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "base/value.hpp"
4 #include "base/array.hpp"
5 #include "base/dictionary.hpp"
6 #include "base/datetime.hpp"
7 #include "base/convert.hpp"
8 #include "base/utility.hpp"
9 #include "base/objectlock.hpp"
10 #include <boost/lexical_cast.hpp>
11
12 using namespace icinga;
13
14 Value::operator double() const
15 {
16         const double *value = boost::get<double>(&m_Value);
17
18         if (value)
19                 return *value;
20
21         const bool *fvalue = boost::get<bool>(&m_Value);
22
23         if (fvalue)
24                 return *fvalue;
25
26         if (IsEmpty())
27                 return 0;
28
29         try {
30                 return boost::lexical_cast<double>(m_Value);
31         } catch (const std::exception&) {
32                 std::ostringstream msgbuf;
33                 msgbuf << "Can't convert '" << *this << "' to a floating point number.";
34                 BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str()));
35         }
36 }
37
38 Value::operator String() const
39 {
40         Object *object;
41
42         switch (GetType()) {
43                 case ValueEmpty:
44                         return String();
45                 case ValueNumber:
46                         return Convert::ToString(boost::get<double>(m_Value));
47                 case ValueBoolean:
48                         if (boost::get<bool>(m_Value))
49                                 return "true";
50                         else
51                                 return "false";
52                 case ValueString:
53                         return boost::get<String>(m_Value);
54                 case ValueObject:
55                         object = boost::get<Object::Ptr>(m_Value).get();
56                         return object->ToString();
57                 default:
58                         BOOST_THROW_EXCEPTION(std::runtime_error("Unknown value type."));
59         }
60 }
61
62 std::ostream& icinga::operator<<(std::ostream& stream, const Value& value)
63 {
64         if (value.IsBoolean())
65                 stream << static_cast<int>(value);
66         else
67                 stream << static_cast<String>(value);
68
69         return stream;
70 }
71
72 std::istream& icinga::operator>>(std::istream& stream, Value& value)
73 {
74         String tstr;
75         stream >> tstr;
76         value = tstr;
77         return stream;
78 }
79
80 bool Value::operator==(bool rhs) const
81 {
82         return *this == Value(rhs);
83 }
84
85 bool Value::operator!=(bool rhs) const
86 {
87         return !(*this == rhs);
88 }
89
90 bool Value::operator==(int rhs) const
91 {
92         return *this == Value(rhs);
93 }
94
95 bool Value::operator!=(int rhs) const
96 {
97         return !(*this == rhs);
98 }
99
100 bool Value::operator==(double rhs) const
101 {
102         return *this == Value(rhs);
103 }
104
105 bool Value::operator!=(double rhs) const
106 {
107         return !(*this == rhs);
108 }
109
110 bool Value::operator==(const char *rhs) const
111 {
112         return static_cast<String>(*this) == rhs;
113 }
114
115 bool Value::operator!=(const char *rhs) const
116 {
117         return !(*this == rhs);
118 }
119
120 bool Value::operator==(const String& rhs) const
121 {
122         return static_cast<String>(*this) == rhs;
123 }
124
125 bool Value::operator!=(const String& rhs) const
126 {
127         return !(*this == rhs);
128 }
129
130 bool Value::operator==(const Value& rhs) const
131 {
132         if (IsNumber() && rhs.IsNumber())
133                 return Get<double>() == rhs.Get<double>();
134         else if ((IsBoolean() || IsNumber()) && (rhs.IsBoolean() || rhs.IsNumber()) && !(IsEmpty() && rhs.IsEmpty()))
135                 return static_cast<double>(*this) == static_cast<double>(rhs);
136
137         if (IsString() && rhs.IsString())
138                 return Get<String>() == rhs.Get<String>();
139         else if ((IsString() || IsEmpty()) && (rhs.IsString() || rhs.IsEmpty()) && !(IsEmpty() && rhs.IsEmpty()))
140                 return static_cast<String>(*this) == static_cast<String>(rhs);
141
142         if (IsEmpty() != rhs.IsEmpty())
143                 return false;
144
145         if (IsEmpty())
146                 return true;
147
148         if (IsObject() != rhs.IsObject())
149                 return false;
150
151         if (IsObject()) {
152                 if (IsObjectType<DateTime>() && rhs.IsObjectType<DateTime>()) {
153                         DateTime::Ptr dt1 = *this;
154                         DateTime::Ptr dt2 = rhs;
155
156                         return dt1->GetValue() == dt2->GetValue();
157                 }
158
159                 if (IsObjectType<Array>() && rhs.IsObjectType<Array>()) {
160                         Array::Ptr arr1 = *this;
161                         Array::Ptr arr2 = rhs;
162
163                         if (arr1 == arr2)
164                                 return true;
165
166                         if (arr1->GetLength() != arr2->GetLength())
167                                 return false;
168
169                         for (Array::SizeType i = 0; i < arr1->GetLength(); i++) {
170                                 if (arr1->Get(i) != arr2->Get(i))
171                                         return false;
172                         }
173
174                         return true;
175                 }
176
177                 return Get<Object::Ptr>() == rhs.Get<Object::Ptr>();
178         }
179
180         return false;
181 }
182
183 bool Value::operator!=(const Value& rhs) const
184 {
185         return !(*this == rhs);
186 }
187
188 Value icinga::operator+(const Value& lhs, const char *rhs)
189 {
190         return lhs + Value(rhs);
191 }
192
193 Value icinga::operator+(const char *lhs, const Value& rhs)
194 {
195         return Value(lhs) + rhs;
196 }
197
198 Value icinga::operator+(const Value& lhs, const String& rhs)
199 {
200         return lhs + Value(rhs);
201 }
202
203 Value icinga::operator+(const String& lhs, const Value& rhs)
204 {
205         return Value(lhs) + rhs;
206 }
207
208 Value icinga::operator+(const Value& lhs, const Value& rhs)
209 {
210         if ((lhs.IsEmpty() || lhs.IsNumber()) && !lhs.IsString() && (rhs.IsEmpty() || rhs.IsNumber()) && !rhs.IsString() && !(lhs.IsEmpty() && rhs.IsEmpty()))
211                 return static_cast<double>(lhs) + static_cast<double>(rhs);
212         if ((lhs.IsString() || lhs.IsEmpty() || lhs.IsNumber()) && (rhs.IsString() || rhs.IsEmpty() || rhs.IsNumber()) && (!(lhs.IsEmpty() && rhs.IsEmpty()) || lhs.IsString() || rhs.IsString()))
213                 return static_cast<String>(lhs) + static_cast<String>(rhs);
214         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
215                 return static_cast<double>(lhs) + static_cast<double>(rhs);
216         else if (lhs.IsObjectType<DateTime>() && rhs.IsNumber())
217                 return new DateTime(Convert::ToDateTimeValue(lhs) + rhs);
218         else if ((lhs.IsObjectType<Array>() || lhs.IsEmpty()) && (rhs.IsObjectType<Array>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
219                 Array::Ptr result = new Array();
220                 if (!lhs.IsEmpty())
221                         static_cast<Array::Ptr>(lhs)->CopyTo(result);
222                 if (!rhs.IsEmpty())
223                         static_cast<Array::Ptr>(rhs)->CopyTo(result);
224                 return result;
225         } else if ((lhs.IsObjectType<Dictionary>() || lhs.IsEmpty()) && (rhs.IsObjectType<Dictionary>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
226                 Dictionary::Ptr result = new Dictionary();
227                 if (!lhs.IsEmpty())
228                         static_cast<Dictionary::Ptr>(lhs)->CopyTo(result);
229                 if (!rhs.IsEmpty())
230                         static_cast<Dictionary::Ptr>(rhs)->CopyTo(result);
231                 return result;
232         } else {
233                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator + cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
234         }
235 }
236
237 Value icinga::operator+(const Value& lhs, double rhs)
238 {
239         return lhs + Value(rhs);
240 }
241
242 Value icinga::operator+(double lhs, const Value& rhs)
243 {
244         return Value(lhs) + rhs;
245 }
246
247 Value icinga::operator+(const Value& lhs, int rhs)
248 {
249         return lhs + Value(rhs);
250 }
251
252 Value icinga::operator+(int lhs, const Value& rhs)
253 {
254         return Value(lhs) + rhs;
255 }
256
257 Value icinga::operator-(const Value& lhs, const Value& rhs)
258 {
259         if ((lhs.IsNumber() || lhs.IsEmpty()) && !lhs.IsString() && (rhs.IsNumber() || rhs.IsEmpty()) && !rhs.IsString() && !(lhs.IsEmpty() && rhs.IsEmpty()))
260                 return static_cast<double>(lhs) - static_cast<double>(rhs);
261         else if (lhs.IsObjectType<DateTime>() && rhs.IsNumber())
262                 return new DateTime(Convert::ToDateTimeValue(lhs) - rhs);
263         else if (lhs.IsObjectType<DateTime>() && rhs.IsObjectType<DateTime>())
264                 return Convert::ToDateTimeValue(lhs) - Convert::ToDateTimeValue(rhs);
265         else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
266                 return new DateTime(Convert::ToDateTimeValue(lhs) - Convert::ToDateTimeValue(rhs));
267         else if ((lhs.IsObjectType<Array>() || lhs.IsEmpty()) && (rhs.IsObjectType<Array>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
268                 if (lhs.IsEmpty())
269                         return new Array();
270
271                 ArrayData result;
272                 Array::Ptr left = lhs;
273                 Array::Ptr right = rhs;
274
275                 ObjectLock olock(left);
276                 for (const Value& lv : left) {
277                         bool found = false;
278                         ObjectLock xlock(right);
279                         for (const Value& rv : right) {
280                                 if (lv == rv) {
281                                         found = true;
282                                         break;
283                                 }
284                         }
285
286                         if (found)
287                                 continue;
288
289                         result.push_back(lv);
290                 }
291
292                 return new Array(std::move(result));
293         } else
294                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator - cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
295 }
296
297 Value icinga::operator-(const Value& lhs, double rhs)
298 {
299         return lhs - Value(rhs);
300 }
301
302 Value icinga::operator-(double lhs, const Value& rhs)
303 {
304         return Value(lhs) - rhs;
305 }
306
307 Value icinga::operator-(const Value& lhs, int rhs)
308 {
309         return lhs - Value(rhs);
310 }
311
312 Value icinga::operator-(int lhs, const Value& rhs)
313 {
314         return Value(lhs) - rhs;
315 }
316
317 Value icinga::operator*(const Value& lhs, const Value& rhs)
318 {
319         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
320                 return static_cast<double>(lhs) * static_cast<double>(rhs);
321         else
322                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator * cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
323 }
324
325 Value icinga::operator*(const Value& lhs, double rhs)
326 {
327         return lhs * Value(rhs);
328 }
329
330 Value icinga::operator*(double lhs, const Value& rhs)
331 {
332         return Value(lhs) * rhs;
333 }
334
335 Value icinga::operator*(const Value& lhs, int rhs)
336 {
337         return lhs * Value(rhs);
338 }
339
340 Value icinga::operator*(int lhs, const Value& rhs)
341 {
342         return Value(lhs) * rhs;
343 }
344
345 Value icinga::operator/(const Value& lhs, const Value& rhs)
346 {
347         if (rhs.IsEmpty())
348                 BOOST_THROW_EXCEPTION(std::invalid_argument("Right-hand side argument for operator / is Empty."));
349         else if ((lhs.IsEmpty() || lhs.IsNumber()) && rhs.IsNumber()) {
350                 if (static_cast<double>(rhs) == 0)
351                         BOOST_THROW_EXCEPTION(std::invalid_argument("Right-hand side argument for operator / is 0."));
352
353                 return static_cast<double>(lhs) / static_cast<double>(rhs);
354         } else
355                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator / cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
356 }
357
358 Value icinga::operator/(const Value& lhs, double rhs)
359 {
360         return lhs / Value(rhs);
361 }
362
363 Value icinga::operator/(double lhs, const Value& rhs)
364 {
365         return Value(lhs) / rhs;
366 }
367
368 Value icinga::operator/(const Value& lhs, int rhs)
369 {
370         return lhs / Value(rhs);
371 }
372
373 Value icinga::operator/(int lhs, const Value& rhs)
374 {
375         return Value(lhs) / rhs;
376 }
377
378 Value icinga::operator%(const Value& lhs, const Value& rhs)
379 {
380         if (rhs.IsEmpty())
381                 BOOST_THROW_EXCEPTION(std::invalid_argument("Right-hand side argument for operator % is Empty."));
382         else if ((rhs.IsNumber() || lhs.IsNumber()) && rhs.IsNumber()) {
383                 if (static_cast<double>(rhs) == 0)
384                         BOOST_THROW_EXCEPTION(std::invalid_argument("Right-hand side argument for operator % is 0."));
385
386                 return static_cast<int>(lhs) % static_cast<int>(rhs);
387         } else
388                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator % cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
389 }
390
391 Value icinga::operator%(const Value& lhs, double rhs)
392 {
393         return lhs % Value(rhs);
394 }
395
396 Value icinga::operator%(double lhs, const Value& rhs)
397 {
398         return Value(lhs) % rhs;
399 }
400
401 Value icinga::operator%(const Value& lhs, int rhs)
402 {
403         return lhs % Value(rhs);
404 }
405
406 Value icinga::operator%(int lhs, const Value& rhs)
407 {
408         return Value(lhs) % rhs;
409 }
410
411 Value icinga::operator^(const Value& lhs, const Value& rhs)
412 {
413         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
414                 return static_cast<int>(lhs) ^ static_cast<int>(rhs);
415         else
416                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator & cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
417 }
418
419 Value icinga::operator^(const Value& lhs, double rhs)
420 {
421         return lhs ^ Value(rhs);
422 }
423
424 Value icinga::operator^(double lhs, const Value& rhs)
425 {
426         return Value(lhs) ^ rhs;
427 }
428
429 Value icinga::operator^(const Value& lhs, int rhs)
430 {
431         return lhs ^ Value(rhs);
432 }
433
434 Value icinga::operator^(int lhs, const Value& rhs)
435 {
436         return Value(lhs) ^ rhs;
437 }
438
439 Value icinga::operator&(const Value& lhs, const Value& rhs)
440 {
441         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
442                 return static_cast<int>(lhs) & static_cast<int>(rhs);
443         else
444                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator & cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
445 }
446
447 Value icinga::operator&(const Value& lhs, double rhs)
448 {
449         return lhs & Value(rhs);
450 }
451
452 Value icinga::operator&(double lhs, const Value& rhs)
453 {
454         return Value(lhs) & rhs;
455 }
456
457 Value icinga::operator&(const Value& lhs, int rhs)
458 {
459         return lhs & Value(rhs);
460 }
461
462 Value icinga::operator&(int lhs, const Value& rhs)
463 {
464         return Value(lhs) & rhs;
465 }
466
467 Value icinga::operator|(const Value& lhs, const Value& rhs)
468 {
469         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
470                 return static_cast<int>(lhs) | static_cast<int>(rhs);
471         else
472                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator | cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
473 }
474
475 Value icinga::operator|(const Value& lhs, double rhs)
476 {
477         return lhs | Value(rhs);
478 }
479
480 Value icinga::operator|(double lhs, const Value& rhs)
481 {
482         return Value(lhs) | rhs;
483 }
484
485 Value icinga::operator|(const Value& lhs, int rhs)
486 {
487         return lhs | Value(rhs);
488 }
489
490 Value icinga::operator|(int lhs, const Value& rhs)
491 {
492         return Value(lhs) | rhs;
493 }
494
495 Value icinga::operator<<(const Value& lhs, const Value& rhs)
496 {
497         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
498                 return static_cast<int>(lhs) << static_cast<int>(rhs);
499         else
500                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator << cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
501 }
502
503 Value icinga::operator<<(const Value& lhs, double rhs)
504 {
505         return lhs << Value(rhs);
506 }
507
508 Value icinga::operator<<(double lhs, const Value& rhs)
509 {
510         return Value(lhs) << rhs;
511 }
512
513 Value icinga::operator<<(const Value& lhs, int rhs)
514 {
515         return lhs << Value(rhs);
516 }
517
518 Value icinga::operator<<(int lhs, const Value& rhs)
519 {
520         return Value(lhs) << rhs;
521 }
522
523 Value icinga::operator>>(const Value& lhs, const Value& rhs)
524 {
525         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
526                 return static_cast<int>(lhs) >> static_cast<int>(rhs);
527         else
528                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator >> cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
529 }
530
531 Value icinga::operator>>(const Value& lhs, double rhs)
532 {
533         return lhs >> Value(rhs);
534 }
535
536 Value icinga::operator>>(double lhs, const Value& rhs)
537 {
538         return Value(lhs) >> rhs;
539 }
540
541 Value icinga::operator>>(const Value& lhs, int rhs)
542 {
543         return lhs >> Value(rhs);
544 }
545
546 Value icinga::operator>>(int lhs, const Value& rhs)
547 {
548         return Value(lhs) >> rhs;
549 }
550
551 bool icinga::operator<(const Value& lhs, const Value& rhs)
552 {
553         if (lhs.IsString() && rhs.IsString())
554                 return static_cast<String>(lhs) < static_cast<String>(rhs);
555         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
556                 return static_cast<double>(lhs) < static_cast<double>(rhs);
557         else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
558                 return Convert::ToDateTimeValue(lhs) < Convert::ToDateTimeValue(rhs);
559         else if (lhs.IsObjectType<Array>() && rhs.IsObjectType<Array>()) {
560                 Array::Ptr larr = lhs;
561                 Array::Ptr rarr = rhs;
562
563                 ObjectLock llock(larr);
564                 ObjectLock rlock(rarr);
565
566                 Array::SizeType llen = larr->GetLength();
567                 Array::SizeType rlen = rarr->GetLength();
568
569                 for (Array::SizeType i = 0; i < std::max(llen, rlen); i++) {
570                         Value lval = (i >= llen) ? Empty : larr->Get(i);
571                         Value rval = (i >= rlen) ? Empty : rarr->Get(i);
572
573                         if (lval < rval)
574                                 return true;
575                         else if (lval > rval)
576                                 return false;
577                 }
578
579                 return false;
580         } else
581                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator < cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
582 }
583
584 bool icinga::operator<(const Value& lhs, double rhs)
585 {
586         return lhs < Value(rhs);
587 }
588
589 bool icinga::operator<(double lhs, const Value& rhs)
590 {
591         return Value(lhs) < rhs;
592 }
593
594 bool icinga::operator<(const Value& lhs, int rhs)
595 {
596         return lhs < Value(rhs);
597 }
598
599 bool icinga::operator<(int lhs, const Value& rhs)
600 {
601         return Value(lhs) < rhs;
602 }
603
604 bool icinga::operator>(const Value& lhs, const Value& rhs)
605 {
606         if (lhs.IsString() && rhs.IsString())
607                 return static_cast<String>(lhs) > static_cast<String>(rhs);
608         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
609                 return static_cast<double>(lhs) > static_cast<double>(rhs);
610         else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
611                 return Convert::ToDateTimeValue(lhs) > Convert::ToDateTimeValue(rhs);
612         else if (lhs.IsObjectType<Array>() && rhs.IsObjectType<Array>()) {
613                 Array::Ptr larr = lhs;
614                 Array::Ptr rarr = rhs;
615
616                 ObjectLock llock(larr);
617                 ObjectLock rlock(rarr);
618
619                 Array::SizeType llen = larr->GetLength();
620                 Array::SizeType rlen = rarr->GetLength();
621
622                 for (Array::SizeType i = 0; i < std::max(llen, rlen); i++) {
623                         Value lval = (i >= llen) ? Empty : larr->Get(i);
624                         Value rval = (i >= rlen) ? Empty : rarr->Get(i);
625
626                         if (lval > rval)
627                                 return true;
628                         else if (lval < rval)
629                                 return false;
630                 }
631
632                 return false;
633         } else
634                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator > cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
635 }
636
637 bool icinga::operator>(const Value& lhs, double rhs)
638 {
639         return lhs > Value(rhs);
640 }
641
642 bool icinga::operator>(double lhs, const Value& rhs)
643 {
644         return Value(lhs) > rhs;
645 }
646
647 bool icinga::operator>(const Value& lhs, int rhs)
648 {
649         return lhs > Value(rhs);
650 }
651
652 bool icinga::operator>(int lhs, const Value& rhs)
653 {
654         return Value(lhs) > rhs;
655 }
656
657 bool icinga::operator<=(const Value& lhs, const Value& rhs)
658 {
659         if (lhs.IsString() && rhs.IsString())
660                 return static_cast<String>(lhs) <= static_cast<String>(rhs);
661         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
662                 return static_cast<double>(lhs) <= static_cast<double>(rhs);
663         else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
664                 return Convert::ToDateTimeValue(lhs) <= Convert::ToDateTimeValue(rhs);
665         else
666                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator <= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
667 }
668
669 bool icinga::operator<=(const Value& lhs, double rhs)
670 {
671         return lhs <= Value(rhs);
672 }
673
674 bool icinga::operator<=(double lhs, const Value& rhs)
675 {
676         return Value(lhs) <= rhs;
677 }
678
679 bool icinga::operator<=(const Value& lhs, int rhs)
680 {
681         return lhs <= Value(rhs);
682 }
683
684 bool icinga::operator<=(int lhs, const Value& rhs)
685 {
686         return Value(lhs) <= rhs;
687 }
688
689 bool icinga::operator>=(const Value& lhs, const Value& rhs)
690 {
691         if (lhs.IsString() && rhs.IsString())
692                 return static_cast<String>(lhs) >= static_cast<String>(rhs);
693         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
694                 return static_cast<double>(lhs) >= static_cast<double>(rhs);
695         else if ((lhs.IsObjectType<DateTime>() || lhs.IsEmpty()) && (rhs.IsObjectType<DateTime>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
696                 return Convert::ToDateTimeValue(lhs) >= Convert::ToDateTimeValue(rhs);
697         else
698                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator >= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
699 }
700
701 bool icinga::operator>=(const Value& lhs, double rhs)
702 {
703         return lhs >= Value(rhs);
704 }
705
706 bool icinga::operator>=(double lhs, const Value& rhs)
707 {
708         return Value(lhs) >= rhs;
709 }
710
711 bool icinga::operator>=(const Value& lhs, int rhs)
712 {
713         return lhs >= Value(rhs);
714 }
715
716 bool icinga::operator>=(int lhs, const Value& rhs)
717 {
718         return Value(lhs) >= rhs;
719 }