JsonCpp 1.10.0
JSON data format manipulation library
Loading...
Searching...
No Matches
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// Provide implementation equivalent of std::snprintf for older _MSC compilers
21#if defined(_MSC_VER) && _MSC_VER < 1900
22#include <stdarg.h>
23static 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
33int 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}
41#endif
42
43// Disable warning C4702 : unreachable code
44#if defined(_MSC_VER)
45#pragma warning(disable : 4702)
46#endif
47
48#define JSON_ASSERT_UNREACHABLE assert(false)
49
50namespace Json {
51template <typename T>
52static 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}
59
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
68
69// static
71 static Value const nullStatic;
72 return nullStatic;
73}
74
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
80
81// static
83#endif
84
85#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
86template <typename T, typename U>
87static inline bool InRange(double d, T min, U max) {
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) &&
91 !(static_cast<U>(d) == min && d != static_cast<double>(min));
92}
93#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
94static inline double integerToDouble(Json::UInt64 value) {
95 return static_cast<double>(Int64(value / 2)) * 2.0 +
96 static_cast<double>(Int64(value & 1));
97}
98
99template <typename T> static inline double integerToDouble(T value) {
100 return static_cast<double>(value);
101}
102
103template <typename T, typename U>
104static inline bool InRange(double d, T min, U max) {
105 return d >= integerToDouble(min) && d <= integerToDouble(max) &&
106 !(static_cast<U>(d) == min && d != integerToDouble(min));
107}
108#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
109
117static inline char* duplicateStringValue(const char* value, size_t length) {
118 // Avoid an integer overflow in the call to malloc below by limiting length
119 // to a sane value.
120 if (length >= static_cast<size_t>(Value::maxInt))
121 length = Value::maxInt - 1;
122
123 auto newString = static_cast<char*>(malloc(length + 1));
124 if (newString == nullptr) {
125 throwRuntimeError("in Json::Value::duplicateStringValue(): "
126 "Failed to allocate string value buffer");
127 }
128 memcpy(newString, value, length);
129 newString[length] = 0;
130 return newString;
131}
132
133/* Record the length as a prefix.
134 */
135static inline char* duplicateAndPrefixStringValue(const char* value,
136 unsigned int length) {
137 // Avoid an integer overflow in the call to malloc below by limiting length
138 // to a sane value.
139 JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -
140 sizeof(unsigned) - 1U,
141 "in Json::Value::duplicateAndPrefixStringValue(): "
142 "length too big for prefixing");
143 size_t actualLength = sizeof(length) + length + 1;
144 auto newString = static_cast<char*>(malloc(actualLength));
145 if (newString == nullptr) {
146 throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
147 "Failed to allocate string value buffer");
148 }
149 *reinterpret_cast<unsigned*>(newString) = length;
150 memcpy(newString + sizeof(unsigned), value, length);
151 newString[actualLength - 1U] =
152 0; // to avoid buffer over-run accidents by users later
153 return newString;
154}
155inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
156 unsigned* length, char const** value) {
157 if (!isPrefixed) {
158 *length = static_cast<unsigned>(strlen(prefixed));
159 *value = prefixed;
160 } else {
161 *length = *reinterpret_cast<unsigned const*>(prefixed);
162 *value = prefixed + sizeof(unsigned);
163 }
164}
165
168#if JSONCPP_USE_SECURE_MEMORY
169static inline void releasePrefixedStringValue(char* value) {
170 unsigned length = 0;
171 char const* valueDecoded;
172 decodePrefixedString(true, value, &length, &valueDecoded);
173 size_t const size = sizeof(unsigned) + length + 1U;
174 memset(value, 0, size);
175 free(value);
176}
177static inline void releaseStringValue(char* value, unsigned length) {
178 // length==0 => we allocated the strings memory
179 size_t size = (length == 0) ? strlen(value) : length;
180 memset(value, 0, size);
181 free(value);
182}
183#else // !JSONCPP_USE_SECURE_MEMORY
184static inline void releasePrefixedStringValue(char* value) { free(value); }
185static inline void releaseStringValue(char* value, unsigned) { free(value); }
186#endif // JSONCPP_USE_SECURE_MEMORY
187
188} // namespace Json
189
190// //////////////////////////////////////////////////////////////////
191// //////////////////////////////////////////////////////////////////
192// //////////////////////////////////////////////////////////////////
193// ValueInternals...
194// //////////////////////////////////////////////////////////////////
195// //////////////////////////////////////////////////////////////////
196
197namespace Json {
198
199static const char* valueTypeToString(ValueType type) {
200 switch (type) {
201 case nullValue:
202 return "nullValue";
203 case intValue:
204 return "intValue";
205 case uintValue:
206 return "uintValue";
207 case realValue:
208 return "realValue";
209 case stringValue:
210 return "stringValue";
211 case booleanValue:
212 return "booleanValue";
213 case arrayValue:
214 return "arrayValue";
215 case objectValue:
216 return "objectValue";
217 }
218 return "unknown";
219}
220
221} // namespace Json
222// //////////////////////////////////////////////////////////////////
223#if !defined(JSON_IS_AMALGAMATION)
224
225#include "json_valueiterator.inl"
226#endif // if !defined(JSON_IS_AMALGAMATION)
227
228namespace Json {
229
230#if JSON_USE_EXCEPTION
231Exception::Exception(String msg) : msg_(std::move(msg)) {}
232Exception::~Exception() noexcept = default;
233char const* Exception::what() const noexcept { return msg_.c_str(); }
236JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
237 throw RuntimeError(msg);
238}
239JSONCPP_NORETURN void throwLogicError(String const& msg) {
240 throw LogicError(msg);
241}
242#else // !JSON_USE_EXCEPTION
243JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
244 std::cerr << msg << std::endl;
245 abort();
246}
247JSONCPP_NORETURN void throwLogicError(String const& msg) {
248 std::cerr << msg << std::endl;
249 abort();
250}
251#endif
252
253// //////////////////////////////////////////////////////////////////
254// //////////////////////////////////////////////////////////////////
255// //////////////////////////////////////////////////////////////////
256// class Value::CZString
257// //////////////////////////////////////////////////////////////////
258// //////////////////////////////////////////////////////////////////
259// //////////////////////////////////////////////////////////////////
260
262// CZString is a private implementation detail of Value; hide it from doxygen.
263
264// Notes: policy_ indicates if the string was allocated when
265// a string is stored.
266
267Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
268
269Value::CZString::CZString(char const* str, unsigned length,
270 DuplicationPolicy allocate)
271 : cstr_(str) {
272 // allocate != duplicate
273 storage_.policy_ = allocate & 0x3;
274 storage_.length_ = length & 0x3FFFFFFF;
275}
276
277Value::CZString::CZString(const CZString& other) {
278 cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
279 ? duplicateStringValue(other.cstr_, other.storage_.length_)
280 : other.cstr_);
281 if (other.cstr_) {
282 storage_.policy_ =
283 static_cast<unsigned>(
284 other.cstr_
285 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
286 noDuplication
287 ? noDuplication
288 : duplicate)
289 : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
290 3U;
291 storage_.length_ = other.storage_.length_;
292 } else {
293 index_ = other.index_;
294 }
295}
296
297Value::CZString::CZString(CZString&& other) noexcept : cstr_(other.cstr_) {
298 if (other.cstr_) {
299 storage_.policy_ = other.storage_.policy_;
300 storage_.length_ = other.storage_.length_;
301 } else {
302 index_ = other.index_;
303 }
304 other.cstr_ = nullptr;
305}
306
307Value::CZString::~CZString() {
308 if (cstr_ && storage_.policy_ == duplicate) {
309 releaseStringValue(const_cast<char*>(cstr_),
310 storage_.length_ + 1U); // +1 for null terminating
311 // character for sake of
312 // completeness but not actually
313 // necessary
314 }
315}
316
317void Value::CZString::swap(CZString& other) {
318 std::swap(cstr_, other.cstr_);
319 std::swap(index_, other.index_);
320}
321
322Value::CZString& Value::CZString::operator=(const CZString& other) {
323 // Copy-and-swap so a duplicate-policy buffer is deep-copied and the old one
324 // released once. The prior shallow copy aliased other.cstr_, double-freeing
325 // an owned string and leaking the overwritten one.
326 CZString temp(other);
327 swap(temp);
328 return *this;
329}
330
331Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
332 if (cstr_ && storage_.policy_ == duplicate) {
333 // CZString keys come from duplicateStringValue (no length prefix), so
334 // release with the matching non-prefixed variant, as the destructor does.
335 releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1U);
336 }
337 cstr_ = other.cstr_;
338 if (other.cstr_) {
339 storage_.policy_ = other.storage_.policy_;
340 storage_.length_ = other.storage_.length_;
341 } else {
342 index_ = other.index_;
343 }
344 other.cstr_ = nullptr;
345 return *this;
346}
347
348bool Value::CZString::operator<(const CZString& other) const {
349 if (!cstr_)
350 return index_ < other.index_;
351 // return strcmp(cstr_, other.cstr_) < 0;
352 // Assume both are strings.
353 unsigned this_len = this->storage_.length_;
354 unsigned other_len = other.storage_.length_;
355 unsigned min_len = std::min<unsigned>(this_len, other_len);
356 JSON_ASSERT(this->cstr_ && other.cstr_);
357 int comp = memcmp(this->cstr_, other.cstr_, min_len);
358 if (comp < 0)
359 return true;
360 if (comp > 0)
361 return false;
362 return (this_len < other_len);
363}
364
365bool Value::CZString::operator==(const CZString& other) const {
366 if (!cstr_)
367 return index_ == other.index_;
368 // return strcmp(cstr_, other.cstr_) == 0;
369 // Assume both are strings.
370 unsigned this_len = this->storage_.length_;
371 unsigned other_len = other.storage_.length_;
372 if (this_len != other_len)
373 return false;
374 JSON_ASSERT(this->cstr_ && other.cstr_);
375 int comp = memcmp(this->cstr_, other.cstr_, this_len);
376 return comp == 0;
377}
378
379ArrayIndex Value::CZString::index() const { return index_; }
380
381// const char* Value::CZString::c_str() const { return cstr_; }
382const char* Value::CZString::data() const { return cstr_; }
383unsigned Value::CZString::length() const { return storage_.length_; }
384bool Value::CZString::isStaticString() const {
385 return storage_.policy_ == noDuplication;
386}
388
389// //////////////////////////////////////////////////////////////////
390// //////////////////////////////////////////////////////////////////
391// //////////////////////////////////////////////////////////////////
392// class Value::Value
393// //////////////////////////////////////////////////////////////////
394// //////////////////////////////////////////////////////////////////
395// //////////////////////////////////////////////////////////////////
396
402 static char const emptyString[] = "";
403 initBasic(type);
404 switch (type) {
405 case nullValue:
406 break;
407 case intValue:
408 case uintValue:
409 value_.int_ = 0;
410 break;
411 case realValue:
412 value_.real_ = 0.0;
413 break;
414 case stringValue:
415 // allocated_ == false, so this is safe.
416 value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
417 break;
418 case arrayValue:
419 case objectValue:
420 value_.map_ = new ObjectValues();
421 break;
422 case booleanValue:
423 value_.bool_ = false;
424 break;
425 default:
427 }
428}
429
431 initBasic(intValue);
432 value_.int_ = value;
433}
434
436 initBasic(uintValue);
437 value_.uint_ = value;
438}
439#if defined(JSON_HAS_INT64)
441 initBasic(intValue);
442 value_.int_ = value;
443}
445 initBasic(uintValue);
446 value_.uint_ = value;
447}
448#endif // defined(JSON_HAS_INT64)
449
450Value::Value(double value) {
451 initBasic(realValue);
452 value_.real_ = value;
453}
454
455Value::Value(const char* value) {
456 initBasic(stringValue, true);
457 JSON_ASSERT_MESSAGE(value != nullptr,
458 "Null Value Passed to Value Constructor");
459 value_.string_ = duplicateAndPrefixStringValue(
460 value, static_cast<unsigned>(strlen(value)));
461}
462
463Value::Value(const char* begin, const char* end) {
464 initBasic(stringValue, true);
465 value_.string_ =
466 duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
467}
468
469Value::Value(const String& value) {
470 initBasic(stringValue, true);
471 value_.string_ = duplicateAndPrefixStringValue(
472 value.data(), static_cast<unsigned>(value.length()));
473}
474
476 initBasic(stringValue);
477 value_.string_ = const_cast<char*>(value.c_str());
478}
479
480Value::Value(bool value) {
481 initBasic(booleanValue);
482 value_.bool_ = value;
483}
484
485Value::Value(const Value& other) {
486 dupPayload(other);
487 dupMeta(other);
488}
489
490Value::Value(Value&& other) noexcept {
491 initBasic(nullValue);
492 swap(other);
493}
494
496 releasePayload();
497 value_.uint_ = 0;
498}
499
501 Value(other).swap(*this);
502 return *this;
503}
504
505Value& Value::operator=(Value&& other) noexcept {
506 other.swap(*this);
507 return *this;
508}
509
511 std::swap(bits_, other.bits_);
512 std::swap(value_, other.value_);
513}
514
515void Value::copyPayload(const Value& other) {
516 releasePayload();
517 dupPayload(other);
518}
519
520void Value::swap(Value& other) {
521 swapPayload(other);
522 std::swap(comments_, other.comments_);
523 std::swap(start_, other.start_);
524 std::swap(limit_, other.limit_);
525}
526
527void Value::copy(const Value& other) {
528 copyPayload(other);
529 dupMeta(other);
530}
531
533 return static_cast<ValueType>(bits_.value_type_);
534}
535
536int Value::compare(const Value& other) const {
537 if (*this < other)
538 return -1;
539 if (*this > other)
540 return 1;
541 return 0;
542}
543
544bool Value::operator<(const Value& other) const {
545 int typeDelta = type() - other.type();
546 if (typeDelta)
547 return typeDelta < 0;
548 switch (type()) {
549 case nullValue:
550 return false;
551 case intValue:
552 return value_.int_ < other.value_.int_;
553 case uintValue:
554 return value_.uint_ < other.value_.uint_;
555 case realValue:
556 return value_.real_ < other.value_.real_;
557 case booleanValue:
558 return value_.bool_ < other.value_.bool_;
559 case stringValue: {
560 if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
561 return other.value_.string_ != nullptr;
562 }
563 unsigned this_len;
564 unsigned other_len;
565 char const* this_str;
566 char const* other_str;
567 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
568 &this_str);
569 decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
570 &other_str);
571 unsigned min_len = std::min<unsigned>(this_len, other_len);
572 JSON_ASSERT(this_str && other_str);
573 int comp = memcmp(this_str, other_str, min_len);
574 if (comp < 0)
575 return true;
576 if (comp > 0)
577 return false;
578 return (this_len < other_len);
579 }
580 case arrayValue:
581 case objectValue: {
582 auto thisSize = value_.map_->size();
583 auto otherSize = other.value_.map_->size();
584 if (thisSize != otherSize)
585 return thisSize < otherSize;
586 return (*value_.map_) < (*other.value_.map_);
587 }
588 default:
590 }
591 return false; // unreachable
592}
593
594bool Value::operator<=(const Value& other) const { return !(other < *this); }
595
596bool Value::operator>=(const Value& other) const { return !(*this < other); }
597
598bool Value::operator>(const Value& other) const { return other < *this; }
599
600bool Value::operator==(const Value& other) const {
601 if (type() != other.type())
602 return false;
603 switch (type()) {
604 case nullValue:
605 return true;
606 case intValue:
607 return value_.int_ == other.value_.int_;
608 case uintValue:
609 return value_.uint_ == other.value_.uint_;
610 case realValue:
611 return value_.real_ == other.value_.real_;
612 case booleanValue:
613 return value_.bool_ == other.value_.bool_;
614 case stringValue: {
615 if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
616 return (value_.string_ == other.value_.string_);
617 }
618 unsigned this_len;
619 unsigned other_len;
620 char const* this_str;
621 char const* other_str;
622 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
623 &this_str);
624 decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
625 &other_str);
626 if (this_len != other_len)
627 return false;
628 JSON_ASSERT(this_str && other_str);
629 int comp = memcmp(this_str, other_str, this_len);
630 return comp == 0;
631 }
632 case arrayValue:
633 case objectValue:
634 return value_.map_->size() == other.value_.map_->size() &&
635 (*value_.map_) == (*other.value_.map_);
636 default:
638 }
639 return false; // unreachable
640}
641
642bool Value::operator!=(const Value& other) const { return !(*this == other); }
643
644const char* Value::asCString() const {
646 "in Json::Value::asCString(): requires stringValue");
647 if (value_.string_ == nullptr)
648 return nullptr;
649 unsigned this_len;
650 char const* this_str;
651 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
652 &this_str);
653 return this_str;
654}
655
656#if JSONCPP_USE_SECURE_MEMORY
657unsigned Value::getCStringLength() const {
659 "in Json::Value::asCString(): requires stringValue");
660 if (value_.string_ == 0)
661 return 0;
662 unsigned this_len;
663 char const* this_str;
664 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
665 &this_str);
666 return this_len;
667}
668#endif
669
670bool Value::getString(char const** begin, char const** end) const {
671 if (type() != stringValue)
672 return false;
673 if (value_.string_ == nullptr)
674 return false;
675 unsigned length;
676 decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
677 begin);
678 *end = *begin + length;
679 return true;
680}
681
683 switch (type()) {
684 case nullValue:
685 return "";
686 case stringValue: {
687 if (value_.string_ == nullptr)
688 return "";
689 unsigned this_len;
690 char const* this_str;
691 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
692 &this_str);
693 return String(this_str, this_len);
694 }
695 case booleanValue:
696 return value_.bool_ ? "true" : "false";
697 case intValue:
698 return valueToString(value_.int_);
699 case uintValue:
700 return valueToString(value_.uint_);
701 case realValue:
702 return valueToString(value_.real_);
703 default:
704 JSON_FAIL_MESSAGE("Type is not convertible to string");
705 }
706}
707
709 switch (type()) {
710 case intValue:
711 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
712 return Int(value_.int_);
713 case uintValue:
714 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
715 return Int(value_.uint_);
716 case realValue:
718 "double out of Int range");
719 return Int(value_.real_);
720 case nullValue:
721 return 0;
722 case booleanValue:
723 return value_.bool_ ? 1 : 0;
724 default:
725 break;
726 }
727 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
728}
729
731 switch (type()) {
732 case intValue:
733 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
734 return UInt(value_.int_);
735 case uintValue:
736 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
737 return UInt(value_.uint_);
738 case realValue:
739 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt),
740 "double out of UInt range");
741 return UInt(value_.real_);
742 case nullValue:
743 return 0;
744 case booleanValue:
745 return value_.bool_ ? 1 : 0;
746 default:
747 break;
748 }
749 JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
750}
751
752#if defined(JSON_HAS_INT64)
753
755 switch (type()) {
756 case intValue:
757 return Int64(value_.int_);
758 case uintValue:
759 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
760 return Int64(value_.uint_);
761 case realValue:
762 // If the double value is in proximity to minInt64, it will be rounded to
763 // minInt64. The correct value in this scenario is indeterminable
765 value_.real_ != minInt64,
766 "Double value is minInt64, precise value cannot be determined");
768 "double out of Int64 range");
769 return Int64(value_.real_);
770 case nullValue:
771 return 0;
772 case booleanValue:
773 return value_.bool_ ? 1 : 0;
774 default:
775 break;
776 }
777 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
778}
779
781 switch (type()) {
782 case intValue:
783 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
784 return UInt64(value_.int_);
785 case uintValue:
786 return UInt64(value_.uint_);
787 case realValue:
788 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt64),
789 "double out of UInt64 range");
790 return UInt64(value_.real_);
791 case nullValue:
792 return 0;
793 case booleanValue:
794 return value_.bool_ ? 1 : 0;
795 default:
796 break;
797 }
798 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
799}
800#endif // if defined(JSON_HAS_INT64)
801
803#if defined(JSON_NO_INT64)
804 return asInt();
805#else
806 return asInt64();
807#endif
808}
809
811#if defined(JSON_NO_INT64)
812 return asUInt();
813#else
814 return asUInt64();
815#endif
816}
817
818double Value::asDouble() const {
819 switch (type()) {
820 case intValue:
821 return static_cast<double>(value_.int_);
822 case uintValue:
823#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
824 return static_cast<double>(value_.uint_);
825#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
826 return integerToDouble(value_.uint_);
827#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
828 case realValue:
829 return value_.real_;
830 case nullValue:
831 return 0.0;
832 case booleanValue:
833 return value_.bool_ ? 1.0 : 0.0;
834 default:
835 break;
836 }
837 JSON_FAIL_MESSAGE("Value is not convertible to double.");
838}
839
840float Value::asFloat() const {
841 switch (type()) {
842 case intValue:
843 return static_cast<float>(value_.int_);
844 case uintValue:
845#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
846 return static_cast<float>(value_.uint_);
847#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
848 // This can fail (silently?) if the value is bigger than MAX_FLOAT.
849 return static_cast<float>(integerToDouble(value_.uint_));
850#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
851 case realValue:
852 return static_cast<float>(value_.real_);
853 case nullValue:
854 return 0.0;
855 case booleanValue:
856 return value_.bool_ ? 1.0F : 0.0F;
857 default:
858 break;
859 }
860 JSON_FAIL_MESSAGE("Value is not convertible to float.");
861}
862
863bool Value::asBool() const {
864 switch (type()) {
865 case booleanValue:
866 return value_.bool_;
867 case nullValue:
868 return false;
869 case intValue:
870 return value_.int_ != 0;
871 case uintValue:
872 return value_.uint_ != 0;
873 case realValue: {
874 // According to JavaScript language zero or NaN is regarded as false
875 const auto value_classification = std::fpclassify(value_.real_);
876 return value_classification != FP_ZERO && value_classification != FP_NAN;
877 }
878 default:
879 break;
880 }
881 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
882}
883
885 switch (other) {
886 case nullValue:
887 return (isNumeric() && asDouble() == 0.0) ||
888 (type() == booleanValue && !value_.bool_) ||
889 (type() == stringValue && asString().empty()) ||
890 (type() == arrayValue && value_.map_->empty()) ||
891 (type() == objectValue && value_.map_->empty()) ||
892 type() == nullValue;
893 case intValue:
894 return isInt() ||
895 (type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
896 type() == booleanValue || type() == nullValue;
897 case uintValue:
898 return isUInt() ||
899 (type() == realValue && InRange(value_.real_, 0u, maxUInt)) ||
900 type() == booleanValue || type() == nullValue;
901 case realValue:
902 return isNumeric() || type() == booleanValue || type() == nullValue;
903 case booleanValue:
904 return isNumeric() || type() == booleanValue || type() == nullValue;
905 case stringValue:
906 return isNumeric() || type() == booleanValue || type() == stringValue ||
907 type() == nullValue;
908 case arrayValue:
909 return type() == arrayValue || type() == nullValue;
910 case objectValue:
911 return type() == objectValue || type() == nullValue;
912 }
914 return false;
915}
916
919 switch (type()) {
920 case nullValue:
921 case intValue:
922 case uintValue:
923 case realValue:
924 case booleanValue:
925 case stringValue:
926 return 0;
927 case arrayValue: // size of the array is highest index + 1
928 if (!value_.map_->empty()) {
929 ObjectValues::const_iterator itLast = value_.map_->end();
930 --itLast;
931 return (*itLast).first.index() + 1;
932 }
933 return 0;
934 case objectValue:
935 return ArrayIndex(value_.map_->size());
936 }
938 return 0; // unreachable;
939}
940
941bool Value::empty() const {
942 if (isNull() || isArray() || isObject())
943 return size() == 0U;
944 return false;
945}
946
947Value::operator bool() const { return !isNull(); }
948
951 type() == objectValue,
952 "in Json::Value::clear(): requires complex value");
953 start_ = 0;
954 limit_ = 0;
955 switch (type()) {
956 case arrayValue:
957 case objectValue:
958 value_.map_->clear();
959 break;
960 default:
961 break;
962 }
963}
964
967 type() == nullValue || type() == arrayValue,
968 "in Json::Value::resize(): requires arrayValue, but found "
969 << valueTypeToString(type()));
970 if (type() == nullValue)
971 *this = Value(arrayValue);
972 ArrayIndex oldSize = size();
973 if (newSize == 0)
974 clear();
975 else if (newSize > oldSize)
976 for (ArrayIndex i = oldSize; i < newSize; ++i)
977 (*this)[i];
978 else {
979 for (ArrayIndex index = newSize; index < oldSize; ++index) {
980 value_.map_->erase(index);
981 }
982 JSON_ASSERT(size() == newSize);
983 }
984}
985
988 type() == nullValue || type() == arrayValue,
989 "in Json::Value::operator[](ArrayIndex): requires arrayValue");
990 if (type() == nullValue)
991 *this = Value(arrayValue);
992 CZString key(index);
993 auto it = value_.map_->lower_bound(key);
994 if (it != value_.map_->end() && (*it).first == key)
995 return (*it).second;
996
997 // JSON arrays are dense: materialize any gap between the current size and
998 // `index` with null so that size(), iteration, and serialization stay
999 // consistent. Without this, `arr[5] = x` on an empty array would store a
1000 // single element while size() reported 6 and serialization emitted six
1001 // (see issue #1611). resize() already grows arrays this same way.
1002 for (ArrayIndex i = size(); i < index; ++i)
1003 value_.map_->insert(value_.map_->end(),
1004 ObjectValues::value_type(CZString(i), nullSingleton()));
1005
1006 ObjectValues::value_type defaultValue(key, nullSingleton());
1007 it = value_.map_->insert(it, defaultValue);
1008 return (*it).second;
1009}
1010
1013 index >= 0,
1014 "in Json::Value::operator[](int index): index cannot be negative");
1015 return (*this)[ArrayIndex(index)];
1016}
1017
1020 type() == nullValue || type() == arrayValue,
1021 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
1022 if (type() == nullValue)
1023 return nullSingleton();
1024 CZString key(index);
1025 ObjectValues::const_iterator it = value_.map_->find(key);
1026 if (it == value_.map_->end())
1027 return nullSingleton();
1028 return (*it).second;
1029}
1030
1031const Value& Value::operator[](int index) const {
1033 index >= 0,
1034 "in Json::Value::operator[](int index) const: index cannot be negative");
1035 return (*this)[ArrayIndex(index)];
1036}
1037
1038void Value::initBasic(ValueType type, bool allocated) {
1039 setType(type);
1040 setIsAllocated(allocated);
1041 comments_ = Comments{};
1042 start_ = 0;
1043 limit_ = 0;
1044}
1045
1046void Value::dupPayload(const Value& other) {
1047 setType(other.type());
1048 setIsAllocated(false);
1049 switch (type()) {
1050 case nullValue:
1051 case intValue:
1052 case uintValue:
1053 case realValue:
1054 case booleanValue:
1055 value_ = other.value_;
1056 break;
1057 case stringValue:
1058 if (other.value_.string_ && other.isAllocated()) {
1059 unsigned len;
1060 char const* str;
1061 decodePrefixedString(other.isAllocated(), other.value_.string_, &len,
1062 &str);
1063 value_.string_ = duplicateAndPrefixStringValue(str, len);
1064 setIsAllocated(true);
1065 } else {
1066 value_.string_ = other.value_.string_;
1067 }
1068 break;
1069 case arrayValue:
1070 case objectValue:
1071 value_.map_ = new ObjectValues(*other.value_.map_);
1072 break;
1073 default:
1075 }
1076}
1077
1078void Value::releasePayload() {
1079 switch (type()) {
1080 case nullValue:
1081 case intValue:
1082 case uintValue:
1083 case realValue:
1084 case booleanValue:
1085 break;
1086 case stringValue:
1087 if (isAllocated())
1088 releasePrefixedStringValue(value_.string_);
1089 break;
1090 case arrayValue:
1091 case objectValue:
1092 delete value_.map_;
1093 break;
1094 default:
1096 }
1097}
1098
1099void Value::dupMeta(const Value& other) {
1100 comments_ = other.comments_;
1101 start_ = other.start_;
1102 limit_ = other.limit_;
1103}
1104
1105// Access an object value by name, create a null member if it does not exist.
1106// @pre Type of '*this' is object or null.
1107// @param key is null-terminated.
1108Value& Value::resolveReference(const char* key) {
1110 type() == nullValue || type() == objectValue,
1111 "in Json::Value::resolveReference(): requires objectValue, but found "
1112 << valueTypeToString(type()));
1113 if (type() == nullValue)
1114 *this = Value(objectValue);
1115 CZString actualKey(key, static_cast<unsigned>(strlen(key)),
1116 CZString::noDuplication); // NOTE!
1117 auto it = value_.map_->lower_bound(actualKey);
1118 if (it != value_.map_->end() && (*it).first == actualKey)
1119 return (*it).second;
1120
1121 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1122 it = value_.map_->insert(it, defaultValue);
1123 Value& value = (*it).second;
1124 return value;
1125}
1126
1127// @param key is not null-terminated.
1128Value& Value::resolveReference(char const* key, char const* end) {
1129 JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
1130 "in Json::Value::resolveReference(key, end): requires "
1131 "objectValue, but found "
1132 << valueTypeToString(type()));
1133 if (type() == nullValue)
1134 *this = Value(objectValue);
1135 CZString actualKey(key, static_cast<unsigned>(end - key),
1136 CZString::duplicateOnCopy);
1137 auto it = value_.map_->lower_bound(actualKey);
1138 if (it != value_.map_->end() && (*it).first == actualKey)
1139 return (*it).second;
1140
1141 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1142 it = value_.map_->insert(it, defaultValue);
1143 Value& value = (*it).second;
1144 return value;
1145}
1146
1147Value Value::get(ArrayIndex index, const Value& defaultValue) const {
1148 const Value* value = &((*this)[index]);
1149 return value == &nullSingleton() ? defaultValue : *value;
1150}
1151
1152bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
1153
1154Value const* Value::find(char const* begin, char const* end) const {
1156 "in Json::Value::find(begin, end): requires "
1157 "objectValue or nullValue");
1158 if (type() == nullValue)
1159 return nullptr;
1160 CZString actualKey(begin, static_cast<unsigned>(end - begin),
1161 CZString::noDuplication);
1162 ObjectValues::const_iterator it = value_.map_->find(actualKey);
1163 if (it == value_.map_->end())
1164 return nullptr;
1165 return &(*it).second;
1166}
1167Value const* Value::find(const String& key) const {
1168 return find(key.data(), key.data() + key.length());
1169}
1170
1171Value const* Value::findNull(const String& key) const {
1173}
1174Value const* Value::findBool(const String& key) const {
1176}
1177Value const* Value::findInt(const String& key) const {
1179}
1180Value const* Value::findInt64(const String& key) const {
1182}
1183Value const* Value::findUInt(const String& key) const {
1185}
1186Value const* Value::findUInt64(const String& key) const {
1188}
1189Value const* Value::findIntegral(const String& key) const {
1191}
1192Value const* Value::findDouble(const String& key) const {
1194}
1195Value const* Value::findNumeric(const String& key) const {
1197}
1198Value const* Value::findString(const String& key) const {
1200}
1201Value const* Value::findArray(const String& key) const {
1203}
1204Value const* Value::findObject(const String& key) const {
1206}
1207
1208Value* Value::demand(char const* begin, char const* end) {
1210 "in Json::Value::demand(begin, end): requires "
1211 "objectValue or nullValue");
1212 return &resolveReference(begin, end);
1213}
1214const Value& Value::operator[](const char* key) const {
1215 Value const* found = find(key, key + strlen(key));
1216 if (!found)
1217 return nullSingleton();
1218 return *found;
1219}
1220Value const& Value::operator[](const String& key) const {
1221 Value const* found = find(key);
1222 if (!found)
1223 return nullSingleton();
1224 return *found;
1225}
1226
1227Value& Value::operator[](const char* key) {
1228 return resolveReference(key, key + strlen(key));
1229}
1230
1232 return resolveReference(key.data(), key.data() + key.length());
1233}
1234
1236 return resolveReference(key.c_str());
1237}
1238
1239Value& Value::append(const Value& value) { return append(Value(value)); }
1240
1243 "in Json::Value::append: requires arrayValue, but found "
1244 << valueTypeToString(type()));
1245 if (type() == nullValue) {
1246 *this = Value(arrayValue);
1247 }
1248 return this->value_.map_->emplace(size(), std::move(value)).first->second;
1249}
1250
1251bool Value::insert(ArrayIndex index, const Value& newValue) {
1252 return insert(index, Value(newValue));
1253}
1254
1255bool Value::insert(ArrayIndex index, Value&& newValue) {
1257 "in Json::Value::insert: requires arrayValue");
1258 ArrayIndex length = size();
1259 if (index > length) {
1260 return false;
1261 }
1262 for (ArrayIndex i = length; i > index; i--) {
1263 (*this)[i] = std::move((*this)[i - 1]);
1264 }
1265 (*this)[index] = std::move(newValue);
1266 return true;
1267}
1268
1269Value Value::get(char const* begin, char const* end,
1270 Value const& defaultValue) const {
1271 Value const* found = find(begin, end);
1272 return !found ? defaultValue : *found;
1273}
1274Value Value::get(char const* key, Value const& defaultValue) const {
1275 return get(key, key + strlen(key), defaultValue);
1276}
1277Value Value::get(String const& key, Value const& defaultValue) const {
1278 return get(key.data(), key.data() + key.length(), defaultValue);
1279}
1280
1281bool Value::removeMember(const char* begin, const char* end, Value* removed) {
1282 if (type() != objectValue) {
1283 return false;
1284 }
1285 CZString actualKey(begin, static_cast<unsigned>(end - begin),
1286 CZString::noDuplication);
1287 auto it = value_.map_->find(actualKey);
1288 if (it == value_.map_->end())
1289 return false;
1290 if (removed)
1291 *removed = std::move(it->second);
1292 value_.map_->erase(it);
1293 return true;
1294}
1295bool Value::removeMember(const char* key, Value* removed) {
1296 return removeMember(key, key + strlen(key), removed);
1297}
1298bool Value::removeMember(String const& key, Value* removed) {
1299 return removeMember(key.data(), key.data() + key.length(), removed);
1300}
1301
1302void Value::removeMember(const char* key) {
1304 type() == nullValue || type() == objectValue,
1305 "in Json::Value::removeMember(): requires objectValue, but found "
1306 << valueTypeToString(type()));
1307 if (type() == nullValue)
1308 return;
1309
1310 CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
1311 value_.map_->erase(actualKey);
1312}
1313void Value::removeMember(const String& key) {
1315 type() == nullValue || type() == objectValue,
1316 "in Json::Value::removeMember(): requires objectValue, but found "
1317 << valueTypeToString(type()));
1318 removeMember(key, nullptr);
1319}
1320
1321bool Value::removeIndex(ArrayIndex index, Value* removed) {
1322 if (type() != arrayValue) {
1323 return false;
1324 }
1325 CZString key(index);
1326 auto it = value_.map_->find(key);
1327 if (it == value_.map_->end()) {
1328 return false;
1329 }
1330 if (removed)
1331 *removed = std::move(it->second);
1332 ArrayIndex oldSize = size();
1333 // shift left all items left, into the place of the "removed"
1334 for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
1335 CZString keey(i);
1336 (*value_.map_)[keey] = (*this)[i + 1];
1337 }
1338 // erase the last one ("leftover")
1339 CZString keyLast(oldSize - 1);
1340 auto itLast = value_.map_->find(keyLast);
1341 value_.map_->erase(itLast);
1342 return true;
1343}
1344
1345bool Value::isMember(char const* begin, char const* end) const {
1346 Value const* value = find(begin, end);
1347 return nullptr != value;
1348}
1349bool Value::isMember(char const* key) const {
1350 return isMember(key, key + strlen(key));
1351}
1352bool Value::isMember(String const& key) const {
1353 return isMember(key.data(), key.data() + key.length());
1354}
1355
1358 type() == nullValue || type() == objectValue,
1359 "in Json::Value::getMemberNames(), value must be objectValue");
1360 if (type() == nullValue)
1361 return Value::Members();
1363 members.reserve(value_.map_->size());
1364 ObjectValues::const_iterator it = value_.map_->begin();
1365 ObjectValues::const_iterator itEnd = value_.map_->end();
1366 for (; it != itEnd; ++it) {
1367 members.push_back(String((*it).first.data(), (*it).first.length()));
1368 }
1369 return members;
1370}
1371
1372static bool IsIntegral(double d) {
1373 double integral_part;
1374 return modf(d, &integral_part) == 0.0;
1375}
1376
1377bool Value::isNull() const { return type() == nullValue; }
1378
1379bool Value::isBool() const { return type() == booleanValue; }
1380
1381bool Value::isInt() const {
1382 switch (type()) {
1383 case intValue:
1384#if defined(JSON_HAS_INT64)
1385 return value_.int_ >= minInt && value_.int_ <= maxInt;
1386#else
1387 return true;
1388#endif
1389 case uintValue:
1390 return value_.uint_ <= UInt(maxInt);
1391 case realValue:
1392 return value_.real_ >= minInt && value_.real_ <= maxInt &&
1393 IsIntegral(value_.real_);
1394 default:
1395 break;
1396 }
1397 return false;
1398}
1399
1400bool Value::isUInt() const {
1401 switch (type()) {
1402 case intValue:
1403#if defined(JSON_HAS_INT64)
1404 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
1405#else
1406 return value_.int_ >= 0;
1407#endif
1408 case uintValue:
1409#if defined(JSON_HAS_INT64)
1410 return value_.uint_ <= maxUInt;
1411#else
1412 return true;
1413#endif
1414 case realValue:
1415 return value_.real_ >= 0 && value_.real_ <= maxUInt &&
1416 IsIntegral(value_.real_);
1417 default:
1418 break;
1419 }
1420 return false;
1421}
1422
1423bool Value::isInt64() const {
1424#if defined(JSON_HAS_INT64)
1425 switch (type()) {
1426 case intValue:
1427 return true;
1428 case uintValue:
1429 return value_.uint_ <= UInt64(maxInt64);
1430 case realValue:
1431 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
1432 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
1433 // require the value to be strictly less than the limit.
1434 // minInt64 is -2^63 which can be represented as a double, but since double
1435 // values in its proximity are also rounded to -2^63, we require the value
1436 // to be strictly greater than the limit to avoid returning 'true' for
1437 // values that are not in the range
1438 return value_.real_ > double(minInt64) && value_.real_ < double(maxInt64) &&
1439 IsIntegral(value_.real_);
1440 default:
1441 break;
1442 }
1443#endif // JSON_HAS_INT64
1444 return false;
1445}
1446
1447bool Value::isUInt64() const {
1448#if defined(JSON_HAS_INT64)
1449 switch (type()) {
1450 case intValue:
1451 return value_.int_ >= 0;
1452 case uintValue:
1453 return true;
1454 case realValue:
1455 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1456 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1457 // require the value to be strictly less than the limit.
1458 return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
1459 IsIntegral(value_.real_);
1460 default:
1461 break;
1462 }
1463#endif // JSON_HAS_INT64
1464 return false;
1465}
1466
1467bool Value::isIntegral() const {
1468 switch (type()) {
1469 case intValue:
1470 case uintValue:
1471 return true;
1472 case realValue:
1473#if defined(JSON_HAS_INT64)
1474 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1475 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1476 // require the value to be strictly less than the limit.
1477 // minInt64 is -2^63 which can be represented as a double, but since double
1478 // values in its proximity are also rounded to -2^63, we require the value
1479 // to be strictly greater than the limit to avoid returning 'true' for
1480 // values that are not in the range
1481 return value_.real_ > double(minInt64) &&
1482 value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
1483#else
1484 return value_.real_ >= minInt && value_.real_ <= maxUInt &&
1485 IsIntegral(value_.real_);
1486#endif // JSON_HAS_INT64
1487 default:
1488 break;
1489 }
1490 return false;
1491}
1492
1493bool Value::isDouble() const {
1494 return type() == intValue || type() == uintValue || type() == realValue;
1495}
1496
1497bool Value::isNumeric() const { return isDouble(); }
1498
1499bool Value::isString() const { return type() == stringValue; }
1500
1501bool Value::isArray() const { return type() == arrayValue; }
1502
1503bool Value::isObject() const { return type() == objectValue; }
1504
1505Value::Comments::Comments(const Comments& that)
1506 : ptr_{cloneUnique(that.ptr_)} {}
1507
1508Value::Comments::Comments(Comments&& that) noexcept
1509 : ptr_{std::move(that.ptr_)} {}
1510
1511Value::Comments& Value::Comments::operator=(const Comments& that) {
1512 ptr_ = cloneUnique(that.ptr_);
1513 return *this;
1514}
1515
1516Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
1517 ptr_ = std::move(that.ptr_);
1518 return *this;
1519}
1520
1521bool Value::Comments::has(CommentPlacement slot) const {
1522 return ptr_ && !(*ptr_)[slot].empty();
1523}
1524
1525String Value::Comments::get(CommentPlacement slot) const {
1526 if (!ptr_)
1527 return {};
1528 return (*ptr_)[slot];
1529}
1530
1531void Value::Comments::set(CommentPlacement slot, String comment) {
1533 return;
1534 if (!ptr_)
1535 ptr_ = std::unique_ptr<Array>(new Array());
1536 (*ptr_)[slot] = std::move(comment);
1537}
1538
1540 if (!comment.empty() && (comment.back() == '\n')) {
1541 // Always discard trailing newline, to aid indentation.
1542 comment.pop_back();
1543 }
1545 comment.empty() || comment[0] == '/',
1546 "in Json::Value::setComment(): Comments must start with /");
1547 comments_.set(placement, std::move(comment));
1548}
1549
1551 return comments_.has(placement);
1552}
1553
1555 return comments_.get(placement);
1556}
1557
1558void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
1559
1560void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
1561
1562ptrdiff_t Value::getOffsetStart() const { return start_; }
1563
1564ptrdiff_t Value::getOffsetLimit() const { return limit_; }
1565
1567 StreamWriterBuilder builder;
1568
1569 String out = this->hasComment(commentBefore) ? "\n" : "";
1570 out += Json::writeString(builder, *this);
1571 out += '\n';
1572
1573 return out;
1574}
1575
1577 switch (type()) {
1578 case arrayValue:
1579 case objectValue:
1580 if (value_.map_)
1581 return const_iterator(value_.map_->begin());
1582 break;
1583 default:
1584 break;
1585 }
1586 return {};
1587}
1588
1590 switch (type()) {
1591 case arrayValue:
1592 case objectValue:
1593 if (value_.map_)
1594 return const_iterator(value_.map_->end());
1595 break;
1596 default:
1597 break;
1598 }
1599 return {};
1600}
1601
1603 switch (type()) {
1604 case arrayValue:
1605 case objectValue:
1606 if (value_.map_)
1607 return iterator(value_.map_->begin());
1608 break;
1609 default:
1610 break;
1611 }
1612 return iterator();
1613}
1614
1616 switch (type()) {
1617 case arrayValue:
1618 case objectValue:
1619 if (value_.map_)
1620 return iterator(value_.map_->end());
1621 break;
1622 default:
1623 break;
1624 }
1625 return iterator();
1626}
1627
1628// class PathArgument
1629// //////////////////////////////////////////////////////////////////
1630
1631PathArgument::PathArgument() = default;
1632
1634 : index_(index), kind_(kindIndex) {}
1635
1636PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
1637
1638PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
1639
1640// class Path
1641// //////////////////////////////////////////////////////////////////
1642
1643Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
1644 const PathArgument& a3, const PathArgument& a4,
1645 const PathArgument& a5) {
1646 InArgs in;
1647 in.reserve(5);
1648 in.push_back(&a1);
1649 in.push_back(&a2);
1650 in.push_back(&a3);
1651 in.push_back(&a4);
1652 in.push_back(&a5);
1653 makePath(path, in);
1654}
1655
1656void Path::makePath(const String& path, const InArgs& in) {
1657 const char* current = path.c_str();
1658 const char* end = current + path.length();
1659 auto itInArg = in.begin();
1660 while (current != end) {
1661 if (*current == '[') {
1662 ++current;
1663 if (*current == '%')
1664 addPathInArg(path, in, itInArg, PathArgument::kindIndex);
1665 else {
1666 ArrayIndex index = 0;
1667 for (; current != end && *current >= '0' && *current <= '9'; ++current)
1668 index = index * 10 + ArrayIndex(*current - '0');
1669 args_.push_back(index);
1670 }
1671 if (current == end || *++current != ']')
1672 invalidPath(path, int(current - path.c_str()));
1673 } else if (*current == '%') {
1674 addPathInArg(path, in, itInArg, PathArgument::kindKey);
1675 ++current;
1676 } else if (*current == '.' || *current == ']') {
1677 ++current;
1678 } else {
1679 const char* beginName = current;
1680 while (current != end && !strchr("[.", *current))
1681 ++current;
1682 args_.push_back(String(beginName, current));
1683 }
1684 }
1685}
1686
1687void Path::addPathInArg(const String& /*path*/, const InArgs& in,
1688 InArgs::const_iterator& itInArg,
1689 PathArgument::Kind kind) {
1690 if (itInArg == in.end()) {
1691 // Error: missing argument %d
1692 } else if ((*itInArg)->kind_ != kind) {
1693 // Error: bad argument type
1694 } else {
1695 args_.push_back(**itInArg++);
1696 }
1697}
1698
1699void Path::invalidPath(const String& /*path*/, int /*location*/) {
1700 // Error: invalid path.
1701}
1702
1703const Value& Path::resolve(const Value& root) const {
1704 const Value* node = &root;
1705 for (const auto& arg : args_) {
1706 if (arg.kind_ == PathArgument::kindIndex) {
1707 if (!node->isArray() || !node->isValidIndex(arg.index_)) {
1708 // Error: unable to resolve path (array value expected at position... )
1709 return Value::nullSingleton();
1710 }
1711 node = &((*node)[arg.index_]);
1712 } else if (arg.kind_ == PathArgument::kindKey) {
1713 if (!node->isObject()) {
1714 // Error: unable to resolve path (object value expected at position...)
1715 return Value::nullSingleton();
1716 }
1717 node = &((*node)[arg.key_]);
1718 if (node == &Value::nullSingleton()) {
1719 // Error: unable to resolve path (object has no member named '' at
1720 // position...)
1721 return Value::nullSingleton();
1722 }
1723 }
1724 }
1725 return *node;
1726}
1727
1728Value Path::resolve(const Value& root, const Value& defaultValue) const {
1729 const Value* node = &root;
1730 for (const auto& arg : args_) {
1731 if (arg.kind_ == PathArgument::kindIndex) {
1732 if (!node->isArray() || !node->isValidIndex(arg.index_))
1733 return defaultValue;
1734 node = &((*node)[arg.index_]);
1735 } else if (arg.kind_ == PathArgument::kindKey) {
1736 if (!node->isObject())
1737 return defaultValue;
1738 node = &((*node)[arg.key_]);
1739 if (node == &Value::nullSingleton())
1740 return defaultValue;
1741 }
1742 }
1743 return *node;
1744}
1745
1746Value& Path::make(Value& root) const {
1747 Value* node = &root;
1748 for (const auto& arg : args_) {
1749 if (arg.kind_ == PathArgument::kindIndex) {
1750 if (!node->isArray()) {
1751 // Error: node is not an array at position ...
1752 }
1753 node = &((*node)[arg.index_]);
1754 } else if (arg.kind_ == PathArgument::kindKey) {
1755 if (!node->isObject()) {
1756 // Error: node is not an object at position...
1757 }
1758 node = &((*node)[arg.key_]);
1759 }
1760 }
1761 return *node;
1762}
1763
1764const char* version() { return JSONCPP_VERSION_STRING; }
1765
1766} // 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:815
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
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, CommentPlacement placement)
Definition value.h:666
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.
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
void removeMember(std::string_view key)
Remove and return the named member.
Definition value.h:607
UInt asUInt() const
bool isMember(std::string_view key) const
Return true if the object has a member named key.
Definition value.h:644
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:577
ValueType type() const
bool isObject() const
Value const * findInt64(const String &key) const
void setOffsetStart(ptrdiff_t start)
ValueMembersView members()
Definition value.h:1168
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
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_ASSERT_UNREACHABLE
JSON (JavaScript Object Notation).
Definition allocator.h:16
void throwLogicError(String const &msg)
used internally
const char * version()
static char * duplicateStringValue(const char *value, size_t length)
Duplicates the specified string value.
int64_t Int64
Definition config.h:121
static bool IsIntegral(double d)
unsigned int ArrayIndex
Definition forwards.h:32
static const char * valueTypeToString(ValueType type)
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
void throwRuntimeError(String const &msg)
used internally
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:135
uint64_t UInt64
Definition config.h:122
static std::unique_ptr< T > cloneUnique(const std::unique_ptr< T > &p)
static char * duplicateAndPrefixStringValue(const char *value, unsigned int length)
void swap(Value &a, Value &b)
Definition value.h:1175
static bool InRange(double d, T min, U max)
#define JSONCPP_VERSION_STRING
Definition version.h:13