cesium-native 0.43.0
Loading...
Searching...
No Matches
JsonValue.h
1#pragma once
2
3#include "Library.h"
4
5#include <cmath>
6#include <cstdint>
7#include <initializer_list>
8#include <map>
9#include <optional>
10#include <stdexcept>
11#include <string>
12#include <string_view>
13#include <type_traits>
14#include <variant>
15#include <vector>
16
17namespace CesiumUtility {
18
28template <typename T, typename U>
29constexpr std::optional<T> losslessNarrow(U u) noexcept {
30 constexpr const bool is_different_signedness =
31 (std::is_signed<T>::value != std::is_signed<U>::value);
32
33 const T t = static_cast<T>(u);
34
35 if (static_cast<U>(t) != u ||
36 (is_different_signedness && ((t < T{}) != (u < U{})))) {
37 return std::nullopt;
38 }
39
40 return t;
41}
42
54template <typename T, typename U>
55constexpr T losslessNarrowOrDefault(U u, T defaultValue) noexcept {
56 constexpr const bool is_different_signedness =
57 (std::is_signed<T>::value != std::is_signed<U>::value);
58
59 const T t = static_cast<T>(u);
60
61 if (static_cast<U>(t) != u ||
62 (is_different_signedness && ((t < T{}) != (u < U{})))) {
63 return defaultValue;
64 }
65
66 return t;
67}
68
75class CESIUMUTILITY_API JsonValue final {
76public:
80 using Null = std::nullptr_t;
81
85 using Bool = bool;
86
90 using String = std::string;
91
95 using Object = std::map<std::string, JsonValue>;
96
100 using Array = std::vector<JsonValue>;
101
105 JsonValue() noexcept : value() {}
106
110 JsonValue(std::nullptr_t) noexcept : value(nullptr) {}
111
117 JsonValue(double v) noexcept {
118 if (std::isnan(v) || std::isinf(v)) {
119 value = nullptr;
120 } else {
121 value = v;
122 }
123 }
124
129 JsonValue(std::int8_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
130
135 JsonValue(std::uint8_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
136
141 JsonValue(std::int16_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
142
147 JsonValue(std::uint16_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
148
153 JsonValue(std::int32_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
154
159 JsonValue(std::uint32_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
160
164 JsonValue(std::int64_t v) noexcept : value(v) {}
165
169 JsonValue(std::uint64_t v) noexcept : value(v) {}
170
174 JsonValue(bool v) noexcept : value(v) {}
175
179 JsonValue(const std::string& v) : value(v) {}
180
184 JsonValue(std::string&& v) noexcept : value(std::move(v)) {}
185
189 JsonValue(const char* v) : value(std::string(v)) {}
190
194 JsonValue(const std::map<std::string, JsonValue>& v) : value(v) {}
195
199 JsonValue(std::map<std::string, JsonValue>&& v) : value(std::move(v)) {}
200
204 JsonValue(const std::vector<JsonValue>& v) : value(v) {}
205
209 JsonValue(std::vector<JsonValue>&& v) noexcept : value(std::move(v)) {}
210
214 JsonValue(std::initializer_list<JsonValue> v)
215 : value(std::vector<JsonValue>(v)) {}
216
220 JsonValue(std::initializer_list<std::pair<const std::string, JsonValue>> v)
221 : value(std::map<std::string, JsonValue>(v)) {}
222
231 [[nodiscard]] const JsonValue*
232 getValuePtrForKey(const std::string& key) const;
234 [[nodiscard]] JsonValue* getValuePtrForKey(const std::string& key);
235
250 template <typename T>
251 const T* getValuePtrForKey(const std::string& key) const {
252 const JsonValue* pValue = this->getValuePtrForKey(key);
253 if (!pValue) {
254 return nullptr;
255 }
256
257 return std::get_if<T>(&pValue->value);
258 }
259
274 template <typename T> T* getValuePtrForKey(const std::string& key) {
275 JsonValue* pValue = this->getValuePtrForKey(key);
276 return std::get_if<T>(&pValue->value);
277 }
278
294 template <
295 typename To,
296 typename std::enable_if<
297 std::is_integral<To>::value ||
298 std::is_floating_point<To>::value>::type* = nullptr>
299 [[nodiscard]] std::optional<To>
300 getSafeNumericalValueForKey(const std::string& key) const {
301 const Object& pObject = std::get<Object>(this->value);
302 const auto it = pObject.find(key);
303 if (it == pObject.end()) {
304 return std::nullopt;
305 }
306 return it->second.getSafeNumber<To>();
307 }
308
328 template <
329 typename To,
330 typename std::enable_if<
331 std::is_integral<To>::value ||
332 std::is_floating_point<To>::value>::type* = nullptr>
334 const std::string& key,
335 To defaultValue) const {
336 const Object& pObject = std::get<Object>(this->value);
337 const auto it = pObject.find(key);
338 if (it == pObject.end()) {
339 return defaultValue;
340 }
341 return it->second.getSafeNumberOrDefault<To>(defaultValue);
342 }
343
351 [[nodiscard]] inline bool hasKey(const std::string& key) const {
352 const Object* pObject = std::get_if<Object>(&this->value);
353 if (!pObject) {
354 return false;
355 }
356
357 return pObject->find(key) != pObject->end();
358 }
359
368 template <
369 typename To,
370 typename std::enable_if<
371 std::is_integral<To>::value ||
372 std::is_floating_point<To>::value>::type* = nullptr>
373 [[nodiscard]] std::optional<To> getSafeNumber() const {
374 const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value);
375 if (uInt) {
376 return losslessNarrow<To>(*uInt);
377 }
378
379 const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value);
380 if (sInt) {
381 return losslessNarrow<To>(*sInt);
382 }
383
384 const double* real = std::get_if<double>(&this->value);
385 if (real) {
386 return losslessNarrow<To>(*real);
387 }
388
389 return std::nullopt;
390 }
391
399 template <
400 typename To,
401 typename std::enable_if<
402 std::is_integral<To>::value ||
403 std::is_floating_point<To>::value>::type* = nullptr>
404 [[nodiscard]] To getSafeNumberOrDefault(To defaultValue) const noexcept {
405 const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value);
406 if (uInt) {
407 return losslessNarrowOrDefault<To>(*uInt, defaultValue);
408 }
409
410 const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value);
411 if (sInt) {
412 return losslessNarrowOrDefault<To>(*sInt, defaultValue);
413 }
414
415 const double* real = std::get_if<double>(&this->value);
416 if (real) {
417 return losslessNarrowOrDefault<To>(*real, defaultValue);
418 }
419
420 return defaultValue;
421 }
422
430 [[nodiscard]] inline const JsonValue::Object& getObject() const {
431 return std::get<JsonValue::Object>(this->value);
432 }
433
440 [[nodiscard]] inline const JsonValue::String& getString() const {
441 return std::get<String>(this->value);
442 }
443
450 [[nodiscard]] inline const JsonValue::Array& getArray() const {
451 return std::get<JsonValue::Array>(this->value);
452 }
453
462 [[nodiscard]] std::vector<std::string>
463 getArrayOfStrings(const std::string& defaultString) const;
464
471 [[nodiscard]] inline bool getBool() const {
472 return std::get<bool>(this->value);
473 }
474
480 [[nodiscard]] inline double getDouble() const {
481 return std::get<double>(this->value);
482 }
483
490 [[nodiscard]] std::uint64_t getUint64() const {
491 return std::get<std::uint64_t>(this->value);
492 }
493
500 [[nodiscard]] std::int64_t getInt64() const {
501 return std::get<std::int64_t>(this->value);
502 }
503
508 [[nodiscard]] inline bool getBoolOrDefault(bool defaultValue) const noexcept {
509 const auto* v = std::get_if<bool>(&this->value);
510 if (v) {
511 return *v;
512 }
513
514 return defaultValue;
515 }
516
521 [[nodiscard]] inline const JsonValue::String
522 getStringOrDefault(String defaultValue) const {
523 const auto* v = std::get_if<JsonValue::String>(&this->value);
524 if (v) {
525 return *v;
526 }
527
528 return defaultValue;
529 }
530
535 [[nodiscard]] inline double
536 getDoubleOrDefault(double defaultValue) const noexcept {
537 const auto* v = std::get_if<double>(&this->value);
538 if (v) {
539 return *v;
540 }
541
542 return defaultValue;
543 }
544
549 [[nodiscard]] inline std::uint64_t
550 getUint64OrDefault(std::uint64_t defaultValue) const noexcept {
551 const auto* v = std::get_if<std::uint64_t>(&this->value);
552 if (v) {
553 return *v;
554 }
555
556 return defaultValue;
557 }
558
563 [[nodiscard]] inline std::int64_t
564 getInt64OrDefault(std::int64_t defaultValue) const noexcept {
565 const auto* v = std::get_if<std::int64_t>(&this->value);
566 if (v) {
567 return *v;
568 }
569
570 return defaultValue;
571 }
572
576 [[nodiscard]] inline bool isNull() const noexcept {
577 return std::holds_alternative<Null>(this->value);
578 }
579
585 [[nodiscard]] inline bool isNumber() const noexcept {
586 return isDouble() || isUint64() || isInt64();
587 }
588
592 [[nodiscard]] inline bool isBool() const noexcept {
593 return std::holds_alternative<Bool>(this->value);
594 }
595
599 [[nodiscard]] inline bool isString() const noexcept {
600 return std::holds_alternative<String>(this->value);
601 }
602
606 [[nodiscard]] inline bool isObject() const noexcept {
607 return std::holds_alternative<Object>(this->value);
608 }
609
613 [[nodiscard]] inline bool isArray() const noexcept {
614 return std::holds_alternative<Array>(this->value);
615 }
616
620 [[nodiscard]] inline bool isDouble() const noexcept {
621 return std::holds_alternative<double>(this->value);
622 }
623
627 [[nodiscard]] inline bool isUint64() const noexcept {
628 return std::holds_alternative<std::uint64_t>(this->value);
629 }
630
634 [[nodiscard]] inline bool isInt64() const noexcept {
635 return std::holds_alternative<std::int64_t>(this->value);
636 }
637
641 inline bool operator==(const JsonValue& rhs) const noexcept {
642 return this->value == rhs.value;
643 };
644
648 int64_t getSizeBytes() const noexcept {
649 struct Operation {
650 int64_t operator()([[maybe_unused]] const Null& /*inside*/) { return 0; }
651 int64_t operator()([[maybe_unused]] const double& /*inside*/) {
652 return 0;
653 }
654 int64_t operator()([[maybe_unused]] const std::uint64_t& /*inside*/) {
655 return 0;
656 }
657 int64_t operator()([[maybe_unused]] const std::int64_t& /*inside*/) {
658 return 0;
659 }
660 int64_t operator()([[maybe_unused]] const Bool& /*inside*/) { return 0; }
661 int64_t operator()(const String& inside) {
662 return int64_t(inside.capacity() * sizeof(char));
663 }
664 int64_t operator()(const Object& inside) {
665 int64_t accum = 0;
666 accum +=
667 int64_t(inside.size() * (sizeof(std::string) + sizeof(JsonValue)));
668 for (const auto& [k, v] : inside) {
669 accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
670 accum += v.getSizeBytes() - int64_t(sizeof(JsonValue));
671 }
672
673 return accum;
674 }
675 int64_t operator()(const Array& inside) {
676 int64_t accum = 0;
677 accum += int64_t(sizeof(JsonValue) * inside.capacity());
678 for (const JsonValue& v : inside) {
679 accum += v.getSizeBytes() - int64_t(sizeof(JsonValue));
680 }
681 return accum;
682 }
683 };
684
685 return static_cast<int64_t>(sizeof(JsonValue)) +
686 std::visit(Operation{}, this->value);
687 }
688
701 std::variant<
702 Null,
703 double,
704 std::uint64_t,
705 std::int64_t,
706 Bool,
707 String,
708 Object,
709 Array>
711};
712} // namespace CesiumUtility
A generic implementation of a value in a JSON structure.
Definition JsonValue.h:75
std::vector< std::string > getArrayOfStrings(const std::string &defaultString) const
Gets an array of strings from the value.
std::map< std::string, JsonValue > Object
The type to represent an Object JSON value.
Definition JsonValue.h:95
JsonValue(std::int8_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int8_t).
Definition JsonValue.h:129
std::optional< To > getSafeNumericalValueForKey(const std::string &key) const
Converts the numerical value corresponding to the given key to the provided numerical template type.
Definition JsonValue.h:300
bool getBool() const
Gets the bool from the value.
Definition JsonValue.h:471
JsonValue(const std::map< std::string, JsonValue > &v)
Creates an Object JSON value with the given properties.
Definition JsonValue.h:194
bool isInt64() const noexcept
Returns whether this value is a std::int64_t value.
Definition JsonValue.h:634
const JsonValue::String & getString() const
Gets the string from the value.
Definition JsonValue.h:440
JsonValue(std::int16_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int16_t).
Definition JsonValue.h:141
bool isNumber() const noexcept
Returns whether this value is a double, std::uint64_t or std::int64_t. Use this function in conjuncti...
Definition JsonValue.h:585
bool isDouble() const noexcept
Returns whether this value is a double value.
Definition JsonValue.h:620
JsonValue(std::vector< JsonValue > &&v) noexcept
Creates an Array JSON value with the given elements.
Definition JsonValue.h:209
std::vector< JsonValue > Array
The type to represent an Array JSON value.
Definition JsonValue.h:100
double getDoubleOrDefault(double defaultValue) const noexcept
Gets the double from the value or returns defaultValue.
Definition JsonValue.h:536
JsonValue * getValuePtrForKey(const std::string &key)
Attempts to obtain a pointer to a JsonValue for the given key on this object.
JsonValue(std::initializer_list< JsonValue > v)
Creates an JSON value from the given initializer list.
Definition JsonValue.h:214
JsonValue(std::uint16_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint16_t).
Definition JsonValue.h:147
std::variant< Null, double, std::uint64_t, std::int64_t, Bool, String, Object, Array > value
The actual value.
Definition JsonValue.h:710
bool isBool() const noexcept
Returns whether this value is a Bool value.
Definition JsonValue.h:592
const JsonValue::String getStringOrDefault(String defaultValue) const
Gets the string from the value or returns defaultValue.
Definition JsonValue.h:522
JsonValue(std::nullptr_t) noexcept
Creates a null JSON value.
Definition JsonValue.h:110
JsonValue(std::string &&v) noexcept
Creates a String JSON value.
Definition JsonValue.h:184
bool Bool
The type to represent a Bool JSON value.
Definition JsonValue.h:85
JsonValue(bool v) noexcept
Creates a Bool JSON value.
Definition JsonValue.h:174
bool isNull() const noexcept
Returns whether this value is a null value.
Definition JsonValue.h:576
const T * getValuePtrForKey(const std::string &key) const
Gets a typed value corresponding to the given key in the object represented by this instance.
Definition JsonValue.h:251
std::uint64_t getUint64() const
Gets the std::uint64_t from the value.
Definition JsonValue.h:490
bool operator==(const JsonValue &rhs) const noexcept
Returns true if two values are equal.
Definition JsonValue.h:641
std::int64_t getInt64OrDefault(std::int64_t defaultValue) const noexcept
Gets the int64_t from the value or returns defaultValue.
Definition JsonValue.h:564
std::string String
The type to represent a String JSON value.
Definition JsonValue.h:90
JsonValue(const char *v)
Creates a String JSON value.
Definition JsonValue.h:189
bool isUint64() const noexcept
Returns whether this value is a std::uint64_t value.
Definition JsonValue.h:627
T * getValuePtrForKey(const std::string &key)
Gets a typed value corresponding to the given key in the object represented by this instance.
Definition JsonValue.h:274
JsonValue(std::int64_t v) noexcept
Creates a std::int64_t JSON value.
Definition JsonValue.h:164
bool isArray() const noexcept
Returns whether this value is an Array value.
Definition JsonValue.h:613
JsonValue() noexcept
Default constructor.
Definition JsonValue.h:105
bool isString() const noexcept
Returns whether this value is a String value.
Definition JsonValue.h:599
bool isObject() const noexcept
Returns whether this value is an Object value.
Definition JsonValue.h:606
JsonValue(double v) noexcept
Creates a Number JSON value.
Definition JsonValue.h:117
std::int64_t getInt64() const
Gets the std::int64_t from the value.
Definition JsonValue.h:500
JsonValue(std::map< std::string, JsonValue > &&v)
Creates an Object JSON value with the given properties.
Definition JsonValue.h:199
bool getBoolOrDefault(bool defaultValue) const noexcept
Gets the bool from the value or returns defaultValue.
Definition JsonValue.h:508
To getSafeNumberOrDefault(To defaultValue) const noexcept
Gets the numerical quantity from the value casted to the To type or returns defaultValue if unable to...
Definition JsonValue.h:404
double getDouble() const
Gets the double from the value.
Definition JsonValue.h:480
JsonValue(const std::string &v)
Creates a String JSON value.
Definition JsonValue.h:179
JsonValue(std::uint32_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint32_t).
Definition JsonValue.h:159
const JsonValue::Object & getObject() const
Gets the object from the value.
Definition JsonValue.h:430
const JsonValue * getValuePtrForKey(const std::string &key) const
Attempts to obtain a pointer to a JsonValue for the given key on this object.
std::uint64_t getUint64OrDefault(std::uint64_t defaultValue) const noexcept
Gets the uint64_t from the value or returns defaultValue.
Definition JsonValue.h:550
JsonValue(std::uint8_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint8_t).
Definition JsonValue.h:135
int64_t getSizeBytes() const noexcept
Returns the size in bytes of this JsonValue.
Definition JsonValue.h:648
JsonValue(std::int32_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int32_t).
Definition JsonValue.h:153
JsonValue(std::uint64_t v) noexcept
Creates a std::uint64_t JSON value.
Definition JsonValue.h:169
std::optional< To > getSafeNumber() const
Gets the numerical quantity from the value casted to the To type. This function should be used over g...
Definition JsonValue.h:373
To getSafeNumericalValueOrDefaultForKey(const std::string &key, To defaultValue) const
Converts the numerical value corresponding to the given key to the provided numerical template type.
Definition JsonValue.h:333
const JsonValue::Array & getArray() const
Gets the array from the value.
Definition JsonValue.h:450
JsonValue(const std::vector< JsonValue > &v)
Creates an Array JSON value with the given elements.
Definition JsonValue.h:204
JsonValue(std::initializer_list< std::pair< const std::string, JsonValue > > v)
Creates an JSON value from the given initializer list.
Definition JsonValue.h:220
std::nullptr_t Null
The type to represent a null JSON value.
Definition JsonValue.h:80
bool hasKey(const std::string &key) const
Determines if this value is an Object and has the given key.
Definition JsonValue.h:351
Utility classes for Cesium.
constexpr T losslessNarrowOrDefault(U u, T defaultValue) noexcept
Attempts a narrowing conversion of U into T without losing information. If a lossless conversion can'...
Definition JsonValue.h:55
constexpr std::optional< T > losslessNarrow(U u) noexcept
Attempts a narrowing conversion of U into T without losing information. If a lossless conversion can'...
Definition JsonValue.h:29
STL namespace.