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 <math.h>
12 #include <sstream>
13 #include <utility>
14 #include <cstring>
15 #include <cassert>
16 #ifdef JSON_USE_CPPTL
17 #include <cpptl/conststring.h>
18 #endif
19 #include <cstddef> // size_t
20 #include <algorithm> // min()
21
22 #define JSON_ASSERT_UNREACHABLE assert(false)
23
24 namespace Json {
25
26 // This is a walkaround to avoid the static initialization of Value::null.
27 // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
28 // 8 (instead of 4) as a bit of future-proofing.
29 #if defined(__ARMEL__)
30 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
31 #else
32 #define ALIGNAS(byte_alignment)
33 #endif
34 //static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
35 //const unsigned char& kNullRef = kNull[0];
36 //const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
37 //const Value& Value::nullRef = null;
38
39 // static
nullSingleton()40 Value const& Value::nullSingleton()
41 {
42 static Value const nullStatic;
43 return nullStatic;
44 }
45
46 // for backwards compatibility, we'll leave these global references around, but DO NOT
47 // use them in JSONCPP library code any more!
48 Value const& Value::null = Value::nullSingleton();
49 Value const& Value::nullRef = Value::nullSingleton();
50
51 const Int Value::minInt = Int(~(UInt(-1) / 2));
52 const Int Value::maxInt = Int(UInt(-1) / 2);
53 const UInt Value::maxUInt = UInt(-1);
54 #if defined(JSON_HAS_INT64)
55 const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
56 const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
57 const UInt64 Value::maxUInt64 = UInt64(-1);
58 // The constant is hard-coded because some compiler have trouble
59 // converting Value::maxUInt64 to a double correctly (AIX/xlC).
60 // Assumes that UInt64 is a 64 bits integer.
61 static const double maxUInt64AsDouble = 18446744073709551615.0;
62 #endif // defined(JSON_HAS_INT64)
63 const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
64 const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
65 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
66
67 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
68 template <typename T, typename U>
InRange(double d,T min,U max)69 static inline bool InRange(double d, T min, U max) {
70 // The casts can lose precision, but we are looking only for
71 // an approximate range. Might fail on edge cases though. ~cdunn
72 //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
73 return d >= min && d <= max;
74 }
75 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
integerToDouble(Json::UInt64 value)76 static inline double integerToDouble(Json::UInt64 value) {
77 return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
78 }
79
integerToDouble(T value)80 template <typename T> static inline double integerToDouble(T value) {
81 return static_cast<double>(value);
82 }
83
84 template <typename T, typename U>
InRange(double d,T min,U max)85 static inline bool InRange(double d, T min, U max) {
86 return d >= integerToDouble(min) && d <= integerToDouble(max);
87 }
88 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
89
90 /** Duplicates the specified string value.
91 * @param value Pointer to the string to duplicate. Must be zero-terminated if
92 * length is "unknown".
93 * @param length Length of the value. if equals to unknown, then it will be
94 * computed using strlen(value).
95 * @return Pointer on the duplicate instance of string.
96 */
duplicateStringValue(const char * value,size_t length)97 static inline char* duplicateStringValue(const char* value,
98 size_t length)
99 {
100 // Avoid an integer overflow in the call to malloc below by limiting length
101 // to a sane value.
102 if (length >= static_cast<size_t>(Value::maxInt))
103 length = Value::maxInt - 1;
104
105 char* newString = static_cast<char*>(malloc(length + 1));
106 if (newString == NULL) {
107 throwRuntimeError(
108 "in Json::Value::duplicateStringValue(): "
109 "Failed to allocate string value buffer");
110 }
111 memcpy(newString, value, length);
112 newString[length] = 0;
113 return newString;
114 }
115
116 /* Record the length as a prefix.
117 */
duplicateAndPrefixStringValue(const char * value,unsigned int length)118 static inline char* duplicateAndPrefixStringValue(
119 const char* value,
120 unsigned int length)
121 {
122 // Avoid an integer overflow in the call to malloc below by limiting length
123 // to a sane value.
124 JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
125 "in Json::Value::duplicateAndPrefixStringValue(): "
126 "length too big for prefixing");
127 unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
128 char* newString = static_cast<char*>(malloc(actualLength));
129 if (newString == 0) {
130 throwRuntimeError(
131 "in Json::Value::duplicateAndPrefixStringValue(): "
132 "Failed to allocate string value buffer");
133 }
134 *reinterpret_cast<unsigned*>(newString) = length;
135 memcpy(newString + sizeof(unsigned), value, length);
136 newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
137 return newString;
138 }
decodePrefixedString(bool isPrefixed,char const * prefixed,unsigned * length,char const ** value)139 inline static void decodePrefixedString(
140 bool isPrefixed, char const* prefixed,
141 unsigned* length, char const** value)
142 {
143 if (!isPrefixed) {
144 *length = static_cast<unsigned>(strlen(prefixed));
145 *value = prefixed;
146 } else {
147 *length = *reinterpret_cast<unsigned const*>(prefixed);
148 *value = prefixed + sizeof(unsigned);
149 }
150 }
151 /** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
152 */
153 #if JSONCPP_USING_SECURE_MEMORY
releasePrefixedStringValue(char * value)154 static inline void releasePrefixedStringValue(char* value) {
155 unsigned length = 0;
156 char const* valueDecoded;
157 decodePrefixedString(true, value, &length, &valueDecoded);
158 size_t const size = sizeof(unsigned) + length + 1U;
159 memset(value, 0, size);
160 free(value);
161 }
releaseStringValue(char * value,unsigned length)162 static inline void releaseStringValue(char* value, unsigned length) {
163 // length==0 => we allocated the strings memory
164 size_t size = (length==0) ? strlen(value) : length;
165 memset(value, 0, size);
166 free(value);
167 }
168 #else // !JSONCPP_USING_SECURE_MEMORY
releasePrefixedStringValue(char * value)169 static inline void releasePrefixedStringValue(char* value) {
170 free(value);
171 }
releaseStringValue(char * value,unsigned)172 static inline void releaseStringValue(char* value, unsigned) {
173 free(value);
174 }
175 #endif // JSONCPP_USING_SECURE_MEMORY
176
177 } // namespace Json
178
179 // //////////////////////////////////////////////////////////////////
180 // //////////////////////////////////////////////////////////////////
181 // //////////////////////////////////////////////////////////////////
182 // ValueInternals...
183 // //////////////////////////////////////////////////////////////////
184 // //////////////////////////////////////////////////////////////////
185 // //////////////////////////////////////////////////////////////////
186 #if !defined(JSON_IS_AMALGAMATION)
187
188 #include "json_valueiterator.inl"
189 #endif // if !defined(JSON_IS_AMALGAMATION)
190
191 namespace Json {
192
Exception(JSONCPP_STRING const & msg)193 Exception::Exception(JSONCPP_STRING const& msg)
194 : msg_(msg)
195 {}
~Exception()196 Exception::~Exception() JSONCPP_NOEXCEPT
197 {}
what() const198 char const* Exception::what() const JSONCPP_NOEXCEPT
199 {
200 return msg_.c_str();
201 }
RuntimeError(JSONCPP_STRING const & msg)202 RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
203 : Exception(msg)
204 {}
LogicError(JSONCPP_STRING const & msg)205 LogicError::LogicError(JSONCPP_STRING const& msg)
206 : Exception(msg)
207 {}
throwRuntimeError(JSONCPP_STRING const & msg)208 JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
209 {
210 throw RuntimeError(msg);
211 }
throwLogicError(JSONCPP_STRING const & msg)212 JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
213 {
214 throw LogicError(msg);
215 }
216
217 // //////////////////////////////////////////////////////////////////
218 // //////////////////////////////////////////////////////////////////
219 // //////////////////////////////////////////////////////////////////
220 // class Value::CommentInfo
221 // //////////////////////////////////////////////////////////////////
222 // //////////////////////////////////////////////////////////////////
223 // //////////////////////////////////////////////////////////////////
224
CommentInfo()225 Value::CommentInfo::CommentInfo() : comment_(0)
226 {}
227
~CommentInfo()228 Value::CommentInfo::~CommentInfo() {
229 if (comment_)
230 releaseStringValue(comment_, 0u);
231 }
232
setComment(const char * text,size_t len)233 void Value::CommentInfo::setComment(const char* text, size_t len) {
234 if (comment_) {
235 releaseStringValue(comment_, 0u);
236 comment_ = 0;
237 }
238 JSON_ASSERT(text != 0);
239 JSON_ASSERT_MESSAGE(
240 text[0] == '\0' || text[0] == '/',
241 "in Json::Value::setComment(): Comments must start with /");
242 // It seems that /**/ style comments are acceptable as well.
243 comment_ = duplicateStringValue(text, len);
244 }
245
246 // //////////////////////////////////////////////////////////////////
247 // //////////////////////////////////////////////////////////////////
248 // //////////////////////////////////////////////////////////////////
249 // class Value::CZString
250 // //////////////////////////////////////////////////////////////////
251 // //////////////////////////////////////////////////////////////////
252 // //////////////////////////////////////////////////////////////////
253
254 // Notes: policy_ indicates if the string was allocated when
255 // a string is stored.
256
CZString(ArrayIndex aindex)257 Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
258
CZString(char const * str,unsigned ulength,DuplicationPolicy allocate)259 Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
260 : cstr_(str) {
261 // allocate != duplicate
262 storage_.policy_ = allocate & 0x3;
263 storage_.length_ = ulength & 0x3FFFFFFF;
264 }
265
CZString(const CZString & other)266 Value::CZString::CZString(const CZString& other) {
267 cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
268 ? duplicateStringValue(other.cstr_, other.storage_.length_)
269 : other.cstr_);
270 storage_.policy_ = static_cast<unsigned>(other.cstr_
271 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
272 ? noDuplication : duplicate)
273 : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
274 storage_.length_ = other.storage_.length_;
275 }
276
277 #if JSON_HAS_RVALUE_REFERENCES
CZString(CZString && other)278 Value::CZString::CZString(CZString&& other)
279 : cstr_(other.cstr_), index_(other.index_) {
280 other.cstr_ = nullptr;
281 }
282 #endif
283
~CZString()284 Value::CZString::~CZString() {
285 if (cstr_ && storage_.policy_ == duplicate) {
286 releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
287 }
288 }
289
swap(CZString & other)290 void Value::CZString::swap(CZString& other) {
291 std::swap(cstr_, other.cstr_);
292 std::swap(index_, other.index_);
293 }
294
operator =(const CZString & other)295 Value::CZString& Value::CZString::operator=(const CZString& other) {
296 cstr_ = other.cstr_;
297 index_ = other.index_;
298 return *this;
299 }
300
301 #if JSON_HAS_RVALUE_REFERENCES
operator =(CZString && other)302 Value::CZString& Value::CZString::operator=(CZString&& other) {
303 cstr_ = other.cstr_;
304 index_ = other.index_;
305 other.cstr_ = nullptr;
306 return *this;
307 }
308 #endif
309
operator <(const CZString & other) const310 bool Value::CZString::operator<(const CZString& other) const {
311 if (!cstr_) return index_ < other.index_;
312 //return strcmp(cstr_, other.cstr_) < 0;
313 // Assume both are strings.
314 unsigned this_len = this->storage_.length_;
315 unsigned other_len = other.storage_.length_;
316 unsigned min_len = std::min<unsigned>(this_len, other_len);
317 JSON_ASSERT(this->cstr_ && other.cstr_);
318 int comp = memcmp(this->cstr_, other.cstr_, min_len);
319 if (comp < 0) return true;
320 if (comp > 0) return false;
321 return (this_len < other_len);
322 }
323
operator ==(const CZString & other) const324 bool Value::CZString::operator==(const CZString& other) const {
325 if (!cstr_) return index_ == other.index_;
326 //return strcmp(cstr_, other.cstr_) == 0;
327 // Assume both are strings.
328 unsigned this_len = this->storage_.length_;
329 unsigned other_len = other.storage_.length_;
330 if (this_len != other_len) return false;
331 JSON_ASSERT(this->cstr_ && other.cstr_);
332 int comp = memcmp(this->cstr_, other.cstr_, this_len);
333 return comp == 0;
334 }
335
index() const336 ArrayIndex Value::CZString::index() const { return index_; }
337
338 //const char* Value::CZString::c_str() const { return cstr_; }
data() const339 const char* Value::CZString::data() const { return cstr_; }
length() const340 unsigned Value::CZString::length() const { return storage_.length_; }
isStaticString() const341 bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
342
343 // //////////////////////////////////////////////////////////////////
344 // //////////////////////////////////////////////////////////////////
345 // //////////////////////////////////////////////////////////////////
346 // class Value::Value
347 // //////////////////////////////////////////////////////////////////
348 // //////////////////////////////////////////////////////////////////
349 // //////////////////////////////////////////////////////////////////
350
351 /*! \internal Default constructor initialization must be equivalent to:
352 * memset( this, 0, sizeof(Value) )
353 * This optimization is used in ValueInternalMap fast allocator.
354 */
Value(ValueType vtype)355 Value::Value(ValueType vtype) {
356 static char const emptyString[] = "";
357 initBasic(vtype);
358 switch (vtype) {
359 case nullValue:
360 break;
361 case intValue:
362 case uintValue:
363 value_.int_ = 0;
364 break;
365 case realValue:
366 value_.real_ = 0.0;
367 break;
368 case stringValue:
369 // allocated_ == false, so this is safe.
370 value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
371 break;
372 case arrayValue:
373 case objectValue:
374 value_.map_ = new ObjectValues();
375 break;
376 case booleanValue:
377 value_.bool_ = false;
378 break;
379 default:
380 JSON_ASSERT_UNREACHABLE;
381 }
382 }
383
Value(Int value)384 Value::Value(Int value) {
385 initBasic(intValue);
386 value_.int_ = value;
387 }
388
Value(UInt value)389 Value::Value(UInt value) {
390 initBasic(uintValue);
391 value_.uint_ = value;
392 }
393 #if defined(JSON_HAS_INT64)
Value(Int64 value)394 Value::Value(Int64 value) {
395 initBasic(intValue);
396 value_.int_ = value;
397 }
Value(UInt64 value)398 Value::Value(UInt64 value) {
399 initBasic(uintValue);
400 value_.uint_ = value;
401 }
402 #endif // defined(JSON_HAS_INT64)
403
Value(double value)404 Value::Value(double value) {
405 initBasic(realValue);
406 value_.real_ = value;
407 }
408
Value(const char * value)409 Value::Value(const char* value) {
410 initBasic(stringValue, true);
411 JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
412 value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
413 }
414
Value(const char * beginValue,const char * endValue)415 Value::Value(const char* beginValue, const char* endValue) {
416 initBasic(stringValue, true);
417 value_.string_ =
418 duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
419 }
420
Value(const JSONCPP_STRING & value)421 Value::Value(const JSONCPP_STRING& value) {
422 initBasic(stringValue, true);
423 value_.string_ =
424 duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
425 }
426
Value(const StaticString & value)427 Value::Value(const StaticString& value) {
428 initBasic(stringValue);
429 value_.string_ = const_cast<char*>(value.c_str());
430 }
431
432 #ifdef JSON_USE_CPPTL
Value(const CppTL::ConstString & value)433 Value::Value(const CppTL::ConstString& value) {
434 initBasic(stringValue, true);
435 value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
436 }
437 #endif
438
Value(bool value)439 Value::Value(bool value) {
440 initBasic(booleanValue);
441 value_.bool_ = value;
442 }
443
Value(Value const & other)444 Value::Value(Value const& other)
445 : type_(other.type_), allocated_(false)
446 ,
447 comments_(0), start_(other.start_), limit_(other.limit_)
448 {
449 switch (type_) {
450 case nullValue:
451 case intValue:
452 case uintValue:
453 case realValue:
454 case booleanValue:
455 value_ = other.value_;
456 break;
457 case stringValue:
458 if (other.value_.string_ && other.allocated_) {
459 unsigned len;
460 char const* str;
461 decodePrefixedString(other.allocated_, other.value_.string_,
462 &len, &str);
463 value_.string_ = duplicateAndPrefixStringValue(str, len);
464 allocated_ = true;
465 } else {
466 value_.string_ = other.value_.string_;
467 allocated_ = false;
468 }
469 break;
470 case arrayValue:
471 case objectValue:
472 value_.map_ = new ObjectValues(*other.value_.map_);
473 break;
474 default:
475 JSON_ASSERT_UNREACHABLE;
476 }
477 if (other.comments_) {
478 comments_ = new CommentInfo[numberOfCommentPlacement];
479 for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
480 const CommentInfo& otherComment = other.comments_[comment];
481 if (otherComment.comment_)
482 comments_[comment].setComment(
483 otherComment.comment_, strlen(otherComment.comment_));
484 }
485 }
486 }
487
488 #if JSON_HAS_RVALUE_REFERENCES
489 // Move constructor
Value(Value && other)490 Value::Value(Value&& other) {
491 initBasic(nullValue);
492 swap(other);
493 }
494 #endif
495
~Value()496 Value::~Value() {
497 switch (type_) {
498 case nullValue:
499 case intValue:
500 case uintValue:
501 case realValue:
502 case booleanValue:
503 break;
504 case stringValue:
505 if (allocated_)
506 releasePrefixedStringValue(value_.string_);
507 break;
508 case arrayValue:
509 case objectValue:
510 delete value_.map_;
511 break;
512 default:
513 JSON_ASSERT_UNREACHABLE;
514 }
515
516 delete[] comments_;
517
518 value_.uint_ = 0;
519 }
520
operator =(Value other)521 Value& Value::operator=(Value other) {
522 swap(other);
523 return *this;
524 }
525
swapPayload(Value & other)526 void Value::swapPayload(Value& other) {
527 ValueType temp = type_;
528 type_ = other.type_;
529 other.type_ = temp;
530 std::swap(value_, other.value_);
531 int temp2 = allocated_;
532 allocated_ = other.allocated_;
533 other.allocated_ = temp2 & 0x1;
534 }
535
copyPayload(const Value & other)536 void Value::copyPayload(const Value& other) {
537 type_ = other.type_;
538 value_ = other.value_;
539 allocated_ = other.allocated_;
540 }
541
swap(Value & other)542 void Value::swap(Value& other) {
543 swapPayload(other);
544 std::swap(comments_, other.comments_);
545 std::swap(start_, other.start_);
546 std::swap(limit_, other.limit_);
547 }
548
copy(const Value & other)549 void Value::copy(const Value& other) {
550 copyPayload(other);
551 comments_ = other.comments_;
552 start_ = other.start_;
553 limit_ = other.limit_;
554 }
555
type() const556 ValueType Value::type() const { return type_; }
557
compare(const Value & other) const558 int Value::compare(const Value& other) const {
559 if (*this < other)
560 return -1;
561 if (*this > other)
562 return 1;
563 return 0;
564 }
565
operator <(const Value & other) const566 bool Value::operator<(const Value& other) const {
567 int typeDelta = type_ - other.type_;
568 if (typeDelta)
569 return typeDelta < 0 ? true : false;
570 switch (type_) {
571 case nullValue:
572 return false;
573 case intValue:
574 return value_.int_ < other.value_.int_;
575 case uintValue:
576 return value_.uint_ < other.value_.uint_;
577 case realValue:
578 return value_.real_ < other.value_.real_;
579 case booleanValue:
580 return value_.bool_ < other.value_.bool_;
581 case stringValue:
582 {
583 if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
584 if (other.value_.string_) return true;
585 else return false;
586 }
587 unsigned this_len;
588 unsigned other_len;
589 char const* this_str;
590 char const* other_str;
591 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
592 decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
593 unsigned min_len = std::min<unsigned>(this_len, other_len);
594 JSON_ASSERT(this_str && other_str);
595 int comp = memcmp(this_str, other_str, min_len);
596 if (comp < 0) return true;
597 if (comp > 0) return false;
598 return (this_len < other_len);
599 }
600 case arrayValue:
601 case objectValue: {
602 int delta = int(value_.map_->size() - other.value_.map_->size());
603 if (delta)
604 return delta < 0;
605 return (*value_.map_) < (*other.value_.map_);
606 }
607 default:
608 JSON_ASSERT_UNREACHABLE;
609 }
610 return false; // unreachable
611 }
612
operator <=(const Value & other) const613 bool Value::operator<=(const Value& other) const { return !(other < *this); }
614
operator >=(const Value & other) const615 bool Value::operator>=(const Value& other) const { return !(*this < other); }
616
operator >(const Value & other) const617 bool Value::operator>(const Value& other) const { return other < *this; }
618
operator ==(const Value & other) const619 bool Value::operator==(const Value& other) const {
620 // if ( type_ != other.type_ )
621 // GCC 2.95.3 says:
622 // attempt to take address of bit-field structure member `Json::Value::type_'
623 // Beats me, but a temp solves the problem.
624 int temp = other.type_;
625 if (type_ != temp)
626 return false;
627 switch (type_) {
628 case nullValue:
629 return true;
630 case intValue:
631 return value_.int_ == other.value_.int_;
632 case uintValue:
633 return value_.uint_ == other.value_.uint_;
634 case realValue:
635 return value_.real_ == other.value_.real_;
636 case booleanValue:
637 return value_.bool_ == other.value_.bool_;
638 case stringValue:
639 {
640 if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
641 return (value_.string_ == other.value_.string_);
642 }
643 unsigned this_len;
644 unsigned other_len;
645 char const* this_str;
646 char const* other_str;
647 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
648 decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
649 if (this_len != other_len) return false;
650 JSON_ASSERT(this_str && other_str);
651 int comp = memcmp(this_str, other_str, this_len);
652 return comp == 0;
653 }
654 case arrayValue:
655 case objectValue:
656 return value_.map_->size() == other.value_.map_->size() &&
657 (*value_.map_) == (*other.value_.map_);
658 default:
659 JSON_ASSERT_UNREACHABLE;
660 }
661 return false; // unreachable
662 }
663
operator !=(const Value & other) const664 bool Value::operator!=(const Value& other) const { return !(*this == other); }
665
asCString() const666 const char* Value::asCString() const {
667 JSON_ASSERT_MESSAGE(type_ == stringValue,
668 "in Json::Value::asCString(): requires stringValue");
669 if (value_.string_ == 0) return 0;
670 unsigned this_len;
671 char const* this_str;
672 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
673 return this_str;
674 }
675
676 #if JSONCPP_USING_SECURE_MEMORY
getCStringLength() const677 unsigned Value::getCStringLength() const {
678 JSON_ASSERT_MESSAGE(type_ == stringValue,
679 "in Json::Value::asCString(): requires stringValue");
680 if (value_.string_ == 0) return 0;
681 unsigned this_len;
682 char const* this_str;
683 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
684 return this_len;
685 }
686 #endif
687
getString(char const ** str,char const ** cend) const688 bool Value::getString(char const** str, char const** cend) const {
689 if (type_ != stringValue) return false;
690 if (value_.string_ == 0) return false;
691 unsigned length;
692 decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
693 *cend = *str + length;
694 return true;
695 }
696
asString() const697 JSONCPP_STRING Value::asString() const {
698 switch (type_) {
699 case nullValue:
700 return "";
701 case stringValue:
702 {
703 if (value_.string_ == 0) return "";
704 unsigned this_len;
705 char const* this_str;
706 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
707 return JSONCPP_STRING(this_str, this_len);
708 }
709 case booleanValue:
710 return value_.bool_ ? "true" : "false";
711 case intValue:
712 return valueToString(value_.int_);
713 case uintValue:
714 return valueToString(value_.uint_);
715 case realValue:
716 return valueToString(value_.real_);
717 default:
718 JSON_FAIL_MESSAGE("Type is not convertible to string");
719 }
720 }
721
722 #ifdef JSON_USE_CPPTL
asConstString() const723 CppTL::ConstString Value::asConstString() const {
724 unsigned len;
725 char const* str;
726 decodePrefixedString(allocated_, value_.string_,
727 &len, &str);
728 return CppTL::ConstString(str, len);
729 }
730 #endif
731
asInt() const732 Value::Int Value::asInt() const {
733 switch (type_) {
734 case intValue:
735 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
736 return Int(value_.int_);
737 case uintValue:
738 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
739 return Int(value_.uint_);
740 case realValue:
741 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
742 "double out of Int range");
743 return Int(value_.real_);
744 case nullValue:
745 return 0;
746 case booleanValue:
747 return value_.bool_ ? 1 : 0;
748 default:
749 break;
750 }
751 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
752 }
753
asUInt() const754 Value::UInt Value::asUInt() const {
755 switch (type_) {
756 case intValue:
757 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
758 return UInt(value_.int_);
759 case uintValue:
760 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
761 return UInt(value_.uint_);
762 case realValue:
763 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
764 "double out of UInt range");
765 return UInt(value_.real_);
766 case nullValue:
767 return 0;
768 case booleanValue:
769 return value_.bool_ ? 1 : 0;
770 default:
771 break;
772 }
773 JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
774 }
775
776 #if defined(JSON_HAS_INT64)
777
asInt64() const778 Value::Int64 Value::asInt64() const {
779 switch (type_) {
780 case intValue:
781 return Int64(value_.int_);
782 case uintValue:
783 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
784 return Int64(value_.uint_);
785 case realValue:
786 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
787 "double out of Int64 range");
788 return Int64(value_.real_);
789 case nullValue:
790 return 0;
791 case booleanValue:
792 return value_.bool_ ? 1 : 0;
793 default:
794 break;
795 }
796 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
797 }
798
asUInt64() const799 Value::UInt64 Value::asUInt64() const {
800 switch (type_) {
801 case intValue:
802 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
803 return UInt64(value_.int_);
804 case uintValue:
805 return UInt64(value_.uint_);
806 case realValue:
807 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
808 "double out of UInt64 range");
809 return UInt64(value_.real_);
810 case nullValue:
811 return 0;
812 case booleanValue:
813 return value_.bool_ ? 1 : 0;
814 default:
815 break;
816 }
817 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
818 }
819 #endif // if defined(JSON_HAS_INT64)
820
asLargestInt() const821 LargestInt Value::asLargestInt() const {
822 #if defined(JSON_NO_INT64)
823 return asInt();
824 #else
825 return asInt64();
826 #endif
827 }
828
asLargestUInt() const829 LargestUInt Value::asLargestUInt() const {
830 #if defined(JSON_NO_INT64)
831 return asUInt();
832 #else
833 return asUInt64();
834 #endif
835 }
836
asDouble() const837 double Value::asDouble() const {
838 switch (type_) {
839 case intValue:
840 return static_cast<double>(value_.int_);
841 case uintValue:
842 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
843 return static_cast<double>(value_.uint_);
844 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
845 return integerToDouble(value_.uint_);
846 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
847 case realValue:
848 return value_.real_;
849 case nullValue:
850 return 0.0;
851 case booleanValue:
852 return value_.bool_ ? 1.0 : 0.0;
853 default:
854 break;
855 }
856 JSON_FAIL_MESSAGE("Value is not convertible to double.");
857 }
858
asFloat() const859 float Value::asFloat() const {
860 switch (type_) {
861 case intValue:
862 return static_cast<float>(value_.int_);
863 case uintValue:
864 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
865 return static_cast<float>(value_.uint_);
866 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
867 // This can fail (silently?) if the value is bigger than MAX_FLOAT.
868 return static_cast<float>(integerToDouble(value_.uint_));
869 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
870 case realValue:
871 return static_cast<float>(value_.real_);
872 case nullValue:
873 return 0.0;
874 case booleanValue:
875 return value_.bool_ ? 1.0f : 0.0f;
876 default:
877 break;
878 }
879 JSON_FAIL_MESSAGE("Value is not convertible to float.");
880 }
881
asBool() const882 bool Value::asBool() const {
883 switch (type_) {
884 case booleanValue:
885 return value_.bool_;
886 case nullValue:
887 return false;
888 case intValue:
889 return value_.int_ ? true : false;
890 case uintValue:
891 return value_.uint_ ? true : false;
892 case realValue:
893 // This is kind of strange. Not recommended.
894 return (value_.real_ != 0.0) ? true : false;
895 default:
896 break;
897 }
898 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
899 }
900
isConvertibleTo(ValueType other) const901 bool Value::isConvertibleTo(ValueType other) const {
902 switch (other) {
903 case nullValue:
904 return (isNumeric() && asDouble() == 0.0) ||
905 (type_ == booleanValue && value_.bool_ == false) ||
906 (type_ == stringValue && asString().empty()) ||
907 (type_ == arrayValue && value_.map_->size() == 0) ||
908 (type_ == objectValue && value_.map_->size() == 0) ||
909 type_ == nullValue;
910 case intValue:
911 return isInt() ||
912 (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
913 type_ == booleanValue || type_ == nullValue;
914 case uintValue:
915 return isUInt() ||
916 (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
917 type_ == booleanValue || type_ == nullValue;
918 case realValue:
919 return isNumeric() || type_ == booleanValue || type_ == nullValue;
920 case booleanValue:
921 return isNumeric() || type_ == booleanValue || type_ == nullValue;
922 case stringValue:
923 return isNumeric() || type_ == booleanValue || type_ == stringValue ||
924 type_ == nullValue;
925 case arrayValue:
926 return type_ == arrayValue || type_ == nullValue;
927 case objectValue:
928 return type_ == objectValue || type_ == nullValue;
929 }
930 JSON_ASSERT_UNREACHABLE;
931 return false;
932 }
933
934 /// Number of values in array or object
size() const935 ArrayIndex Value::size() const {
936 switch (type_) {
937 case nullValue:
938 case intValue:
939 case uintValue:
940 case realValue:
941 case booleanValue:
942 case stringValue:
943 return 0;
944 case arrayValue: // size of the array is highest index + 1
945 if (!value_.map_->empty()) {
946 ObjectValues::const_iterator itLast = value_.map_->end();
947 --itLast;
948 return (*itLast).first.index() + 1;
949 }
950 return 0;
951 case objectValue:
952 return ArrayIndex(value_.map_->size());
953 }
954 JSON_ASSERT_UNREACHABLE;
955 return 0; // unreachable;
956 }
957
empty() const958 bool Value::empty() const {
959 if (isNull() || isArray() || isObject())
960 return size() == 0u;
961 else
962 return false;
963 }
964
operator bool() const965 Value::operator bool() const { return ! isNull(); }
966
clear()967 void Value::clear() {
968 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
969 type_ == objectValue,
970 "in Json::Value::clear(): requires complex value");
971 start_ = 0;
972 limit_ = 0;
973 switch (type_) {
974 case arrayValue:
975 case objectValue:
976 value_.map_->clear();
977 break;
978 default:
979 break;
980 }
981 }
982
resize(ArrayIndex newSize)983 void Value::resize(ArrayIndex newSize) {
984 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
985 "in Json::Value::resize(): requires arrayValue");
986 if (type_ == nullValue)
987 *this = Value(arrayValue);
988 ArrayIndex oldSize = size();
989 if (newSize == 0)
990 clear();
991 else if (newSize > oldSize)
992 (*this)[newSize - 1];
993 else {
994 for (ArrayIndex index = newSize; index < oldSize; ++index) {
995 value_.map_->erase(index);
996 }
997 JSON_ASSERT(size() == newSize);
998 }
999 }
1000
operator [](ArrayIndex index)1001 Value& Value::operator[](ArrayIndex index) {
1002 JSON_ASSERT_MESSAGE(
1003 type_ == nullValue || type_ == arrayValue,
1004 "in Json::Value::operator[](ArrayIndex): requires arrayValue");
1005 if (type_ == nullValue)
1006 *this = Value(arrayValue);
1007 CZString key(index);
1008 ObjectValues::iterator it = value_.map_->lower_bound(key);
1009 if (it != value_.map_->end() && (*it).first == key)
1010 return (*it).second;
1011
1012 ObjectValues::value_type defaultValue(key, nullSingleton());
1013 it = value_.map_->insert(it, defaultValue);
1014 return (*it).second;
1015 }
1016
operator [](int index)1017 Value& Value::operator[](int index) {
1018 JSON_ASSERT_MESSAGE(
1019 index >= 0,
1020 "in Json::Value::operator[](int index): index cannot be negative");
1021 return (*this)[ArrayIndex(index)];
1022 }
1023
operator [](ArrayIndex index) const1024 const Value& Value::operator[](ArrayIndex index) const {
1025 JSON_ASSERT_MESSAGE(
1026 type_ == nullValue || type_ == arrayValue,
1027 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
1028 if (type_ == nullValue)
1029 return nullSingleton();
1030 CZString key(index);
1031 ObjectValues::const_iterator it = value_.map_->find(key);
1032 if (it == value_.map_->end())
1033 return nullSingleton();
1034 return (*it).second;
1035 }
1036
operator [](int index) const1037 const Value& Value::operator[](int index) const {
1038 JSON_ASSERT_MESSAGE(
1039 index >= 0,
1040 "in Json::Value::operator[](int index) const: index cannot be negative");
1041 return (*this)[ArrayIndex(index)];
1042 }
1043
initBasic(ValueType vtype,bool allocated)1044 void Value::initBasic(ValueType vtype, bool allocated) {
1045 type_ = vtype;
1046 allocated_ = allocated;
1047 comments_ = 0;
1048 start_ = 0;
1049 limit_ = 0;
1050 }
1051
1052 // Access an object value by name, create a null member if it does not exist.
1053 // @pre Type of '*this' is object or null.
1054 // @param key is null-terminated.
resolveReference(const char * key)1055 Value& Value::resolveReference(const char* key) {
1056 JSON_ASSERT_MESSAGE(
1057 type_ == nullValue || type_ == objectValue,
1058 "in Json::Value::resolveReference(): requires objectValue");
1059 if (type_ == nullValue)
1060 *this = Value(objectValue);
1061 CZString actualKey(
1062 key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
1063 ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
1064 if (it != value_.map_->end() && (*it).first == actualKey)
1065 return (*it).second;
1066
1067 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1068 it = value_.map_->insert(it, defaultValue);
1069 Value& value = (*it).second;
1070 return value;
1071 }
1072
1073 // @param key is not null-terminated.
resolveReference(char const * key,char const * cend)1074 Value& Value::resolveReference(char const* key, char const* cend)
1075 {
1076 JSON_ASSERT_MESSAGE(
1077 type_ == nullValue || type_ == objectValue,
1078 "in Json::Value::resolveReference(key, end): requires objectValue");
1079 if (type_ == nullValue)
1080 *this = Value(objectValue);
1081 CZString actualKey(
1082 key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
1083 ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
1084 if (it != value_.map_->end() && (*it).first == actualKey)
1085 return (*it).second;
1086
1087 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1088 it = value_.map_->insert(it, defaultValue);
1089 Value& value = (*it).second;
1090 return value;
1091 }
1092
get(ArrayIndex index,const Value & defaultValue) const1093 Value Value::get(ArrayIndex index, const Value& defaultValue) const {
1094 const Value* value = &((*this)[index]);
1095 return value == &nullSingleton() ? defaultValue : *value;
1096 }
1097
isValidIndex(ArrayIndex index) const1098 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
1099
find(char const * key,char const * cend) const1100 Value const* Value::find(char const* key, char const* cend) const
1101 {
1102 JSON_ASSERT_MESSAGE(
1103 type_ == nullValue || type_ == objectValue,
1104 "in Json::Value::find(key, end, found): requires objectValue or nullValue");
1105 if (type_ == nullValue) return NULL;
1106 CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
1107 ObjectValues::const_iterator it = value_.map_->find(actualKey);
1108 if (it == value_.map_->end()) return NULL;
1109 return &(*it).second;
1110 }
operator [](const char * key) const1111 const Value& Value::operator[](const char* key) const
1112 {
1113 Value const* found = find(key, key + strlen(key));
1114 if (!found) return nullSingleton();
1115 return *found;
1116 }
operator [](JSONCPP_STRING const & key) const1117 Value const& Value::operator[](JSONCPP_STRING const& key) const
1118 {
1119 Value const* found = find(key.data(), key.data() + key.length());
1120 if (!found) return nullSingleton();
1121 return *found;
1122 }
1123
operator [](const char * key)1124 Value& Value::operator[](const char* key) {
1125 return resolveReference(key, key + strlen(key));
1126 }
1127
operator [](const JSONCPP_STRING & key)1128 Value& Value::operator[](const JSONCPP_STRING& key) {
1129 return resolveReference(key.data(), key.data() + key.length());
1130 }
1131
operator [](const StaticString & key)1132 Value& Value::operator[](const StaticString& key) {
1133 return resolveReference(key.c_str());
1134 }
1135
1136 #ifdef JSON_USE_CPPTL
operator [](const CppTL::ConstString & key)1137 Value& Value::operator[](const CppTL::ConstString& key) {
1138 return resolveReference(key.c_str(), key.end_c_str());
1139 }
operator [](CppTL::ConstString const & key) const1140 Value const& Value::operator[](CppTL::ConstString const& key) const
1141 {
1142 Value const* found = find(key.c_str(), key.end_c_str());
1143 if (!found) return nullSingleton();
1144 return *found;
1145 }
1146 #endif
1147
append(const Value & value)1148 Value& Value::append(const Value& value) { return (*this)[size()] = value; }
1149
1150 #if JSON_HAS_RVALUE_REFERENCES
append(Value && value)1151 Value& Value::append(Value&& value) { return (*this)[size()] = std::move(value); }
1152 #endif
1153
get(char const * key,char const * cend,Value const & defaultValue) const1154 Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
1155 {
1156 Value const* found = find(key, cend);
1157 return !found ? defaultValue : *found;
1158 }
get(char const * key,Value const & defaultValue) const1159 Value Value::get(char const* key, Value const& defaultValue) const
1160 {
1161 return get(key, key + strlen(key), defaultValue);
1162 }
get(JSONCPP_STRING const & key,Value const & defaultValue) const1163 Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
1164 {
1165 return get(key.data(), key.data() + key.length(), defaultValue);
1166 }
1167
1168
removeMember(const char * key,const char * cend,Value * removed)1169 bool Value::removeMember(const char* key, const char* cend, Value* removed)
1170 {
1171 if (type_ != objectValue) {
1172 return false;
1173 }
1174 CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
1175 ObjectValues::iterator it = value_.map_->find(actualKey);
1176 if (it == value_.map_->end())
1177 return false;
1178 *removed = it->second;
1179 value_.map_->erase(it);
1180 return true;
1181 }
removeMember(const char * key,Value * removed)1182 bool Value::removeMember(const char* key, Value* removed)
1183 {
1184 return removeMember(key, key + strlen(key), removed);
1185 }
removeMember(JSONCPP_STRING const & key,Value * removed)1186 bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
1187 {
1188 return removeMember(key.data(), key.data() + key.length(), removed);
1189 }
removeMember(const char * key)1190 void Value::removeMember(const char* key)
1191 {
1192 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
1193 "in Json::Value::removeMember(): requires objectValue");
1194 if (type_ == nullValue)
1195 return;
1196
1197 CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
1198 value_.map_->erase(actualKey);
1199 }
removeMember(const JSONCPP_STRING & key)1200 void Value::removeMember(const JSONCPP_STRING& key)
1201 {
1202 removeMember(key.c_str());
1203 }
1204
removeIndex(ArrayIndex index,Value * removed)1205 bool Value::removeIndex(ArrayIndex index, Value* removed) {
1206 if (type_ != arrayValue) {
1207 return false;
1208 }
1209 CZString key(index);
1210 ObjectValues::iterator it = value_.map_->find(key);
1211 if (it == value_.map_->end()) {
1212 return false;
1213 }
1214 *removed = it->second;
1215 ArrayIndex oldSize = size();
1216 // shift left all items left, into the place of the "removed"
1217 for (ArrayIndex i = index; i < (oldSize - 1); ++i){
1218 CZString keey(i);
1219 (*value_.map_)[keey] = (*this)[i + 1];
1220 }
1221 // erase the last one ("leftover")
1222 CZString keyLast(oldSize - 1);
1223 ObjectValues::iterator itLast = value_.map_->find(keyLast);
1224 value_.map_->erase(itLast);
1225 return true;
1226 }
1227
1228 #ifdef JSON_USE_CPPTL
get(const CppTL::ConstString & key,const Value & defaultValue) const1229 Value Value::get(const CppTL::ConstString& key,
1230 const Value& defaultValue) const {
1231 return get(key.c_str(), key.end_c_str(), defaultValue);
1232 }
1233 #endif
1234
isMember(char const * key,char const * cend) const1235 bool Value::isMember(char const* key, char const* cend) const
1236 {
1237 Value const* value = find(key, cend);
1238 return NULL != value;
1239 }
isMember(char const * key) const1240 bool Value::isMember(char const* key) const
1241 {
1242 return isMember(key, key + strlen(key));
1243 }
isMember(JSONCPP_STRING const & key) const1244 bool Value::isMember(JSONCPP_STRING const& key) const
1245 {
1246 return isMember(key.data(), key.data() + key.length());
1247 }
1248
1249 #ifdef JSON_USE_CPPTL
isMember(const CppTL::ConstString & key) const1250 bool Value::isMember(const CppTL::ConstString& key) const {
1251 return isMember(key.c_str(), key.end_c_str());
1252 }
1253 #endif
1254
getMemberNames() const1255 Value::Members Value::getMemberNames() const {
1256 JSON_ASSERT_MESSAGE(
1257 type_ == nullValue || type_ == objectValue,
1258 "in Json::Value::getMemberNames(), value must be objectValue");
1259 if (type_ == nullValue)
1260 return Value::Members();
1261 Members members;
1262 members.reserve(value_.map_->size());
1263 ObjectValues::const_iterator it = value_.map_->begin();
1264 ObjectValues::const_iterator itEnd = value_.map_->end();
1265 for (; it != itEnd; ++it) {
1266 members.push_back(JSONCPP_STRING((*it).first.data(),
1267 (*it).first.length()));
1268 }
1269 return members;
1270 }
1271 //
1272 //# ifdef JSON_USE_CPPTL
1273 // EnumMemberNames
1274 // Value::enumMemberNames() const
1275 //{
1276 // if ( type_ == objectValue )
1277 // {
1278 // return CppTL::Enum::any( CppTL::Enum::transform(
1279 // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
1280 // MemberNamesTransform() ) );
1281 // }
1282 // return EnumMemberNames();
1283 //}
1284 //
1285 //
1286 // EnumValues
1287 // Value::enumValues() const
1288 //{
1289 // if ( type_ == objectValue || type_ == arrayValue )
1290 // return CppTL::Enum::anyValues( *(value_.map_),
1291 // CppTL::Type<const Value &>() );
1292 // return EnumValues();
1293 //}
1294 //
1295 //# endif
1296
IsIntegral(double d)1297 static bool IsIntegral(double d) {
1298 double integral_part;
1299 return modf(d, &integral_part) == 0.0;
1300 }
1301
isNull() const1302 bool Value::isNull() const { return type_ == nullValue; }
1303
isBool() const1304 bool Value::isBool() const { return type_ == booleanValue; }
1305
isInt() const1306 bool Value::isInt() const {
1307 switch (type_) {
1308 case intValue:
1309 #if defined(JSON_HAS_INT64)
1310 return value_.int_ >= minInt && value_.int_ <= maxInt;
1311 #else
1312 return true;
1313 #endif
1314 case uintValue:
1315 return value_.uint_ <= UInt(maxInt);
1316 case realValue:
1317 return value_.real_ >= minInt && value_.real_ <= maxInt &&
1318 IsIntegral(value_.real_);
1319 default:
1320 break;
1321 }
1322 return false;
1323 }
1324
isUInt() const1325 bool Value::isUInt() const {
1326 switch (type_) {
1327 case intValue:
1328 #if defined(JSON_HAS_INT64)
1329 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
1330 #else
1331 return value_.int_ >= 0;
1332 #endif
1333 case uintValue:
1334 #if defined(JSON_HAS_INT64)
1335 return value_.uint_ <= maxUInt;
1336 #else
1337 return true;
1338 #endif
1339 case realValue:
1340 return value_.real_ >= 0 && value_.real_ <= maxUInt &&
1341 IsIntegral(value_.real_);
1342 default:
1343 break;
1344 }
1345 return false;
1346 }
1347
isInt64() const1348 bool Value::isInt64() const {
1349 #if defined(JSON_HAS_INT64)
1350 switch (type_) {
1351 case intValue:
1352 return true;
1353 case uintValue:
1354 return value_.uint_ <= UInt64(maxInt64);
1355 case realValue:
1356 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
1357 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
1358 // require the value to be strictly less than the limit.
1359 return value_.real_ >= double(minInt64) &&
1360 value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
1361 default:
1362 break;
1363 }
1364 #endif // JSON_HAS_INT64
1365 return false;
1366 }
1367
isUInt64() const1368 bool Value::isUInt64() const {
1369 #if defined(JSON_HAS_INT64)
1370 switch (type_) {
1371 case intValue:
1372 return value_.int_ >= 0;
1373 case uintValue:
1374 return true;
1375 case realValue:
1376 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1377 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1378 // require the value to be strictly less than the limit.
1379 return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
1380 IsIntegral(value_.real_);
1381 default:
1382 break;
1383 }
1384 #endif // JSON_HAS_INT64
1385 return false;
1386 }
1387
isIntegral() const1388 bool Value::isIntegral() const {
1389 switch (type_) {
1390 case intValue:
1391 case uintValue:
1392 return true;
1393 case realValue:
1394 #if defined(JSON_HAS_INT64)
1395 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1396 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1397 // require the value to be strictly less than the limit.
1398 return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
1399 #else
1400 return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
1401 #endif // JSON_HAS_INT64
1402 default:
1403 break;
1404 }
1405 return false;
1406 }
1407
isDouble() const1408 bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
1409
isNumeric() const1410 bool Value::isNumeric() const { return isDouble(); }
1411
isString() const1412 bool Value::isString() const { return type_ == stringValue; }
1413
isArray() const1414 bool Value::isArray() const { return type_ == arrayValue; }
1415
isObject() const1416 bool Value::isObject() const { return type_ == objectValue; }
1417
setComment(const char * comment,size_t len,CommentPlacement placement)1418 void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
1419 if (!comments_)
1420 comments_ = new CommentInfo[numberOfCommentPlacement];
1421 if ((len > 0) && (comment[len-1] == '\n')) {
1422 // Always discard trailing newline, to aid indentation.
1423 len -= 1;
1424 }
1425 comments_[placement].setComment(comment, len);
1426 }
1427
setComment(const char * comment,CommentPlacement placement)1428 void Value::setComment(const char* comment, CommentPlacement placement) {
1429 setComment(comment, strlen(comment), placement);
1430 }
1431
setComment(const JSONCPP_STRING & comment,CommentPlacement placement)1432 void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
1433 setComment(comment.c_str(), comment.length(), placement);
1434 }
1435
hasComment(CommentPlacement placement) const1436 bool Value::hasComment(CommentPlacement placement) const {
1437 return comments_ != 0 && comments_[placement].comment_ != 0;
1438 }
1439
getComment(CommentPlacement placement) const1440 JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
1441 if (hasComment(placement))
1442 return comments_[placement].comment_;
1443 return "";
1444 }
1445
setOffsetStart(ptrdiff_t start)1446 void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
1447
setOffsetLimit(ptrdiff_t limit)1448 void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
1449
getOffsetStart() const1450 ptrdiff_t Value::getOffsetStart() const { return start_; }
1451
getOffsetLimit() const1452 ptrdiff_t Value::getOffsetLimit() const { return limit_; }
1453
toStyledString() const1454 JSONCPP_STRING Value::toStyledString() const {
1455 StreamWriterBuilder builder;
1456
1457 JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
1458 out += Json::writeString(builder, *this);
1459 out += "\n";
1460
1461 return out;
1462 }
1463
begin() const1464 Value::const_iterator Value::begin() const {
1465 switch (type_) {
1466 case arrayValue:
1467 case objectValue:
1468 if (value_.map_)
1469 return const_iterator(value_.map_->begin());
1470 break;
1471 default:
1472 break;
1473 }
1474 return const_iterator();
1475 }
1476
end() const1477 Value::const_iterator Value::end() const {
1478 switch (type_) {
1479 case arrayValue:
1480 case objectValue:
1481 if (value_.map_)
1482 return const_iterator(value_.map_->end());
1483 break;
1484 default:
1485 break;
1486 }
1487 return const_iterator();
1488 }
1489
begin()1490 Value::iterator Value::begin() {
1491 switch (type_) {
1492 case arrayValue:
1493 case objectValue:
1494 if (value_.map_)
1495 return iterator(value_.map_->begin());
1496 break;
1497 default:
1498 break;
1499 }
1500 return iterator();
1501 }
1502
end()1503 Value::iterator Value::end() {
1504 switch (type_) {
1505 case arrayValue:
1506 case objectValue:
1507 if (value_.map_)
1508 return iterator(value_.map_->end());
1509 break;
1510 default:
1511 break;
1512 }
1513 return iterator();
1514 }
1515
1516 // class PathArgument
1517 // //////////////////////////////////////////////////////////////////
1518
PathArgument()1519 PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
1520
PathArgument(ArrayIndex index)1521 PathArgument::PathArgument(ArrayIndex index)
1522 : key_(), index_(index), kind_(kindIndex) {}
1523
PathArgument(const char * key)1524 PathArgument::PathArgument(const char* key)
1525 : key_(key), index_(), kind_(kindKey) {}
1526
PathArgument(const JSONCPP_STRING & key)1527 PathArgument::PathArgument(const JSONCPP_STRING& key)
1528 : key_(key.c_str()), index_(), kind_(kindKey) {}
1529
1530 // class Path
1531 // //////////////////////////////////////////////////////////////////
1532
Path(const JSONCPP_STRING & path,const PathArgument & a1,const PathArgument & a2,const PathArgument & a3,const PathArgument & a4,const PathArgument & a5)1533 Path::Path(const JSONCPP_STRING& path,
1534 const PathArgument& a1,
1535 const PathArgument& a2,
1536 const PathArgument& a3,
1537 const PathArgument& a4,
1538 const PathArgument& a5) {
1539 InArgs in;
1540 in.reserve(5);
1541 in.push_back(&a1);
1542 in.push_back(&a2);
1543 in.push_back(&a3);
1544 in.push_back(&a4);
1545 in.push_back(&a5);
1546 makePath(path, in);
1547 }
1548
makePath(const JSONCPP_STRING & path,const InArgs & in)1549 void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
1550 const char* current = path.c_str();
1551 const char* end = current + path.length();
1552 InArgs::const_iterator itInArg = in.begin();
1553 while (current != end) {
1554 if (*current == '[') {
1555 ++current;
1556 if (*current == '%')
1557 addPathInArg(path, in, itInArg, PathArgument::kindIndex);
1558 else {
1559 ArrayIndex index = 0;
1560 for (; current != end && *current >= '0' && *current <= '9'; ++current)
1561 index = index * 10 + ArrayIndex(*current - '0');
1562 args_.push_back(index);
1563 }
1564 if (current == end || *++current != ']')
1565 invalidPath(path, int(current - path.c_str()));
1566 } else if (*current == '%') {
1567 addPathInArg(path, in, itInArg, PathArgument::kindKey);
1568 ++current;
1569 } else if (*current == '.' || *current == ']') {
1570 ++current;
1571 } else {
1572 const char* beginName = current;
1573 while (current != end && !strchr("[.", *current))
1574 ++current;
1575 args_.push_back(JSONCPP_STRING(beginName, current));
1576 }
1577 }
1578 }
1579
addPathInArg(const JSONCPP_STRING &,const InArgs & in,InArgs::const_iterator & itInArg,PathArgument::Kind kind)1580 void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
1581 const InArgs& in,
1582 InArgs::const_iterator& itInArg,
1583 PathArgument::Kind kind) {
1584 if (itInArg == in.end()) {
1585 // Error: missing argument %d
1586 } else if ((*itInArg)->kind_ != kind) {
1587 // Error: bad argument type
1588 } else {
1589 args_.push_back(**itInArg++);
1590 }
1591 }
1592
invalidPath(const JSONCPP_STRING &,int)1593 void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
1594 // Error: invalid path.
1595 }
1596
resolve(const Value & root) const1597 const Value& Path::resolve(const Value& root) const {
1598 const Value* node = &root;
1599 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
1600 const PathArgument& arg = *it;
1601 if (arg.kind_ == PathArgument::kindIndex) {
1602 if (!node->isArray() || !node->isValidIndex(arg.index_)) {
1603 // Error: unable to resolve path (array value expected at position...
1604 return Value::null;
1605 }
1606 node = &((*node)[arg.index_]);
1607 } else if (arg.kind_ == PathArgument::kindKey) {
1608 if (!node->isObject()) {
1609 // Error: unable to resolve path (object value expected at position...)
1610 return Value::null;
1611 }
1612 node = &((*node)[arg.key_]);
1613 if (node == &Value::nullSingleton()) {
1614 // Error: unable to resolve path (object has no member named '' at
1615 // position...)
1616 return Value::null;
1617 }
1618 }
1619 }
1620 return *node;
1621 }
1622
resolve(const Value & root,const Value & defaultValue) const1623 Value Path::resolve(const Value& root, const Value& defaultValue) const {
1624 const Value* node = &root;
1625 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
1626 const PathArgument& arg = *it;
1627 if (arg.kind_ == PathArgument::kindIndex) {
1628 if (!node->isArray() || !node->isValidIndex(arg.index_))
1629 return defaultValue;
1630 node = &((*node)[arg.index_]);
1631 } else if (arg.kind_ == PathArgument::kindKey) {
1632 if (!node->isObject())
1633 return defaultValue;
1634 node = &((*node)[arg.key_]);
1635 if (node == &Value::nullSingleton())
1636 return defaultValue;
1637 }
1638 }
1639 return *node;
1640 }
1641
make(Value & root) const1642 Value& Path::make(Value& root) const {
1643 Value* node = &root;
1644 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
1645 const PathArgument& arg = *it;
1646 if (arg.kind_ == PathArgument::kindIndex) {
1647 if (!node->isArray()) {
1648 // Error: node is not an array at position ...
1649 }
1650 node = &((*node)[arg.index_]);
1651 } else if (arg.kind_ == PathArgument::kindKey) {
1652 if (!node->isObject()) {
1653 // Error: node is not an object at position...
1654 }
1655 node = &((*node)[arg.key_]);
1656 }
1657 }
1658 return *node;
1659 }
1660
1661 } // namespace Json
1662