]> granicus.if.org Git - icinga2/blob - lib/base/value-operators.cpp
Merge branch 'feature/config-parser-5846' into next
[icinga2] / lib / base / value-operators.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "base/application.h"
21 #include "base/array.h"
22 #include "base/logger_fwd.h"
23 #include "base/utility.h"
24 #include <cJSON.h>
25 #include <boost/lexical_cast.hpp>
26
27 using namespace icinga;
28
29 Value::operator double(void) const
30 {
31         const double *value = boost::get<double>(&m_Value);
32
33         if (value)
34                 return *value;
35
36         if (IsEmpty())
37                 return 0;
38
39         return boost::lexical_cast<double>(m_Value);
40 }
41
42 Value::operator String(void) const
43 {
44         Object *object;
45         double integral, fractional;
46
47         switch (GetType()) {
48                 case ValueEmpty:
49                         return String();
50                 case ValueNumber:
51                         fractional = modf(boost::get<double>(m_Value), &integral);
52
53                         if (fractional != 0)
54                                 return boost::lexical_cast<String>(m_Value);
55                         else
56                                 return boost::lexical_cast<String>((long)integral);
57                 case ValueString:
58                         return boost::get<String>(m_Value);
59                 case ValueObject:
60                         object = boost::get<Object::Ptr>(m_Value).get();
61                         return "Object of type '" + Utility::GetTypeName(typeid(*object)) + "'";
62                 default:
63                         BOOST_THROW_EXCEPTION(std::runtime_error("Unknown value type."));
64         }
65 }
66
67 std::ostream& icinga::operator<<(std::ostream& stream, const Value& value)
68 {
69         stream << static_cast<String>(value);
70         return stream;
71 }
72
73 std::istream& icinga::operator>>(std::istream& stream, Value& value)
74 {
75         String tstr;
76         stream >> tstr;
77         value = tstr;
78         return stream;
79 }
80
81 bool Value::operator==(bool rhs) const
82 {
83         return *this == Value(rhs);
84 }
85
86 bool Value::operator!=(bool rhs) const
87 {
88         return !(*this == rhs);
89 }
90
91 bool Value::operator==(int rhs) const
92 {
93         return *this == Value(rhs);
94 }
95
96 bool Value::operator!=(int rhs) const
97 {
98         return !(*this == rhs);
99 }
100
101 bool Value::operator==(double rhs) const
102 {
103         return *this == Value(rhs);
104 }
105
106 bool Value::operator!=(double rhs) const
107 {
108         return !(*this == rhs);
109 }
110
111 bool Value::operator==(const char *rhs) const
112 {
113         return static_cast<String>(*this) == rhs;
114 }
115
116 bool Value::operator!=(const char *rhs) const
117 {
118         return !(*this == rhs);
119 }
120
121 bool Value::operator==(const String& rhs) const
122 {
123         return static_cast<String>(*this) == rhs;
124 }
125
126 bool Value::operator!=(const String& rhs) const
127 {
128         return !(*this == rhs);
129 }
130
131 bool Value::operator==(const Value& rhs) const
132 {
133         if (IsEmpty() != rhs.IsEmpty())
134                 return false;
135
136         if (IsEmpty())
137                 return true;
138
139         if (IsObject() != rhs.IsObject())
140                 return false;
141
142         if (IsObject()) {
143                 if (IsObjectType<Array>() && rhs.IsObjectType<Array>()) {
144                         Array::Ptr arr1 = *this;
145                         Array::Ptr arr2 = rhs;
146
147                         if (arr1 == arr2)
148                                 return true;
149
150                         if (arr1->GetLength() != arr2->GetLength())
151                                 return false;
152
153                         for (int i = 0; i < arr1->GetLength(); i++) {
154                                 if (arr1->Get(i) != arr2->Get(i))
155                                         return false;
156                         }
157
158                         return true;
159                 }
160
161                 return static_cast<Object::Ptr>(*this) == static_cast<Object::Ptr>(rhs);
162         }
163
164         if ((IsNumber() || IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(IsEmpty() && rhs.IsEmpty()))
165                 return static_cast<double>(*this) == static_cast<double>(rhs);
166
167         if ((IsString() || IsEmpty()) && (rhs.IsString() || rhs.IsEmpty()) && !(IsEmpty() && rhs.IsEmpty()))
168                 return static_cast<String>(*this) == static_cast<String>(rhs);
169
170         return false;
171 }
172
173 bool Value::operator!=(const Value& rhs) const
174 {
175         return !(*this == rhs);
176 }
177
178 Value icinga::operator+(const Value& lhs, const char *rhs)
179 {
180         return lhs + Value(rhs);
181 }
182
183 Value icinga::operator+(const char *lhs, const Value& rhs)
184 {
185         return Value(lhs) + rhs;
186 }
187
188 Value icinga::operator+(const Value& lhs, const String& rhs)
189 {
190         return lhs + Value(rhs);
191 }
192
193 Value icinga::operator+(const String& lhs, const Value& rhs)
194 {
195         return Value(lhs) + rhs;
196 }
197
198 Value icinga::operator+(const Value& lhs, const Value& rhs)
199 {
200         if ((lhs.IsString() || lhs.IsEmpty()) && (rhs.IsString() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
201                 return static_cast<String>(lhs) + static_cast<String>(rhs);
202         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
203                 return static_cast<double>(lhs) + static_cast<double>(rhs);
204         else if ((lhs.IsObjectType<Array>() || lhs.IsEmpty()) && (rhs.IsObjectType<Array>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
205                 Array::Ptr result = make_shared<Array>();
206                 if (!lhs.IsEmpty())
207                         static_cast<Array::Ptr>(lhs)->CopyTo(result);
208                 if (!rhs.IsEmpty())
209                         static_cast<Array::Ptr>(rhs)->CopyTo(result);
210                 return result;
211         } else if ((lhs.IsObjectType<Dictionary>() || lhs.IsEmpty()) && (rhs.IsObjectType<Dictionary>() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty())) {
212                 Dictionary::Ptr result = make_shared<Dictionary>();
213                 if (!lhs.IsEmpty())
214                         static_cast<Dictionary::Ptr>(lhs)->CopyTo(result);
215                 if (!rhs.IsEmpty())
216                         static_cast<Dictionary::Ptr>(rhs)->CopyTo(result);
217                 return result;
218         } else {
219                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator + cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
220         }
221 }
222
223 Value icinga::operator+(const Value& lhs, double rhs)
224 {
225         return lhs + Value(rhs);
226 }
227
228 Value icinga::operator+(double lhs, const Value& rhs)
229 {
230         return Value(lhs) + rhs;
231 }
232
233 Value icinga::operator+(const Value& lhs, int rhs)
234 {
235         return lhs + Value(rhs);
236 }
237
238 Value icinga::operator+(int lhs, const Value& rhs)
239 {
240         return Value(lhs) + rhs;
241 }
242
243 Value icinga::operator-(const Value& lhs, const Value& rhs)
244 {
245         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
246                 return static_cast<double>(lhs) - static_cast<double>(rhs);
247         else
248                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator - cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
249 }
250
251 Value icinga::operator-(const Value& lhs, double rhs)
252 {
253         return lhs - Value(rhs);
254 }
255
256 Value icinga::operator-(double lhs, const Value& rhs)
257 {
258         return Value(lhs) - rhs;
259 }
260
261 Value icinga::operator-(const Value& lhs, int rhs)
262 {
263         return lhs - Value(rhs);
264 }
265
266 Value icinga::operator-(int lhs, const Value& rhs)
267 {
268         return Value(lhs) - rhs;
269 }
270
271 Value icinga::operator*(const Value& lhs, const Value& rhs)
272 {
273         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
274                 return static_cast<double>(lhs) * static_cast<double>(rhs);
275         else
276                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator * cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
277 }
278
279 Value icinga::operator*(const Value& lhs, double rhs)
280 {
281         return lhs * Value(rhs);
282 }
283
284 Value icinga::operator*(double lhs, const Value& rhs)
285 {
286         return Value(lhs) * rhs;
287 }
288
289 Value icinga::operator*(const Value& lhs, int rhs)
290 {
291         return lhs * Value(rhs);
292 }
293
294 Value icinga::operator*(int lhs, const Value& rhs)
295 {
296         return Value(lhs) * rhs;
297 }
298
299 Value icinga::operator/(const Value& lhs, const Value& rhs)
300 {
301         if (lhs.IsEmpty())
302                 return 0;
303         else if (rhs.IsEmpty())
304                 BOOST_THROW_EXCEPTION(std::invalid_argument("Right-hand side argument for operator / is Empty."));
305         else if (lhs.IsNumber() && rhs.IsNumber()) {
306                 if (static_cast<double>(rhs) == 0)
307                         BOOST_THROW_EXCEPTION(std::invalid_argument("Right-hand side argument for operator / is 0."));
308
309                 return static_cast<double>(lhs) / static_cast<double>(rhs);
310         } else
311                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator / cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
312 }
313
314 Value icinga::operator/(const Value& lhs, double rhs)
315 {
316         return lhs / Value(rhs);
317 }
318
319 Value icinga::operator/(double lhs, const Value& rhs)
320 {
321         return Value(lhs) / rhs;
322 }
323
324 Value icinga::operator/(const Value& lhs, int rhs)
325 {
326         return lhs / Value(rhs);
327 }
328
329 Value icinga::operator/(int lhs, const Value& rhs)
330 {
331         return Value(lhs) / rhs;
332 }
333
334 Value icinga::operator&(const Value& lhs, const Value& rhs)
335 {
336         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
337                 return static_cast<int>(lhs) & static_cast<int>(rhs);
338         else
339                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator & cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
340 }
341
342 Value icinga::operator&(const Value& lhs, double rhs)
343 {
344         return lhs & Value(rhs);
345 }
346
347 Value icinga::operator&(double lhs, const Value& rhs)
348 {
349         return Value(lhs) & rhs;
350 }
351
352 Value icinga::operator&(const Value& lhs, int rhs)
353 {
354         return lhs & Value(rhs);
355 }
356
357 Value icinga::operator&(int lhs, const Value& rhs)
358 {
359         return Value(lhs) & rhs;
360 }
361
362 Value icinga::operator|(const Value& lhs, const Value& rhs)
363 {
364         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
365                 return static_cast<int>(lhs) | static_cast<int>(rhs);
366         else
367                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator | cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
368 }
369
370 Value icinga::operator|(const Value& lhs, double rhs)
371 {
372         return lhs | Value(rhs);
373 }
374
375 Value icinga::operator|(double lhs, const Value& rhs)
376 {
377         return Value(lhs) | rhs;
378 }
379
380 Value icinga::operator|(const Value& lhs, int rhs)
381 {
382         return lhs | Value(rhs);
383 }
384
385 Value icinga::operator|(int lhs, const Value& rhs)
386 {
387         return Value(lhs) | rhs;
388 }
389
390 Value icinga::operator<<(const Value& lhs, const Value& rhs)
391 {
392         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
393                 return static_cast<int>(lhs) << static_cast<int>(rhs);
394         else
395                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator << cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
396 }
397
398 Value icinga::operator<<(const Value& lhs, double rhs)
399 {
400         return lhs << Value(rhs);
401 }
402
403 Value icinga::operator<<(double lhs, const Value& rhs)
404 {
405         return Value(lhs) << rhs;
406 }
407
408 Value icinga::operator<<(const Value& lhs, int rhs)
409 {
410         return lhs << Value(rhs);
411 }
412
413 Value icinga::operator<<(int lhs, const Value& rhs)
414 {
415         return Value(lhs) << rhs;
416 }
417
418 Value icinga::operator>>(const Value& lhs, const Value& rhs)
419 {
420         if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
421                 return static_cast<int>(lhs) >> static_cast<int>(rhs);
422         else
423                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator >> cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
424 }
425
426 Value icinga::operator>>(const Value& lhs, double rhs)
427 {
428         return lhs >> Value(rhs);
429 }
430
431 Value icinga::operator>>(double lhs, const Value& rhs)
432 {
433         return Value(lhs) >> rhs;
434 }
435
436 Value icinga::operator>>(const Value& lhs, int rhs)
437 {
438         return lhs >> Value(rhs);
439 }
440
441 Value icinga::operator>>(int lhs, const Value& rhs)
442 {
443         return Value(lhs) >> rhs;
444 }
445
446 Value icinga::operator<(const Value& lhs, const Value& rhs)
447 {
448         if (lhs.IsString() && rhs.IsString())
449                 return static_cast<String>(lhs) < static_cast<String>(rhs);
450         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
451                 return static_cast<int>(lhs) < static_cast<int>(rhs);
452         else if (lhs.GetTypeName() != rhs.GetTypeName())
453                 return lhs.GetTypeName() < rhs.GetTypeName();
454         else
455                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator < cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
456 }
457
458 Value icinga::operator<(const Value& lhs, double rhs)
459 {
460         return lhs < Value(rhs);
461 }
462
463 Value icinga::operator<(double lhs, const Value& rhs)
464 {
465         return Value(lhs) < rhs;
466 }
467
468 Value icinga::operator<(const Value& lhs, int rhs)
469 {
470         return lhs < Value(rhs);
471 }
472
473 Value icinga::operator<(int lhs, const Value& rhs)
474 {
475         return Value(lhs) < rhs;
476 }
477
478 Value icinga::operator>(const Value& lhs, const Value& rhs)
479 {
480         if (lhs.IsString() && rhs.IsString())
481                 return static_cast<String>(lhs) > static_cast<String>(rhs);
482         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
483                 return static_cast<int>(lhs) > static_cast<int>(rhs);
484         else if (lhs.GetTypeName() != rhs.GetTypeName())
485                 return lhs.GetTypeName() > rhs.GetTypeName();
486         else
487                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator > cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
488 }
489
490 Value icinga::operator>(const Value& lhs, double rhs)
491 {
492         return lhs > Value(rhs);
493 }
494
495 Value icinga::operator>(double lhs, const Value& rhs)
496 {
497         return Value(lhs) > rhs;
498 }
499
500 Value icinga::operator>(const Value& lhs, int rhs)
501 {
502         return lhs > Value(rhs);
503 }
504
505 Value icinga::operator>(int lhs, const Value& rhs)
506 {
507         return Value(lhs) > rhs;
508 }
509
510 Value icinga::operator<=(const Value& lhs, const Value& rhs)
511 {
512         if (lhs.IsString() && rhs.IsString())
513                 return static_cast<String>(lhs) <= static_cast<String>(rhs);
514         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
515                 return static_cast<int>(lhs) <= static_cast<int>(rhs);
516         else if (lhs.GetTypeName() != rhs.GetTypeName())
517                 return lhs.GetTypeName() <= rhs.GetTypeName();
518         else
519                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator <= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
520 }
521
522 Value icinga::operator<=(const Value& lhs, double rhs)
523 {
524         return lhs <= Value(rhs);
525 }
526
527 Value icinga::operator<=(double lhs, const Value& rhs)
528 {
529         return Value(lhs) <= rhs;
530 }
531
532 Value icinga::operator<=(const Value& lhs, int rhs)
533 {
534         return lhs <= Value(rhs);
535 }
536
537 Value icinga::operator<=(int lhs, const Value& rhs)
538 {
539         return Value(lhs) <= rhs;
540 }
541
542 Value icinga::operator>=(const Value& lhs, const Value& rhs)
543 {
544         if (lhs.IsString() && rhs.IsString())
545                 return static_cast<String>(lhs) >= static_cast<String>(rhs);
546         else if ((lhs.IsNumber() || lhs.IsEmpty()) && (rhs.IsNumber() || rhs.IsEmpty()) && !(lhs.IsEmpty() && rhs.IsEmpty()))
547                 return static_cast<int>(lhs) >= static_cast<int>(rhs);
548         else if (lhs.GetTypeName() != rhs.GetTypeName())
549                 return lhs.GetTypeName() >= rhs.GetTypeName();
550         else
551                 BOOST_THROW_EXCEPTION(std::invalid_argument("Operator >= cannot be applied to values of type '" + lhs.GetTypeName() + "' and '" + rhs.GetTypeName() + "'"));
552 }
553
554 Value icinga::operator>=(const Value& lhs, double rhs)
555 {
556         return lhs >= Value(rhs);
557 }
558
559 Value icinga::operator>=(double lhs, const Value& rhs)
560 {
561         return Value(lhs) >= rhs;
562 }
563
564 Value icinga::operator>=(const Value& lhs, int rhs)
565 {
566         return lhs >= Value(rhs);
567 }
568
569 Value icinga::operator>=(int lhs, const Value& rhs)
570 {
571         return Value(lhs) >= rhs;
572 }