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