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