JsonCpp project page Classes Namespace JsonCpp home page

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