JsonCpp project page JsonCpp home page

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