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 cstr_ = other.cstr_;
324 index_ = other.index_;
325 return *this;
326}
327
328Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
329 if (cstr_ && storage_.policy_ == duplicate) {
330 // CZString keys come from duplicateStringValue (no length prefix), so
331 // release with the matching non-prefixed variant, as the destructor does.
332 releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1U);
333 }
334 cstr_ = other.cstr_;
335 if (other.cstr_) {
336 storage_.policy_ = other.storage_.policy_;
337 storage_.length_ = other.storage_.length_;
338 } else {
339 index_ = other.index_;
340 }
341 other.cstr_ = nullptr;
342 return *this;
343}
344
345bool Value::CZString::operator<(const CZString& other) const {
346 if (!cstr_)
347 return index_ < other.index_;
348 // return strcmp(cstr_, other.cstr_) < 0;
349 // Assume both are strings.
350 unsigned this_len = this->storage_.length_;
351 unsigned other_len = other.storage_.length_;
352 unsigned min_len = std::min<unsigned>(this_len, other_len);
353 JSON_ASSERT(this->cstr_ && other.cstr_);
354 int comp = memcmp(this->cstr_, other.cstr_, min_len);
355 if (comp < 0)
356 return true;
357 if (comp > 0)
358 return false;
359 return (this_len < other_len);
360}
361
362bool Value::CZString::operator==(const CZString& other) const {
363 if (!cstr_)
364 return index_ == other.index_;
365 // return strcmp(cstr_, other.cstr_) == 0;
366 // Assume both are strings.
367 unsigned this_len = this->storage_.length_;
368 unsigned other_len = other.storage_.length_;
369 if (this_len != other_len)
370 return false;
371 JSON_ASSERT(this->cstr_ && other.cstr_);
372 int comp = memcmp(this->cstr_, other.cstr_, this_len);
373 return comp == 0;
374}
375
376ArrayIndex Value::CZString::index() const { return index_; }
377
378// const char* Value::CZString::c_str() const { return cstr_; }
379const char* Value::CZString::data() const { return cstr_; }
380unsigned Value::CZString::length() const { return storage_.length_; }
381bool Value::CZString::isStaticString() const {
382 return storage_.policy_ == noDuplication;
383}
385
386// //////////////////////////////////////////////////////////////////
387// //////////////////////////////////////////////////////////////////
388// //////////////////////////////////////////////////////////////////
389// class Value::Value
390// //////////////////////////////////////////////////////////////////
391// //////////////////////////////////////////////////////////////////
392// //////////////////////////////////////////////////////////////////
393
399 static char const emptyString[] = "";
400 initBasic(type);
401 switch (type) {
402 case nullValue:
403 break;
404 case intValue:
405 case uintValue:
406 value_.int_ = 0;
407 break;
408 case realValue:
409 value_.real_ = 0.0;
410 break;
411 case stringValue:
412 // allocated_ == false, so this is safe.
413 value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
414 break;
415 case arrayValue:
416 case objectValue:
417 value_.map_ = new ObjectValues();
418 break;
419 case booleanValue:
420 value_.bool_ = false;
421 break;
422 default:
424 }
425}
426
428 initBasic(intValue);
429 value_.int_ = value;
430}
431
433 initBasic(uintValue);
434 value_.uint_ = value;
435}
436#if defined(JSON_HAS_INT64)
438 initBasic(intValue);
439 value_.int_ = value;
440}
442 initBasic(uintValue);
443 value_.uint_ = value;
444}
445#endif // defined(JSON_HAS_INT64)
446
447Value::Value(double value) {
448 initBasic(realValue);
449 value_.real_ = value;
450}
451
452Value::Value(const char* value) {
453 initBasic(stringValue, true);
454 JSON_ASSERT_MESSAGE(value != nullptr,
455 "Null Value Passed to Value Constructor");
456 value_.string_ = duplicateAndPrefixStringValue(
457 value, static_cast<unsigned>(strlen(value)));
458}
459
460Value::Value(const char* begin, const char* end) {
461 initBasic(stringValue, true);
462 value_.string_ =
463 duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
464}
465
466Value::Value(const String& value) {
467 initBasic(stringValue, true);
468 value_.string_ = duplicateAndPrefixStringValue(
469 value.data(), static_cast<unsigned>(value.length()));
470}
471
473 initBasic(stringValue);
474 value_.string_ = const_cast<char*>(value.c_str());
475}
476
477Value::Value(bool value) {
478 initBasic(booleanValue);
479 value_.bool_ = value;
480}
481
482Value::Value(const Value& other) {
483 dupPayload(other);
484 dupMeta(other);
485}
486
487Value::Value(Value&& other) noexcept {
488 initBasic(nullValue);
489 swap(other);
490}
491
493 releasePayload();
494 value_.uint_ = 0;
495}
496
498 Value(other).swap(*this);
499 return *this;
500}
501
502Value& Value::operator=(Value&& other) noexcept {
503 other.swap(*this);
504 return *this;
505}
506
508 std::swap(bits_, other.bits_);
509 std::swap(value_, other.value_);
510}
511
512void Value::copyPayload(const Value& other) {
513 releasePayload();
514 dupPayload(other);
515}
516
517void Value::swap(Value& other) {
518 swapPayload(other);
519 std::swap(comments_, other.comments_);
520 std::swap(start_, other.start_);
521 std::swap(limit_, other.limit_);
522}
523
524void Value::copy(const Value& other) {
525 copyPayload(other);
526 dupMeta(other);
527}
528
530 return static_cast<ValueType>(bits_.value_type_);
531}
532
533int Value::compare(const Value& other) const {
534 if (*this < other)
535 return -1;
536 if (*this > other)
537 return 1;
538 return 0;
539}
540
541bool Value::operator<(const Value& other) const {
542 int typeDelta = type() - other.type();
543 if (typeDelta)
544 return typeDelta < 0;
545 switch (type()) {
546 case nullValue:
547 return false;
548 case intValue:
549 return value_.int_ < other.value_.int_;
550 case uintValue:
551 return value_.uint_ < other.value_.uint_;
552 case realValue:
553 return value_.real_ < other.value_.real_;
554 case booleanValue:
555 return value_.bool_ < other.value_.bool_;
556 case stringValue: {
557 if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
558 return other.value_.string_ != nullptr;
559 }
560 unsigned this_len;
561 unsigned other_len;
562 char const* this_str;
563 char const* other_str;
564 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
565 &this_str);
566 decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
567 &other_str);
568 unsigned min_len = std::min<unsigned>(this_len, other_len);
569 JSON_ASSERT(this_str && other_str);
570 int comp = memcmp(this_str, other_str, min_len);
571 if (comp < 0)
572 return true;
573 if (comp > 0)
574 return false;
575 return (this_len < other_len);
576 }
577 case arrayValue:
578 case objectValue: {
579 auto thisSize = value_.map_->size();
580 auto otherSize = other.value_.map_->size();
581 if (thisSize != otherSize)
582 return thisSize < otherSize;
583 return (*value_.map_) < (*other.value_.map_);
584 }
585 default:
587 }
588 return false; // unreachable
589}
590
591bool Value::operator<=(const Value& other) const { return !(other < *this); }
592
593bool Value::operator>=(const Value& other) const { return !(*this < other); }
594
595bool Value::operator>(const Value& other) const { return other < *this; }
596
597bool Value::operator==(const Value& other) const {
598 if (type() != other.type())
599 return false;
600 switch (type()) {
601 case nullValue:
602 return true;
603 case intValue:
604 return value_.int_ == other.value_.int_;
605 case uintValue:
606 return value_.uint_ == other.value_.uint_;
607 case realValue:
608 return value_.real_ == other.value_.real_;
609 case booleanValue:
610 return value_.bool_ == other.value_.bool_;
611 case stringValue: {
612 if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
613 return (value_.string_ == other.value_.string_);
614 }
615 unsigned this_len;
616 unsigned other_len;
617 char const* this_str;
618 char const* other_str;
619 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
620 &this_str);
621 decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
622 &other_str);
623 if (this_len != other_len)
624 return false;
625 JSON_ASSERT(this_str && other_str);
626 int comp = memcmp(this_str, other_str, this_len);
627 return comp == 0;
628 }
629 case arrayValue:
630 case objectValue:
631 return value_.map_->size() == other.value_.map_->size() &&
632 (*value_.map_) == (*other.value_.map_);
633 default:
635 }
636 return false; // unreachable
637}
638
639bool Value::operator!=(const Value& other) const { return !(*this == other); }
640
641const char* Value::asCString() const {
643 "in Json::Value::asCString(): requires stringValue");
644 if (value_.string_ == nullptr)
645 return nullptr;
646 unsigned this_len;
647 char const* this_str;
648 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
649 &this_str);
650 return this_str;
651}
652
653#if JSONCPP_USE_SECURE_MEMORY
654unsigned Value::getCStringLength() const {
656 "in Json::Value::asCString(): requires stringValue");
657 if (value_.string_ == 0)
658 return 0;
659 unsigned this_len;
660 char const* this_str;
661 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
662 &this_str);
663 return this_len;
664}
665#endif
666
667bool Value::getString(char const** begin, char const** end) const {
668 if (type() != stringValue)
669 return false;
670 if (value_.string_ == nullptr)
671 return false;
672 unsigned length;
673 decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
674 begin);
675 *end = *begin + length;
676 return true;
677}
678
680 switch (type()) {
681 case nullValue:
682 return "";
683 case stringValue: {
684 if (value_.string_ == nullptr)
685 return "";
686 unsigned this_len;
687 char const* this_str;
688 decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
689 &this_str);
690 return String(this_str, this_len);
691 }
692 case booleanValue:
693 return value_.bool_ ? "true" : "false";
694 case intValue:
695 return valueToString(value_.int_);
696 case uintValue:
697 return valueToString(value_.uint_);
698 case realValue:
699 return valueToString(value_.real_);
700 default:
701 JSON_FAIL_MESSAGE("Type is not convertible to string");
702 }
703}
704
706 switch (type()) {
707 case intValue:
708 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
709 return Int(value_.int_);
710 case uintValue:
711 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
712 return Int(value_.uint_);
713 case realValue:
715 "double out of Int range");
716 return Int(value_.real_);
717 case nullValue:
718 return 0;
719 case booleanValue:
720 return value_.bool_ ? 1 : 0;
721 default:
722 break;
723 }
724 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
725}
726
728 switch (type()) {
729 case intValue:
730 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
731 return UInt(value_.int_);
732 case uintValue:
733 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
734 return UInt(value_.uint_);
735 case realValue:
736 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt),
737 "double out of UInt range");
738 return UInt(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 UInt.");
747}
748
749#if defined(JSON_HAS_INT64)
750
752 switch (type()) {
753 case intValue:
754 return Int64(value_.int_);
755 case uintValue:
756 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
757 return Int64(value_.uint_);
758 case realValue:
759 // If the double value is in proximity to minInt64, it will be rounded to
760 // minInt64. The correct value in this scenario is indeterminable
762 value_.real_ != minInt64,
763 "Double value is minInt64, precise value cannot be determined");
765 "double out of Int64 range");
766 return Int64(value_.real_);
767 case nullValue:
768 return 0;
769 case booleanValue:
770 return value_.bool_ ? 1 : 0;
771 default:
772 break;
773 }
774 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
775}
776
778 switch (type()) {
779 case intValue:
780 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
781 return UInt64(value_.int_);
782 case uintValue:
783 return UInt64(value_.uint_);
784 case realValue:
785 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt64),
786 "double out of UInt64 range");
787 return UInt64(value_.real_);
788 case nullValue:
789 return 0;
790 case booleanValue:
791 return value_.bool_ ? 1 : 0;
792 default:
793 break;
794 }
795 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
796}
797#endif // if defined(JSON_HAS_INT64)
798
800#if defined(JSON_NO_INT64)
801 return asInt();
802#else
803 return asInt64();
804#endif
805}
806
808#if defined(JSON_NO_INT64)
809 return asUInt();
810#else
811 return asUInt64();
812#endif
813}
814
815double Value::asDouble() const {
816 switch (type()) {
817 case intValue:
818 return static_cast<double>(value_.int_);
819 case uintValue:
820#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
821 return static_cast<double>(value_.uint_);
822#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
823 return integerToDouble(value_.uint_);
824#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
825 case realValue:
826 return value_.real_;
827 case nullValue:
828 return 0.0;
829 case booleanValue:
830 return value_.bool_ ? 1.0 : 0.0;
831 default:
832 break;
833 }
834 JSON_FAIL_MESSAGE("Value is not convertible to double.");
835}
836
837float Value::asFloat() const {
838 switch (type()) {
839 case intValue:
840 return static_cast<float>(value_.int_);
841 case uintValue:
842#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
843 return static_cast<float>(value_.uint_);
844#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
845 // This can fail (silently?) if the value is bigger than MAX_FLOAT.
846 return static_cast<float>(integerToDouble(value_.uint_));
847#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
848 case realValue:
849 return static_cast<float>(value_.real_);
850 case nullValue:
851 return 0.0;
852 case booleanValue:
853 return value_.bool_ ? 1.0F : 0.0F;
854 default:
855 break;
856 }
857 JSON_FAIL_MESSAGE("Value is not convertible to float.");
858}
859
860bool Value::asBool() const {
861 switch (type()) {
862 case booleanValue:
863 return value_.bool_;
864 case nullValue:
865 return false;
866 case intValue:
867 return value_.int_ != 0;
868 case uintValue:
869 return value_.uint_ != 0;
870 case realValue: {
871 // According to JavaScript language zero or NaN is regarded as false
872 const auto value_classification = std::fpclassify(value_.real_);
873 return value_classification != FP_ZERO && value_classification != FP_NAN;
874 }
875 default:
876 break;
877 }
878 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
879}
880
882 switch (other) {
883 case nullValue:
884 return (isNumeric() && asDouble() == 0.0) ||
885 (type() == booleanValue && !value_.bool_) ||
886 (type() == stringValue && asString().empty()) ||
887 (type() == arrayValue && value_.map_->empty()) ||
888 (type() == objectValue && value_.map_->empty()) ||
889 type() == nullValue;
890 case intValue:
891 return isInt() ||
892 (type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
893 type() == booleanValue || type() == nullValue;
894 case uintValue:
895 return isUInt() ||
896 (type() == realValue && InRange(value_.real_, 0u, maxUInt)) ||
897 type() == booleanValue || type() == nullValue;
898 case realValue:
899 return isNumeric() || type() == booleanValue || type() == nullValue;
900 case booleanValue:
901 return isNumeric() || type() == booleanValue || type() == nullValue;
902 case stringValue:
903 return isNumeric() || type() == booleanValue || type() == stringValue ||
904 type() == nullValue;
905 case arrayValue:
906 return type() == arrayValue || type() == nullValue;
907 case objectValue:
908 return type() == objectValue || type() == nullValue;
909 }
911 return false;
912}
913
916 switch (type()) {
917 case nullValue:
918 case intValue:
919 case uintValue:
920 case realValue:
921 case booleanValue:
922 case stringValue:
923 return 0;
924 case arrayValue: // size of the array is highest index + 1
925 if (!value_.map_->empty()) {
926 ObjectValues::const_iterator itLast = value_.map_->end();
927 --itLast;
928 return (*itLast).first.index() + 1;
929 }
930 return 0;
931 case objectValue:
932 return ArrayIndex(value_.map_->size());
933 }
935 return 0; // unreachable;
936}
937
938bool Value::empty() const {
939 if (isNull() || isArray() || isObject())
940 return size() == 0U;
941 return false;
942}
943
944Value::operator bool() const { return !isNull(); }
945
948 type() == objectValue,
949 "in Json::Value::clear(): requires complex value");
950 start_ = 0;
951 limit_ = 0;
952 switch (type()) {
953 case arrayValue:
954 case objectValue:
955 value_.map_->clear();
956 break;
957 default:
958 break;
959 }
960}
961
964 type() == nullValue || type() == arrayValue,
965 "in Json::Value::resize(): requires arrayValue, but found "
966 << valueTypeToString(type()));
967 if (type() == nullValue)
968 *this = Value(arrayValue);
969 ArrayIndex oldSize = size();
970 if (newSize == 0)
971 clear();
972 else if (newSize > oldSize)
973 for (ArrayIndex i = oldSize; i < newSize; ++i)
974 (*this)[i];
975 else {
976 for (ArrayIndex index = newSize; index < oldSize; ++index) {
977 value_.map_->erase(index);
978 }
979 JSON_ASSERT(size() == newSize);
980 }
981}
982
985 type() == nullValue || type() == arrayValue,
986 "in Json::Value::operator[](ArrayIndex): requires arrayValue");
987 if (type() == nullValue)
988 *this = Value(arrayValue);
989 CZString key(index);
990 auto it = value_.map_->lower_bound(key);
991 if (it != value_.map_->end() && (*it).first == key)
992 return (*it).second;
993
994 // JSON arrays are dense: materialize any gap between the current size and
995 // `index` with null so that size(), iteration, and serialization stay
996 // consistent. Without this, `arr[5] = x` on an empty array would store a
997 // single element while size() reported 6 and serialization emitted six
998 // (see issue #1611). resize() already grows arrays this same way.
999 for (ArrayIndex i = size(); i < index; ++i)
1000 value_.map_->insert(value_.map_->end(),
1001 ObjectValues::value_type(CZString(i), nullSingleton()));
1002
1003 ObjectValues::value_type defaultValue(key, nullSingleton());
1004 it = value_.map_->insert(it, defaultValue);
1005 return (*it).second;
1006}
1007
1010 index >= 0,
1011 "in Json::Value::operator[](int index): index cannot be negative");
1012 return (*this)[ArrayIndex(index)];
1013}
1014
1017 type() == nullValue || type() == arrayValue,
1018 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
1019 if (type() == nullValue)
1020 return nullSingleton();
1021 CZString key(index);
1022 ObjectValues::const_iterator it = value_.map_->find(key);
1023 if (it == value_.map_->end())
1024 return nullSingleton();
1025 return (*it).second;
1026}
1027
1028const Value& Value::operator[](int index) const {
1030 index >= 0,
1031 "in Json::Value::operator[](int index) const: index cannot be negative");
1032 return (*this)[ArrayIndex(index)];
1033}
1034
1035void Value::initBasic(ValueType type, bool allocated) {
1036 setType(type);
1037 setIsAllocated(allocated);
1038 comments_ = Comments{};
1039 start_ = 0;
1040 limit_ = 0;
1041}
1042
1043void Value::dupPayload(const Value& other) {
1044 setType(other.type());
1045 setIsAllocated(false);
1046 switch (type()) {
1047 case nullValue:
1048 case intValue:
1049 case uintValue:
1050 case realValue:
1051 case booleanValue:
1052 value_ = other.value_;
1053 break;
1054 case stringValue:
1055 if (other.value_.string_ && other.isAllocated()) {
1056 unsigned len;
1057 char const* str;
1058 decodePrefixedString(other.isAllocated(), other.value_.string_, &len,
1059 &str);
1060 value_.string_ = duplicateAndPrefixStringValue(str, len);
1061 setIsAllocated(true);
1062 } else {
1063 value_.string_ = other.value_.string_;
1064 }
1065 break;
1066 case arrayValue:
1067 case objectValue:
1068 value_.map_ = new ObjectValues(*other.value_.map_);
1069 break;
1070 default:
1072 }
1073}
1074
1075void Value::releasePayload() {
1076 switch (type()) {
1077 case nullValue:
1078 case intValue:
1079 case uintValue:
1080 case realValue:
1081 case booleanValue:
1082 break;
1083 case stringValue:
1084 if (isAllocated())
1085 releasePrefixedStringValue(value_.string_);
1086 break;
1087 case arrayValue:
1088 case objectValue:
1089 delete value_.map_;
1090 break;
1091 default:
1093 }
1094}
1095
1096void Value::dupMeta(const Value& other) {
1097 comments_ = other.comments_;
1098 start_ = other.start_;
1099 limit_ = other.limit_;
1100}
1101
1102// Access an object value by name, create a null member if it does not exist.
1103// @pre Type of '*this' is object or null.
1104// @param key is null-terminated.
1105Value& Value::resolveReference(const char* key) {
1107 type() == nullValue || type() == objectValue,
1108 "in Json::Value::resolveReference(): requires objectValue, but found "
1109 << valueTypeToString(type()));
1110 if (type() == nullValue)
1111 *this = Value(objectValue);
1112 CZString actualKey(key, static_cast<unsigned>(strlen(key)),
1113 CZString::noDuplication); // NOTE!
1114 auto it = value_.map_->lower_bound(actualKey);
1115 if (it != value_.map_->end() && (*it).first == actualKey)
1116 return (*it).second;
1117
1118 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1119 it = value_.map_->insert(it, defaultValue);
1120 Value& value = (*it).second;
1121 return value;
1122}
1123
1124// @param key is not null-terminated.
1125Value& Value::resolveReference(char const* key, char const* end) {
1126 JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
1127 "in Json::Value::resolveReference(key, end): requires "
1128 "objectValue, but found "
1129 << valueTypeToString(type()));
1130 if (type() == nullValue)
1131 *this = Value(objectValue);
1132 CZString actualKey(key, static_cast<unsigned>(end - key),
1133 CZString::duplicateOnCopy);
1134 auto it = value_.map_->lower_bound(actualKey);
1135 if (it != value_.map_->end() && (*it).first == actualKey)
1136 return (*it).second;
1137
1138 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1139 it = value_.map_->insert(it, defaultValue);
1140 Value& value = (*it).second;
1141 return value;
1142}
1143
1144Value Value::get(ArrayIndex index, const Value& defaultValue) const {
1145 const Value* value = &((*this)[index]);
1146 return value == &nullSingleton() ? defaultValue : *value;
1147}
1148
1149bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
1150
1151Value const* Value::find(char const* begin, char const* end) const {
1153 "in Json::Value::find(begin, end): requires "
1154 "objectValue or nullValue");
1155 if (type() == nullValue)
1156 return nullptr;
1157 CZString actualKey(begin, static_cast<unsigned>(end - begin),
1158 CZString::noDuplication);
1159 ObjectValues::const_iterator it = value_.map_->find(actualKey);
1160 if (it == value_.map_->end())
1161 return nullptr;
1162 return &(*it).second;
1163}
1164Value const* Value::find(const String& key) const {
1165 return find(key.data(), key.data() + key.length());
1166}
1167
1168Value const* Value::findNull(const String& key) const {
1170}
1171Value const* Value::findBool(const String& key) const {
1173}
1174Value const* Value::findInt(const String& key) const {
1176}
1177Value const* Value::findInt64(const String& key) const {
1179}
1180Value const* Value::findUInt(const String& key) const {
1182}
1183Value const* Value::findUInt64(const String& key) const {
1185}
1186Value const* Value::findIntegral(const String& key) const {
1188}
1189Value const* Value::findDouble(const String& key) const {
1191}
1192Value const* Value::findNumeric(const String& key) const {
1194}
1195Value const* Value::findString(const String& key) const {
1197}
1198Value const* Value::findArray(const String& key) const {
1200}
1201Value const* Value::findObject(const String& key) const {
1203}
1204
1205Value* Value::demand(char const* begin, char const* end) {
1207 "in Json::Value::demand(begin, end): requires "
1208 "objectValue or nullValue");
1209 return &resolveReference(begin, end);
1210}
1211const Value& Value::operator[](const char* key) const {
1212 Value const* found = find(key, key + strlen(key));
1213 if (!found)
1214 return nullSingleton();
1215 return *found;
1216}
1217Value const& Value::operator[](const String& key) const {
1218 Value const* found = find(key);
1219 if (!found)
1220 return nullSingleton();
1221 return *found;
1222}
1223
1224Value& Value::operator[](const char* key) {
1225 return resolveReference(key, key + strlen(key));
1226}
1227
1229 return resolveReference(key.data(), key.data() + key.length());
1230}
1231
1233 return resolveReference(key.c_str());
1234}
1235
1236Value& Value::append(const Value& value) { return append(Value(value)); }
1237
1240 "in Json::Value::append: requires arrayValue, but found "
1241 << valueTypeToString(type()));
1242 if (type() == nullValue) {
1243 *this = Value(arrayValue);
1244 }
1245 return this->value_.map_->emplace(size(), std::move(value)).first->second;
1246}
1247
1248bool Value::insert(ArrayIndex index, const Value& newValue) {
1249 return insert(index, Value(newValue));
1250}
1251
1252bool Value::insert(ArrayIndex index, Value&& newValue) {
1254 "in Json::Value::insert: requires arrayValue");
1255 ArrayIndex length = size();
1256 if (index > length) {
1257 return false;
1258 }
1259 for (ArrayIndex i = length; i > index; i--) {
1260 (*this)[i] = std::move((*this)[i - 1]);
1261 }
1262 (*this)[index] = std::move(newValue);
1263 return true;
1264}
1265
1266Value Value::get(char const* begin, char const* end,
1267 Value const& defaultValue) const {
1268 Value const* found = find(begin, end);
1269 return !found ? defaultValue : *found;
1270}
1271Value Value::get(char const* key, Value const& defaultValue) const {
1272 return get(key, key + strlen(key), defaultValue);
1273}
1274Value Value::get(String const& key, Value const& defaultValue) const {
1275 return get(key.data(), key.data() + key.length(), defaultValue);
1276}
1277
1278bool Value::removeMember(const char* begin, const char* end, Value* removed) {
1279 if (type() != objectValue) {
1280 return false;
1281 }
1282 CZString actualKey(begin, static_cast<unsigned>(end - begin),
1283 CZString::noDuplication);
1284 auto it = value_.map_->find(actualKey);
1285 if (it == value_.map_->end())
1286 return false;
1287 if (removed)
1288 *removed = std::move(it->second);
1289 value_.map_->erase(it);
1290 return true;
1291}
1292bool Value::removeMember(const char* key, Value* removed) {
1293 return removeMember(key, key + strlen(key), removed);
1294}
1295bool Value::removeMember(String const& key, Value* removed) {
1296 return removeMember(key.data(), key.data() + key.length(), removed);
1297}
1298
1299void Value::removeMember(const char* key) {
1301 type() == nullValue || type() == objectValue,
1302 "in Json::Value::removeMember(): requires objectValue, but found "
1303 << valueTypeToString(type()));
1304 if (type() == nullValue)
1305 return;
1306
1307 CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
1308 value_.map_->erase(actualKey);
1309}
1310void Value::removeMember(const String& key) { removeMember(key.c_str()); }
1311
1312bool Value::removeIndex(ArrayIndex index, Value* removed) {
1313 if (type() != arrayValue) {
1314 return false;
1315 }
1316 CZString key(index);
1317 auto it = value_.map_->find(key);
1318 if (it == value_.map_->end()) {
1319 return false;
1320 }
1321 if (removed)
1322 *removed = std::move(it->second);
1323 ArrayIndex oldSize = size();
1324 // shift left all items left, into the place of the "removed"
1325 for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
1326 CZString keey(i);
1327 (*value_.map_)[keey] = (*this)[i + 1];
1328 }
1329 // erase the last one ("leftover")
1330 CZString keyLast(oldSize - 1);
1331 auto itLast = value_.map_->find(keyLast);
1332 value_.map_->erase(itLast);
1333 return true;
1334}
1335
1336bool Value::isMember(char const* begin, char const* end) const {
1337 Value const* value = find(begin, end);
1338 return nullptr != value;
1339}
1340bool Value::isMember(char const* key) const {
1341 return isMember(key, key + strlen(key));
1342}
1343bool Value::isMember(String const& key) const {
1344 return isMember(key.data(), key.data() + key.length());
1345}
1346
1349 type() == nullValue || type() == objectValue,
1350 "in Json::Value::getMemberNames(), value must be objectValue");
1351 if (type() == nullValue)
1352 return Value::Members();
1354 members.reserve(value_.map_->size());
1355 ObjectValues::const_iterator it = value_.map_->begin();
1356 ObjectValues::const_iterator itEnd = value_.map_->end();
1357 for (; it != itEnd; ++it) {
1358 members.push_back(String((*it).first.data(), (*it).first.length()));
1359 }
1360 return members;
1361}
1362
1363static bool IsIntegral(double d) {
1364 double integral_part;
1365 return modf(d, &integral_part) == 0.0;
1366}
1367
1368bool Value::isNull() const { return type() == nullValue; }
1369
1370bool Value::isBool() const { return type() == booleanValue; }
1371
1372bool Value::isInt() const {
1373 switch (type()) {
1374 case intValue:
1375#if defined(JSON_HAS_INT64)
1376 return value_.int_ >= minInt && value_.int_ <= maxInt;
1377#else
1378 return true;
1379#endif
1380 case uintValue:
1381 return value_.uint_ <= UInt(maxInt);
1382 case realValue:
1383 return value_.real_ >= minInt && value_.real_ <= maxInt &&
1384 IsIntegral(value_.real_);
1385 default:
1386 break;
1387 }
1388 return false;
1389}
1390
1391bool Value::isUInt() const {
1392 switch (type()) {
1393 case intValue:
1394#if defined(JSON_HAS_INT64)
1395 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
1396#else
1397 return value_.int_ >= 0;
1398#endif
1399 case uintValue:
1400#if defined(JSON_HAS_INT64)
1401 return value_.uint_ <= maxUInt;
1402#else
1403 return true;
1404#endif
1405 case realValue:
1406 return value_.real_ >= 0 && value_.real_ <= maxUInt &&
1407 IsIntegral(value_.real_);
1408 default:
1409 break;
1410 }
1411 return false;
1412}
1413
1414bool Value::isInt64() const {
1415#if defined(JSON_HAS_INT64)
1416 switch (type()) {
1417 case intValue:
1418 return true;
1419 case uintValue:
1420 return value_.uint_ <= UInt64(maxInt64);
1421 case realValue:
1422 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
1423 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
1424 // require the value to be strictly less than the limit.
1425 // minInt64 is -2^63 which can be represented as a double, but since double
1426 // values in its proximity are also rounded to -2^63, we require the value
1427 // to be strictly greater than the limit to avoid returning 'true' for
1428 // values that are not in the range
1429 return value_.real_ > double(minInt64) && value_.real_ < double(maxInt64) &&
1430 IsIntegral(value_.real_);
1431 default:
1432 break;
1433 }
1434#endif // JSON_HAS_INT64
1435 return false;
1436}
1437
1438bool Value::isUInt64() const {
1439#if defined(JSON_HAS_INT64)
1440 switch (type()) {
1441 case intValue:
1442 return value_.int_ >= 0;
1443 case uintValue:
1444 return true;
1445 case realValue:
1446 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1447 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1448 // require the value to be strictly less than the limit.
1449 return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
1450 IsIntegral(value_.real_);
1451 default:
1452 break;
1453 }
1454#endif // JSON_HAS_INT64
1455 return false;
1456}
1457
1458bool Value::isIntegral() const {
1459 switch (type()) {
1460 case intValue:
1461 case uintValue:
1462 return true;
1463 case realValue:
1464#if defined(JSON_HAS_INT64)
1465 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1466 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1467 // require the value to be strictly less than the limit.
1468 // minInt64 is -2^63 which can be represented as a double, but since double
1469 // values in its proximity are also rounded to -2^63, we require the value
1470 // to be strictly greater than the limit to avoid returning 'true' for
1471 // values that are not in the range
1472 return value_.real_ > double(minInt64) &&
1473 value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
1474#else
1475 return value_.real_ >= minInt && value_.real_ <= maxUInt &&
1476 IsIntegral(value_.real_);
1477#endif // JSON_HAS_INT64
1478 default:
1479 break;
1480 }
1481 return false;
1482}
1483
1484bool Value::isDouble() const {
1485 return type() == intValue || type() == uintValue || type() == realValue;
1486}
1487
1488bool Value::isNumeric() const { return isDouble(); }
1489
1490bool Value::isString() const { return type() == stringValue; }
1491
1492bool Value::isArray() const { return type() == arrayValue; }
1493
1494bool Value::isObject() const { return type() == objectValue; }
1495
1496Value::Comments::Comments(const Comments& that)
1497 : ptr_{cloneUnique(that.ptr_)} {}
1498
1499Value::Comments::Comments(Comments&& that) noexcept
1500 : ptr_{std::move(that.ptr_)} {}
1501
1502Value::Comments& Value::Comments::operator=(const Comments& that) {
1503 ptr_ = cloneUnique(that.ptr_);
1504 return *this;
1505}
1506
1507Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
1508 ptr_ = std::move(that.ptr_);
1509 return *this;
1510}
1511
1512bool Value::Comments::has(CommentPlacement slot) const {
1513 return ptr_ && !(*ptr_)[slot].empty();
1514}
1515
1516String Value::Comments::get(CommentPlacement slot) const {
1517 if (!ptr_)
1518 return {};
1519 return (*ptr_)[slot];
1520}
1521
1522void Value::Comments::set(CommentPlacement slot, String comment) {
1524 return;
1525 if (!ptr_)
1526 ptr_ = std::unique_ptr<Array>(new Array());
1527 (*ptr_)[slot] = std::move(comment);
1528}
1529
1531 if (!comment.empty() && (comment.back() == '\n')) {
1532 // Always discard trailing newline, to aid indentation.
1533 comment.pop_back();
1534 }
1536 comment.empty() || comment[0] == '/',
1537 "in Json::Value::setComment(): Comments must start with /");
1538 comments_.set(placement, std::move(comment));
1539}
1540
1542 return comments_.has(placement);
1543}
1544
1546 return comments_.get(placement);
1547}
1548
1549void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
1550
1551void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
1552
1553ptrdiff_t Value::getOffsetStart() const { return start_; }
1554
1555ptrdiff_t Value::getOffsetLimit() const { return limit_; }
1556
1558 StreamWriterBuilder builder;
1559
1560 String out = this->hasComment(commentBefore) ? "\n" : "";
1561 out += Json::writeString(builder, *this);
1562 out += '\n';
1563
1564 return out;
1565}
1566
1568 switch (type()) {
1569 case arrayValue:
1570 case objectValue:
1571 if (value_.map_)
1572 return const_iterator(value_.map_->begin());
1573 break;
1574 default:
1575 break;
1576 }
1577 return {};
1578}
1579
1581 switch (type()) {
1582 case arrayValue:
1583 case objectValue:
1584 if (value_.map_)
1585 return const_iterator(value_.map_->end());
1586 break;
1587 default:
1588 break;
1589 }
1590 return {};
1591}
1592
1594 switch (type()) {
1595 case arrayValue:
1596 case objectValue:
1597 if (value_.map_)
1598 return iterator(value_.map_->begin());
1599 break;
1600 default:
1601 break;
1602 }
1603 return iterator();
1604}
1605
1607 switch (type()) {
1608 case arrayValue:
1609 case objectValue:
1610 if (value_.map_)
1611 return iterator(value_.map_->end());
1612 break;
1613 default:
1614 break;
1615 }
1616 return iterator();
1617}
1618
1619// class PathArgument
1620// //////////////////////////////////////////////////////////////////
1621
1622PathArgument::PathArgument() = default;
1623
1625 : index_(index), kind_(kindIndex) {}
1626
1627PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
1628
1629PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
1630
1631// class Path
1632// //////////////////////////////////////////////////////////////////
1633
1634Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
1635 const PathArgument& a3, const PathArgument& a4,
1636 const PathArgument& a5) {
1637 InArgs in;
1638 in.reserve(5);
1639 in.push_back(&a1);
1640 in.push_back(&a2);
1641 in.push_back(&a3);
1642 in.push_back(&a4);
1643 in.push_back(&a5);
1644 makePath(path, in);
1645}
1646
1647void Path::makePath(const String& path, const InArgs& in) {
1648 const char* current = path.c_str();
1649 const char* end = current + path.length();
1650 auto itInArg = in.begin();
1651 while (current != end) {
1652 if (*current == '[') {
1653 ++current;
1654 if (*current == '%')
1655 addPathInArg(path, in, itInArg, PathArgument::kindIndex);
1656 else {
1657 ArrayIndex index = 0;
1658 for (; current != end && *current >= '0' && *current <= '9'; ++current)
1659 index = index * 10 + ArrayIndex(*current - '0');
1660 args_.push_back(index);
1661 }
1662 if (current == end || *++current != ']')
1663 invalidPath(path, int(current - path.c_str()));
1664 } else if (*current == '%') {
1665 addPathInArg(path, in, itInArg, PathArgument::kindKey);
1666 ++current;
1667 } else if (*current == '.' || *current == ']') {
1668 ++current;
1669 } else {
1670 const char* beginName = current;
1671 while (current != end && !strchr("[.", *current))
1672 ++current;
1673 args_.push_back(String(beginName, current));
1674 }
1675 }
1676}
1677
1678void Path::addPathInArg(const String& /*path*/, const InArgs& in,
1679 InArgs::const_iterator& itInArg,
1680 PathArgument::Kind kind) {
1681 if (itInArg == in.end()) {
1682 // Error: missing argument %d
1683 } else if ((*itInArg)->kind_ != kind) {
1684 // Error: bad argument type
1685 } else {
1686 args_.push_back(**itInArg++);
1687 }
1688}
1689
1690void Path::invalidPath(const String& /*path*/, int /*location*/) {
1691 // Error: invalid path.
1692}
1693
1694const Value& Path::resolve(const Value& root) const {
1695 const Value* node = &root;
1696 for (const auto& arg : args_) {
1697 if (arg.kind_ == PathArgument::kindIndex) {
1698 if (!node->isArray() || !node->isValidIndex(arg.index_)) {
1699 // Error: unable to resolve path (array value expected at position... )
1700 return Value::nullSingleton();
1701 }
1702 node = &((*node)[arg.index_]);
1703 } else if (arg.kind_ == PathArgument::kindKey) {
1704 if (!node->isObject()) {
1705 // Error: unable to resolve path (object value expected at position...)
1706 return Value::nullSingleton();
1707 }
1708 node = &((*node)[arg.key_]);
1709 if (node == &Value::nullSingleton()) {
1710 // Error: unable to resolve path (object has no member named '' at
1711 // position...)
1712 return Value::nullSingleton();
1713 }
1714 }
1715 }
1716 return *node;
1717}
1718
1719Value Path::resolve(const Value& root, const Value& defaultValue) const {
1720 const Value* node = &root;
1721 for (const auto& arg : args_) {
1722 if (arg.kind_ == PathArgument::kindIndex) {
1723 if (!node->isArray() || !node->isValidIndex(arg.index_))
1724 return defaultValue;
1725 node = &((*node)[arg.index_]);
1726 } else if (arg.kind_ == PathArgument::kindKey) {
1727 if (!node->isObject())
1728 return defaultValue;
1729 node = &((*node)[arg.key_]);
1730 if (node == &Value::nullSingleton())
1731 return defaultValue;
1732 }
1733 }
1734 return *node;
1735}
1736
1737Value& Path::make(Value& root) const {
1738 Value* node = &root;
1739 for (const auto& arg : args_) {
1740 if (arg.kind_ == PathArgument::kindIndex) {
1741 if (!node->isArray()) {
1742 // Error: node is not an array at position ...
1743 }
1744 node = &((*node)[arg.index_]);
1745 } else if (arg.kind_ == PathArgument::kindKey) {
1746 if (!node->isObject()) {
1747 // Error: node is not an object at position...
1748 }
1749 node = &((*node)[arg.key_]);
1750 }
1751 }
1752 return *node;
1753}
1754
1755const char* version() { return JSONCPP_VERSION_STRING; }
1756
1757} // 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)
static bool InRange(double d, T min, U max)
#define JSONCPP_VERSION_STRING
Definition version.h:13