1 // Copyright 2011 Baptiste Lepilleur
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 #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
11 #include "json_batchallocator.h"
12 #endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
13 #endif // if !defined(JSON_IS_AMALGAMATION)
14 #include <math.h>
15 #include <sstream>
16 #include <utility>
17 #include <cstring>
18 #include <cassert>
19 #ifdef JSON_USE_CPPTL
20 #include <cpptl/conststring.h>
21 #endif
22 #include <cstddef> // size_t
23
24 #define JSON_ASSERT_UNREACHABLE assert(false)
25
26 namespace Json {
27
28 // This is a walkaround to avoid the static initialization of Value::null.
29 // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
30 // 8 (instead of 4) as a bit of future-proofing.
31 #if defined(__ARMEL__)
32 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
33 #else
34 #define ALIGNAS(byte_alignment)
35 #endif
36 static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
37 const unsigned char& kNullRef = kNull[0];
38 const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
39
40 const Int Value::minInt = Int(~(UInt(-1) / 2));
41 const Int Value::maxInt = Int(UInt(-1) / 2);
42 const UInt Value::maxUInt = UInt(-1);
43 #if defined(JSON_HAS_INT64)
44 const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
45 const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
46 const UInt64 Value::maxUInt64 = UInt64(-1);
47 // The constant is hard-coded because some compiler have trouble
48 // converting Value::maxUInt64 to a double correctly (AIX/xlC).
49 // Assumes that UInt64 is a 64 bits integer.
50 static const double maxUInt64AsDouble = 18446744073709551615.0;
51 #endif // defined(JSON_HAS_INT64)
52 const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
53 const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
54 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
55
56 /// Unknown size marker
57 static const unsigned int unknown = (unsigned)-1;
58
59 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
60 template <typename T, typename U>
InRange(double d,T min,U max)61 static inline bool InRange(double d, T min, U max) {
62 return d >= min && d <= max;
63 }
64 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
integerToDouble(Json::UInt64 value)65 static inline double integerToDouble(Json::UInt64 value) {
66 return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
67 }
68
integerToDouble(T value)69 template <typename T> static inline double integerToDouble(T value) {
70 return static_cast<double>(value);
71 }
72
73 template <typename T, typename U>
InRange(double d,T min,U max)74 static inline bool InRange(double d, T min, U max) {
75 return d >= integerToDouble(min) && d <= integerToDouble(max);
76 }
77 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
78
79 /** Duplicates the specified string value.
80 * @param value Pointer to the string to duplicate. Must be zero-terminated if
81 * length is "unknown".
82 * @param length Length of the value. if equals to unknown, then it will be
83 * computed using strlen(value).
84 * @return Pointer on the duplicate instance of string.
85 */
duplicateStringValue(const char * value,unsigned int length=unknown)86 static inline char* duplicateStringValue(const char* value,
87 unsigned int length = unknown) {
88 if (length == unknown)
89 length = (unsigned int)strlen(value);
90
91 // Avoid an integer overflow in the call to malloc below by limiting length
92 // to a sane value.
93 if (length >= (unsigned)Value::maxInt)
94 length = Value::maxInt - 1;
95
96 char* newString = static_cast<char*>(malloc(length + 1));
97 JSON_ASSERT_MESSAGE(newString != 0,
98 "in Json::Value::duplicateStringValue(): "
99 "Failed to allocate string value buffer");
100 memcpy(newString, value, length);
101 newString[length] = 0;
102 return newString;
103 }
104
105 /** Free the string duplicated by duplicateStringValue().
106 */
releaseStringValue(char * value)107 static inline void releaseStringValue(char* value) { free(value); }
108
109 } // namespace Json
110
111 // //////////////////////////////////////////////////////////////////
112 // //////////////////////////////////////////////////////////////////
113 // //////////////////////////////////////////////////////////////////
114 // ValueInternals...
115 // //////////////////////////////////////////////////////////////////
116 // //////////////////////////////////////////////////////////////////
117 // //////////////////////////////////////////////////////////////////
118 #if !defined(JSON_IS_AMALGAMATION)
119 #ifdef JSON_VALUE_USE_INTERNAL_MAP
120 #include "json_internalarray.inl"
121 #include "json_internalmap.inl"
122 #endif // JSON_VALUE_USE_INTERNAL_MAP
123
124 #include "json_valueiterator.inl"
125 #endif // if !defined(JSON_IS_AMALGAMATION)
126
127 namespace Json {
128
129 // //////////////////////////////////////////////////////////////////
130 // //////////////////////////////////////////////////////////////////
131 // //////////////////////////////////////////////////////////////////
132 // class Value::CommentInfo
133 // //////////////////////////////////////////////////////////////////
134 // //////////////////////////////////////////////////////////////////
135 // //////////////////////////////////////////////////////////////////
136
CommentInfo()137 Value::CommentInfo::CommentInfo() : comment_(0) {}
138
~CommentInfo()139 Value::CommentInfo::~CommentInfo() {
140 if (comment_)
141 releaseStringValue(comment_);
142 }
143
setComment(const char * text)144 void Value::CommentInfo::setComment(const char* text) {
145 if (comment_)
146 releaseStringValue(comment_);
147 JSON_ASSERT(text != 0);
148 JSON_ASSERT_MESSAGE(
149 text[0] == '\0' || text[0] == '/',
150 "in Json::Value::setComment(): Comments must start with /");
151 // It seems that /**/ style comments are acceptable as well.
152 comment_ = duplicateStringValue(text);
153 }
154
155 // //////////////////////////////////////////////////////////////////
156 // //////////////////////////////////////////////////////////////////
157 // //////////////////////////////////////////////////////////////////
158 // class Value::CZString
159 // //////////////////////////////////////////////////////////////////
160 // //////////////////////////////////////////////////////////////////
161 // //////////////////////////////////////////////////////////////////
162 #ifndef JSON_VALUE_USE_INTERNAL_MAP
163
164 // Notes: index_ indicates if the string was allocated when
165 // a string is stored.
166
CZString(ArrayIndex index)167 Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {}
168
CZString(const char * cstr,DuplicationPolicy allocate)169 Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate)
170 : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr),
171 index_(allocate) {}
172
CZString(const CZString & other)173 Value::CZString::CZString(const CZString& other)
174 : cstr_(other.index_ != noDuplication && other.cstr_ != 0
175 ? duplicateStringValue(other.cstr_)
176 : other.cstr_),
177 index_(other.cstr_
178 ? static_cast<ArrayIndex>(other.index_ == noDuplication
179 ? noDuplication : duplicate)
180 : other.index_) {}
181
~CZString()182 Value::CZString::~CZString() {
183 if (cstr_ && index_ == duplicate)
184 releaseStringValue(const_cast<char*>(cstr_));
185 }
186
swap(CZString & other)187 void Value::CZString::swap(CZString& other) {
188 std::swap(cstr_, other.cstr_);
189 std::swap(index_, other.index_);
190 }
191
operator =(CZString other)192 Value::CZString& Value::CZString::operator=(CZString other) {
193 swap(other);
194 return *this;
195 }
196
operator <(const CZString & other) const197 bool Value::CZString::operator<(const CZString& other) const {
198 if (cstr_)
199 return strcmp(cstr_, other.cstr_) < 0;
200 return index_ < other.index_;
201 }
202
operator ==(const CZString & other) const203 bool Value::CZString::operator==(const CZString& other) const {
204 if (cstr_)
205 return strcmp(cstr_, other.cstr_) == 0;
206 return index_ == other.index_;
207 }
208
index() const209 ArrayIndex Value::CZString::index() const { return index_; }
210
c_str() const211 const char* Value::CZString::c_str() const { return cstr_; }
212
isStaticString() const213 bool Value::CZString::isStaticString() const { return index_ == noDuplication; }
214
215 #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
216
217 // //////////////////////////////////////////////////////////////////
218 // //////////////////////////////////////////////////////////////////
219 // //////////////////////////////////////////////////////////////////
220 // class Value::Value
221 // //////////////////////////////////////////////////////////////////
222 // //////////////////////////////////////////////////////////////////
223 // //////////////////////////////////////////////////////////////////
224
225 /*! \internal Default constructor initialization must be equivalent to:
226 * memset( this, 0, sizeof(Value) )
227 * This optimization is used in ValueInternalMap fast allocator.
228 */
Value(ValueType type)229 Value::Value(ValueType type) {
230 initBasic(type);
231 switch (type) {
232 case nullValue:
233 break;
234 case intValue:
235 case uintValue:
236 value_.int_ = 0;
237 break;
238 case realValue:
239 value_.real_ = 0.0;
240 break;
241 case stringValue:
242 value_.string_ = 0;
243 break;
244 #ifndef JSON_VALUE_USE_INTERNAL_MAP
245 case arrayValue:
246 case objectValue:
247 value_.map_ = new ObjectValues();
248 break;
249 #else
250 case arrayValue:
251 value_.array_ = arrayAllocator()->newArray();
252 break;
253 case objectValue:
254 value_.map_ = mapAllocator()->newMap();
255 break;
256 #endif
257 case booleanValue:
258 value_.bool_ = false;
259 break;
260 default:
261 JSON_ASSERT_UNREACHABLE;
262 }
263 }
264
Value(Int value)265 Value::Value(Int value) {
266 initBasic(intValue);
267 value_.int_ = value;
268 }
269
Value(UInt value)270 Value::Value(UInt value) {
271 initBasic(uintValue);
272 value_.uint_ = value;
273 }
274 #if defined(JSON_HAS_INT64)
Value(Int64 value)275 Value::Value(Int64 value) {
276 initBasic(intValue);
277 value_.int_ = value;
278 }
Value(UInt64 value)279 Value::Value(UInt64 value) {
280 initBasic(uintValue);
281 value_.uint_ = value;
282 }
283 #endif // defined(JSON_HAS_INT64)
284
Value(double value)285 Value::Value(double value) {
286 initBasic(realValue);
287 value_.real_ = value;
288 }
289
Value(const char * value)290 Value::Value(const char* value) {
291 initBasic(stringValue, true);
292 value_.string_ = duplicateStringValue(value);
293 }
294
Value(const char * beginValue,const char * endValue)295 Value::Value(const char* beginValue, const char* endValue) {
296 initBasic(stringValue, true);
297 value_.string_ =
298 duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue));
299 }
300
Value(const std::string & value)301 Value::Value(const std::string& value) {
302 initBasic(stringValue, true);
303 value_.string_ =
304 duplicateStringValue(value.c_str(), (unsigned int)value.length());
305 }
306
Value(const StaticString & value)307 Value::Value(const StaticString& value) {
308 initBasic(stringValue);
309 value_.string_ = const_cast<char*>(value.c_str());
310 }
311
312 #ifdef JSON_USE_CPPTL
Value(const CppTL::ConstString & value)313 Value::Value(const CppTL::ConstString& value) {
314 initBasic(stringValue, true);
315 value_.string_ = duplicateStringValue(value, value.length());
316 }
317 #endif
318
Value(bool value)319 Value::Value(bool value) {
320 initBasic(booleanValue);
321 value_.bool_ = value;
322 }
323
Value(const Value & other)324 Value::Value(const Value& other)
325 : type_(other.type_), allocated_(false)
326 #ifdef JSON_VALUE_USE_INTERNAL_MAP
327 ,
328 itemIsUsed_(0)
329 #endif
330 ,
331 comments_(0), start_(other.start_), limit_(other.limit_) {
332 switch (type_) {
333 case nullValue:
334 case intValue:
335 case uintValue:
336 case realValue:
337 case booleanValue:
338 value_ = other.value_;
339 break;
340 case stringValue:
341 if (other.value_.string_) {
342 value_.string_ = duplicateStringValue(other.value_.string_);
343 allocated_ = true;
344 } else {
345 value_.string_ = 0;
346 allocated_ = false;
347 }
348 break;
349 #ifndef JSON_VALUE_USE_INTERNAL_MAP
350 case arrayValue:
351 case objectValue:
352 value_.map_ = new ObjectValues(*other.value_.map_);
353 break;
354 #else
355 case arrayValue:
356 value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_);
357 break;
358 case objectValue:
359 value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_);
360 break;
361 #endif
362 default:
363 JSON_ASSERT_UNREACHABLE;
364 }
365 if (other.comments_) {
366 comments_ = new CommentInfo[numberOfCommentPlacement];
367 for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
368 const CommentInfo& otherComment = other.comments_[comment];
369 if (otherComment.comment_)
370 comments_[comment].setComment(otherComment.comment_);
371 }
372 }
373 }
374
~Value()375 Value::~Value() {
376 switch (type_) {
377 case nullValue:
378 case intValue:
379 case uintValue:
380 case realValue:
381 case booleanValue:
382 break;
383 case stringValue:
384 if (allocated_)
385 releaseStringValue(value_.string_);
386 break;
387 #ifndef JSON_VALUE_USE_INTERNAL_MAP
388 case arrayValue:
389 case objectValue:
390 delete value_.map_;
391 break;
392 #else
393 case arrayValue:
394 arrayAllocator()->destructArray(value_.array_);
395 break;
396 case objectValue:
397 mapAllocator()->destructMap(value_.map_);
398 break;
399 #endif
400 default:
401 JSON_ASSERT_UNREACHABLE;
402 }
403
404 if (comments_)
405 delete[] comments_;
406 }
407
operator =(Value other)408 Value& Value::operator=(Value other) {
409 swap(other);
410 return *this;
411 }
412
swap(Value & other)413 void Value::swap(Value& other) {
414 ValueType temp = type_;
415 type_ = other.type_;
416 other.type_ = temp;
417 std::swap(value_, other.value_);
418 int temp2 = allocated_;
419 allocated_ = other.allocated_;
420 other.allocated_ = temp2;
421 std::swap(start_, other.start_);
422 std::swap(limit_, other.limit_);
423 }
424
type() const425 ValueType Value::type() const { return type_; }
426
compare(const Value & other) const427 int Value::compare(const Value& other) const {
428 if (*this < other)
429 return -1;
430 if (*this > other)
431 return 1;
432 return 0;
433 }
434
operator <(const Value & other) const435 bool Value::operator<(const Value& other) const {
436 int typeDelta = type_ - other.type_;
437 if (typeDelta)
438 return typeDelta < 0 ? true : false;
439 switch (type_) {
440 case nullValue:
441 return false;
442 case intValue:
443 return value_.int_ < other.value_.int_;
444 case uintValue:
445 return value_.uint_ < other.value_.uint_;
446 case realValue:
447 return value_.real_ < other.value_.real_;
448 case booleanValue:
449 return value_.bool_ < other.value_.bool_;
450 case stringValue:
451 return (value_.string_ == 0 && other.value_.string_) ||
452 (other.value_.string_ && value_.string_ &&
453 strcmp(value_.string_, other.value_.string_) < 0);
454 #ifndef JSON_VALUE_USE_INTERNAL_MAP
455 case arrayValue:
456 case objectValue: {
457 int delta = int(value_.map_->size() - other.value_.map_->size());
458 if (delta)
459 return delta < 0;
460 return (*value_.map_) < (*other.value_.map_);
461 }
462 #else
463 case arrayValue:
464 return value_.array_->compare(*(other.value_.array_)) < 0;
465 case objectValue:
466 return value_.map_->compare(*(other.value_.map_)) < 0;
467 #endif
468 default:
469 JSON_ASSERT_UNREACHABLE;
470 }
471 return false; // unreachable
472 }
473
operator <=(const Value & other) const474 bool Value::operator<=(const Value& other) const { return !(other < *this); }
475
operator >=(const Value & other) const476 bool Value::operator>=(const Value& other) const { return !(*this < other); }
477
operator >(const Value & other) const478 bool Value::operator>(const Value& other) const { return other < *this; }
479
operator ==(const Value & other) const480 bool Value::operator==(const Value& other) const {
481 // if ( type_ != other.type_ )
482 // GCC 2.95.3 says:
483 // attempt to take address of bit-field structure member `Json::Value::type_'
484 // Beats me, but a temp solves the problem.
485 int temp = other.type_;
486 if (type_ != temp)
487 return false;
488 switch (type_) {
489 case nullValue:
490 return true;
491 case intValue:
492 return value_.int_ == other.value_.int_;
493 case uintValue:
494 return value_.uint_ == other.value_.uint_;
495 case realValue:
496 return value_.real_ == other.value_.real_;
497 case booleanValue:
498 return value_.bool_ == other.value_.bool_;
499 case stringValue:
500 return (value_.string_ == other.value_.string_) ||
501 (other.value_.string_ && value_.string_ &&
502 strcmp(value_.string_, other.value_.string_) == 0);
503 #ifndef JSON_VALUE_USE_INTERNAL_MAP
504 case arrayValue:
505 case objectValue:
506 return value_.map_->size() == other.value_.map_->size() &&
507 (*value_.map_) == (*other.value_.map_);
508 #else
509 case arrayValue:
510 return value_.array_->compare(*(other.value_.array_)) == 0;
511 case objectValue:
512 return value_.map_->compare(*(other.value_.map_)) == 0;
513 #endif
514 default:
515 JSON_ASSERT_UNREACHABLE;
516 }
517 return false; // unreachable
518 }
519
operator !=(const Value & other) const520 bool Value::operator!=(const Value& other) const { return !(*this == other); }
521
asCString() const522 const char* Value::asCString() const {
523 JSON_ASSERT_MESSAGE(type_ == stringValue,
524 "in Json::Value::asCString(): requires stringValue");
525 return value_.string_;
526 }
527
asString() const528 std::string Value::asString() const {
529 switch (type_) {
530 case nullValue:
531 return "";
532 case stringValue:
533 return value_.string_ ? value_.string_ : "";
534 case booleanValue:
535 return value_.bool_ ? "true" : "false";
536 case intValue:
537 return valueToString(value_.int_);
538 case uintValue:
539 return valueToString(value_.uint_);
540 case realValue:
541 return valueToString(value_.real_);
542 default:
543 JSON_FAIL_MESSAGE("Type is not convertible to string");
544 }
545 }
546
547 #ifdef JSON_USE_CPPTL
asConstString() const548 CppTL::ConstString Value::asConstString() const {
549 return CppTL::ConstString(asString().c_str());
550 }
551 #endif
552
asInt() const553 Value::Int Value::asInt() const {
554 switch (type_) {
555 case intValue:
556 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
557 return Int(value_.int_);
558 case uintValue:
559 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
560 return Int(value_.uint_);
561 case realValue:
562 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
563 "double out of Int range");
564 return Int(value_.real_);
565 case nullValue:
566 return 0;
567 case booleanValue:
568 return value_.bool_ ? 1 : 0;
569 default:
570 break;
571 }
572 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
573 }
574
asUInt() const575 Value::UInt Value::asUInt() const {
576 switch (type_) {
577 case intValue:
578 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
579 return UInt(value_.int_);
580 case uintValue:
581 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
582 return UInt(value_.uint_);
583 case realValue:
584 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
585 "double out of UInt range");
586 return UInt(value_.real_);
587 case nullValue:
588 return 0;
589 case booleanValue:
590 return value_.bool_ ? 1 : 0;
591 default:
592 break;
593 }
594 JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
595 }
596
597 #if defined(JSON_HAS_INT64)
598
asInt64() const599 Value::Int64 Value::asInt64() const {
600 switch (type_) {
601 case intValue:
602 return Int64(value_.int_);
603 case uintValue:
604 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
605 return Int64(value_.uint_);
606 case realValue:
607 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
608 "double out of Int64 range");
609 return Int64(value_.real_);
610 case nullValue:
611 return 0;
612 case booleanValue:
613 return value_.bool_ ? 1 : 0;
614 default:
615 break;
616 }
617 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
618 }
619
asUInt64() const620 Value::UInt64 Value::asUInt64() const {
621 switch (type_) {
622 case intValue:
623 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
624 return UInt64(value_.int_);
625 case uintValue:
626 return UInt64(value_.uint_);
627 case realValue:
628 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
629 "double out of UInt64 range");
630 return UInt64(value_.real_);
631 case nullValue:
632 return 0;
633 case booleanValue:
634 return value_.bool_ ? 1 : 0;
635 default:
636 break;
637 }
638 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
639 }
640 #endif // if defined(JSON_HAS_INT64)
641
asLargestInt() const642 LargestInt Value::asLargestInt() const {
643 #if defined(JSON_NO_INT64)
644 return asInt();
645 #else
646 return asInt64();
647 #endif
648 }
649
asLargestUInt() const650 LargestUInt Value::asLargestUInt() const {
651 #if defined(JSON_NO_INT64)
652 return asUInt();
653 #else
654 return asUInt64();
655 #endif
656 }
657
asDouble() const658 double Value::asDouble() const {
659 switch (type_) {
660 case intValue:
661 return static_cast<double>(value_.int_);
662 case uintValue:
663 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
664 return static_cast<double>(value_.uint_);
665 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
666 return integerToDouble(value_.uint_);
667 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
668 case realValue:
669 return value_.real_;
670 case nullValue:
671 return 0.0;
672 case booleanValue:
673 return value_.bool_ ? 1.0 : 0.0;
674 default:
675 break;
676 }
677 JSON_FAIL_MESSAGE("Value is not convertible to double.");
678 }
679
asFloat() const680 float Value::asFloat() const {
681 switch (type_) {
682 case intValue:
683 return static_cast<float>(value_.int_);
684 case uintValue:
685 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
686 return static_cast<float>(value_.uint_);
687 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
688 return integerToDouble(value_.uint_);
689 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
690 case realValue:
691 return static_cast<float>(value_.real_);
692 case nullValue:
693 return 0.0;
694 case booleanValue:
695 return value_.bool_ ? 1.0f : 0.0f;
696 default:
697 break;
698 }
699 JSON_FAIL_MESSAGE("Value is not convertible to float.");
700 }
701
asBool() const702 bool Value::asBool() const {
703 switch (type_) {
704 case booleanValue:
705 return value_.bool_;
706 case nullValue:
707 return false;
708 case intValue:
709 return value_.int_ ? true : false;
710 case uintValue:
711 return value_.uint_ ? true : false;
712 case realValue:
713 return value_.real_ ? true : false;
714 default:
715 break;
716 }
717 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
718 }
719
isConvertibleTo(ValueType other) const720 bool Value::isConvertibleTo(ValueType other) const {
721 switch (other) {
722 case nullValue:
723 return (isNumeric() && asDouble() == 0.0) ||
724 (type_ == booleanValue && value_.bool_ == false) ||
725 (type_ == stringValue && asString() == "") ||
726 (type_ == arrayValue && value_.map_->size() == 0) ||
727 (type_ == objectValue && value_.map_->size() == 0) ||
728 type_ == nullValue;
729 case intValue:
730 return isInt() ||
731 (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
732 type_ == booleanValue || type_ == nullValue;
733 case uintValue:
734 return isUInt() ||
735 (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
736 type_ == booleanValue || type_ == nullValue;
737 case realValue:
738 return isNumeric() || type_ == booleanValue || type_ == nullValue;
739 case booleanValue:
740 return isNumeric() || type_ == booleanValue || type_ == nullValue;
741 case stringValue:
742 return isNumeric() || type_ == booleanValue || type_ == stringValue ||
743 type_ == nullValue;
744 case arrayValue:
745 return type_ == arrayValue || type_ == nullValue;
746 case objectValue:
747 return type_ == objectValue || type_ == nullValue;
748 }
749 JSON_ASSERT_UNREACHABLE;
750 return false;
751 }
752
753 /// Number of values in array or object
size() const754 ArrayIndex Value::size() const {
755 switch (type_) {
756 case nullValue:
757 case intValue:
758 case uintValue:
759 case realValue:
760 case booleanValue:
761 case stringValue:
762 return 0;
763 #ifndef JSON_VALUE_USE_INTERNAL_MAP
764 case arrayValue: // size of the array is highest index + 1
765 if (!value_.map_->empty()) {
766 ObjectValues::const_iterator itLast = value_.map_->end();
767 --itLast;
768 return (*itLast).first.index() + 1;
769 }
770 return 0;
771 case objectValue:
772 return ArrayIndex(value_.map_->size());
773 #else
774 case arrayValue:
775 return Int(value_.array_->size());
776 case objectValue:
777 return Int(value_.map_->size());
778 #endif
779 }
780 JSON_ASSERT_UNREACHABLE;
781 return 0; // unreachable;
782 }
783
empty() const784 bool Value::empty() const {
785 if (isNull() || isArray() || isObject())
786 return size() == 0u;
787 else
788 return false;
789 }
790
operator !() const791 bool Value::operator!() const { return isNull(); }
792
clear()793 void Value::clear() {
794 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
795 type_ == objectValue,
796 "in Json::Value::clear(): requires complex value");
797 start_ = 0;
798 limit_ = 0;
799 switch (type_) {
800 #ifndef JSON_VALUE_USE_INTERNAL_MAP
801 case arrayValue:
802 case objectValue:
803 value_.map_->clear();
804 break;
805 #else
806 case arrayValue:
807 value_.array_->clear();
808 break;
809 case objectValue:
810 value_.map_->clear();
811 break;
812 #endif
813 default:
814 break;
815 }
816 }
817
resize(ArrayIndex newSize)818 void Value::resize(ArrayIndex newSize) {
819 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
820 "in Json::Value::resize(): requires arrayValue");
821 if (type_ == nullValue)
822 *this = Value(arrayValue);
823 #ifndef JSON_VALUE_USE_INTERNAL_MAP
824 ArrayIndex oldSize = size();
825 if (newSize == 0)
826 clear();
827 else if (newSize > oldSize)
828 (*this)[newSize - 1];
829 else {
830 for (ArrayIndex index = newSize; index < oldSize; ++index) {
831 value_.map_->erase(index);
832 }
833 assert(size() == newSize);
834 }
835 #else
836 value_.array_->resize(newSize);
837 #endif
838 }
839
operator [](ArrayIndex index)840 Value& Value::operator[](ArrayIndex index) {
841 JSON_ASSERT_MESSAGE(
842 type_ == nullValue || type_ == arrayValue,
843 "in Json::Value::operator[](ArrayIndex): requires arrayValue");
844 if (type_ == nullValue)
845 *this = Value(arrayValue);
846 #ifndef JSON_VALUE_USE_INTERNAL_MAP
847 CZString key(index);
848 ObjectValues::iterator it = value_.map_->lower_bound(key);
849 if (it != value_.map_->end() && (*it).first == key)
850 return (*it).second;
851
852 ObjectValues::value_type defaultValue(key, null);
853 it = value_.map_->insert(it, defaultValue);
854 return (*it).second;
855 #else
856 return value_.array_->resolveReference(index);
857 #endif
858 }
859
operator [](int index)860 Value& Value::operator[](int index) {
861 JSON_ASSERT_MESSAGE(
862 index >= 0,
863 "in Json::Value::operator[](int index): index cannot be negative");
864 return (*this)[ArrayIndex(index)];
865 }
866
operator [](ArrayIndex index) const867 const Value& Value::operator[](ArrayIndex index) const {
868 JSON_ASSERT_MESSAGE(
869 type_ == nullValue || type_ == arrayValue,
870 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
871 if (type_ == nullValue)
872 return null;
873 #ifndef JSON_VALUE_USE_INTERNAL_MAP
874 CZString key(index);
875 ObjectValues::const_iterator it = value_.map_->find(key);
876 if (it == value_.map_->end())
877 return null;
878 return (*it).second;
879 #else
880 Value* value = value_.array_->find(index);
881 return value ? *value : null;
882 #endif
883 }
884
operator [](int index) const885 const Value& Value::operator[](int index) const {
886 JSON_ASSERT_MESSAGE(
887 index >= 0,
888 "in Json::Value::operator[](int index) const: index cannot be negative");
889 return (*this)[ArrayIndex(index)];
890 }
891
operator [](const char * key)892 Value& Value::operator[](const char* key) {
893 return resolveReference(key, false);
894 }
895
initBasic(ValueType type,bool allocated)896 void Value::initBasic(ValueType type, bool allocated) {
897 type_ = type;
898 allocated_ = allocated;
899 #ifdef JSON_VALUE_USE_INTERNAL_MAP
900 itemIsUsed_ = 0;
901 #endif
902 comments_ = 0;
903 start_ = 0;
904 limit_ = 0;
905 }
906
resolveReference(const char * key,bool isStatic)907 Value& Value::resolveReference(const char* key, bool isStatic) {
908 JSON_ASSERT_MESSAGE(
909 type_ == nullValue || type_ == objectValue,
910 "in Json::Value::resolveReference(): requires objectValue");
911 if (type_ == nullValue)
912 *this = Value(objectValue);
913 #ifndef JSON_VALUE_USE_INTERNAL_MAP
914 CZString actualKey(
915 key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy);
916 ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
917 if (it != value_.map_->end() && (*it).first == actualKey)
918 return (*it).second;
919
920 ObjectValues::value_type defaultValue(actualKey, null);
921 it = value_.map_->insert(it, defaultValue);
922 Value& value = (*it).second;
923 return value;
924 #else
925 return value_.map_->resolveReference(key, isStatic);
926 #endif
927 }
928
get(ArrayIndex index,const Value & defaultValue) const929 Value Value::get(ArrayIndex index, const Value& defaultValue) const {
930 const Value* value = &((*this)[index]);
931 return value == &null ? defaultValue : *value;
932 }
933
isValidIndex(ArrayIndex index) const934 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
935
operator [](const char * key) const936 const Value& Value::operator[](const char* key) const {
937 JSON_ASSERT_MESSAGE(
938 type_ == nullValue || type_ == objectValue,
939 "in Json::Value::operator[](char const*)const: requires objectValue");
940 if (type_ == nullValue)
941 return null;
942 #ifndef JSON_VALUE_USE_INTERNAL_MAP
943 CZString actualKey(key, CZString::noDuplication);
944 ObjectValues::const_iterator it = value_.map_->find(actualKey);
945 if (it == value_.map_->end())
946 return null;
947 return (*it).second;
948 #else
949 const Value* value = value_.map_->find(key);
950 return value ? *value : null;
951 #endif
952 }
953
operator [](const std::string & key)954 Value& Value::operator[](const std::string& key) {
955 return (*this)[key.c_str()];
956 }
957
operator [](const std::string & key) const958 const Value& Value::operator[](const std::string& key) const {
959 return (*this)[key.c_str()];
960 }
961
operator [](const StaticString & key)962 Value& Value::operator[](const StaticString& key) {
963 return resolveReference(key, true);
964 }
965
966 #ifdef JSON_USE_CPPTL
operator [](const CppTL::ConstString & key)967 Value& Value::operator[](const CppTL::ConstString& key) {
968 return (*this)[key.c_str()];
969 }
970
operator [](const CppTL::ConstString & key) const971 const Value& Value::operator[](const CppTL::ConstString& key) const {
972 return (*this)[key.c_str()];
973 }
974 #endif
975
append(const Value & value)976 Value& Value::append(const Value& value) { return (*this)[size()] = value; }
977
get(const char * key,const Value & defaultValue) const978 Value Value::get(const char* key, const Value& defaultValue) const {
979 const Value* value = &((*this)[key]);
980 return value == &null ? defaultValue : *value;
981 }
982
get(const std::string & key,const Value & defaultValue) const983 Value Value::get(const std::string& key, const Value& defaultValue) const {
984 return get(key.c_str(), defaultValue);
985 }
986
removeMember(const char * key)987 Value Value::removeMember(const char* key) {
988 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
989 "in Json::Value::removeMember(): requires objectValue");
990 if (type_ == nullValue)
991 return null;
992 #ifndef JSON_VALUE_USE_INTERNAL_MAP
993 CZString actualKey(key, CZString::noDuplication);
994 ObjectValues::iterator it = value_.map_->find(actualKey);
995 if (it == value_.map_->end())
996 return null;
997 Value old(it->second);
998 value_.map_->erase(it);
999 return old;
1000 #else
1001 Value* value = value_.map_->find(key);
1002 if (value) {
1003 Value old(*value);
1004 value_.map_.remove(key);
1005 return old;
1006 } else {
1007 return null;
1008 }
1009 #endif
1010 }
1011
removeMember(const std::string & key)1012 Value Value::removeMember(const std::string& key) {
1013 return removeMember(key.c_str());
1014 }
1015
1016 #ifdef JSON_USE_CPPTL
get(const CppTL::ConstString & key,const Value & defaultValue) const1017 Value Value::get(const CppTL::ConstString& key,
1018 const Value& defaultValue) const {
1019 return get(key.c_str(), defaultValue);
1020 }
1021 #endif
1022
isMember(const char * key) const1023 bool Value::isMember(const char* key) const {
1024 const Value* value = &((*this)[key]);
1025 return value != &null;
1026 }
1027
isMember(const std::string & key) const1028 bool Value::isMember(const std::string& key) const {
1029 return isMember(key.c_str());
1030 }
1031
1032 #ifdef JSON_USE_CPPTL
isMember(const CppTL::ConstString & key) const1033 bool Value::isMember(const CppTL::ConstString& key) const {
1034 return isMember(key.c_str());
1035 }
1036 #endif
1037
getMemberNames() const1038 Value::Members Value::getMemberNames() const {
1039 JSON_ASSERT_MESSAGE(
1040 type_ == nullValue || type_ == objectValue,
1041 "in Json::Value::getMemberNames(), value must be objectValue");
1042 if (type_ == nullValue)
1043 return Value::Members();
1044 Members members;
1045 members.reserve(value_.map_->size());
1046 #ifndef JSON_VALUE_USE_INTERNAL_MAP
1047 ObjectValues::const_iterator it = value_.map_->begin();
1048 ObjectValues::const_iterator itEnd = value_.map_->end();
1049 for (; it != itEnd; ++it)
1050 members.push_back(std::string((*it).first.c_str()));
1051 #else
1052 ValueInternalMap::IteratorState it;
1053 ValueInternalMap::IteratorState itEnd;
1054 value_.map_->makeBeginIterator(it);
1055 value_.map_->makeEndIterator(itEnd);
1056 for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it))
1057 members.push_back(std::string(ValueInternalMap::key(it)));
1058 #endif
1059 return members;
1060 }
1061 //
1062 //# ifdef JSON_USE_CPPTL
1063 // EnumMemberNames
1064 // Value::enumMemberNames() const
1065 //{
1066 // if ( type_ == objectValue )
1067 // {
1068 // return CppTL::Enum::any( CppTL::Enum::transform(
1069 // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
1070 // MemberNamesTransform() ) );
1071 // }
1072 // return EnumMemberNames();
1073 //}
1074 //
1075 //
1076 // EnumValues
1077 // Value::enumValues() const
1078 //{
1079 // if ( type_ == objectValue || type_ == arrayValue )
1080 // return CppTL::Enum::anyValues( *(value_.map_),
1081 // CppTL::Type<const Value &>() );
1082 // return EnumValues();
1083 //}
1084 //
1085 //# endif
1086
IsIntegral(double d)1087 static bool IsIntegral(double d) {
1088 double integral_part;
1089 return modf(d, &integral_part) == 0.0;
1090 }
1091
isNull() const1092 bool Value::isNull() const { return type_ == nullValue; }
1093
isBool() const1094 bool Value::isBool() const { return type_ == booleanValue; }
1095
isInt() const1096 bool Value::isInt() const {
1097 switch (type_) {
1098 case intValue:
1099 return value_.int_ >= minInt && value_.int_ <= maxInt;
1100 case uintValue:
1101 return value_.uint_ <= UInt(maxInt);
1102 case realValue:
1103 return value_.real_ >= minInt && value_.real_ <= maxInt &&
1104 IsIntegral(value_.real_);
1105 default:
1106 break;
1107 }
1108 return false;
1109 }
1110
isUInt() const1111 bool Value::isUInt() const {
1112 switch (type_) {
1113 case intValue:
1114 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
1115 case uintValue:
1116 return value_.uint_ <= maxUInt;
1117 case realValue:
1118 return value_.real_ >= 0 && value_.real_ <= maxUInt &&
1119 IsIntegral(value_.real_);
1120 default:
1121 break;
1122 }
1123 return false;
1124 }
1125
isInt64() const1126 bool Value::isInt64() const {
1127 #if defined(JSON_HAS_INT64)
1128 switch (type_) {
1129 case intValue:
1130 return true;
1131 case uintValue:
1132 return value_.uint_ <= UInt64(maxInt64);
1133 case realValue:
1134 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
1135 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
1136 // require the value to be strictly less than the limit.
1137 return value_.real_ >= double(minInt64) &&
1138 value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
1139 default:
1140 break;
1141 }
1142 #endif // JSON_HAS_INT64
1143 return false;
1144 }
1145
isUInt64() const1146 bool Value::isUInt64() const {
1147 #if defined(JSON_HAS_INT64)
1148 switch (type_) {
1149 case intValue:
1150 return value_.int_ >= 0;
1151 case uintValue:
1152 return true;
1153 case realValue:
1154 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1155 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1156 // require the value to be strictly less than the limit.
1157 return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
1158 IsIntegral(value_.real_);
1159 default:
1160 break;
1161 }
1162 #endif // JSON_HAS_INT64
1163 return false;
1164 }
1165
isIntegral() const1166 bool Value::isIntegral() const {
1167 #if defined(JSON_HAS_INT64)
1168 return isInt64() || isUInt64();
1169 #else
1170 return isInt() || isUInt();
1171 #endif
1172 }
1173
isDouble() const1174 bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
1175
isNumeric() const1176 bool Value::isNumeric() const { return isIntegral() || isDouble(); }
1177
isString() const1178 bool Value::isString() const { return type_ == stringValue; }
1179
isArray() const1180 bool Value::isArray() const { return type_ == arrayValue; }
1181
isObject() const1182 bool Value::isObject() const { return type_ == objectValue; }
1183
setComment(const char * comment,CommentPlacement placement)1184 void Value::setComment(const char* comment, CommentPlacement placement) {
1185 if (!comments_)
1186 comments_ = new CommentInfo[numberOfCommentPlacement];
1187 comments_[placement].setComment(comment);
1188 }
1189
setComment(const std::string & comment,CommentPlacement placement)1190 void Value::setComment(const std::string& comment, CommentPlacement placement) {
1191 setComment(comment.c_str(), placement);
1192 }
1193
hasComment(CommentPlacement placement) const1194 bool Value::hasComment(CommentPlacement placement) const {
1195 return comments_ != 0 && comments_[placement].comment_ != 0;
1196 }
1197
getComment(CommentPlacement placement) const1198 std::string Value::getComment(CommentPlacement placement) const {
1199 if (hasComment(placement))
1200 return comments_[placement].comment_;
1201 return "";
1202 }
1203
setOffsetStart(size_t start)1204 void Value::setOffsetStart(size_t start) { start_ = start; }
1205
setOffsetLimit(size_t limit)1206 void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
1207
getOffsetStart() const1208 size_t Value::getOffsetStart() const { return start_; }
1209
getOffsetLimit() const1210 size_t Value::getOffsetLimit() const { return limit_; }
1211
toStyledString() const1212 std::string Value::toStyledString() const {
1213 StyledWriter writer;
1214 return writer.write(*this);
1215 }
1216
begin() const1217 Value::const_iterator Value::begin() const {
1218 switch (type_) {
1219 #ifdef JSON_VALUE_USE_INTERNAL_MAP
1220 case arrayValue:
1221 if (value_.array_) {
1222 ValueInternalArray::IteratorState it;
1223 value_.array_->makeBeginIterator(it);
1224 return const_iterator(it);
1225 }
1226 break;
1227 case objectValue:
1228 if (value_.map_) {
1229 ValueInternalMap::IteratorState it;
1230 value_.map_->makeBeginIterator(it);
1231 return const_iterator(it);
1232 }
1233 break;
1234 #else
1235 case arrayValue:
1236 case objectValue:
1237 if (value_.map_)
1238 return const_iterator(value_.map_->begin());
1239 break;
1240 #endif
1241 default:
1242 break;
1243 }
1244 return const_iterator();
1245 }
1246
end() const1247 Value::const_iterator Value::end() const {
1248 switch (type_) {
1249 #ifdef JSON_VALUE_USE_INTERNAL_MAP
1250 case arrayValue:
1251 if (value_.array_) {
1252 ValueInternalArray::IteratorState it;
1253 value_.array_->makeEndIterator(it);
1254 return const_iterator(it);
1255 }
1256 break;
1257 case objectValue:
1258 if (value_.map_) {
1259 ValueInternalMap::IteratorState it;
1260 value_.map_->makeEndIterator(it);
1261 return const_iterator(it);
1262 }
1263 break;
1264 #else
1265 case arrayValue:
1266 case objectValue:
1267 if (value_.map_)
1268 return const_iterator(value_.map_->end());
1269 break;
1270 #endif
1271 default:
1272 break;
1273 }
1274 return const_iterator();
1275 }
1276
begin()1277 Value::iterator Value::begin() {
1278 switch (type_) {
1279 #ifdef JSON_VALUE_USE_INTERNAL_MAP
1280 case arrayValue:
1281 if (value_.array_) {
1282 ValueInternalArray::IteratorState it;
1283 value_.array_->makeBeginIterator(it);
1284 return iterator(it);
1285 }
1286 break;
1287 case objectValue:
1288 if (value_.map_) {
1289 ValueInternalMap::IteratorState it;
1290 value_.map_->makeBeginIterator(it);
1291 return iterator(it);
1292 }
1293 break;
1294 #else
1295 case arrayValue:
1296 case objectValue:
1297 if (value_.map_)
1298 return iterator(value_.map_->begin());
1299 break;
1300 #endif
1301 default:
1302 break;
1303 }
1304 return iterator();
1305 }
1306
end()1307 Value::iterator Value::end() {
1308 switch (type_) {
1309 #ifdef JSON_VALUE_USE_INTERNAL_MAP
1310 case arrayValue:
1311 if (value_.array_) {
1312 ValueInternalArray::IteratorState it;
1313 value_.array_->makeEndIterator(it);
1314 return iterator(it);
1315 }
1316 break;
1317 case objectValue:
1318 if (value_.map_) {
1319 ValueInternalMap::IteratorState it;
1320 value_.map_->makeEndIterator(it);
1321 return iterator(it);
1322 }
1323 break;
1324 #else
1325 case arrayValue:
1326 case objectValue:
1327 if (value_.map_)
1328 return iterator(value_.map_->end());
1329 break;
1330 #endif
1331 default:
1332 break;
1333 }
1334 return iterator();
1335 }
1336
1337 // class PathArgument
1338 // //////////////////////////////////////////////////////////////////
1339
PathArgument()1340 PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
1341
PathArgument(ArrayIndex index)1342 PathArgument::PathArgument(ArrayIndex index)
1343 : key_(), index_(index), kind_(kindIndex) {}
1344
PathArgument(const char * key)1345 PathArgument::PathArgument(const char* key)
1346 : key_(key), index_(), kind_(kindKey) {}
1347
PathArgument(const std::string & key)1348 PathArgument::PathArgument(const std::string& key)
1349 : key_(key.c_str()), index_(), kind_(kindKey) {}
1350
1351 // class Path
1352 // //////////////////////////////////////////////////////////////////
1353
Path(const std::string & path,const PathArgument & a1,const PathArgument & a2,const PathArgument & a3,const PathArgument & a4,const PathArgument & a5)1354 Path::Path(const std::string& path,
1355 const PathArgument& a1,
1356 const PathArgument& a2,
1357 const PathArgument& a3,
1358 const PathArgument& a4,
1359 const PathArgument& a5) {
1360 InArgs in;
1361 in.push_back(&a1);
1362 in.push_back(&a2);
1363 in.push_back(&a3);
1364 in.push_back(&a4);
1365 in.push_back(&a5);
1366 makePath(path, in);
1367 }
1368
makePath(const std::string & path,const InArgs & in)1369 void Path::makePath(const std::string& path, const InArgs& in) {
1370 const char* current = path.c_str();
1371 const char* end = current + path.length();
1372 InArgs::const_iterator itInArg = in.begin();
1373 while (current != end) {
1374 if (*current == '[') {
1375 ++current;
1376 if (*current == '%')
1377 addPathInArg(path, in, itInArg, PathArgument::kindIndex);
1378 else {
1379 ArrayIndex index = 0;
1380 for (; current != end && *current >= '0' && *current <= '9'; ++current)
1381 index = index * 10 + ArrayIndex(*current - '0');
1382 args_.push_back(index);
1383 }
1384 if (current == end || *current++ != ']')
1385 invalidPath(path, int(current - path.c_str()));
1386 } else if (*current == '%') {
1387 addPathInArg(path, in, itInArg, PathArgument::kindKey);
1388 ++current;
1389 } else if (*current == '.') {
1390 ++current;
1391 } else {
1392 const char* beginName = current;
1393 while (current != end && !strchr("[.", *current))
1394 ++current;
1395 args_.push_back(std::string(beginName, current));
1396 }
1397 }
1398 }
1399
addPathInArg(const std::string &,const InArgs & in,InArgs::const_iterator & itInArg,PathArgument::Kind kind)1400 void Path::addPathInArg(const std::string& /*path*/,
1401 const InArgs& in,
1402 InArgs::const_iterator& itInArg,
1403 PathArgument::Kind kind) {
1404 if (itInArg == in.end()) {
1405 // Error: missing argument %d
1406 } else if ((*itInArg)->kind_ != kind) {
1407 // Error: bad argument type
1408 } else {
1409 args_.push_back(**itInArg);
1410 }
1411 }
1412
invalidPath(const std::string &,int)1413 void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
1414 // Error: invalid path.
1415 }
1416
resolve(const Value & root) const1417 const Value& Path::resolve(const Value& root) const {
1418 const Value* node = &root;
1419 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
1420 const PathArgument& arg = *it;
1421 if (arg.kind_ == PathArgument::kindIndex) {
1422 if (!node->isArray() || !node->isValidIndex(arg.index_)) {
1423 // Error: unable to resolve path (array value expected at position...
1424 }
1425 node = &((*node)[arg.index_]);
1426 } else if (arg.kind_ == PathArgument::kindKey) {
1427 if (!node->isObject()) {
1428 // Error: unable to resolve path (object value expected at position...)
1429 }
1430 node = &((*node)[arg.key_]);
1431 if (node == &Value::null) {
1432 // Error: unable to resolve path (object has no member named '' at
1433 // position...)
1434 }
1435 }
1436 }
1437 return *node;
1438 }
1439
resolve(const Value & root,const Value & defaultValue) const1440 Value Path::resolve(const Value& root, const Value& defaultValue) const {
1441 const Value* node = &root;
1442 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
1443 const PathArgument& arg = *it;
1444 if (arg.kind_ == PathArgument::kindIndex) {
1445 if (!node->isArray() || !node->isValidIndex(arg.index_))
1446 return defaultValue;
1447 node = &((*node)[arg.index_]);
1448 } else if (arg.kind_ == PathArgument::kindKey) {
1449 if (!node->isObject())
1450 return defaultValue;
1451 node = &((*node)[arg.key_]);
1452 if (node == &Value::null)
1453 return defaultValue;
1454 }
1455 }
1456 return *node;
1457 }
1458
make(Value & root) const1459 Value& Path::make(Value& root) const {
1460 Value* node = &root;
1461 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
1462 const PathArgument& arg = *it;
1463 if (arg.kind_ == PathArgument::kindIndex) {
1464 if (!node->isArray()) {
1465 // Error: node is not an array at position ...
1466 }
1467 node = &((*node)[arg.index_]);
1468 } else if (arg.kind_ == PathArgument::kindKey) {
1469 if (!node->isObject()) {
1470 // Error: node is not an object at position...
1471 }
1472 node = &((*node)[arg.key_]);
1473 }
1474 }
1475 return *node;
1476 }
1477
1478 } // namespace Json
1479