![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
json test
jsoncpp/src/lib_json/json_value.cpp@0:2ee762ea11b3, 2018-01-26 (annotated)
- Committer:
- tgw
- Date:
- Fri Jan 26 06:05:31 2018 +0000
- Revision:
- 0:2ee762ea11b3
json
Who changed what in which revision?
User | Revision | Line number | New 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 |