LCOV - code coverage report
Current view: top level - toolkit/components/jsoncpp/src/lib_json - json_value.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 17 799 2.1 %
Date: 2017-07-14 16:53:18 Functions: 3 148 2.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13