Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1 | // Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 2 | // Distributed under MIT license, or public domain if desired and |
| 3 | // recognized in your jurisdiction. |
| 4 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE |
| 5 | |
| 6 | #if !defined(JSON_IS_AMALGAMATION) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 7 | #include <json/assertions.h> |
| 8 | #include <json/value.h> |
| 9 | #include <json/writer.h> |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 10 | #endif // if !defined(JSON_IS_AMALGAMATION) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 11 | #include <algorithm> |
| 12 | #include <cassert> |
| 13 | #include <cmath> |
| 14 | #include <cstddef> |
| 15 | #include <cstring> |
| 16 | #include <iostream> |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 17 | #include <sstream> |
| 18 | #include <utility> |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 19 | |
| 20 | // Provide implementation equivalent of std::snprintf for older _MSC compilers |
| 21 | #if defined(_MSC_VER) && _MSC_VER < 1900 |
| 22 | #include <stdarg.h> |
| 23 | static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size, |
| 24 | const char* format, va_list ap) { |
| 25 | int count = -1; |
| 26 | if (size != 0) |
| 27 | count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); |
| 28 | if (count == -1) |
| 29 | count = _vscprintf(format, ap); |
| 30 | return count; |
| 31 | } |
| 32 | |
| 33 | int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size, |
| 34 | const char* format, ...) { |
| 35 | va_list ap; |
| 36 | va_start(ap, format); |
| 37 | const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap); |
| 38 | va_end(ap); |
| 39 | return count; |
| 40 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 41 | #endif |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 42 | |
| 43 | // Disable warning C4702 : unreachable code |
| 44 | #if defined(_MSC_VER) |
| 45 | #pragma warning(disable : 4702) |
| 46 | #endif |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 47 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 48 | #define JSON_ASSERT_UNREACHABLE assert(false) |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 49 | |
| 50 | namespace Json { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 51 | template <typename T> |
| 52 | static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) { |
| 53 | std::unique_ptr<T> r; |
| 54 | if (p) { |
| 55 | r = std::unique_ptr<T>(new T(*p)); |
| 56 | } |
| 57 | return r; |
| 58 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 59 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 60 | // This is a walkaround to avoid the static initialization of Value::null. |
| 61 | // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of |
| 62 | // 8 (instead of 4) as a bit of future-proofing. |
| 63 | #if defined(__ARMEL__) |
| 64 | #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) |
| 65 | #else |
| 66 | #define ALIGNAS(byte_alignment) |
| 67 | #endif |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 68 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 69 | // static |
| 70 | Value const& Value::nullSingleton() { |
| 71 | static Value const nullStatic; |
| 72 | return nullStatic; |
| 73 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 74 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 75 | #if JSON_USE_NULLREF |
| 76 | // for backwards compatibility, we'll leave these global references around, but |
| 77 | // DO NOT use them in JSONCPP library code any more! |
| 78 | // static |
| 79 | Value const& Value::null = Value::nullSingleton(); |
| 80 | |
| 81 | // static |
| 82 | Value const& Value::nullRef = Value::nullSingleton(); |
| 83 | #endif |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 84 | |
| 85 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
| 86 | template <typename T, typename U> |
| 87 | static inline bool InRange(double d, T min, U max) { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 88 | // The casts can lose precision, but we are looking only for |
| 89 | // an approximate range. Might fail on edge cases though. ~cdunn |
| 90 | return d >= static_cast<double>(min) && d <= static_cast<double>(max); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 91 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 92 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
| 93 | static inline double integerToDouble(Json::UInt64 value) { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 94 | return static_cast<double>(Int64(value / 2)) * 2.0 + |
| 95 | static_cast<double>(Int64(value & 1)); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 96 | } |
| 97 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 98 | template <typename T> static inline double integerToDouble(T value) { |
| 99 | return static_cast<double>(value); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | template <typename T, typename U> |
| 103 | static inline bool InRange(double d, T min, U max) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 104 | return d >= integerToDouble(min) && d <= integerToDouble(max); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 105 | } |
| 106 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
| 107 | |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 108 | /** Duplicates the specified string value. |
| 109 | * @param value Pointer to the string to duplicate. Must be zero-terminated if |
| 110 | * length is "unknown". |
| 111 | * @param length Length of the value. if equals to unknown, then it will be |
| 112 | * computed using strlen(value). |
| 113 | * @return Pointer on the duplicate instance of string. |
| 114 | */ |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 115 | static inline char* duplicateStringValue(const char* value, size_t length) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 116 | // Avoid an integer overflow in the call to malloc below by limiting length |
| 117 | // to a sane value. |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 118 | if (length >= static_cast<size_t>(Value::maxInt)) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 119 | length = Value::maxInt - 1; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 120 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 121 | auto newString = static_cast<char*>(malloc(length + 1)); |
| 122 | if (newString == nullptr) { |
| 123 | throwRuntimeError("in Json::Value::duplicateStringValue(): " |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 124 | "Failed to allocate string value buffer"); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 125 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 126 | memcpy(newString, value, length); |
| 127 | newString[length] = 0; |
| 128 | return newString; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 129 | } |
| 130 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 131 | /* Record the length as a prefix. |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 132 | */ |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 133 | static inline char* duplicateAndPrefixStringValue(const char* value, |
| 134 | unsigned int length) { |
| 135 | // Avoid an integer overflow in the call to malloc below by limiting length |
| 136 | // to a sane value. |
| 137 | JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - |
| 138 | sizeof(unsigned) - 1U, |
| 139 | "in Json::Value::duplicateAndPrefixStringValue(): " |
| 140 | "length too big for prefixing"); |
| 141 | size_t actualLength = sizeof(length) + length + 1; |
| 142 | auto newString = static_cast<char*>(malloc(actualLength)); |
| 143 | if (newString == nullptr) { |
| 144 | throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " |
| 145 | "Failed to allocate string value buffer"); |
| 146 | } |
| 147 | *reinterpret_cast<unsigned*>(newString) = length; |
| 148 | memcpy(newString + sizeof(unsigned), value, length); |
| 149 | newString[actualLength - 1U] = |
| 150 | 0; // to avoid buffer over-run accidents by users later |
| 151 | return newString; |
| 152 | } |
| 153 | inline static void decodePrefixedString(bool isPrefixed, char const* prefixed, |
| 154 | unsigned* length, char const** value) { |
| 155 | if (!isPrefixed) { |
| 156 | *length = static_cast<unsigned>(strlen(prefixed)); |
| 157 | *value = prefixed; |
| 158 | } else { |
| 159 | *length = *reinterpret_cast<unsigned const*>(prefixed); |
| 160 | *value = prefixed + sizeof(unsigned); |
| 161 | } |
| 162 | } |
| 163 | /** Free the string duplicated by |
| 164 | * duplicateStringValue()/duplicateAndPrefixStringValue(). |
| 165 | */ |
| 166 | #if JSONCPP_USING_SECURE_MEMORY |
| 167 | static inline void releasePrefixedStringValue(char* value) { |
| 168 | unsigned length = 0; |
| 169 | char const* valueDecoded; |
| 170 | decodePrefixedString(true, value, &length, &valueDecoded); |
| 171 | size_t const size = sizeof(unsigned) + length + 1U; |
| 172 | memset(value, 0, size); |
| 173 | free(value); |
| 174 | } |
| 175 | static inline void releaseStringValue(char* value, unsigned length) { |
| 176 | // length==0 => we allocated the strings memory |
| 177 | size_t size = (length == 0) ? strlen(value) : length; |
| 178 | memset(value, 0, size); |
| 179 | free(value); |
| 180 | } |
| 181 | #else // !JSONCPP_USING_SECURE_MEMORY |
| 182 | static inline void releasePrefixedStringValue(char* value) { free(value); } |
| 183 | static inline void releaseStringValue(char* value, unsigned) { free(value); } |
| 184 | #endif // JSONCPP_USING_SECURE_MEMORY |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 185 | |
| 186 | } // namespace Json |
| 187 | |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 188 | // ////////////////////////////////////////////////////////////////// |
| 189 | // ////////////////////////////////////////////////////////////////// |
| 190 | // ////////////////////////////////////////////////////////////////// |
| 191 | // ValueInternals... |
| 192 | // ////////////////////////////////////////////////////////////////// |
| 193 | // ////////////////////////////////////////////////////////////////// |
| 194 | // ////////////////////////////////////////////////////////////////// |
| 195 | #if !defined(JSON_IS_AMALGAMATION) |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 196 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 197 | #include "json_valueiterator.inl" |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 198 | #endif // if !defined(JSON_IS_AMALGAMATION) |
| 199 | |
| 200 | namespace Json { |
| 201 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 202 | #if JSON_USE_EXCEPTION |
| 203 | Exception::Exception(String msg) : msg_(std::move(msg)) {} |
| 204 | Exception::~Exception() noexcept = default; |
| 205 | char const* Exception::what() const noexcept { return msg_.c_str(); } |
| 206 | RuntimeError::RuntimeError(String const& msg) : Exception(msg) {} |
| 207 | LogicError::LogicError(String const& msg) : Exception(msg) {} |
| 208 | JSONCPP_NORETURN void throwRuntimeError(String const& msg) { |
| 209 | throw RuntimeError(msg); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 210 | } |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 211 | JSONCPP_NORETURN void throwLogicError(String const& msg) { |
| 212 | throw LogicError(msg); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 213 | } |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 214 | #else // !JSON_USE_EXCEPTION |
| 215 | JSONCPP_NORETURN void throwRuntimeError(String const& msg) { |
| 216 | std::cerr << msg << std::endl; |
| 217 | abort(); |
| 218 | } |
| 219 | JSONCPP_NORETURN void throwLogicError(String const& msg) { |
| 220 | std::cerr << msg << std::endl; |
| 221 | abort(); |
| 222 | } |
| 223 | #endif |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 224 | |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 225 | // ////////////////////////////////////////////////////////////////// |
| 226 | // ////////////////////////////////////////////////////////////////// |
| 227 | // ////////////////////////////////////////////////////////////////// |
| 228 | // class Value::CZString |
| 229 | // ////////////////////////////////////////////////////////////////// |
| 230 | // ////////////////////////////////////////////////////////////////// |
| 231 | // ////////////////////////////////////////////////////////////////// |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 232 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 233 | // Notes: policy_ indicates if the string was allocated when |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 234 | // a string is stored. |
| 235 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 236 | Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {} |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 237 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 238 | Value::CZString::CZString(char const* str, unsigned length, |
| 239 | DuplicationPolicy allocate) |
| 240 | : cstr_(str) { |
| 241 | // allocate != duplicate |
| 242 | storage_.policy_ = allocate & 0x3; |
| 243 | storage_.length_ = length & 0x3FFFFFFF; |
| 244 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 245 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 246 | Value::CZString::CZString(const CZString& other) { |
| 247 | cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr |
| 248 | ? duplicateStringValue(other.cstr_, other.storage_.length_) |
| 249 | : other.cstr_); |
| 250 | storage_.policy_ = |
| 251 | static_cast<unsigned>( |
| 252 | other.cstr_ |
| 253 | ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == |
| 254 | noDuplication |
| 255 | ? noDuplication |
| 256 | : duplicate) |
| 257 | : static_cast<DuplicationPolicy>(other.storage_.policy_)) & |
| 258 | 3U; |
| 259 | storage_.length_ = other.storage_.length_; |
| 260 | } |
| 261 | |
| 262 | Value::CZString::CZString(CZString&& other) |
| 263 | : cstr_(other.cstr_), index_(other.index_) { |
| 264 | other.cstr_ = nullptr; |
| 265 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 266 | |
| 267 | Value::CZString::~CZString() { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 268 | if (cstr_ && storage_.policy_ == duplicate) { |
| 269 | releaseStringValue(const_cast<char*>(cstr_), |
| 270 | storage_.length_ + 1U); // +1 for null terminating |
| 271 | // character for sake of |
| 272 | // completeness but not actually |
| 273 | // necessary |
| 274 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 275 | } |
| 276 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 277 | void Value::CZString::swap(CZString& other) { |
| 278 | std::swap(cstr_, other.cstr_); |
| 279 | std::swap(index_, other.index_); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 280 | } |
| 281 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 282 | Value::CZString& Value::CZString::operator=(const CZString& other) { |
| 283 | cstr_ = other.cstr_; |
| 284 | index_ = other.index_; |
| 285 | return *this; |
| 286 | } |
| 287 | |
| 288 | Value::CZString& Value::CZString::operator=(CZString&& other) { |
| 289 | cstr_ = other.cstr_; |
| 290 | index_ = other.index_; |
| 291 | other.cstr_ = nullptr; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 292 | return *this; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 293 | } |
| 294 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 295 | bool Value::CZString::operator<(const CZString& other) const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 296 | if (!cstr_) |
| 297 | return index_ < other.index_; |
| 298 | // return strcmp(cstr_, other.cstr_) < 0; |
| 299 | // Assume both are strings. |
| 300 | unsigned this_len = this->storage_.length_; |
| 301 | unsigned other_len = other.storage_.length_; |
| 302 | unsigned min_len = std::min<unsigned>(this_len, other_len); |
| 303 | JSON_ASSERT(this->cstr_ && other.cstr_); |
| 304 | int comp = memcmp(this->cstr_, other.cstr_, min_len); |
| 305 | if (comp < 0) |
| 306 | return true; |
| 307 | if (comp > 0) |
| 308 | return false; |
| 309 | return (this_len < other_len); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 310 | } |
| 311 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 312 | bool Value::CZString::operator==(const CZString& other) const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 313 | if (!cstr_) |
| 314 | return index_ == other.index_; |
| 315 | // return strcmp(cstr_, other.cstr_) == 0; |
| 316 | // Assume both are strings. |
| 317 | unsigned this_len = this->storage_.length_; |
| 318 | unsigned other_len = other.storage_.length_; |
| 319 | if (this_len != other_len) |
| 320 | return false; |
| 321 | JSON_ASSERT(this->cstr_ && other.cstr_); |
| 322 | int comp = memcmp(this->cstr_, other.cstr_, this_len); |
| 323 | return comp == 0; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 324 | } |
| 325 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 326 | ArrayIndex Value::CZString::index() const { return index_; } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 327 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 328 | // const char* Value::CZString::c_str() const { return cstr_; } |
| 329 | const char* Value::CZString::data() const { return cstr_; } |
| 330 | unsigned Value::CZString::length() const { return storage_.length_; } |
| 331 | bool Value::CZString::isStaticString() const { |
| 332 | return storage_.policy_ == noDuplication; |
| 333 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 334 | |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 335 | // ////////////////////////////////////////////////////////////////// |
| 336 | // ////////////////////////////////////////////////////////////////// |
| 337 | // ////////////////////////////////////////////////////////////////// |
| 338 | // class Value::Value |
| 339 | // ////////////////////////////////////////////////////////////////// |
| 340 | // ////////////////////////////////////////////////////////////////// |
| 341 | // ////////////////////////////////////////////////////////////////// |
| 342 | |
| 343 | /*! \internal Default constructor initialization must be equivalent to: |
| 344 | * memset( this, 0, sizeof(Value) ) |
| 345 | * This optimization is used in ValueInternalMap fast allocator. |
| 346 | */ |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 347 | Value::Value(ValueType type) { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 348 | static char const emptyString[] = ""; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 349 | initBasic(type); |
| 350 | switch (type) { |
| 351 | case nullValue: |
| 352 | break; |
| 353 | case intValue: |
| 354 | case uintValue: |
| 355 | value_.int_ = 0; |
| 356 | break; |
| 357 | case realValue: |
| 358 | value_.real_ = 0.0; |
| 359 | break; |
| 360 | case stringValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 361 | // allocated_ == false, so this is safe. |
| 362 | value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString)); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 363 | break; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 364 | case arrayValue: |
| 365 | case objectValue: |
| 366 | value_.map_ = new ObjectValues(); |
| 367 | break; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 368 | case booleanValue: |
| 369 | value_.bool_ = false; |
| 370 | break; |
| 371 | default: |
| 372 | JSON_ASSERT_UNREACHABLE; |
| 373 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 374 | } |
| 375 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 376 | Value::Value(Int value) { |
| 377 | initBasic(intValue); |
| 378 | value_.int_ = value; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 379 | } |
| 380 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 381 | Value::Value(UInt value) { |
| 382 | initBasic(uintValue); |
| 383 | value_.uint_ = value; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 384 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 385 | #if defined(JSON_HAS_INT64) |
| 386 | Value::Value(Int64 value) { |
| 387 | initBasic(intValue); |
| 388 | value_.int_ = value; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 389 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 390 | Value::Value(UInt64 value) { |
| 391 | initBasic(uintValue); |
| 392 | value_.uint_ = value; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 393 | } |
| 394 | #endif // defined(JSON_HAS_INT64) |
| 395 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 396 | Value::Value(double value) { |
| 397 | initBasic(realValue); |
| 398 | value_.real_ = value; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 399 | } |
| 400 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 401 | Value::Value(const char* value) { |
| 402 | initBasic(stringValue, true); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 403 | JSON_ASSERT_MESSAGE(value != nullptr, |
| 404 | "Null Value Passed to Value Constructor"); |
| 405 | value_.string_ = duplicateAndPrefixStringValue( |
| 406 | value, static_cast<unsigned>(strlen(value))); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 407 | } |
| 408 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 409 | Value::Value(const char* begin, const char* end) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 410 | initBasic(stringValue, true); |
| 411 | value_.string_ = |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 412 | duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin)); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 413 | } |
| 414 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 415 | Value::Value(const String& value) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 416 | initBasic(stringValue, true); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 417 | value_.string_ = duplicateAndPrefixStringValue( |
| 418 | value.data(), static_cast<unsigned>(value.length())); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 419 | } |
| 420 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 421 | Value::Value(const StaticString& value) { |
| 422 | initBasic(stringValue); |
| 423 | value_.string_ = const_cast<char*>(value.c_str()); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 424 | } |
| 425 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 426 | Value::Value(bool value) { |
| 427 | initBasic(booleanValue); |
| 428 | value_.bool_ = value; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 429 | } |
| 430 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 431 | Value::Value(const Value& other) { |
| 432 | dupPayload(other); |
| 433 | dupMeta(other); |
| 434 | } |
| 435 | |
| 436 | Value::Value(Value&& other) { |
| 437 | initBasic(nullValue); |
| 438 | swap(other); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 439 | } |
| 440 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 441 | Value::~Value() { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 442 | releasePayload(); |
| 443 | value_.uint_ = 0; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 444 | } |
| 445 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 446 | Value& Value::operator=(const Value& other) { |
| 447 | Value(other).swap(*this); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 448 | return *this; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 449 | } |
| 450 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 451 | Value& Value::operator=(Value&& other) { |
| 452 | other.swap(*this); |
| 453 | return *this; |
| 454 | } |
| 455 | |
| 456 | void Value::swapPayload(Value& other) { |
| 457 | std::swap(bits_, other.bits_); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 458 | std::swap(value_, other.value_); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 459 | } |
| 460 | |
| 461 | void Value::copyPayload(const Value& other) { |
| 462 | releasePayload(); |
| 463 | dupPayload(other); |
| 464 | } |
| 465 | |
| 466 | void Value::swap(Value& other) { |
| 467 | swapPayload(other); |
| 468 | std::swap(comments_, other.comments_); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 469 | std::swap(start_, other.start_); |
| 470 | std::swap(limit_, other.limit_); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 471 | } |
| 472 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 473 | void Value::copy(const Value& other) { |
| 474 | copyPayload(other); |
| 475 | dupMeta(other); |
| 476 | } |
| 477 | |
| 478 | ValueType Value::type() const { |
| 479 | return static_cast<ValueType>(bits_.value_type_); |
| 480 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 481 | |
| 482 | int Value::compare(const Value& other) const { |
| 483 | if (*this < other) |
| 484 | return -1; |
| 485 | if (*this > other) |
| 486 | return 1; |
| 487 | return 0; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 488 | } |
| 489 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 490 | bool Value::operator<(const Value& other) const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 491 | int typeDelta = type() - other.type(); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 492 | if (typeDelta) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 493 | return typeDelta < 0; |
| 494 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 495 | case nullValue: |
| 496 | return false; |
| 497 | case intValue: |
| 498 | return value_.int_ < other.value_.int_; |
| 499 | case uintValue: |
| 500 | return value_.uint_ < other.value_.uint_; |
| 501 | case realValue: |
| 502 | return value_.real_ < other.value_.real_; |
| 503 | case booleanValue: |
| 504 | return value_.bool_ < other.value_.bool_; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 505 | case stringValue: { |
| 506 | if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { |
| 507 | return other.value_.string_ != nullptr; |
| 508 | } |
| 509 | unsigned this_len; |
| 510 | unsigned other_len; |
| 511 | char const* this_str; |
| 512 | char const* other_str; |
| 513 | decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, |
| 514 | &this_str); |
| 515 | decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, |
| 516 | &other_str); |
| 517 | unsigned min_len = std::min<unsigned>(this_len, other_len); |
| 518 | JSON_ASSERT(this_str && other_str); |
| 519 | int comp = memcmp(this_str, other_str, min_len); |
| 520 | if (comp < 0) |
| 521 | return true; |
| 522 | if (comp > 0) |
| 523 | return false; |
| 524 | return (this_len < other_len); |
| 525 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 526 | case arrayValue: |
| 527 | case objectValue: { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 528 | auto thisSize = value_.map_->size(); |
| 529 | auto otherSize = other.value_.map_->size(); |
| 530 | if (thisSize != otherSize) |
| 531 | return thisSize < otherSize; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 532 | return (*value_.map_) < (*other.value_.map_); |
| 533 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 534 | default: |
| 535 | JSON_ASSERT_UNREACHABLE; |
| 536 | } |
| 537 | return false; // unreachable |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 538 | } |
| 539 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 540 | bool Value::operator<=(const Value& other) const { return !(other < *this); } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 541 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 542 | bool Value::operator>=(const Value& other) const { return !(*this < other); } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 543 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 544 | bool Value::operator>(const Value& other) const { return other < *this; } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 545 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 546 | bool Value::operator==(const Value& other) const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 547 | if (type() != other.type()) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 548 | return false; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 549 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 550 | case nullValue: |
| 551 | return true; |
| 552 | case intValue: |
| 553 | return value_.int_ == other.value_.int_; |
| 554 | case uintValue: |
| 555 | return value_.uint_ == other.value_.uint_; |
| 556 | case realValue: |
| 557 | return value_.real_ == other.value_.real_; |
| 558 | case booleanValue: |
| 559 | return value_.bool_ == other.value_.bool_; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 560 | case stringValue: { |
| 561 | if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { |
| 562 | return (value_.string_ == other.value_.string_); |
| 563 | } |
| 564 | unsigned this_len; |
| 565 | unsigned other_len; |
| 566 | char const* this_str; |
| 567 | char const* other_str; |
| 568 | decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, |
| 569 | &this_str); |
| 570 | decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, |
| 571 | &other_str); |
| 572 | if (this_len != other_len) |
| 573 | return false; |
| 574 | JSON_ASSERT(this_str && other_str); |
| 575 | int comp = memcmp(this_str, other_str, this_len); |
| 576 | return comp == 0; |
| 577 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 578 | case arrayValue: |
| 579 | case objectValue: |
| 580 | return value_.map_->size() == other.value_.map_->size() && |
| 581 | (*value_.map_) == (*other.value_.map_); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 582 | default: |
| 583 | JSON_ASSERT_UNREACHABLE; |
| 584 | } |
| 585 | return false; // unreachable |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 586 | } |
| 587 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 588 | bool Value::operator!=(const Value& other) const { return !(*this == other); } |
| 589 | |
| 590 | const char* Value::asCString() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 591 | JSON_ASSERT_MESSAGE(type() == stringValue, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 592 | "in Json::Value::asCString(): requires stringValue"); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 593 | if (value_.string_ == nullptr) |
| 594 | return nullptr; |
| 595 | unsigned this_len; |
| 596 | char const* this_str; |
| 597 | decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, |
| 598 | &this_str); |
| 599 | return this_str; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 600 | } |
| 601 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 602 | #if JSONCPP_USING_SECURE_MEMORY |
| 603 | unsigned Value::getCStringLength() const { |
| 604 | JSON_ASSERT_MESSAGE(type() == stringValue, |
| 605 | "in Json::Value::asCString(): requires stringValue"); |
| 606 | if (value_.string_ == 0) |
| 607 | return 0; |
| 608 | unsigned this_len; |
| 609 | char const* this_str; |
| 610 | decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, |
| 611 | &this_str); |
| 612 | return this_len; |
| 613 | } |
| 614 | #endif |
| 615 | |
| 616 | bool Value::getString(char const** begin, char const** end) const { |
| 617 | if (type() != stringValue) |
| 618 | return false; |
| 619 | if (value_.string_ == nullptr) |
| 620 | return false; |
| 621 | unsigned length; |
| 622 | decodePrefixedString(this->isAllocated(), this->value_.string_, &length, |
| 623 | begin); |
| 624 | *end = *begin + length; |
| 625 | return true; |
| 626 | } |
| 627 | |
| 628 | String Value::asString() const { |
| 629 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 630 | case nullValue: |
| 631 | return ""; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 632 | case stringValue: { |
| 633 | if (value_.string_ == nullptr) |
| 634 | return ""; |
| 635 | unsigned this_len; |
| 636 | char const* this_str; |
| 637 | decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, |
| 638 | &this_str); |
| 639 | return String(this_str, this_len); |
| 640 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 641 | case booleanValue: |
| 642 | return value_.bool_ ? "true" : "false"; |
| 643 | case intValue: |
| 644 | return valueToString(value_.int_); |
| 645 | case uintValue: |
| 646 | return valueToString(value_.uint_); |
| 647 | case realValue: |
| 648 | return valueToString(value_.real_); |
| 649 | default: |
| 650 | JSON_FAIL_MESSAGE("Type is not convertible to string"); |
| 651 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 652 | } |
| 653 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 654 | Value::Int Value::asInt() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 655 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 656 | case intValue: |
| 657 | JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); |
| 658 | return Int(value_.int_); |
| 659 | case uintValue: |
| 660 | JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); |
| 661 | return Int(value_.uint_); |
| 662 | case realValue: |
| 663 | JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), |
| 664 | "double out of Int range"); |
| 665 | return Int(value_.real_); |
| 666 | case nullValue: |
| 667 | return 0; |
| 668 | case booleanValue: |
| 669 | return value_.bool_ ? 1 : 0; |
| 670 | default: |
| 671 | break; |
| 672 | } |
| 673 | JSON_FAIL_MESSAGE("Value is not convertible to Int."); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 674 | } |
| 675 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 676 | Value::UInt Value::asUInt() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 677 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 678 | case intValue: |
| 679 | JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); |
| 680 | return UInt(value_.int_); |
| 681 | case uintValue: |
| 682 | JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); |
| 683 | return UInt(value_.uint_); |
| 684 | case realValue: |
| 685 | JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), |
| 686 | "double out of UInt range"); |
| 687 | return UInt(value_.real_); |
| 688 | case nullValue: |
| 689 | return 0; |
| 690 | case booleanValue: |
| 691 | return value_.bool_ ? 1 : 0; |
| 692 | default: |
| 693 | break; |
| 694 | } |
| 695 | JSON_FAIL_MESSAGE("Value is not convertible to UInt."); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 696 | } |
| 697 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 698 | #if defined(JSON_HAS_INT64) |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 699 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 700 | Value::Int64 Value::asInt64() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 701 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 702 | case intValue: |
| 703 | return Int64(value_.int_); |
| 704 | case uintValue: |
| 705 | JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); |
| 706 | return Int64(value_.uint_); |
| 707 | case realValue: |
| 708 | JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), |
| 709 | "double out of Int64 range"); |
| 710 | return Int64(value_.real_); |
| 711 | case nullValue: |
| 712 | return 0; |
| 713 | case booleanValue: |
| 714 | return value_.bool_ ? 1 : 0; |
| 715 | default: |
| 716 | break; |
| 717 | } |
| 718 | JSON_FAIL_MESSAGE("Value is not convertible to Int64."); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 719 | } |
| 720 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 721 | Value::UInt64 Value::asUInt64() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 722 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 723 | case intValue: |
| 724 | JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); |
| 725 | return UInt64(value_.int_); |
| 726 | case uintValue: |
| 727 | return UInt64(value_.uint_); |
| 728 | case realValue: |
| 729 | JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), |
| 730 | "double out of UInt64 range"); |
| 731 | return UInt64(value_.real_); |
| 732 | case nullValue: |
| 733 | return 0; |
| 734 | case booleanValue: |
| 735 | return value_.bool_ ? 1 : 0; |
| 736 | default: |
| 737 | break; |
| 738 | } |
| 739 | JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 740 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 741 | #endif // if defined(JSON_HAS_INT64) |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 742 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 743 | LargestInt Value::asLargestInt() const { |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 744 | #if defined(JSON_NO_INT64) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 745 | return asInt(); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 746 | #else |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 747 | return asInt64(); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 748 | #endif |
| 749 | } |
| 750 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 751 | LargestUInt Value::asLargestUInt() const { |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 752 | #if defined(JSON_NO_INT64) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 753 | return asUInt(); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 754 | #else |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 755 | return asUInt64(); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 756 | #endif |
| 757 | } |
| 758 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 759 | double Value::asDouble() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 760 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 761 | case intValue: |
| 762 | return static_cast<double>(value_.int_); |
| 763 | case uintValue: |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 764 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 765 | return static_cast<double>(value_.uint_); |
| 766 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
| 767 | return integerToDouble(value_.uint_); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 768 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 769 | case realValue: |
| 770 | return value_.real_; |
| 771 | case nullValue: |
| 772 | return 0.0; |
| 773 | case booleanValue: |
| 774 | return value_.bool_ ? 1.0 : 0.0; |
| 775 | default: |
| 776 | break; |
| 777 | } |
| 778 | JSON_FAIL_MESSAGE("Value is not convertible to double."); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 779 | } |
| 780 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 781 | float Value::asFloat() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 782 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 783 | case intValue: |
| 784 | return static_cast<float>(value_.int_); |
| 785 | case uintValue: |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 786 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 787 | return static_cast<float>(value_.uint_); |
| 788 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 789 | // This can fail (silently?) if the value is bigger than MAX_FLOAT. |
| 790 | return static_cast<float>(integerToDouble(value_.uint_)); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 791 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 792 | case realValue: |
| 793 | return static_cast<float>(value_.real_); |
| 794 | case nullValue: |
| 795 | return 0.0; |
| 796 | case booleanValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 797 | return value_.bool_ ? 1.0F : 0.0F; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 798 | default: |
| 799 | break; |
| 800 | } |
| 801 | JSON_FAIL_MESSAGE("Value is not convertible to float."); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 802 | } |
| 803 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 804 | bool Value::asBool() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 805 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 806 | case booleanValue: |
| 807 | return value_.bool_; |
| 808 | case nullValue: |
| 809 | return false; |
| 810 | case intValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 811 | return value_.int_ != 0; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 812 | case uintValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 813 | return value_.uint_ != 0; |
| 814 | case realValue: { |
| 815 | // According to JavaScript language zero or NaN is regarded as false |
| 816 | const auto value_classification = std::fpclassify(value_.real_); |
| 817 | return value_classification != FP_ZERO && value_classification != FP_NAN; |
| 818 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 819 | default: |
| 820 | break; |
| 821 | } |
| 822 | JSON_FAIL_MESSAGE("Value is not convertible to bool."); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 823 | } |
| 824 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 825 | bool Value::isConvertibleTo(ValueType other) const { |
| 826 | switch (other) { |
| 827 | case nullValue: |
| 828 | return (isNumeric() && asDouble() == 0.0) || |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 829 | (type() == booleanValue && !value_.bool_) || |
| 830 | (type() == stringValue && asString().empty()) || |
| 831 | (type() == arrayValue && value_.map_->empty()) || |
| 832 | (type() == objectValue && value_.map_->empty()) || |
| 833 | type() == nullValue; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 834 | case intValue: |
| 835 | return isInt() || |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 836 | (type() == realValue && InRange(value_.real_, minInt, maxInt)) || |
| 837 | type() == booleanValue || type() == nullValue; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 838 | case uintValue: |
| 839 | return isUInt() || |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 840 | (type() == realValue && InRange(value_.real_, 0, maxUInt)) || |
| 841 | type() == booleanValue || type() == nullValue; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 842 | case realValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 843 | return isNumeric() || type() == booleanValue || type() == nullValue; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 844 | case booleanValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 845 | return isNumeric() || type() == booleanValue || type() == nullValue; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 846 | case stringValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 847 | return isNumeric() || type() == booleanValue || type() == stringValue || |
| 848 | type() == nullValue; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 849 | case arrayValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 850 | return type() == arrayValue || type() == nullValue; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 851 | case objectValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 852 | return type() == objectValue || type() == nullValue; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 853 | } |
| 854 | JSON_ASSERT_UNREACHABLE; |
| 855 | return false; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 856 | } |
| 857 | |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 858 | /// Number of values in array or object |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 859 | ArrayIndex Value::size() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 860 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 861 | case nullValue: |
| 862 | case intValue: |
| 863 | case uintValue: |
| 864 | case realValue: |
| 865 | case booleanValue: |
| 866 | case stringValue: |
| 867 | return 0; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 868 | case arrayValue: // size of the array is highest index + 1 |
| 869 | if (!value_.map_->empty()) { |
| 870 | ObjectValues::const_iterator itLast = value_.map_->end(); |
| 871 | --itLast; |
| 872 | return (*itLast).first.index() + 1; |
| 873 | } |
| 874 | return 0; |
| 875 | case objectValue: |
| 876 | return ArrayIndex(value_.map_->size()); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 877 | } |
| 878 | JSON_ASSERT_UNREACHABLE; |
| 879 | return 0; // unreachable; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 880 | } |
| 881 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 882 | bool Value::empty() const { |
| 883 | if (isNull() || isArray() || isObject()) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 884 | return size() == 0U; |
| 885 | return false; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 886 | } |
| 887 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 888 | Value::operator bool() const { return !isNull(); } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 889 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 890 | void Value::clear() { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 891 | JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue || |
| 892 | type() == objectValue, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 893 | "in Json::Value::clear(): requires complex value"); |
| 894 | start_ = 0; |
| 895 | limit_ = 0; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 896 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 897 | case arrayValue: |
| 898 | case objectValue: |
| 899 | value_.map_->clear(); |
| 900 | break; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 901 | default: |
| 902 | break; |
| 903 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 904 | } |
| 905 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 906 | void Value::resize(ArrayIndex newSize) { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 907 | JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 908 | "in Json::Value::resize(): requires arrayValue"); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 909 | if (type() == nullValue) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 910 | *this = Value(arrayValue); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 911 | ArrayIndex oldSize = size(); |
| 912 | if (newSize == 0) |
| 913 | clear(); |
| 914 | else if (newSize > oldSize) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 915 | this->operator[](newSize - 1); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 916 | else { |
| 917 | for (ArrayIndex index = newSize; index < oldSize; ++index) { |
| 918 | value_.map_->erase(index); |
| 919 | } |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 920 | JSON_ASSERT(size() == newSize); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 921 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 922 | } |
| 923 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 924 | Value& Value::operator[](ArrayIndex index) { |
| 925 | JSON_ASSERT_MESSAGE( |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 926 | type() == nullValue || type() == arrayValue, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 927 | "in Json::Value::operator[](ArrayIndex): requires arrayValue"); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 928 | if (type() == nullValue) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 929 | *this = Value(arrayValue); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 930 | CZString key(index); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 931 | auto it = value_.map_->lower_bound(key); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 932 | if (it != value_.map_->end() && (*it).first == key) |
| 933 | return (*it).second; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 934 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 935 | ObjectValues::value_type defaultValue(key, nullSingleton()); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 936 | it = value_.map_->insert(it, defaultValue); |
| 937 | return (*it).second; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 938 | } |
| 939 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 940 | Value& Value::operator[](int index) { |
| 941 | JSON_ASSERT_MESSAGE( |
| 942 | index >= 0, |
| 943 | "in Json::Value::operator[](int index): index cannot be negative"); |
| 944 | return (*this)[ArrayIndex(index)]; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 945 | } |
| 946 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 947 | const Value& Value::operator[](ArrayIndex index) const { |
| 948 | JSON_ASSERT_MESSAGE( |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 949 | type() == nullValue || type() == arrayValue, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 950 | "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 951 | if (type() == nullValue) |
| 952 | return nullSingleton(); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 953 | CZString key(index); |
| 954 | ObjectValues::const_iterator it = value_.map_->find(key); |
| 955 | if (it == value_.map_->end()) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 956 | return nullSingleton(); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 957 | return (*it).second; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 958 | } |
| 959 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 960 | const Value& Value::operator[](int index) const { |
| 961 | JSON_ASSERT_MESSAGE( |
| 962 | index >= 0, |
| 963 | "in Json::Value::operator[](int index) const: index cannot be negative"); |
| 964 | return (*this)[ArrayIndex(index)]; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 965 | } |
| 966 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 967 | void Value::initBasic(ValueType type, bool allocated) { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 968 | setType(type); |
| 969 | setIsAllocated(allocated); |
| 970 | comments_ = Comments{}; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 971 | start_ = 0; |
| 972 | limit_ = 0; |
| 973 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 974 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 975 | void Value::dupPayload(const Value& other) { |
| 976 | setType(other.type()); |
| 977 | setIsAllocated(false); |
| 978 | switch (type()) { |
| 979 | case nullValue: |
| 980 | case intValue: |
| 981 | case uintValue: |
| 982 | case realValue: |
| 983 | case booleanValue: |
| 984 | value_ = other.value_; |
| 985 | break; |
| 986 | case stringValue: |
| 987 | if (other.value_.string_ && other.isAllocated()) { |
| 988 | unsigned len; |
| 989 | char const* str; |
| 990 | decodePrefixedString(other.isAllocated(), other.value_.string_, &len, |
| 991 | &str); |
| 992 | value_.string_ = duplicateAndPrefixStringValue(str, len); |
| 993 | setIsAllocated(true); |
| 994 | } else { |
| 995 | value_.string_ = other.value_.string_; |
| 996 | } |
| 997 | break; |
| 998 | case arrayValue: |
| 999 | case objectValue: |
| 1000 | value_.map_ = new ObjectValues(*other.value_.map_); |
| 1001 | break; |
| 1002 | default: |
| 1003 | JSON_ASSERT_UNREACHABLE; |
| 1004 | } |
| 1005 | } |
| 1006 | |
| 1007 | void Value::releasePayload() { |
| 1008 | switch (type()) { |
| 1009 | case nullValue: |
| 1010 | case intValue: |
| 1011 | case uintValue: |
| 1012 | case realValue: |
| 1013 | case booleanValue: |
| 1014 | break; |
| 1015 | case stringValue: |
| 1016 | if (isAllocated()) |
| 1017 | releasePrefixedStringValue(value_.string_); |
| 1018 | break; |
| 1019 | case arrayValue: |
| 1020 | case objectValue: |
| 1021 | delete value_.map_; |
| 1022 | break; |
| 1023 | default: |
| 1024 | JSON_ASSERT_UNREACHABLE; |
| 1025 | } |
| 1026 | } |
| 1027 | |
| 1028 | void Value::dupMeta(const Value& other) { |
| 1029 | comments_ = other.comments_; |
| 1030 | start_ = other.start_; |
| 1031 | limit_ = other.limit_; |
| 1032 | } |
| 1033 | |
| 1034 | // Access an object value by name, create a null member if it does not exist. |
| 1035 | // @pre Type of '*this' is object or null. |
| 1036 | // @param key is null-terminated. |
| 1037 | Value& Value::resolveReference(const char* key) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1038 | JSON_ASSERT_MESSAGE( |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1039 | type() == nullValue || type() == objectValue, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1040 | "in Json::Value::resolveReference(): requires objectValue"); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1041 | if (type() == nullValue) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1042 | *this = Value(objectValue); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1043 | CZString actualKey(key, static_cast<unsigned>(strlen(key)), |
| 1044 | CZString::noDuplication); // NOTE! |
| 1045 | auto it = value_.map_->lower_bound(actualKey); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1046 | if (it != value_.map_->end() && (*it).first == actualKey) |
| 1047 | return (*it).second; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1048 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1049 | ObjectValues::value_type defaultValue(actualKey, nullSingleton()); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1050 | it = value_.map_->insert(it, defaultValue); |
| 1051 | Value& value = (*it).second; |
| 1052 | return value; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1053 | } |
| 1054 | |
| 1055 | // @param key is not null-terminated. |
| 1056 | Value& Value::resolveReference(char const* key, char const* end) { |
| 1057 | JSON_ASSERT_MESSAGE( |
| 1058 | type() == nullValue || type() == objectValue, |
| 1059 | "in Json::Value::resolveReference(key, end): requires objectValue"); |
| 1060 | if (type() == nullValue) |
| 1061 | *this = Value(objectValue); |
| 1062 | CZString actualKey(key, static_cast<unsigned>(end - key), |
| 1063 | CZString::duplicateOnCopy); |
| 1064 | auto it = value_.map_->lower_bound(actualKey); |
| 1065 | if (it != value_.map_->end() && (*it).first == actualKey) |
| 1066 | return (*it).second; |
| 1067 | |
| 1068 | ObjectValues::value_type defaultValue(actualKey, nullSingleton()); |
| 1069 | it = value_.map_->insert(it, defaultValue); |
| 1070 | Value& value = (*it).second; |
| 1071 | return value; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1072 | } |
| 1073 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1074 | Value Value::get(ArrayIndex index, const Value& defaultValue) const { |
| 1075 | const Value* value = &((*this)[index]); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1076 | return value == &nullSingleton() ? defaultValue : *value; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1077 | } |
| 1078 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1079 | bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1080 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1081 | Value const* Value::find(char const* begin, char const* end) const { |
| 1082 | JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, |
| 1083 | "in Json::Value::find(begin, end): requires " |
| 1084 | "objectValue or nullValue"); |
| 1085 | if (type() == nullValue) |
| 1086 | return nullptr; |
| 1087 | CZString actualKey(begin, static_cast<unsigned>(end - begin), |
| 1088 | CZString::noDuplication); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1089 | ObjectValues::const_iterator it = value_.map_->find(actualKey); |
| 1090 | if (it == value_.map_->end()) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1091 | return nullptr; |
| 1092 | return &(*it).second; |
| 1093 | } |
| 1094 | Value* Value::demand(char const* begin, char const* end) { |
| 1095 | JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, |
| 1096 | "in Json::Value::demand(begin, end): requires " |
| 1097 | "objectValue or nullValue"); |
| 1098 | return &resolveReference(begin, end); |
| 1099 | } |
| 1100 | const Value& Value::operator[](const char* key) const { |
| 1101 | Value const* found = find(key, key + strlen(key)); |
| 1102 | if (!found) |
| 1103 | return nullSingleton(); |
| 1104 | return *found; |
| 1105 | } |
| 1106 | Value const& Value::operator[](const String& key) const { |
| 1107 | Value const* found = find(key.data(), key.data() + key.length()); |
| 1108 | if (!found) |
| 1109 | return nullSingleton(); |
| 1110 | return *found; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1111 | } |
| 1112 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1113 | Value& Value::operator[](const char* key) { |
| 1114 | return resolveReference(key, key + strlen(key)); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1115 | } |
| 1116 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1117 | Value& Value::operator[](const String& key) { |
| 1118 | return resolveReference(key.data(), key.data() + key.length()); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1119 | } |
| 1120 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1121 | Value& Value::operator[](const StaticString& key) { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1122 | return resolveReference(key.c_str()); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1123 | } |
| 1124 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1125 | Value& Value::append(const Value& value) { return append(Value(value)); } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1126 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1127 | Value& Value::append(Value&& value) { |
| 1128 | JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, |
| 1129 | "in Json::Value::append: requires arrayValue"); |
| 1130 | if (type() == nullValue) { |
| 1131 | *this = Value(arrayValue); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1132 | } |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1133 | return this->value_.map_->emplace(size(), std::move(value)).first->second; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1134 | } |
| 1135 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1136 | bool Value::insert(ArrayIndex index, const Value& newValue) { |
| 1137 | return insert(index, Value(newValue)); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1138 | } |
| 1139 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1140 | bool Value::insert(ArrayIndex index, Value&& newValue) { |
| 1141 | JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, |
| 1142 | "in Json::Value::insert: requires arrayValue"); |
| 1143 | ArrayIndex length = size(); |
| 1144 | if (index > length) { |
| 1145 | return false; |
| 1146 | } |
| 1147 | for (ArrayIndex i = length; i > index; i--) { |
| 1148 | (*this)[i] = std::move((*this)[i - 1]); |
| 1149 | } |
| 1150 | (*this)[index] = std::move(newValue); |
| 1151 | return true; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1152 | } |
| 1153 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1154 | Value Value::get(char const* begin, char const* end, |
| 1155 | Value const& defaultValue) const { |
| 1156 | Value const* found = find(begin, end); |
| 1157 | return !found ? defaultValue : *found; |
| 1158 | } |
| 1159 | Value Value::get(char const* key, Value const& defaultValue) const { |
| 1160 | return get(key, key + strlen(key), defaultValue); |
| 1161 | } |
| 1162 | Value Value::get(String const& key, Value const& defaultValue) const { |
| 1163 | return get(key.data(), key.data() + key.length(), defaultValue); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1164 | } |
| 1165 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1166 | bool Value::removeMember(const char* begin, const char* end, Value* removed) { |
| 1167 | if (type() != objectValue) { |
| 1168 | return false; |
| 1169 | } |
| 1170 | CZString actualKey(begin, static_cast<unsigned>(end - begin), |
| 1171 | CZString::noDuplication); |
| 1172 | auto it = value_.map_->find(actualKey); |
| 1173 | if (it == value_.map_->end()) |
| 1174 | return false; |
| 1175 | if (removed) |
| 1176 | *removed = std::move(it->second); |
| 1177 | value_.map_->erase(it); |
| 1178 | return true; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1179 | } |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1180 | bool Value::removeMember(const char* key, Value* removed) { |
| 1181 | return removeMember(key, key + strlen(key), removed); |
| 1182 | } |
| 1183 | bool Value::removeMember(String const& key, Value* removed) { |
| 1184 | return removeMember(key.data(), key.data() + key.length(), removed); |
| 1185 | } |
| 1186 | void Value::removeMember(const char* key) { |
| 1187 | JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, |
| 1188 | "in Json::Value::removeMember(): requires objectValue"); |
| 1189 | if (type() == nullValue) |
| 1190 | return; |
| 1191 | |
| 1192 | CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication); |
| 1193 | value_.map_->erase(actualKey); |
| 1194 | } |
| 1195 | void Value::removeMember(const String& key) { removeMember(key.c_str()); } |
| 1196 | |
| 1197 | bool Value::removeIndex(ArrayIndex index, Value* removed) { |
| 1198 | if (type() != arrayValue) { |
| 1199 | return false; |
| 1200 | } |
| 1201 | CZString key(index); |
| 1202 | auto it = value_.map_->find(key); |
| 1203 | if (it == value_.map_->end()) { |
| 1204 | return false; |
| 1205 | } |
| 1206 | if (removed) |
| 1207 | *removed = it->second; |
| 1208 | ArrayIndex oldSize = size(); |
| 1209 | // shift left all items left, into the place of the "removed" |
| 1210 | for (ArrayIndex i = index; i < (oldSize - 1); ++i) { |
| 1211 | CZString keey(i); |
| 1212 | (*value_.map_)[keey] = (*this)[i + 1]; |
| 1213 | } |
| 1214 | // erase the last one ("leftover") |
| 1215 | CZString keyLast(oldSize - 1); |
| 1216 | auto itLast = value_.map_->find(keyLast); |
| 1217 | value_.map_->erase(itLast); |
| 1218 | return true; |
| 1219 | } |
| 1220 | |
| 1221 | bool Value::isMember(char const* begin, char const* end) const { |
| 1222 | Value const* value = find(begin, end); |
| 1223 | return nullptr != value; |
| 1224 | } |
| 1225 | bool Value::isMember(char const* key) const { |
| 1226 | return isMember(key, key + strlen(key)); |
| 1227 | } |
| 1228 | bool Value::isMember(String const& key) const { |
| 1229 | return isMember(key.data(), key.data() + key.length()); |
| 1230 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1231 | |
| 1232 | Value::Members Value::getMemberNames() const { |
| 1233 | JSON_ASSERT_MESSAGE( |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1234 | type() == nullValue || type() == objectValue, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1235 | "in Json::Value::getMemberNames(), value must be objectValue"); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1236 | if (type() == nullValue) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1237 | return Value::Members(); |
| 1238 | Members members; |
| 1239 | members.reserve(value_.map_->size()); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1240 | ObjectValues::const_iterator it = value_.map_->begin(); |
| 1241 | ObjectValues::const_iterator itEnd = value_.map_->end(); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1242 | for (; it != itEnd; ++it) { |
| 1243 | members.push_back(String((*it).first.data(), (*it).first.length())); |
| 1244 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1245 | return members; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1246 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1247 | |
| 1248 | static bool IsIntegral(double d) { |
| 1249 | double integral_part; |
| 1250 | return modf(d, &integral_part) == 0.0; |
| 1251 | } |
| 1252 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1253 | bool Value::isNull() const { return type() == nullValue; } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1254 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1255 | bool Value::isBool() const { return type() == booleanValue; } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1256 | |
| 1257 | bool Value::isInt() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1258 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1259 | case intValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1260 | #if defined(JSON_HAS_INT64) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1261 | return value_.int_ >= minInt && value_.int_ <= maxInt; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1262 | #else |
| 1263 | return true; |
| 1264 | #endif |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1265 | case uintValue: |
| 1266 | return value_.uint_ <= UInt(maxInt); |
| 1267 | case realValue: |
| 1268 | return value_.real_ >= minInt && value_.real_ <= maxInt && |
| 1269 | IsIntegral(value_.real_); |
| 1270 | default: |
| 1271 | break; |
| 1272 | } |
| 1273 | return false; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1274 | } |
| 1275 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1276 | bool Value::isUInt() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1277 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1278 | case intValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1279 | #if defined(JSON_HAS_INT64) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1280 | return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1281 | #else |
| 1282 | return value_.int_ >= 0; |
| 1283 | #endif |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1284 | case uintValue: |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1285 | #if defined(JSON_HAS_INT64) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1286 | return value_.uint_ <= maxUInt; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1287 | #else |
| 1288 | return true; |
| 1289 | #endif |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1290 | case realValue: |
| 1291 | return value_.real_ >= 0 && value_.real_ <= maxUInt && |
| 1292 | IsIntegral(value_.real_); |
| 1293 | default: |
| 1294 | break; |
| 1295 | } |
| 1296 | return false; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1297 | } |
| 1298 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1299 | bool Value::isInt64() const { |
| 1300 | #if defined(JSON_HAS_INT64) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1301 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1302 | case intValue: |
| 1303 | return true; |
| 1304 | case uintValue: |
| 1305 | return value_.uint_ <= UInt64(maxInt64); |
| 1306 | case realValue: |
| 1307 | // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a |
| 1308 | // double, so double(maxInt64) will be rounded up to 2^63. Therefore we |
| 1309 | // require the value to be strictly less than the limit. |
| 1310 | return value_.real_ >= double(minInt64) && |
| 1311 | value_.real_ < double(maxInt64) && IsIntegral(value_.real_); |
| 1312 | default: |
| 1313 | break; |
| 1314 | } |
| 1315 | #endif // JSON_HAS_INT64 |
| 1316 | return false; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1317 | } |
| 1318 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1319 | bool Value::isUInt64() const { |
| 1320 | #if defined(JSON_HAS_INT64) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1321 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1322 | case intValue: |
| 1323 | return value_.int_ >= 0; |
| 1324 | case uintValue: |
| 1325 | return true; |
| 1326 | case realValue: |
| 1327 | // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a |
| 1328 | // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we |
| 1329 | // require the value to be strictly less than the limit. |
| 1330 | return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && |
| 1331 | IsIntegral(value_.real_); |
| 1332 | default: |
| 1333 | break; |
| 1334 | } |
| 1335 | #endif // JSON_HAS_INT64 |
| 1336 | return false; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1337 | } |
| 1338 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1339 | bool Value::isIntegral() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1340 | switch (type()) { |
| 1341 | case intValue: |
| 1342 | case uintValue: |
| 1343 | return true; |
| 1344 | case realValue: |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1345 | #if defined(JSON_HAS_INT64) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1346 | // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a |
| 1347 | // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we |
| 1348 | // require the value to be strictly less than the limit. |
| 1349 | return value_.real_ >= double(minInt64) && |
| 1350 | value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1351 | #else |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1352 | return value_.real_ >= minInt && value_.real_ <= maxUInt && |
| 1353 | IsIntegral(value_.real_); |
| 1354 | #endif // JSON_HAS_INT64 |
| 1355 | default: |
| 1356 | break; |
| 1357 | } |
| 1358 | return false; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1359 | } |
| 1360 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1361 | bool Value::isDouble() const { |
| 1362 | return type() == intValue || type() == uintValue || type() == realValue; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1363 | } |
| 1364 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1365 | bool Value::isNumeric() const { return isDouble(); } |
| 1366 | |
| 1367 | bool Value::isString() const { return type() == stringValue; } |
| 1368 | |
| 1369 | bool Value::isArray() const { return type() == arrayValue; } |
| 1370 | |
| 1371 | bool Value::isObject() const { return type() == objectValue; } |
| 1372 | |
| 1373 | Value::Comments::Comments(const Comments& that) |
| 1374 | : ptr_{cloneUnique(that.ptr_)} {} |
| 1375 | |
| 1376 | Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {} |
| 1377 | |
| 1378 | Value::Comments& Value::Comments::operator=(const Comments& that) { |
| 1379 | ptr_ = cloneUnique(that.ptr_); |
| 1380 | return *this; |
| 1381 | } |
| 1382 | |
| 1383 | Value::Comments& Value::Comments::operator=(Comments&& that) { |
| 1384 | ptr_ = std::move(that.ptr_); |
| 1385 | return *this; |
| 1386 | } |
| 1387 | |
| 1388 | bool Value::Comments::has(CommentPlacement slot) const { |
| 1389 | return ptr_ && !(*ptr_)[slot].empty(); |
| 1390 | } |
| 1391 | |
| 1392 | String Value::Comments::get(CommentPlacement slot) const { |
| 1393 | if (!ptr_) |
| 1394 | return {}; |
| 1395 | return (*ptr_)[slot]; |
| 1396 | } |
| 1397 | |
| 1398 | void Value::Comments::set(CommentPlacement slot, String comment) { |
| 1399 | if (!ptr_) { |
| 1400 | ptr_ = std::unique_ptr<Array>(new Array()); |
| 1401 | } |
| 1402 | // check comments array boundry. |
| 1403 | if (slot < CommentPlacement::numberOfCommentPlacement) { |
| 1404 | (*ptr_)[slot] = std::move(comment); |
| 1405 | } |
| 1406 | } |
| 1407 | |
| 1408 | void Value::setComment(String comment, CommentPlacement placement) { |
| 1409 | if (!comment.empty() && (comment.back() == '\n')) { |
| 1410 | // Always discard trailing newline, to aid indentation. |
| 1411 | comment.pop_back(); |
| 1412 | } |
| 1413 | JSON_ASSERT(!comment.empty()); |
| 1414 | JSON_ASSERT_MESSAGE( |
| 1415 | comment[0] == '\0' || comment[0] == '/', |
| 1416 | "in Json::Value::setComment(): Comments must start with /"); |
| 1417 | comments_.set(placement, std::move(comment)); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1418 | } |
| 1419 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1420 | bool Value::hasComment(CommentPlacement placement) const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1421 | return comments_.has(placement); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1422 | } |
| 1423 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1424 | String Value::getComment(CommentPlacement placement) const { |
| 1425 | return comments_.get(placement); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1426 | } |
| 1427 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1428 | void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1429 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1430 | void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1431 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1432 | ptrdiff_t Value::getOffsetStart() const { return start_; } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1433 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1434 | ptrdiff_t Value::getOffsetLimit() const { return limit_; } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1435 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1436 | String Value::toStyledString() const { |
| 1437 | StreamWriterBuilder builder; |
| 1438 | |
| 1439 | String out = this->hasComment(commentBefore) ? "\n" : ""; |
| 1440 | out += Json::writeString(builder, *this); |
| 1441 | out += '\n'; |
| 1442 | |
| 1443 | return out; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1444 | } |
| 1445 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1446 | Value::const_iterator Value::begin() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1447 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1448 | case arrayValue: |
| 1449 | case objectValue: |
| 1450 | if (value_.map_) |
| 1451 | return const_iterator(value_.map_->begin()); |
| 1452 | break; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1453 | default: |
| 1454 | break; |
| 1455 | } |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1456 | return {}; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1457 | } |
| 1458 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1459 | Value::const_iterator Value::end() const { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1460 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1461 | case arrayValue: |
| 1462 | case objectValue: |
| 1463 | if (value_.map_) |
| 1464 | return const_iterator(value_.map_->end()); |
| 1465 | break; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1466 | default: |
| 1467 | break; |
| 1468 | } |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1469 | return {}; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1470 | } |
| 1471 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1472 | Value::iterator Value::begin() { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1473 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1474 | case arrayValue: |
| 1475 | case objectValue: |
| 1476 | if (value_.map_) |
| 1477 | return iterator(value_.map_->begin()); |
| 1478 | break; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1479 | default: |
| 1480 | break; |
| 1481 | } |
| 1482 | return iterator(); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1483 | } |
| 1484 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1485 | Value::iterator Value::end() { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1486 | switch (type()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1487 | case arrayValue: |
| 1488 | case objectValue: |
| 1489 | if (value_.map_) |
| 1490 | return iterator(value_.map_->end()); |
| 1491 | break; |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1492 | default: |
| 1493 | break; |
| 1494 | } |
| 1495 | return iterator(); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1496 | } |
| 1497 | |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1498 | // class PathArgument |
| 1499 | // ////////////////////////////////////////////////////////////////// |
| 1500 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1501 | PathArgument::PathArgument() = default; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1502 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1503 | PathArgument::PathArgument(ArrayIndex index) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1504 | : index_(index), kind_(kindIndex) {} |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1505 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1506 | PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {} |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1507 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1508 | PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {} |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1509 | |
| 1510 | // class Path |
| 1511 | // ////////////////////////////////////////////////////////////////// |
| 1512 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1513 | Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2, |
| 1514 | const PathArgument& a3, const PathArgument& a4, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1515 | const PathArgument& a5) { |
| 1516 | InArgs in; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1517 | in.reserve(5); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1518 | in.push_back(&a1); |
| 1519 | in.push_back(&a2); |
| 1520 | in.push_back(&a3); |
| 1521 | in.push_back(&a4); |
| 1522 | in.push_back(&a5); |
| 1523 | makePath(path, in); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1524 | } |
| 1525 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1526 | void Path::makePath(const String& path, const InArgs& in) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1527 | const char* current = path.c_str(); |
| 1528 | const char* end = current + path.length(); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1529 | auto itInArg = in.begin(); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1530 | while (current != end) { |
| 1531 | if (*current == '[') { |
| 1532 | ++current; |
| 1533 | if (*current == '%') |
| 1534 | addPathInArg(path, in, itInArg, PathArgument::kindIndex); |
| 1535 | else { |
| 1536 | ArrayIndex index = 0; |
| 1537 | for (; current != end && *current >= '0' && *current <= '9'; ++current) |
| 1538 | index = index * 10 + ArrayIndex(*current - '0'); |
| 1539 | args_.push_back(index); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1540 | } |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1541 | if (current == end || *++current != ']') |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1542 | invalidPath(path, int(current - path.c_str())); |
| 1543 | } else if (*current == '%') { |
| 1544 | addPathInArg(path, in, itInArg, PathArgument::kindKey); |
| 1545 | ++current; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1546 | } else if (*current == '.' || *current == ']') { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1547 | ++current; |
| 1548 | } else { |
| 1549 | const char* beginName = current; |
| 1550 | while (current != end && !strchr("[.", *current)) |
| 1551 | ++current; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1552 | args_.push_back(String(beginName, current)); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1553 | } |
| 1554 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1555 | } |
| 1556 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1557 | void Path::addPathInArg(const String& /*path*/, const InArgs& in, |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1558 | InArgs::const_iterator& itInArg, |
| 1559 | PathArgument::Kind kind) { |
| 1560 | if (itInArg == in.end()) { |
| 1561 | // Error: missing argument %d |
| 1562 | } else if ((*itInArg)->kind_ != kind) { |
| 1563 | // Error: bad argument type |
| 1564 | } else { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1565 | args_.push_back(**itInArg++); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1566 | } |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1567 | } |
| 1568 | |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1569 | void Path::invalidPath(const String& /*path*/, int /*location*/) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1570 | // Error: invalid path. |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1571 | } |
| 1572 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1573 | const Value& Path::resolve(const Value& root) const { |
| 1574 | const Value* node = &root; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1575 | for (const auto& arg : args_) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1576 | if (arg.kind_ == PathArgument::kindIndex) { |
| 1577 | if (!node->isArray() || !node->isValidIndex(arg.index_)) { |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1578 | // Error: unable to resolve path (array value expected at position... ) |
| 1579 | return Value::nullSingleton(); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1580 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1581 | node = &((*node)[arg.index_]); |
| 1582 | } else if (arg.kind_ == PathArgument::kindKey) { |
| 1583 | if (!node->isObject()) { |
| 1584 | // Error: unable to resolve path (object value expected at position...) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1585 | return Value::nullSingleton(); |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1586 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1587 | node = &((*node)[arg.key_]); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1588 | if (node == &Value::nullSingleton()) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1589 | // Error: unable to resolve path (object has no member named '' at |
| 1590 | // position...) |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1591 | return Value::nullSingleton(); |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1592 | } |
| 1593 | } |
| 1594 | } |
| 1595 | return *node; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1596 | } |
| 1597 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1598 | Value Path::resolve(const Value& root, const Value& defaultValue) const { |
| 1599 | const Value* node = &root; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1600 | for (const auto& arg : args_) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1601 | if (arg.kind_ == PathArgument::kindIndex) { |
| 1602 | if (!node->isArray() || !node->isValidIndex(arg.index_)) |
| 1603 | return defaultValue; |
| 1604 | node = &((*node)[arg.index_]); |
| 1605 | } else if (arg.kind_ == PathArgument::kindKey) { |
| 1606 | if (!node->isObject()) |
| 1607 | return defaultValue; |
| 1608 | node = &((*node)[arg.key_]); |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1609 | if (node == &Value::nullSingleton()) |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1610 | return defaultValue; |
| 1611 | } |
| 1612 | } |
| 1613 | return *node; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1614 | } |
| 1615 | |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1616 | Value& Path::make(Value& root) const { |
| 1617 | Value* node = &root; |
Haibo Huang | b0bee82 | 2021-02-24 15:40:15 -0800 | [diff] [blame^] | 1618 | for (const auto& arg : args_) { |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1619 | if (arg.kind_ == PathArgument::kindIndex) { |
| 1620 | if (!node->isArray()) { |
| 1621 | // Error: node is not an array at position ... |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1622 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1623 | node = &((*node)[arg.index_]); |
| 1624 | } else if (arg.kind_ == PathArgument::kindKey) { |
| 1625 | if (!node->isObject()) { |
| 1626 | // Error: node is not an object at position... |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1627 | } |
Derek Sollenberger | 2eb3b4d | 2016-01-11 14:41:40 -0500 | [diff] [blame] | 1628 | node = &((*node)[arg.key_]); |
| 1629 | } |
| 1630 | } |
| 1631 | return *node; |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1632 | } |
| 1633 | |
Leon Scroggins III | f59fb0e | 2014-05-28 15:19:42 -0400 | [diff] [blame] | 1634 | } // namespace Json |