blob: b73deac17256f383c4bf528c791a8b56d71f035a [file] [log] [blame]
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001// 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)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05007#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
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040013#endif // if !defined(JSON_IS_AMALGAMATION)
14#include <math.h>
15#include <sstream>
16#include <utility>
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040017#include <cstring>
18#include <cassert>
19#ifdef JSON_USE_CPPTL
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050020#include <cpptl/conststring.h>
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040021#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050022#include <cstddef> // size_t
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040023
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050024#define JSON_ASSERT_UNREACHABLE assert(false)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040025
26namespace Json {
27
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050028// 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
36static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
37const unsigned char& kNullRef = kNull[0];
38const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
39
40const Int Value::minInt = Int(~(UInt(-1) / 2));
41const Int Value::maxInt = Int(UInt(-1) / 2);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040042const UInt Value::maxUInt = UInt(-1);
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050043#if defined(JSON_HAS_INT64)
44const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
45const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040046const 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.
50static const double maxUInt64AsDouble = 18446744073709551615.0;
51#endif // defined(JSON_HAS_INT64)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050052const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
53const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040054const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
55
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040056/// Unknown size marker
57static const unsigned int unknown = (unsigned)-1;
58
59#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
60template <typename T, typename U>
61static inline bool InRange(double d, T min, U max) {
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050062 return d >= min && d <= max;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040063}
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050064#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
65static inline double integerToDouble(Json::UInt64 value) {
66 return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040067}
68
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050069template <typename T> static inline double integerToDouble(T value) {
70 return static_cast<double>(value);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040071}
72
73template <typename T, typename U>
74static inline bool InRange(double d, T min, U max) {
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050075 return d >= integerToDouble(min) && d <= integerToDouble(max);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040076}
77#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
78
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040079/** 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 */
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050086static inline char* duplicateStringValue(const char* value,
87 unsigned int length = unknown) {
88 if (length == unknown)
89 length = (unsigned int)strlen(value);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040090
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050091 // 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040095
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050096 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400103}
104
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400105/** Free the string duplicated by duplicateStringValue().
106 */
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500107static inline void releaseStringValue(char* value) { free(value); }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400108
109} // namespace Json
110
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400111// //////////////////////////////////////////////////////////////////
112// //////////////////////////////////////////////////////////////////
113// //////////////////////////////////////////////////////////////////
114// ValueInternals...
115// //////////////////////////////////////////////////////////////////
116// //////////////////////////////////////////////////////////////////
117// //////////////////////////////////////////////////////////////////
118#if !defined(JSON_IS_AMALGAMATION)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500119#ifdef JSON_VALUE_USE_INTERNAL_MAP
120#include "json_internalarray.inl"
121#include "json_internalmap.inl"
122#endif // JSON_VALUE_USE_INTERNAL_MAP
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400123
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500124#include "json_valueiterator.inl"
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400125#endif // if !defined(JSON_IS_AMALGAMATION)
126
127namespace Json {
128
129// //////////////////////////////////////////////////////////////////
130// //////////////////////////////////////////////////////////////////
131// //////////////////////////////////////////////////////////////////
132// class Value::CommentInfo
133// //////////////////////////////////////////////////////////////////
134// //////////////////////////////////////////////////////////////////
135// //////////////////////////////////////////////////////////////////
136
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500137Value::CommentInfo::CommentInfo() : comment_(0) {}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400138
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500139Value::CommentInfo::~CommentInfo() {
140 if (comment_)
141 releaseStringValue(comment_);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400142}
143
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500144void 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);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400153}
154
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400155// //////////////////////////////////////////////////////////////////
156// //////////////////////////////////////////////////////////////////
157// //////////////////////////////////////////////////////////////////
158// class Value::CZString
159// //////////////////////////////////////////////////////////////////
160// //////////////////////////////////////////////////////////////////
161// //////////////////////////////////////////////////////////////////
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500162#ifndef JSON_VALUE_USE_INTERNAL_MAP
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400163
164// Notes: index_ indicates if the string was allocated when
165// a string is stored.
166
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500167Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {}
168
169Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate)
170 : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr),
171 index_(allocate) {}
172
173Value::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
182Value::CZString::~CZString() {
183 if (cstr_ && index_ == duplicate)
184 releaseStringValue(const_cast<char*>(cstr_));
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400185}
186
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500187void Value::CZString::swap(CZString& other) {
188 std::swap(cstr_, other.cstr_);
189 std::swap(index_, other.index_);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400190}
191
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500192Value::CZString& Value::CZString::operator=(CZString other) {
193 swap(other);
194 return *this;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400195}
196
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500197bool Value::CZString::operator<(const CZString& other) const {
198 if (cstr_)
199 return strcmp(cstr_, other.cstr_) < 0;
200 return index_ < other.index_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400201}
202
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500203bool Value::CZString::operator==(const CZString& other) const {
204 if (cstr_)
205 return strcmp(cstr_, other.cstr_) == 0;
206 return index_ == other.index_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400207}
208
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500209ArrayIndex Value::CZString::index() const { return index_; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400210
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500211const char* Value::CZString::c_str() const { return cstr_; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400212
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500213bool Value::CZString::isStaticString() const { return index_ == noDuplication; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400214
215#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
216
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400217// //////////////////////////////////////////////////////////////////
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 */
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500229Value::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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400244#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500245 case arrayValue:
246 case objectValue:
247 value_.map_ = new ObjectValues();
248 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400249#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500250 case arrayValue:
251 value_.array_ = arrayAllocator()->newArray();
252 break;
253 case objectValue:
254 value_.map_ = mapAllocator()->newMap();
255 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400256#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500257 case booleanValue:
258 value_.bool_ = false;
259 break;
260 default:
261 JSON_ASSERT_UNREACHABLE;
262 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400263}
264
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500265Value::Value(Int value) {
266 initBasic(intValue);
267 value_.int_ = value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400268}
269
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500270Value::Value(UInt value) {
271 initBasic(uintValue);
272 value_.uint_ = value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400273}
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500274#if defined(JSON_HAS_INT64)
275Value::Value(Int64 value) {
276 initBasic(intValue);
277 value_.int_ = value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400278}
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500279Value::Value(UInt64 value) {
280 initBasic(uintValue);
281 value_.uint_ = value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400282}
283#endif // defined(JSON_HAS_INT64)
284
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500285Value::Value(double value) {
286 initBasic(realValue);
287 value_.real_ = value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400288}
289
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500290Value::Value(const char* value) {
291 initBasic(stringValue, true);
292 value_.string_ = duplicateStringValue(value);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400293}
294
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500295Value::Value(const char* beginValue, const char* endValue) {
296 initBasic(stringValue, true);
297 value_.string_ =
298 duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue));
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400299}
300
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500301Value::Value(const std::string& value) {
302 initBasic(stringValue, true);
303 value_.string_ =
304 duplicateStringValue(value.c_str(), (unsigned int)value.length());
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400305}
306
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500307Value::Value(const StaticString& value) {
308 initBasic(stringValue);
309 value_.string_ = const_cast<char*>(value.c_str());
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400310}
311
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500312#ifdef JSON_USE_CPPTL
313Value::Value(const CppTL::ConstString& value) {
314 initBasic(stringValue, true);
315 value_.string_ = duplicateStringValue(value, value.length());
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400316}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400317#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500318
319Value::Value(bool value) {
320 initBasic(booleanValue);
321 value_.bool_ = value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400322}
323
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500324Value::Value(const Value& other)
325 : type_(other.type_), allocated_(false)
326#ifdef JSON_VALUE_USE_INTERNAL_MAP
327 ,
328 itemIsUsed_(0)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400329#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500330 ,
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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400349#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500350 case arrayValue:
351 case objectValue:
352 value_.map_ = new ObjectValues(*other.value_.map_);
353 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400354#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500355 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400361#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500362 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 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400373}
374
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500375Value::~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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400387#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500388 case arrayValue:
389 case objectValue:
390 delete value_.map_;
391 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400392#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500393 case arrayValue:
394 arrayAllocator()->destructArray(value_.array_);
395 break;
396 case objectValue:
397 mapAllocator()->destructMap(value_.map_);
398 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400399#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500400 default:
401 JSON_ASSERT_UNREACHABLE;
402 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400403
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500404 if (comments_)
405 delete[] comments_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400406}
407
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500408Value& Value::operator=(Value other) {
409 swap(other);
410 return *this;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400411}
412
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500413void 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_);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400423}
424
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500425ValueType Value::type() const { return type_; }
426
427int Value::compare(const Value& other) const {
428 if (*this < other)
429 return -1;
430 if (*this > other)
431 return 1;
432 return 0;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400433}
434
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500435bool 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);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400454#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500455 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 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400462#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500463 case arrayValue:
464 return value_.array_->compare(*(other.value_.array_)) < 0;
465 case objectValue:
466 return value_.map_->compare(*(other.value_.map_)) < 0;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400467#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500468 default:
469 JSON_ASSERT_UNREACHABLE;
470 }
471 return false; // unreachable
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400472}
473
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500474bool Value::operator<=(const Value& other) const { return !(other < *this); }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400475
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500476bool Value::operator>=(const Value& other) const { return !(*this < other); }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400477
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500478bool Value::operator>(const Value& other) const { return other < *this; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400479
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500480bool 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);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400503#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500504 case arrayValue:
505 case objectValue:
506 return value_.map_->size() == other.value_.map_->size() &&
507 (*value_.map_) == (*other.value_.map_);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400508#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500509 case arrayValue:
510 return value_.array_->compare(*(other.value_.array_)) == 0;
511 case objectValue:
512 return value_.map_->compare(*(other.value_.map_)) == 0;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400513#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500514 default:
515 JSON_ASSERT_UNREACHABLE;
516 }
517 return false; // unreachable
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400518}
519
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500520bool Value::operator!=(const Value& other) const { return !(*this == other); }
521
522const char* Value::asCString() const {
523 JSON_ASSERT_MESSAGE(type_ == stringValue,
524 "in Json::Value::asCString(): requires stringValue");
525 return value_.string_;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400526}
527
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500528std::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 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400545}
546
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500547#ifdef JSON_USE_CPPTL
548CppTL::ConstString Value::asConstString() const {
549 return CppTL::ConstString(asString().c_str());
550}
551#endif
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400552
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500553Value::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.");
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400573}
574
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500575Value::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.");
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400595}
596
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500597#if defined(JSON_HAS_INT64)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400598
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500599Value::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.");
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400618}
619
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500620Value::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.");
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400639}
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500640#endif // if defined(JSON_HAS_INT64)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400641
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500642LargestInt Value::asLargestInt() const {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400643#if defined(JSON_NO_INT64)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500644 return asInt();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400645#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500646 return asInt64();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400647#endif
648}
649
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500650LargestUInt Value::asLargestUInt() const {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400651#if defined(JSON_NO_INT64)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500652 return asUInt();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400653#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500654 return asUInt64();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400655#endif
656}
657
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500658double Value::asDouble() const {
659 switch (type_) {
660 case intValue:
661 return static_cast<double>(value_.int_);
662 case uintValue:
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400663#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500664 return static_cast<double>(value_.uint_);
665#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
666 return integerToDouble(value_.uint_);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400667#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500668 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.");
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400678}
679
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500680float Value::asFloat() const {
681 switch (type_) {
682 case intValue:
683 return static_cast<float>(value_.int_);
684 case uintValue:
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400685#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500686 return static_cast<float>(value_.uint_);
687#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
688 return integerToDouble(value_.uint_);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400689#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500690 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.");
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400700}
701
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500702bool 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.");
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400718}
719
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500720bool 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400751}
752
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400753/// Number of values in array or object
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500754ArrayIndex 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400763#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500764 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());
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400773#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500774 case arrayValue:
775 return Int(value_.array_->size());
776 case objectValue:
777 return Int(value_.map_->size());
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400778#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500779 }
780 JSON_ASSERT_UNREACHABLE;
781 return 0; // unreachable;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400782}
783
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500784bool Value::empty() const {
785 if (isNull() || isArray() || isObject())
786 return size() == 0u;
787 else
788 return false;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400789}
790
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500791bool Value::operator!() const { return isNull(); }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400792
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500793void 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_) {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400800#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500801 case arrayValue:
802 case objectValue:
803 value_.map_->clear();
804 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400805#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500806 case arrayValue:
807 value_.array_->clear();
808 break;
809 case objectValue:
810 value_.map_->clear();
811 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400812#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500813 default:
814 break;
815 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400816}
817
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500818void 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);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400823#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500824 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 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400835#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500836 value_.array_->resize(newSize);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400837#endif
838}
839
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500840Value& 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);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400846#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500847 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400851
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500852 ObjectValues::value_type defaultValue(key, null);
853 it = value_.map_->insert(it, defaultValue);
854 return (*it).second;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400855#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500856 return value_.array_->resolveReference(index);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400857#endif
858}
859
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500860Value& 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)];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400865}
866
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500867const 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400873#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500874 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400879#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500880 Value* value = value_.array_->find(index);
881 return value ? *value : null;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400882#endif
883}
884
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500885const 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)];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400890}
891
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500892Value& Value::operator[](const char* key) {
893 return resolveReference(key, false);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400894}
895
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500896void 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}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400906
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500907Value& 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);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400913#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500914 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400919
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500920 ObjectValues::value_type defaultValue(actualKey, null);
921 it = value_.map_->insert(it, defaultValue);
922 Value& value = (*it).second;
923 return value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400924#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500925 return value_.map_->resolveReference(key, isStatic);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400926#endif
927}
928
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500929Value Value::get(ArrayIndex index, const Value& defaultValue) const {
930 const Value* value = &((*this)[index]);
931 return value == &null ? defaultValue : *value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400932}
933
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500934bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400935
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500936const 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400942#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500943 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400948#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500949 const Value* value = value_.map_->find(key);
950 return value ? *value : null;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400951#endif
952}
953
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500954Value& Value::operator[](const std::string& key) {
955 return (*this)[key.c_str()];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400956}
957
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500958const Value& Value::operator[](const std::string& key) const {
959 return (*this)[key.c_str()];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400960}
961
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500962Value& Value::operator[](const StaticString& key) {
963 return resolveReference(key, true);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400964}
965
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500966#ifdef JSON_USE_CPPTL
967Value& Value::operator[](const CppTL::ConstString& key) {
968 return (*this)[key.c_str()];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400969}
970
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500971const Value& Value::operator[](const CppTL::ConstString& key) const {
972 return (*this)[key.c_str()];
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400973}
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500974#endif
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400975
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500976Value& Value::append(const Value& value) { return (*this)[size()] = value; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400977
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500978Value Value::get(const char* key, const Value& defaultValue) const {
979 const Value* value = &((*this)[key]);
980 return value == &null ? defaultValue : *value;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400981}
982
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500983Value Value::get(const std::string& key, const Value& defaultValue) const {
984 return get(key.c_str(), defaultValue);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400985}
986
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500987Value 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -0400992#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -0500993 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001000#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001001 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 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001009#endif
1010}
1011
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001012Value Value::removeMember(const std::string& key) {
1013 return removeMember(key.c_str());
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001014}
1015
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001016#ifdef JSON_USE_CPPTL
1017Value Value::get(const CppTL::ConstString& key,
1018 const Value& defaultValue) const {
1019 return get(key.c_str(), defaultValue);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001020}
1021#endif
1022
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001023bool Value::isMember(const char* key) const {
1024 const Value* value = &((*this)[key]);
1025 return value != &null;
1026}
1027
1028bool Value::isMember(const std::string& key) const {
1029 return isMember(key.c_str());
1030}
1031
1032#ifdef JSON_USE_CPPTL
1033bool Value::isMember(const CppTL::ConstString& key) const {
1034 return isMember(key.c_str());
1035}
1036#endif
1037
1038Value::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());
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001046#ifndef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001047 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()));
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001051#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001052 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)));
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001058#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001059 return members;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001060}
1061//
1062//# ifdef JSON_USE_CPPTL
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001063// EnumMemberNames
1064// Value::enumMemberNames() const
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001065//{
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//
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001076// EnumValues
1077// Value::enumValues() const
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001078//{
1079// if ( type_ == objectValue || type_ == arrayValue )
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001080// return CppTL::Enum::anyValues( *(value_.map_),
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001081// CppTL::Type<const Value &>() );
1082// return EnumValues();
1083//}
1084//
1085//# endif
1086
1087static bool IsIntegral(double d) {
1088 double integral_part;
1089 return modf(d, &integral_part) == 0.0;
1090}
1091
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001092bool Value::isNull() const { return type_ == nullValue; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001093
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001094bool Value::isBool() const { return type_ == booleanValue; }
1095
1096bool 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001109}
1110
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001111bool 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001124}
1125
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001126bool 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001144}
1145
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001146bool 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001164}
1165
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001166bool Value::isIntegral() const {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001167#if defined(JSON_HAS_INT64)
1168 return isInt64() || isUInt64();
1169#else
1170 return isInt() || isUInt();
1171#endif
1172}
1173
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001174bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001175
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001176bool Value::isNumeric() const { return isIntegral() || isDouble(); }
1177
1178bool Value::isString() const { return type_ == stringValue; }
1179
1180bool Value::isArray() const { return type_ == arrayValue; }
1181
1182bool Value::isObject() const { return type_ == objectValue; }
1183
1184void Value::setComment(const char* comment, CommentPlacement placement) {
1185 if (!comments_)
1186 comments_ = new CommentInfo[numberOfCommentPlacement];
1187 comments_[placement].setComment(comment);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001188}
1189
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001190void Value::setComment(const std::string& comment, CommentPlacement placement) {
1191 setComment(comment.c_str(), placement);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001192}
1193
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001194bool Value::hasComment(CommentPlacement placement) const {
1195 return comments_ != 0 && comments_[placement].comment_ != 0;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001196}
1197
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001198std::string Value::getComment(CommentPlacement placement) const {
1199 if (hasComment(placement))
1200 return comments_[placement].comment_;
1201 return "";
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001202}
1203
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001204void Value::setOffsetStart(size_t start) { start_ = start; }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001205
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001206void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
1207
1208size_t Value::getOffsetStart() const { return start_; }
1209
1210size_t Value::getOffsetLimit() const { return limit_; }
1211
1212std::string Value::toStyledString() const {
1213 StyledWriter writer;
1214 return writer.write(*this);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001215}
1216
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001217Value::const_iterator Value::begin() const {
1218 switch (type_) {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001219#ifdef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001220 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001234#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001235 case arrayValue:
1236 case objectValue:
1237 if (value_.map_)
1238 return const_iterator(value_.map_->begin());
1239 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001240#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001241 default:
1242 break;
1243 }
1244 return const_iterator();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001245}
1246
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001247Value::const_iterator Value::end() const {
1248 switch (type_) {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001249#ifdef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001250 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001264#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001265 case arrayValue:
1266 case objectValue:
1267 if (value_.map_)
1268 return const_iterator(value_.map_->end());
1269 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001270#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001271 default:
1272 break;
1273 }
1274 return const_iterator();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001275}
1276
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001277Value::iterator Value::begin() {
1278 switch (type_) {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001279#ifdef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001280 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001294#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001295 case arrayValue:
1296 case objectValue:
1297 if (value_.map_)
1298 return iterator(value_.map_->begin());
1299 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001300#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001301 default:
1302 break;
1303 }
1304 return iterator();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001305}
1306
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001307Value::iterator Value::end() {
1308 switch (type_) {
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001309#ifdef JSON_VALUE_USE_INTERNAL_MAP
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001310 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001324#else
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001325 case arrayValue:
1326 case objectValue:
1327 if (value_.map_)
1328 return iterator(value_.map_->end());
1329 break;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001330#endif
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001331 default:
1332 break;
1333 }
1334 return iterator();
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001335}
1336
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001337// class PathArgument
1338// //////////////////////////////////////////////////////////////////
1339
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001340PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001341
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001342PathArgument::PathArgument(ArrayIndex index)
1343 : key_(), index_(index), kind_(kindIndex) {}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001344
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001345PathArgument::PathArgument(const char* key)
1346 : key_(key), index_(), kind_(kindKey) {}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001347
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001348PathArgument::PathArgument(const std::string& key)
1349 : key_(key.c_str()), index_(), kind_(kindKey) {}
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001350
1351// class Path
1352// //////////////////////////////////////////////////////////////////
1353
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001354Path::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);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001367}
1368
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001369void 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);
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001383 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001384 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 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001398}
1399
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001400void 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 }
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001411}
1412
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001413void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
1414 // Error: invalid path.
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001415}
1416
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001417const 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...
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001424 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001425 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...)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001429 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001430 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001438}
1439
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001440Value 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;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001457}
1458
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001459Value& 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 ...
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001466 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001467 node = &((*node)[arg.index_]);
1468 } else if (arg.kind_ == PathArgument::kindKey) {
1469 if (!node->isObject()) {
1470 // Error: node is not an object at position...
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001471 }
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05001472 node = &((*node)[arg.key_]);
1473 }
1474 }
1475 return *node;
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001476}
1477
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001478} // namespace Json