/src/wt/src/Wt/Json/Value.C
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2011 Emweb bv, Herent, Belgium. |
3 | | * |
4 | | * See the LICENSE file for terms of use. |
5 | | */ |
6 | | |
7 | | #include "Wt/Json/Value.h" |
8 | | #include "Wt/Json/Object.h" |
9 | | #include "Wt/Json/Array.h" |
10 | | #include "Wt/WAny.h" |
11 | | #include "Wt/WLogger.h" |
12 | | |
13 | | #include "WebUtils.h" |
14 | | |
15 | | namespace Wt { |
16 | | |
17 | | LOGGER("Json.Value"); |
18 | | |
19 | | namespace Json { |
20 | | |
21 | | namespace { |
22 | | const char *typeNames[] = { |
23 | | "Null", |
24 | | "String", |
25 | | "Bool", |
26 | | "Number", |
27 | | "Object", |
28 | | "Array" |
29 | | }; |
30 | | } |
31 | | |
32 | | TypeException::TypeException(const std::string& name, |
33 | | Type actualType, Type expectedType) |
34 | 0 | : WException("Type error: " + name + " is " |
35 | 0 | + typeNames[static_cast<unsigned int>(actualType)] |
36 | 0 | + ", expected " |
37 | 0 | + typeNames[static_cast<unsigned int>(expectedType)]), |
38 | 0 | name_(name), |
39 | 0 | actualType_(actualType), |
40 | 0 | expectedType_(expectedType) |
41 | 0 | { } |
42 | | |
43 | | TypeException::TypeException(Type actualType, Type expectedType) |
44 | 20 | : WException(std::string("Type error: value is ") |
45 | 20 | + typeNames[static_cast<unsigned int>(actualType)] |
46 | 20 | + ", expected " |
47 | 20 | + typeNames[static_cast<unsigned int>(expectedType)]), |
48 | 20 | actualType_(actualType), |
49 | 20 | expectedType_(expectedType) |
50 | 20 | { } |
51 | | |
52 | | TypeException::~TypeException() throw() |
53 | 20 | { } |
54 | | |
55 | | template <typename T> T Value::get(Type requestedType) const |
56 | 0 | { |
57 | 0 | try { |
58 | 0 | return cpp17::any_cast<T>(v_); |
59 | 0 | } catch (cpp17::bad_any_cast& e) { |
60 | 0 | throw TypeException(type(), requestedType); |
61 | 0 | } |
62 | 0 | } |
63 | | |
64 | | template <typename T> const T& Value::getCR(Type requestedType) const |
65 | 0 | { |
66 | 0 | try { |
67 | 0 | return cpp17::any_cast<const T&>(v_); |
68 | 0 | } catch (cpp17::bad_any_cast& e) { |
69 | 0 | throw TypeException(type(), requestedType); |
70 | 0 | } |
71 | 0 | } Unexecuted instantiation: Wt::WString const& Wt::Json::Value::getCR<Wt::WString>(Wt::Json::Type) const Unexecuted instantiation: Wt::Json::Array const& Wt::Json::Value::getCR<Wt::Json::Array>(Wt::Json::Type) const Unexecuted instantiation: Wt::Json::Object const& Wt::Json::Value::getCR<Wt::Json::Object>(Wt::Json::Type) const |
72 | | |
73 | | template <typename T> T& Value::getR(Type requestedType) |
74 | 87.8k | { |
75 | 87.8k | try { |
76 | 87.8k | return cpp17::any_cast<T&>(v_); |
77 | 87.8k | } catch (cpp17::bad_any_cast& e) { |
78 | 20 | throw TypeException(type(), requestedType); |
79 | 20 | } |
80 | 87.8k | } Wt::Json::Array& Wt::Json::Value::getR<Wt::Json::Array>(Wt::Json::Type) Line | Count | Source | 74 | 76.6k | { | 75 | 76.6k | try { | 76 | 76.6k | return cpp17::any_cast<T&>(v_); | 77 | 76.6k | } catch (cpp17::bad_any_cast& e) { | 78 | 0 | throw TypeException(type(), requestedType); | 79 | 0 | } | 80 | 76.6k | } |
Wt::Json::Object& Wt::Json::Value::getR<Wt::Json::Object>(Wt::Json::Type) Line | Count | Source | 74 | 11.2k | { | 75 | 11.2k | try { | 76 | 11.2k | return cpp17::any_cast<T&>(v_); | 77 | 11.2k | } catch (cpp17::bad_any_cast& e) { | 78 | 20 | throw TypeException(type(), requestedType); | 79 | 20 | } | 80 | 11.2k | } |
|
81 | | |
82 | | const Value Value::Null; |
83 | | const Value Value::True(true); |
84 | | const Value Value::False(false); |
85 | | |
86 | | Value::Value() |
87 | 137k | { } |
88 | | |
89 | | Value::Value(bool value) |
90 | 20 | : v_(value) |
91 | 20 | { } |
92 | | |
93 | | Value::Value(const WT_USTRING& value) |
94 | 0 | : v_(value) |
95 | 0 | { } |
96 | | |
97 | | Value::Value(WT_USTRING&& value) |
98 | 6.11k | : v_(std::move(value)) |
99 | 6.11k | { } |
100 | | |
101 | | Value::Value(int value) |
102 | 0 | : v_(value) |
103 | 0 | { } |
104 | | |
105 | | Value::Value(long value) |
106 | 0 | : v_(value) |
107 | 0 | { } |
108 | | |
109 | | |
110 | | Value::Value(long long value) |
111 | 0 | : v_(value) |
112 | 0 | { } |
113 | | |
114 | | Value::Value(double value) |
115 | 43.2k | : v_(value) |
116 | 43.2k | { } |
117 | | |
118 | | Value::Value(const char* value) |
119 | 0 | : v_(WString(value)) |
120 | 0 | { } |
121 | | |
122 | | Value::Value(const Array& value) |
123 | 0 | : v_(value) |
124 | 0 | { } |
125 | | |
126 | | Value::Value(const Object& value) |
127 | 0 | : v_(value) |
128 | 0 | { } |
129 | | |
130 | | Value::Value(Type type) |
131 | 87.8k | { |
132 | 87.8k | switch (type) { |
133 | 0 | case Type::Null: break; |
134 | 0 | case Type::Bool: v_ = false; break; |
135 | 0 | case Type::Number: v_ = double(0.0); break; |
136 | 0 | case Type::String: v_ = std::string(); break; |
137 | 11.2k | case Type::Object: v_ = Object(); break; |
138 | 76.6k | case Type::Array: v_ = Array(); break; |
139 | 87.8k | } |
140 | 87.8k | } |
141 | | |
142 | | Value::Value(const Value& other) |
143 | 110k | : v_(other.v_) |
144 | 110k | { } |
145 | | |
146 | | Value::Value(Value&& other) |
147 | 112k | : v_(std::move(other.v_)) |
148 | 112k | { } |
149 | | |
150 | | Value::Value(Object&& other) |
151 | 0 | : v_(std::move(other)) |
152 | 0 | { } |
153 | | |
154 | | Value::Value(Array&& other) |
155 | 0 | : v_(std::move(other)) |
156 | 0 | { } |
157 | | |
158 | | Value& Value::operator= (const Value& other) |
159 | 21.7k | { |
160 | 21.7k | v_ = other.v_; |
161 | 21.7k | return *this; |
162 | 21.7k | } |
163 | | |
164 | | Value& Value::operator= (Value &&other) |
165 | 137k | { |
166 | 137k | v_ = std::move(other.v_); |
167 | 137k | return *this; |
168 | 137k | } |
169 | | |
170 | | Value& Value::operator= (Object&& other) |
171 | 0 | { |
172 | 0 | v_ = std::move(other); |
173 | 0 | return *this; |
174 | 0 | } |
175 | | |
176 | | Value& Value::operator= (Array&& other) |
177 | 0 | { |
178 | 0 | v_ = std::move(other); |
179 | 0 | return *this; |
180 | 0 | } |
181 | | |
182 | | bool Value::operator== (const Value& other) const |
183 | 0 | { |
184 | 0 | if (typeid(v_) != typeid(other.v_)) |
185 | 0 | return false; |
186 | 0 | else if (!cpp17::any_has_value(v_) || !cpp17::any_has_value(other.v_)) |
187 | 0 | return cpp17::any_has_value(v_) == cpp17::any_has_value(other.v_); |
188 | 0 | else if (v_.type() == typeid(Json::Object)) |
189 | 0 | return cpp17::any_cast<Json::Object>(v_) == |
190 | 0 | cpp17::any_cast<Json::Object>(other.v_); |
191 | 0 | else if (v_.type() == typeid(Json::Array)) |
192 | 0 | return cpp17::any_cast<Json::Array>(v_) == |
193 | 0 | cpp17::any_cast<Json::Array>(other.v_); |
194 | 0 | else if (v_.type() == typeid(bool)) |
195 | 0 | return cpp17::any_cast<bool>(v_) == cpp17::any_cast<bool>(other.v_); |
196 | 0 | else if (v_.type() == typeid(int)) |
197 | 0 | return cpp17::any_cast<int>(v_) == cpp17::any_cast<int>(other.v_); |
198 | 0 | else if (v_.type() == typeid(long)) |
199 | 0 | return cpp17::any_cast<long>(v_) == cpp17::any_cast<long>(other.v_); |
200 | 0 | else if (v_.type() == typeid(long long)) |
201 | 0 | return cpp17::any_cast<long long>(v_) == |
202 | 0 | cpp17::any_cast<long long>(other.v_); |
203 | 0 | else if (v_.type() == typeid(double)) |
204 | 0 | return cpp17::any_cast<double>(v_) == cpp17::any_cast<double>(other.v_); |
205 | 0 | else if (v_.type() == typeid(Wt::WString)) |
206 | 0 | return cpp17::any_cast<Wt::WString>(v_) == cpp17::any_cast<Wt::WString>(other.v_); |
207 | 0 | else { |
208 | 0 | WStringStream ss; |
209 | 0 | ss << "Value::operator== : unknown value type: " << std::string(v_.type().name()); |
210 | 0 | throw WException(ss.str()); |
211 | 0 | } |
212 | 0 | } |
213 | | |
214 | | bool Value::operator!= (const Value& other) const |
215 | 0 | { |
216 | 0 | return !(*this == other); |
217 | 0 | } |
218 | | |
219 | | Type Value::type() const |
220 | 20 | { |
221 | 20 | if (!cpp17::any_has_value(v_)) |
222 | 0 | return Type::Null; |
223 | 20 | else { |
224 | 20 | return typeOf(v_.type()); |
225 | 20 | } |
226 | 20 | } |
227 | | |
228 | | bool Value::hasType(const std::type_info& aType) const |
229 | 0 | { |
230 | 0 | return type() == typeOf(aType); |
231 | 0 | } |
232 | | |
233 | | Type Value::typeOf(const std::type_info& t) |
234 | 20 | { |
235 | 20 | if (t == typeid(bool)) |
236 | 0 | return Type::Bool; |
237 | 20 | else if (t == typeid(double) || t == typeid(long long) || t == typeid(int) || t == typeid(long)) |
238 | 0 | return Type::Number; |
239 | 20 | else if (t == typeid(WT_USTRING)) |
240 | 0 | return Type::String; |
241 | 20 | else if (t == typeid(Object)) |
242 | 0 | return Type::Object; |
243 | 20 | else if (t == typeid(Array)) |
244 | 20 | return Type::Array; |
245 | 0 | else |
246 | 0 | throw WException(std::string("Value::typeOf(): unsupported type ") |
247 | 0 | + t.name()); |
248 | 20 | } |
249 | | |
250 | | Value::operator const WT_USTRING&() const |
251 | 0 | { |
252 | 0 | return getCR<WT_USTRING>(Type::String); |
253 | 0 | } |
254 | | |
255 | | Value::operator std::string() const |
256 | 0 | { |
257 | 0 | return ((const WT_USTRING&)(*this)).toUTF8(); |
258 | 0 | } |
259 | | |
260 | | Value::operator bool() const |
261 | 0 | { |
262 | 0 | return get<bool>(Type::Bool); |
263 | 0 | } |
264 | | |
265 | | Value::operator int() const |
266 | 0 | { |
267 | 0 | const std::type_info& t = v_.type(); |
268 | |
|
269 | 0 | if (t == typeid(double)) |
270 | 0 | return static_cast<int>(cpp17::any_cast<double>(v_)); |
271 | 0 | else if (t == typeid(long)) |
272 | 0 | return static_cast<int>(cpp17::any_cast<long>(v_)); |
273 | 0 | else if (t == typeid(long long)) |
274 | 0 | return static_cast<int>(cpp17::any_cast<long long>(v_)); |
275 | 0 | else if (t == typeid(int)) |
276 | 0 | return cpp17::any_cast<int>(v_); |
277 | 0 | else |
278 | 0 | throw TypeException(type(), Type::Number); |
279 | 0 | } |
280 | | |
281 | | Value::operator long() const |
282 | 0 | { |
283 | 0 | const std::type_info& t = v_.type(); |
284 | |
|
285 | 0 | if (t == typeid(double)) |
286 | 0 | return static_cast<long>(cpp17::any_cast<double>(v_)); |
287 | 0 | else if (t == typeid(long)) |
288 | 0 | return cpp17::any_cast<long>(v_); |
289 | 0 | else if (t == typeid(long long)) |
290 | 0 | return static_cast<long>(cpp17::any_cast<long long>(v_)); |
291 | 0 | else if (t == typeid(int)) |
292 | 0 | return static_cast<long>(cpp17::any_cast<int>(v_)); |
293 | 0 | else |
294 | 0 | throw TypeException(type(), Type::Number); |
295 | 0 | } |
296 | | |
297 | | Value::operator long long() const |
298 | 0 | { |
299 | 0 | const std::type_info& t = v_.type(); |
300 | |
|
301 | 0 | if (t == typeid(double)) |
302 | 0 | return static_cast<long long>(cpp17::any_cast<double>(v_)); |
303 | 0 | else if (t == typeid(long)) |
304 | 0 | return static_cast<long long>(cpp17::any_cast<long>(v_)); |
305 | 0 | else if (t == typeid(long long)) |
306 | 0 | return cpp17::any_cast<long long>(v_); |
307 | 0 | else if (t == typeid(int)) |
308 | 0 | return static_cast<long long>(cpp17::any_cast<int>(v_)); |
309 | 0 | else |
310 | 0 | throw TypeException(type(), Type::Number); |
311 | 0 | } |
312 | | |
313 | | Value::operator double() const |
314 | 0 | { |
315 | 0 | const std::type_info& t = v_.type(); |
316 | |
|
317 | 0 | if (t == typeid(double)) |
318 | 0 | return cpp17::any_cast<double>(v_); |
319 | 0 | else if (t == typeid(long)) |
320 | 0 | return static_cast<double>(cpp17::any_cast<long>(v_)); |
321 | 0 | else if (t == typeid(long long)) |
322 | 0 | return static_cast<double>(cpp17::any_cast<long long>(v_)); |
323 | 0 | else if (t == typeid(int)) |
324 | 0 | return static_cast<double>(cpp17::any_cast<int>(v_)); |
325 | 0 | else |
326 | 0 | throw TypeException(type(), Type::Number); |
327 | 0 | } |
328 | | |
329 | | Value::operator const Array&() const |
330 | 0 | { |
331 | 0 | return getCR<Array>(Type::Array); |
332 | 0 | } |
333 | | |
334 | | Value::operator const Object&() const |
335 | 0 | { |
336 | 0 | return getCR<Object>(Type::Object); |
337 | 0 | } |
338 | | |
339 | | Value::operator Array&() |
340 | 76.6k | { |
341 | 76.6k | return getR<Array>(Type::Array); |
342 | 76.6k | } |
343 | | |
344 | | Value::operator Object&() |
345 | 11.2k | { |
346 | 11.2k | return getR<Object>(Type::Object); |
347 | 11.2k | } |
348 | | |
349 | | const WT_USTRING& Value::orIfNull(const WT_USTRING& v) const |
350 | 0 | { |
351 | 0 | if (cpp17::any_has_value(v_)) |
352 | 0 | return *this; |
353 | 0 | else |
354 | 0 | return v; |
355 | 0 | } |
356 | | |
357 | | std::string Value::orIfNull(const std::string& v) const |
358 | 0 | { |
359 | 0 | if (cpp17::any_has_value(v_)) |
360 | 0 | return *this; |
361 | 0 | else |
362 | 0 | return v; |
363 | 0 | } |
364 | | |
365 | | std::string Value::orIfNull(const char *v) const |
366 | 0 | { |
367 | 0 | return orIfNull(std::string(v)); |
368 | 0 | } |
369 | | |
370 | | bool Value::orIfNull(bool v) const |
371 | 0 | { |
372 | 0 | if (cpp17::any_has_value(v_)) |
373 | 0 | return *this; |
374 | 0 | else |
375 | 0 | return v; |
376 | 0 | } |
377 | | |
378 | | int Value::orIfNull(int v) const |
379 | 0 | { |
380 | 0 | if (cpp17::any_has_value(v_)) |
381 | 0 | return *this; |
382 | 0 | else |
383 | 0 | return v; |
384 | 0 | } |
385 | | |
386 | | long long Value::orIfNull(long long v) const |
387 | 0 | { |
388 | 0 | if (cpp17::any_has_value(v_)) |
389 | 0 | return *this; |
390 | 0 | else |
391 | 0 | return v; |
392 | 0 | } |
393 | | |
394 | | double Value::orIfNull(double v) const |
395 | 0 | { |
396 | 0 | if (cpp17::any_has_value(v_)) |
397 | 0 | return *this; |
398 | 0 | else |
399 | 0 | return v; |
400 | 0 | } |
401 | | |
402 | | const Array& Value::orIfNull(const Array& v) const |
403 | 0 | { |
404 | 0 | if (cpp17::any_has_value(v_)) |
405 | 0 | return *this; |
406 | 0 | else |
407 | 0 | return v; |
408 | 0 | } |
409 | | |
410 | | const Object& Value::orIfNull(const Object& v) const |
411 | 0 | { |
412 | 0 | if (cpp17::any_has_value(v_)) |
413 | 0 | return *this; |
414 | 0 | else |
415 | 0 | return v; |
416 | 0 | } |
417 | | |
418 | | Value Value::toString() const |
419 | 0 | { |
420 | 0 | const std::type_info& t = v_.type(); |
421 | |
|
422 | 0 | if (t == typeid(Object) || t == typeid(Array)) |
423 | 0 | return Null; |
424 | 0 | else if (t == typeid(WT_USTRING)) |
425 | 0 | return *this; |
426 | 0 | else if(type() == Type::Number) { |
427 | 0 | WString str = asString(v_); |
428 | 0 | std::string sstr = str.toUTF8(); |
429 | 0 | if (sstr.find("nan") != std::string::npos || |
430 | 0 | sstr.find("inf") != std::string::npos) |
431 | 0 | throw WException(std::string("Value::toString(): Not a Number")); |
432 | 0 | return Value(str); |
433 | 0 | } else |
434 | 0 | return Value(asString(v_)); |
435 | 0 | } |
436 | | |
437 | | Value Value::toBool() const |
438 | 0 | { |
439 | 0 | const std::type_info& t = v_.type(); |
440 | |
|
441 | 0 | if (t == typeid(Object) || t == typeid(Array)) |
442 | 0 | return Null; |
443 | 0 | else if (t == typeid(bool)) |
444 | 0 | return *this; |
445 | 0 | else if (t == typeid(WT_USTRING)) { |
446 | 0 | const WT_USTRING& s = cpp17::any_cast<const WT_USTRING& >(v_); |
447 | 0 | if (s == "true") |
448 | 0 | return True; |
449 | 0 | else if (s == "false") |
450 | 0 | return False; |
451 | 0 | else |
452 | 0 | return Null; |
453 | 0 | } else |
454 | 0 | return Null; |
455 | 0 | } |
456 | | |
457 | | Value Value::toNumber() const |
458 | 0 | { |
459 | 0 | const std::type_info& t = v_.type(); |
460 | |
|
461 | 0 | if (t == typeid(Object) || t == typeid(Array)) |
462 | 0 | return Null; |
463 | 0 | else if (t == typeid(double) || t == typeid(long long) || t == typeid(int) || t == typeid(long)) |
464 | 0 | return *this; |
465 | 0 | else if (t == typeid(WT_USTRING)) { |
466 | 0 | const WT_USTRING& s = cpp17::any_cast<const WT_USTRING& >(v_); |
467 | 0 | try { |
468 | 0 | return Utils::stod(s.toUTF8()); |
469 | 0 | } catch (std::exception& e) { |
470 | 0 | LOG_WARN("toNumber() could not cast '" << s << "'"); |
471 | 0 | return Null; |
472 | 0 | } |
473 | 0 | } else |
474 | 0 | return Null; |
475 | 0 | } |
476 | | |
477 | | } |
478 | | } |