cesium-native  0.41.0
JsonValue.h
1 #pragma once
2 
3 #include "Library.h"
4 
5 #include <gsl/narrow>
6 
7 #include <cmath>
8 #include <cstdint>
9 #include <initializer_list>
10 #include <map>
11 #include <optional>
12 #include <stdexcept>
13 #include <string>
14 #include <string_view>
15 #include <type_traits>
16 #include <variant>
17 #include <vector>
18 
19 namespace CesiumUtility {
20 
21 struct JsonValueMissingKey : public std::runtime_error {
22  JsonValueMissingKey(const std::string& key)
23  : std::runtime_error(key + " is not present in Object") {}
24 };
25 
26 struct JsonValueNotRealValue : public std::runtime_error {
28  : std::runtime_error("this->value was not double, uint64_t or int64_t") {}
29 };
30 
31 template <typename T, typename U>
32 constexpr std::optional<T> losslessNarrow(U u) noexcept {
33  constexpr const bool is_different_signedness =
34  (std::is_signed<T>::value != std::is_signed<U>::value);
35 
36  const T t = gsl::narrow_cast<T>(u);
37 
38  if (static_cast<U>(t) != u ||
39  (is_different_signedness && ((t < T{}) != (u < U{})))) {
40  return std::nullopt;
41  }
42 
43  return t;
44 }
45 
46 template <typename T, typename U>
47 constexpr T losslessNarrowOrDefault(U u, T defaultValue) noexcept {
48  constexpr const bool is_different_signedness =
49  (std::is_signed<T>::value != std::is_signed<U>::value);
50 
51  const T t = gsl::narrow_cast<T>(u);
52 
53  if (static_cast<U>(t) != u ||
54  (is_different_signedness && ((t < T{}) != (u < U{})))) {
55  return defaultValue;
56  }
57 
58  return t;
59 }
60 
67 class CESIUMUTILITY_API JsonValue final {
68 public:
72  using Null = std::nullptr_t;
73 
77  using Bool = bool;
78 
82  using String = std::string;
83 
87  using Object = std::map<std::string, JsonValue>;
88 
92  using Array = std::vector<JsonValue>;
93 
97  JsonValue() noexcept : value() {}
98 
102  JsonValue(std::nullptr_t) noexcept : value(nullptr) {}
103 
109  JsonValue(double v) noexcept {
110  if (std::isnan(v) || std::isinf(v)) {
111  value = nullptr;
112  } else {
113  value = v;
114  }
115  }
116 
121  JsonValue(std::int8_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
122 
127  JsonValue(std::uint8_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
128 
133  JsonValue(std::int16_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
134 
139  JsonValue(std::uint16_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
140 
145  JsonValue(std::int32_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
146 
151  JsonValue(std::uint32_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
152 
156  JsonValue(std::int64_t v) noexcept : value(v) {}
157 
161  JsonValue(std::uint64_t v) noexcept : value(v) {}
162 
166  JsonValue(bool v) noexcept : value(v) {}
167 
171  JsonValue(const std::string& v) : value(v) {}
172 
176  JsonValue(std::string&& v) noexcept : value(std::move(v)) {}
177 
181  JsonValue(const char* v) : value(std::string(v)) {}
182 
186  JsonValue(const std::map<std::string, JsonValue>& v) : value(v) {}
187 
191  JsonValue(std::map<std::string, JsonValue>&& v) : value(std::move(v)) {}
192 
196  JsonValue(const std::vector<JsonValue>& v) : value(v) {}
197 
201  JsonValue(std::vector<JsonValue>&& v) noexcept : value(std::move(v)) {}
202 
206  JsonValue(std::initializer_list<JsonValue> v)
207  : value(std::vector<JsonValue>(v)) {}
208 
212  JsonValue(std::initializer_list<std::pair<const std::string, JsonValue>> v)
213  : value(std::map<std::string, JsonValue>(v)) {}
214 
215  [[nodiscard]] const JsonValue*
216  getValuePtrForKey(const std::string& key) const;
217  [[nodiscard]] JsonValue* getValuePtrForKey(const std::string& key);
218 
233  template <typename T>
234  const T* getValuePtrForKey(const std::string& key) const {
235  const JsonValue* pValue = this->getValuePtrForKey(key);
236  if (!pValue) {
237  return nullptr;
238  }
239 
240  return std::get_if<T>(&pValue->value);
241  }
242 
257  template <typename T> T* getValuePtrForKey(const std::string& key) {
258  JsonValue* pValue = this->getValuePtrForKey(key);
259  return std::get_if<T>(&pValue->value);
260  }
261 
281  template <
282  typename To,
283  typename std::enable_if<
284  std::is_integral<To>::value ||
285  std::is_floating_point<To>::value>::type* = nullptr>
286  [[nodiscard]] To getSafeNumericalValueForKey(const std::string& key) const {
287  const Object& pObject = std::get<Object>(this->value);
288  const auto it = pObject.find(key);
289  if (it == pObject.end()) {
290  throw JsonValueMissingKey(key);
291  }
292  return it->second.getSafeNumber<To>();
293  }
294 
312  template <
313  typename To,
314  typename std::enable_if<
315  std::is_integral<To>::value ||
316  std::is_floating_point<To>::value>::type* = nullptr>
318  const std::string& key,
319  To defaultValue) const {
320  const Object& pObject = std::get<Object>(this->value);
321  const auto it = pObject.find(key);
322  if (it == pObject.end()) {
323  return defaultValue;
324  }
325  return it->second.getSafeNumberOrDefault<To>(defaultValue);
326  }
327 
335  [[nodiscard]] inline bool hasKey(const std::string& key) const {
336  const Object* pObject = std::get_if<Object>(&this->value);
337  if (!pObject) {
338  return false;
339  }
340 
341  return pObject->find(key) != pObject->end();
342  }
343 
353  template <
354  typename To,
355  typename std::enable_if<
356  std::is_integral<To>::value ||
357  std::is_floating_point<To>::value>::type* = nullptr>
358  [[nodiscard]] To getSafeNumber() const {
359  const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value);
360  if (uInt) {
361  return gsl::narrow<To>(*uInt);
362  }
363 
364  const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value);
365  if (sInt) {
366  return gsl::narrow<To>(*sInt);
367  }
368 
369  const double* real = std::get_if<double>(&this->value);
370  if (real) {
371  return gsl::narrow<To>(*real);
372  }
373 
374  throw JsonValueNotRealValue();
375  }
376 
384  template <
385  typename To,
386  typename std::enable_if<
387  std::is_integral<To>::value ||
388  std::is_floating_point<To>::value>::type* = nullptr>
389  [[nodiscard]] To getSafeNumberOrDefault(To defaultValue) const noexcept {
390  const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value);
391  if (uInt) {
392  return losslessNarrowOrDefault<To>(*uInt, defaultValue);
393  }
394 
395  const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value);
396  if (sInt) {
397  return losslessNarrowOrDefault<To>(*sInt, defaultValue);
398  }
399 
400  const double* real = std::get_if<double>(&this->value);
401  if (real) {
402  return losslessNarrowOrDefault<To>(*real, defaultValue);
403  }
404 
405  return defaultValue;
406  }
407 
415  [[nodiscard]] inline const JsonValue::Object& getObject() const {
416  return std::get<JsonValue::Object>(this->value);
417  }
418 
425  [[nodiscard]] inline const JsonValue::String& getString() const {
426  return std::get<String>(this->value);
427  }
428 
435  [[nodiscard]] inline const JsonValue::Array& getArray() const {
436  return std::get<JsonValue::Array>(this->value);
437  }
438 
447  [[nodiscard]] std::vector<std::string>
448  getArrayOfStrings(const std::string& defaultString) const;
449 
456  [[nodiscard]] inline bool getBool() const {
457  return std::get<bool>(this->value);
458  }
459 
465  [[nodiscard]] inline double getDouble() const {
466  return std::get<double>(this->value);
467  }
468 
475  [[nodiscard]] std::uint64_t getUint64() const {
476  return std::get<std::uint64_t>(this->value);
477  }
478 
485  [[nodiscard]] std::int64_t getInt64() const {
486  return std::get<std::int64_t>(this->value);
487  }
488 
493  [[nodiscard]] inline bool getBoolOrDefault(bool defaultValue) const noexcept {
494  const auto* v = std::get_if<bool>(&this->value);
495  if (v) {
496  return *v;
497  }
498 
499  return defaultValue;
500  }
501 
506  [[nodiscard]] inline const JsonValue::String
507  getStringOrDefault(String defaultValue) const {
508  const auto* v = std::get_if<JsonValue::String>(&this->value);
509  if (v) {
510  return *v;
511  }
512 
513  return defaultValue;
514  }
515 
520  [[nodiscard]] inline double
521  getDoubleOrDefault(double defaultValue) const noexcept {
522  const auto* v = std::get_if<double>(&this->value);
523  if (v) {
524  return *v;
525  }
526 
527  return defaultValue;
528  }
529 
534  [[nodiscard]] inline std::uint64_t
535  getUint64OrDefault(std::uint64_t defaultValue) const noexcept {
536  const auto* v = std::get_if<std::uint64_t>(&this->value);
537  if (v) {
538  return *v;
539  }
540 
541  return defaultValue;
542  }
543 
548  [[nodiscard]] inline std::int64_t
549  getInt64OrDefault(std::int64_t defaultValue) const noexcept {
550  const auto* v = std::get_if<std::int64_t>(&this->value);
551  if (v) {
552  return *v;
553  }
554 
555  return defaultValue;
556  }
557 
561  [[nodiscard]] inline bool isNull() const noexcept {
562  return std::holds_alternative<Null>(this->value);
563  }
564 
570  [[nodiscard]] inline bool isNumber() const noexcept {
571  return isDouble() || isUint64() || isInt64();
572  }
573 
577  [[nodiscard]] inline bool isBool() const noexcept {
578  return std::holds_alternative<Bool>(this->value);
579  }
580 
584  [[nodiscard]] inline bool isString() const noexcept {
585  return std::holds_alternative<String>(this->value);
586  }
587 
591  [[nodiscard]] inline bool isObject() const noexcept {
592  return std::holds_alternative<Object>(this->value);
593  }
594 
598  [[nodiscard]] inline bool isArray() const noexcept {
599  return std::holds_alternative<Array>(this->value);
600  }
601 
605  [[nodiscard]] inline bool isDouble() const noexcept {
606  return std::holds_alternative<double>(this->value);
607  }
608 
612  [[nodiscard]] inline bool isUint64() const noexcept {
613  return std::holds_alternative<std::uint64_t>(this->value);
614  }
615 
619  [[nodiscard]] inline bool isInt64() const noexcept {
620  return std::holds_alternative<std::int64_t>(this->value);
621  }
622 
635  std::variant<
636  Null,
637  double,
638  std::uint64_t,
639  std::int64_t,
640  Bool,
641  String,
642  Object,
643  Array>
645 };
646 } // namespace CesiumUtility
A generic implementation of a value in a JSON structure.
Definition: JsonValue.h:67
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:286
std::map< std::string, JsonValue > Object
The type to represent an Object JSON value.
Definition: JsonValue.h:87
JsonValue(std::int8_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int8_t).
Definition: JsonValue.h:121
bool getBool() const
Gets the bool from the value.
Definition: JsonValue.h:456
JsonValue(const std::map< std::string, JsonValue > &v)
Creates an Object JSON value with the given properties.
Definition: JsonValue.h:186
std::vector< std::string > getArrayOfStrings(const std::string &defaultString) const
Gets an array of strings from the value.
bool isInt64() const noexcept
Returns whether this value is a std::int64_t value.
Definition: JsonValue.h:619
JsonValue(std::int16_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int16_t).
Definition: JsonValue.h:133
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:570
bool isDouble() const noexcept
Returns whether this value is a double value.
Definition: JsonValue.h:605
JsonValue(std::vector< JsonValue > &&v) noexcept
Creates an Array JSON value with the given elements.
Definition: JsonValue.h:201
std::vector< JsonValue > Array
The type to represent an Array JSON value.
Definition: JsonValue.h:92
double getDoubleOrDefault(double defaultValue) const noexcept
Gets the double from the value or returns defaultValue.
Definition: JsonValue.h:521
JsonValue(std::initializer_list< std::pair< const std::string, JsonValue >> v)
Creates an JSON value from the given initializer list.
Definition: JsonValue.h:212
JsonValue(std::initializer_list< JsonValue > v)
Creates an JSON value from the given initializer list.
Definition: JsonValue.h:206
JsonValue(std::uint16_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint16_t).
Definition: JsonValue.h:139
std::variant< Null, double, std::uint64_t, std::int64_t, Bool, String, Object, Array > value
The actual value.
Definition: JsonValue.h:644
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:358
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:234
bool isBool() const noexcept
Returns whether this value is a Bool value.
Definition: JsonValue.h:577
const JsonValue::String getStringOrDefault(String defaultValue) const
Gets the string from the value or returns defaultValue.
Definition: JsonValue.h:507
JsonValue(std::nullptr_t) noexcept
Creates a null JSON value.
Definition: JsonValue.h:102
JsonValue(std::string &&v) noexcept
Creates a String JSON value.
Definition: JsonValue.h:176
const JsonValue::Object & getObject() const
Gets the object from the value.
Definition: JsonValue.h:415
bool Bool
The type to represent a Bool JSON value.
Definition: JsonValue.h:77
JsonValue(bool v) noexcept
Creates a Bool JSON value.
Definition: JsonValue.h:166
bool isNull() const noexcept
Returns whether this value is a null value.
Definition: JsonValue.h:561
std::uint64_t getUint64() const
Gets the std::uint64_t from the value.
Definition: JsonValue.h:475
std::int64_t getInt64OrDefault(std::int64_t defaultValue) const noexcept
Gets the int64_t from the value or returns defaultValue.
Definition: JsonValue.h:549
std::string String
The type to represent a String JSON value.
Definition: JsonValue.h:82
JsonValue(const char *v)
Creates a String JSON value.
Definition: JsonValue.h:181
const JsonValue::String & getString() const
Gets the string from the value.
Definition: JsonValue.h:425
bool isUint64() const noexcept
Returns whether this value is a std::uint64_t value.
Definition: JsonValue.h:612
JsonValue(std::int64_t v) noexcept
Creates a std::int64_t JSON value.
Definition: JsonValue.h:156
bool isArray() const noexcept
Returns whether this value is an Array value.
Definition: JsonValue.h:598
JsonValue() noexcept
Default constructor.
Definition: JsonValue.h:97
bool isString() const noexcept
Returns whether this value is a String value.
Definition: JsonValue.h:584
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:257
bool isObject() const noexcept
Returns whether this value is an Object value.
Definition: JsonValue.h:591
JsonValue(double v) noexcept
Creates a Number JSON value.
Definition: JsonValue.h:109
std::int64_t getInt64() const
Gets the std::int64_t from the value.
Definition: JsonValue.h:485
JsonValue(std::map< std::string, JsonValue > &&v)
Creates an Object JSON value with the given properties.
Definition: JsonValue.h:191
bool getBoolOrDefault(bool defaultValue) const noexcept
Gets the bool from the value or returns defaultValue.
Definition: JsonValue.h:493
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:389
double getDouble() const
Gets the double from the value.
Definition: JsonValue.h:465
JsonValue(const std::string &v)
Creates a String JSON value.
Definition: JsonValue.h:171
JsonValue(std::uint32_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint32_t).
Definition: JsonValue.h:151
std::uint64_t getUint64OrDefault(std::uint64_t defaultValue) const noexcept
Gets the uint64_t from the value or returns defaultValue.
Definition: JsonValue.h:535
JsonValue(std::uint8_t v) noexcept
Creates a std::uint64_t JSON value (Widening conversion from std::uint8_t).
Definition: JsonValue.h:127
JsonValue(std::int32_t v) noexcept
Creates a std::int64_t JSON value (Widening conversion from std::int32_t).
Definition: JsonValue.h:145
JsonValue(std::uint64_t v) noexcept
Creates a std::uint64_t JSON value.
Definition: JsonValue.h:161
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:317
const JsonValue::Array & getArray() const
Gets the array from the value.
Definition: JsonValue.h:435
JsonValue(const std::vector< JsonValue > &v)
Creates an Array JSON value with the given elements.
Definition: JsonValue.h:196
std::nullptr_t Null
The type to represent a null JSON value.
Definition: JsonValue.h:72
bool hasKey(const std::string &key) const
Determines if this value is an Object and has the given key.
Definition: JsonValue.h:335
Utility classes for Cesium.