]> granicus.if.org Git - icinga2/blob - lib/base/value.cpp
Merge pull request #7185 from Icinga/bugfix/gelfwriter-wrong-log-facility
[icinga2] / lib / base / value.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/type.hpp"
7
8 using namespace icinga;
9
10 template class boost::variant<boost::blank, double, bool, String, Object::Ptr>;
11 template const double& Value::Get<double>() const;
12 template const bool& Value::Get<bool>() const;
13 template const String& Value::Get<String>() const;
14 template const Object::Ptr& Value::Get<Object::Ptr>() const;
15
16 Value icinga::Empty;
17
18 Value::Value(std::nullptr_t)
19 { }
20
21 Value::Value(int value)
22         : m_Value(double(value))
23 { }
24
25 Value::Value(unsigned int value)
26         : m_Value(double(value))
27 { }
28
29 Value::Value(long value)
30         : m_Value(double(value))
31 { }
32
33 Value::Value(unsigned long value)
34         : m_Value(double(value))
35 { }
36
37 Value::Value(long long value)
38         : m_Value(double(value))
39 { }
40
41 Value::Value(unsigned long long value)
42         : m_Value(double(value))
43 { }
44
45 Value::Value(double value)
46         : m_Value(value)
47 { }
48
49 Value::Value(bool value)
50         : m_Value(value)
51 { }
52
53 Value::Value(const String& value)
54         : m_Value(value)
55 { }
56
57 Value::Value(String&& value)
58         : m_Value(value)
59 { }
60
61 Value::Value(const char *value)
62         : m_Value(String(value))
63 { }
64
65 Value::Value(const Value& other)
66         : m_Value(other.m_Value)
67 { }
68
69 Value::Value(Value&& other)
70 {
71 #if BOOST_VERSION >= 105400
72         m_Value = std::move(other.m_Value);
73 #else /* BOOST_VERSION */
74         m_Value.swap(other.m_Value);
75 #endif /* BOOST_VERSION */
76 }
77
78 Value::Value(Object *value)
79         : Value(Object::Ptr(value))
80 { }
81
82 Value::Value(const intrusive_ptr<Object>& value)
83 {
84         if (value)
85                 m_Value = value;
86 }
87
88 Value& Value::operator=(const Value& other)
89 {
90         m_Value = other.m_Value;
91         return *this;
92 }
93
94 Value& Value::operator=(Value&& other)
95 {
96 #if BOOST_VERSION >= 105400
97         m_Value = std::move(other.m_Value);
98 #else /* BOOST_VERSION */
99         m_Value.swap(other.m_Value);
100 #endif /* BOOST_VERSION */
101
102         return *this;
103 }
104
105 /**
106  * Checks whether the variant is empty.
107  *
108  * @returns true if the variant is empty, false otherwise.
109  */
110 bool Value::IsEmpty() const
111 {
112         return (GetType() == ValueEmpty || (IsString() && boost::get<String>(m_Value).IsEmpty()));
113 }
114
115 /**
116  * Checks whether the variant is scalar (i.e. not an object and not empty).
117  *
118  * @returns true if the variant is scalar, false otherwise.
119  */
120 bool Value::IsScalar() const
121 {
122         return !IsEmpty() && !IsObject();
123 }
124
125 /**
126 * Checks whether the variant is a number.
127 *
128 * @returns true if the variant is a number.
129 */
130 bool Value::IsNumber() const
131 {
132         return (GetType() == ValueNumber);
133 }
134
135 /**
136  * Checks whether the variant is a boolean.
137  *
138  * @returns true if the variant is a boolean.
139  */
140 bool Value::IsBoolean() const
141 {
142         return (GetType() == ValueBoolean);
143 }
144
145 /**
146  * Checks whether the variant is a string.
147  *
148  * @returns true if the variant is a string.
149  */
150 bool Value::IsString() const
151 {
152         return (GetType() == ValueString);
153 }
154
155 /**
156  * Checks whether the variant is a non-null object.
157  *
158  * @returns true if the variant is a non-null object, false otherwise.
159  */
160 bool Value::IsObject() const
161 {
162         return  (GetType() == ValueObject);
163 }
164
165 /**
166  * Returns the type of the value.
167  *
168  * @returns The type.
169  */
170 ValueType Value::GetType() const
171 {
172         return static_cast<ValueType>(m_Value.which());
173 }
174
175 void Value::Swap(Value& other)
176 {
177         m_Value.swap(other.m_Value);
178 }
179
180 bool Value::ToBool() const
181 {
182         switch (GetType()) {
183                 case ValueNumber:
184                         return static_cast<bool>(boost::get<double>(m_Value));
185
186                 case ValueBoolean:
187                         return boost::get<bool>(m_Value);
188
189                 case ValueString:
190                         return !boost::get<String>(m_Value).IsEmpty();
191
192                 case ValueObject:
193                         if (IsObjectType<Dictionary>()) {
194                                 Dictionary::Ptr dictionary = *this;
195                                 return dictionary->GetLength() > 0;
196                         } else if (IsObjectType<Array>()) {
197                                 Array::Ptr array = *this;
198                                 return array->GetLength() > 0;
199                         } else {
200                                 return true;
201                         }
202
203                 case ValueEmpty:
204                         return false;
205
206                 default:
207                         BOOST_THROW_EXCEPTION(std::runtime_error("Invalid variant type."));
208         }
209 }
210
211 String Value::GetTypeName() const
212 {
213         Type::Ptr t;
214
215         switch (GetType()) {
216                 case ValueEmpty:
217                         return "Empty";
218                 case ValueNumber:
219                         return "Number";
220                 case ValueBoolean:
221                         return "Boolean";
222                 case ValueString:
223                         return "String";
224                 case ValueObject:
225                         t = boost::get<Object::Ptr>(m_Value)->GetReflectionType();
226                         if (!t) {
227                                 if (IsObjectType<Array>())
228                                         return "Array";
229                                 else if (IsObjectType<Dictionary>())
230                                         return "Dictionary";
231                                 else
232                                         return "Object";
233                         } else
234                                 return t->GetName();
235                 default:
236                         return "Invalid";
237         }
238 }
239
240 Type::Ptr Value::GetReflectionType() const
241 {
242         switch (GetType()) {
243                 case ValueEmpty:
244                         return Object::TypeInstance;
245                 case ValueNumber:
246                         return Type::GetByName("Number");
247                 case ValueBoolean:
248                         return Type::GetByName("Boolean");
249                 case ValueString:
250                         return Type::GetByName("String");
251                 case ValueObject:
252                         return boost::get<Object::Ptr>(m_Value)->GetReflectionType();
253                 default:
254                         return nullptr;
255         }
256 }
257
258 Value Value::Clone() const
259 {
260         if (IsObject())
261                 return static_cast<Object::Ptr>(*this)->Clone();
262         else
263                 return *this;
264 }