• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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