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