JsonCpp project page Classes Namespace JsonCpp home page

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