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