json test

Committer:
tgw
Date:
Fri Jan 26 06:05:31 2018 +0000
Revision:
0:2ee762ea11b3
json

Who changed what in which revision?

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