JsonCpp project page Classes Namespace JsonCpp home page

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