JsonCpp project page Classes Namespace JsonCpp home page

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