Path: blob/master/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
3158 views
// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors1// Distributed under MIT license, or public domain if desired and2// recognized in your jurisdiction.3// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE45#if !defined(JSON_IS_AMALGAMATION)6#include <json/assertions.h>7#include <json/value.h>8#include <json/writer.h>9#endif // if !defined(JSON_IS_AMALGAMATION)10#include <algorithm>11#include <cassert>12#include <cmath>13#include <cstddef>14#include <cstring>15#include <iostream>16#include <sstream>17#include <utility>1819// Provide implementation equivalent of std::snprintf for older _MSC compilers20#if defined(_MSC_VER) && _MSC_VER < 190021#include <stdarg.h>22static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size,23const char* format, va_list ap) {24int count = -1;25if (size != 0)26count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);27if (count == -1)28count = _vscprintf(format, ap);29return count;30}3132int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,33const char* format, ...) {34va_list ap;35va_start(ap, format);36const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap);37va_end(ap);38return count;39}40#endif4142// Disable warning C4702 : unreachable code43#if defined(_MSC_VER)44#pragma warning(disable : 4702)45#endif4647#define JSON_ASSERT_UNREACHABLE assert(false)4849namespace Json {50template <typename T>51static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {52std::unique_ptr<T> r;53if (p) {54r = std::unique_ptr<T>(new T(*p));55}56return r;57}5859// This is a walkaround to avoid the static initialization of Value::null.60// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of61// 8 (instead of 4) as a bit of future-proofing.62#if defined(__ARMEL__)63#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))64#else65#define ALIGNAS(byte_alignment)66#endif6768// static69Value const& Value::nullSingleton() {70static Value const nullStatic;71return nullStatic;72}7374#if JSON_USE_NULLREF75// for backwards compatibility, we'll leave these global references around, but76// DO NOT use them in JSONCPP library code any more!77// static78Value const& Value::null = Value::nullSingleton();7980// static81Value const& Value::nullRef = Value::nullSingleton();82#endif8384#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)85template <typename T, typename U>86static inline bool InRange(double d, T min, U max) {87// The casts can lose precision, but we are looking only for88// an approximate range. Might fail on edge cases though. ~cdunn89return d >= static_cast<double>(min) && d <= static_cast<double>(max);90}91#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)92static inline double integerToDouble(Json::UInt64 value) {93return static_cast<double>(Int64(value / 2)) * 2.0 +94static_cast<double>(Int64(value & 1));95}9697template <typename T> static inline double integerToDouble(T value) {98return static_cast<double>(value);99}100101template <typename T, typename U>102static inline bool InRange(double d, T min, U max) {103return d >= integerToDouble(min) && d <= integerToDouble(max);104}105#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)106107/** Duplicates the specified string value.108* @param value Pointer to the string to duplicate. Must be zero-terminated if109* length is "unknown".110* @param length Length of the value. if equals to unknown, then it will be111* computed using strlen(value).112* @return Pointer on the duplicate instance of string.113*/114static inline char* duplicateStringValue(const char* value, size_t length) {115// Avoid an integer overflow in the call to malloc below by limiting length116// to a sane value.117if (length >= static_cast<size_t>(Value::maxInt))118length = Value::maxInt - 1;119120auto newString = static_cast<char*>(malloc(length + 1));121if (newString == nullptr) {122throwRuntimeError("in Json::Value::duplicateStringValue(): "123"Failed to allocate string value buffer");124}125memcpy(newString, value, length);126newString[length] = 0;127return newString;128}129130/* Record the length as a prefix.131*/132static inline char* duplicateAndPrefixStringValue(const char* value,133unsigned int length) {134// Avoid an integer overflow in the call to malloc below by limiting length135// to a sane value.136JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -137sizeof(unsigned) - 1U,138"in Json::Value::duplicateAndPrefixStringValue(): "139"length too big for prefixing");140size_t actualLength = sizeof(length) + length + 1;141auto newString = static_cast<char*>(malloc(actualLength));142if (newString == nullptr) {143throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "144"Failed to allocate string value buffer");145}146*reinterpret_cast<unsigned*>(newString) = length;147memcpy(newString + sizeof(unsigned), value, length);148newString[actualLength - 1U] =1490; // to avoid buffer over-run accidents by users later150return newString;151}152inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,153unsigned* length, char const** value) {154if (!isPrefixed) {155*length = static_cast<unsigned>(strlen(prefixed));156*value = prefixed;157} else {158*length = *reinterpret_cast<unsigned const*>(prefixed);159*value = prefixed + sizeof(unsigned);160}161}162/** Free the string duplicated by163* duplicateStringValue()/duplicateAndPrefixStringValue().164*/165#if JSONCPP_USING_SECURE_MEMORY166static inline void releasePrefixedStringValue(char* value) {167unsigned length = 0;168char const* valueDecoded;169decodePrefixedString(true, value, &length, &valueDecoded);170size_t const size = sizeof(unsigned) + length + 1U;171memset(value, 0, size);172free(value);173}174static inline void releaseStringValue(char* value, unsigned length) {175// length==0 => we allocated the strings memory176size_t size = (length == 0) ? strlen(value) : length;177memset(value, 0, size);178free(value);179}180#else // !JSONCPP_USING_SECURE_MEMORY181static inline void releasePrefixedStringValue(char* value) { free(value); }182static inline void releaseStringValue(char* value, unsigned) { free(value); }183#endif // JSONCPP_USING_SECURE_MEMORY184185} // namespace Json186187// //////////////////////////////////////////////////////////////////188// //////////////////////////////////////////////////////////////////189// //////////////////////////////////////////////////////////////////190// ValueInternals...191// //////////////////////////////////////////////////////////////////192// //////////////////////////////////////////////////////////////////193// //////////////////////////////////////////////////////////////////194#if !defined(JSON_IS_AMALGAMATION)195196#include "json_valueiterator.inl"197#endif // if !defined(JSON_IS_AMALGAMATION)198199namespace Json {200201#if JSON_USE_EXCEPTION202Exception::Exception(String msg) : msg_(std::move(msg)) {}203Exception::~Exception() noexcept = default;204char const* Exception::what() const noexcept { return msg_.c_str(); }205RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}206LogicError::LogicError(String const& msg) : Exception(msg) {}207JSONCPP_NORETURN void throwRuntimeError(String const& msg) {208throw RuntimeError(msg);209}210JSONCPP_NORETURN void throwLogicError(String const& msg) {211throw LogicError(msg);212}213#else // !JSON_USE_EXCEPTION214JSONCPP_NORETURN void throwRuntimeError(String const& msg) {215std::cerr << msg << std::endl;216abort();217}218JSONCPP_NORETURN void throwLogicError(String const& msg) {219std::cerr << msg << std::endl;220abort();221}222#endif223224// //////////////////////////////////////////////////////////////////225// //////////////////////////////////////////////////////////////////226// //////////////////////////////////////////////////////////////////227// class Value::CZString228// //////////////////////////////////////////////////////////////////229// //////////////////////////////////////////////////////////////////230// //////////////////////////////////////////////////////////////////231232// Notes: policy_ indicates if the string was allocated when233// a string is stored.234235Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}236237Value::CZString::CZString(char const* str, unsigned length,238DuplicationPolicy allocate)239: cstr_(str) {240// allocate != duplicate241storage_.policy_ = allocate & 0x3;242storage_.length_ = length & 0x3FFFFFFF;243}244245Value::CZString::CZString(const CZString& other) {246cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr247? duplicateStringValue(other.cstr_, other.storage_.length_)248: other.cstr_);249storage_.policy_ =250static_cast<unsigned>(251other.cstr_252? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==253noDuplication254? noDuplication255: duplicate)256: static_cast<DuplicationPolicy>(other.storage_.policy_)) &2573U;258storage_.length_ = other.storage_.length_;259}260261Value::CZString::CZString(CZString&& other) noexcept262: cstr_(other.cstr_), index_(other.index_) {263other.cstr_ = nullptr;264}265266Value::CZString::~CZString() {267if (cstr_ && storage_.policy_ == duplicate) {268releaseStringValue(const_cast<char*>(cstr_),269storage_.length_ + 1U); // +1 for null terminating270// character for sake of271// completeness but not actually272// necessary273}274}275276void Value::CZString::swap(CZString& other) {277std::swap(cstr_, other.cstr_);278std::swap(index_, other.index_);279}280281Value::CZString& Value::CZString::operator=(const CZString& other) {282cstr_ = other.cstr_;283index_ = other.index_;284return *this;285}286287Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {288cstr_ = other.cstr_;289index_ = other.index_;290other.cstr_ = nullptr;291return *this;292}293294bool Value::CZString::operator<(const CZString& other) const {295if (!cstr_)296return index_ < other.index_;297// return strcmp(cstr_, other.cstr_) < 0;298// Assume both are strings.299unsigned this_len = this->storage_.length_;300unsigned other_len = other.storage_.length_;301unsigned min_len = std::min<unsigned>(this_len, other_len);302JSON_ASSERT(this->cstr_ && other.cstr_);303int comp = memcmp(this->cstr_, other.cstr_, min_len);304if (comp < 0)305return true;306if (comp > 0)307return false;308return (this_len < other_len);309}310311bool Value::CZString::operator==(const CZString& other) const {312if (!cstr_)313return index_ == other.index_;314// return strcmp(cstr_, other.cstr_) == 0;315// Assume both are strings.316unsigned this_len = this->storage_.length_;317unsigned other_len = other.storage_.length_;318if (this_len != other_len)319return false;320JSON_ASSERT(this->cstr_ && other.cstr_);321int comp = memcmp(this->cstr_, other.cstr_, this_len);322return comp == 0;323}324325ArrayIndex Value::CZString::index() const { return index_; }326327// const char* Value::CZString::c_str() const { return cstr_; }328const char* Value::CZString::data() const { return cstr_; }329unsigned Value::CZString::length() const { return storage_.length_; }330bool Value::CZString::isStaticString() const {331return storage_.policy_ == noDuplication;332}333334// //////////////////////////////////////////////////////////////////335// //////////////////////////////////////////////////////////////////336// //////////////////////////////////////////////////////////////////337// class Value::Value338// //////////////////////////////////////////////////////////////////339// //////////////////////////////////////////////////////////////////340// //////////////////////////////////////////////////////////////////341342/*! internal Default constructor initialization must be equivalent to:343* memset( this, 0, sizeof(Value) )344* This optimization is used in ValueInternalMap fast allocator.345*/346Value::Value(ValueType type) {347static char const emptyString[] = "";348initBasic(type);349switch (type) {350case nullValue:351break;352case intValue:353case uintValue:354value_.int_ = 0;355break;356case realValue:357value_.real_ = 0.0;358break;359case stringValue:360// allocated_ == false, so this is safe.361value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));362break;363case arrayValue:364case objectValue:365value_.map_ = new ObjectValues();366break;367case booleanValue:368value_.bool_ = false;369break;370default:371JSON_ASSERT_UNREACHABLE;372}373}374375Value::Value(Int value) {376initBasic(intValue);377value_.int_ = value;378}379380Value::Value(UInt value) {381initBasic(uintValue);382value_.uint_ = value;383}384#if defined(JSON_HAS_INT64)385Value::Value(Int64 value) {386initBasic(intValue);387value_.int_ = value;388}389Value::Value(UInt64 value) {390initBasic(uintValue);391value_.uint_ = value;392}393#endif // defined(JSON_HAS_INT64)394395Value::Value(double value) {396initBasic(realValue);397value_.real_ = value;398}399400Value::Value(const char* value) {401initBasic(stringValue, true);402JSON_ASSERT_MESSAGE(value != nullptr,403"Null Value Passed to Value Constructor");404value_.string_ = duplicateAndPrefixStringValue(405value, static_cast<unsigned>(strlen(value)));406}407408Value::Value(const char* begin, const char* end) {409initBasic(stringValue, true);410value_.string_ =411duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));412}413414Value::Value(const String& value) {415initBasic(stringValue, true);416value_.string_ = duplicateAndPrefixStringValue(417value.data(), static_cast<unsigned>(value.length()));418}419420Value::Value(const StaticString& value) {421initBasic(stringValue);422value_.string_ = const_cast<char*>(value.c_str());423}424425Value::Value(bool value) {426initBasic(booleanValue);427value_.bool_ = value;428}429430Value::Value(const Value& other) {431dupPayload(other);432dupMeta(other);433}434435Value::Value(Value&& other) noexcept {436initBasic(nullValue);437swap(other);438}439440Value::~Value() {441releasePayload();442value_.uint_ = 0;443}444445Value& Value::operator=(const Value& other) {446Value(other).swap(*this);447return *this;448}449450Value& Value::operator=(Value&& other) noexcept {451other.swap(*this);452return *this;453}454455void Value::swapPayload(Value& other) {456std::swap(bits_, other.bits_);457std::swap(value_, other.value_);458}459460void Value::copyPayload(const Value& other) {461releasePayload();462dupPayload(other);463}464465void Value::swap(Value& other) {466swapPayload(other);467std::swap(comments_, other.comments_);468std::swap(start_, other.start_);469std::swap(limit_, other.limit_);470}471472void Value::copy(const Value& other) {473copyPayload(other);474dupMeta(other);475}476477ValueType Value::type() const {478return static_cast<ValueType>(bits_.value_type_);479}480481int Value::compare(const Value& other) const {482if (*this < other)483return -1;484if (*this > other)485return 1;486return 0;487}488489bool Value::operator<(const Value& other) const {490int typeDelta = type() - other.type();491if (typeDelta)492return typeDelta < 0;493switch (type()) {494case nullValue:495return false;496case intValue:497return value_.int_ < other.value_.int_;498case uintValue:499return value_.uint_ < other.value_.uint_;500case realValue:501return value_.real_ < other.value_.real_;502case booleanValue:503return value_.bool_ < other.value_.bool_;504case stringValue: {505if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {506return other.value_.string_ != nullptr;507}508unsigned this_len;509unsigned other_len;510char const* this_str;511char const* other_str;512decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,513&this_str);514decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,515&other_str);516unsigned min_len = std::min<unsigned>(this_len, other_len);517JSON_ASSERT(this_str && other_str);518int comp = memcmp(this_str, other_str, min_len);519if (comp < 0)520return true;521if (comp > 0)522return false;523return (this_len < other_len);524}525case arrayValue:526case objectValue: {527auto thisSize = value_.map_->size();528auto otherSize = other.value_.map_->size();529if (thisSize != otherSize)530return thisSize < otherSize;531return (*value_.map_) < (*other.value_.map_);532}533default:534JSON_ASSERT_UNREACHABLE;535}536return false; // unreachable537}538539bool Value::operator<=(const Value& other) const { return !(other < *this); }540541bool Value::operator>=(const Value& other) const { return !(*this < other); }542543bool Value::operator>(const Value& other) const { return other < *this; }544545bool Value::operator==(const Value& other) const {546if (type() != other.type())547return false;548switch (type()) {549case nullValue:550return true;551case intValue:552return value_.int_ == other.value_.int_;553case uintValue:554return value_.uint_ == other.value_.uint_;555case realValue:556return value_.real_ == other.value_.real_;557case booleanValue:558return value_.bool_ == other.value_.bool_;559case stringValue: {560if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {561return (value_.string_ == other.value_.string_);562}563unsigned this_len;564unsigned other_len;565char const* this_str;566char const* other_str;567decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,568&this_str);569decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,570&other_str);571if (this_len != other_len)572return false;573JSON_ASSERT(this_str && other_str);574int comp = memcmp(this_str, other_str, this_len);575return comp == 0;576}577case arrayValue:578case objectValue:579return value_.map_->size() == other.value_.map_->size() &&580(*value_.map_) == (*other.value_.map_);581default:582JSON_ASSERT_UNREACHABLE;583}584return false; // unreachable585}586587bool Value::operator!=(const Value& other) const { return !(*this == other); }588589const char* Value::asCString() const {590JSON_ASSERT_MESSAGE(type() == stringValue,591"in Json::Value::asCString(): requires stringValue");592if (value_.string_ == nullptr)593return nullptr;594unsigned this_len;595char const* this_str;596decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,597&this_str);598return this_str;599}600601#if JSONCPP_USING_SECURE_MEMORY602unsigned Value::getCStringLength() const {603JSON_ASSERT_MESSAGE(type() == stringValue,604"in Json::Value::asCString(): requires stringValue");605if (value_.string_ == 0)606return 0;607unsigned this_len;608char const* this_str;609decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,610&this_str);611return this_len;612}613#endif614615bool Value::getString(char const** begin, char const** end) const {616if (type() != stringValue)617return false;618if (value_.string_ == nullptr)619return false;620unsigned length;621decodePrefixedString(this->isAllocated(), this->value_.string_, &length,622begin);623*end = *begin + length;624return true;625}626627String Value::asString() const {628switch (type()) {629case nullValue:630return "";631case stringValue: {632if (value_.string_ == nullptr)633return "";634unsigned this_len;635char const* this_str;636decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,637&this_str);638return String(this_str, this_len);639}640case booleanValue:641return value_.bool_ ? "true" : "false";642case intValue:643return valueToString(value_.int_);644case uintValue:645return valueToString(value_.uint_);646case realValue:647return valueToString(value_.real_);648default:649JSON_FAIL_MESSAGE("Type is not convertible to string");650}651}652653Value::Int Value::asInt() const {654switch (type()) {655case intValue:656JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");657return Int(value_.int_);658case uintValue:659JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");660return Int(value_.uint_);661case realValue:662JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),663"double out of Int range");664return Int(value_.real_);665case nullValue:666return 0;667case booleanValue:668return value_.bool_ ? 1 : 0;669default:670break;671}672JSON_FAIL_MESSAGE("Value is not convertible to Int.");673}674675Value::UInt Value::asUInt() const {676switch (type()) {677case intValue:678JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");679return UInt(value_.int_);680case uintValue:681JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");682return UInt(value_.uint_);683case realValue:684JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),685"double out of UInt range");686return UInt(value_.real_);687case nullValue:688return 0;689case booleanValue:690return value_.bool_ ? 1 : 0;691default:692break;693}694JSON_FAIL_MESSAGE("Value is not convertible to UInt.");695}696697#if defined(JSON_HAS_INT64)698699Value::Int64 Value::asInt64() const {700switch (type()) {701case intValue:702return Int64(value_.int_);703case uintValue:704JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");705return Int64(value_.uint_);706case realValue:707JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),708"double out of Int64 range");709return Int64(value_.real_);710case nullValue:711return 0;712case booleanValue:713return value_.bool_ ? 1 : 0;714default:715break;716}717JSON_FAIL_MESSAGE("Value is not convertible to Int64.");718}719720Value::UInt64 Value::asUInt64() const {721switch (type()) {722case intValue:723JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");724return UInt64(value_.int_);725case uintValue:726return UInt64(value_.uint_);727case realValue:728JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),729"double out of UInt64 range");730return UInt64(value_.real_);731case nullValue:732return 0;733case booleanValue:734return value_.bool_ ? 1 : 0;735default:736break;737}738JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");739}740#endif // if defined(JSON_HAS_INT64)741742LargestInt Value::asLargestInt() const {743#if defined(JSON_NO_INT64)744return asInt();745#else746return asInt64();747#endif748}749750LargestUInt Value::asLargestUInt() const {751#if defined(JSON_NO_INT64)752return asUInt();753#else754return asUInt64();755#endif756}757758double Value::asDouble() const {759switch (type()) {760case intValue:761return static_cast<double>(value_.int_);762case uintValue:763#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)764return static_cast<double>(value_.uint_);765#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)766return integerToDouble(value_.uint_);767#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)768case realValue:769return value_.real_;770case nullValue:771return 0.0;772case booleanValue:773return value_.bool_ ? 1.0 : 0.0;774default:775break;776}777JSON_FAIL_MESSAGE("Value is not convertible to double.");778}779780float Value::asFloat() const {781switch (type()) {782case intValue:783return static_cast<float>(value_.int_);784case uintValue:785#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)786return static_cast<float>(value_.uint_);787#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)788// This can fail (silently?) if the value is bigger than MAX_FLOAT.789return static_cast<float>(integerToDouble(value_.uint_));790#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)791case realValue:792return static_cast<float>(value_.real_);793case nullValue:794return 0.0;795case booleanValue:796return value_.bool_ ? 1.0F : 0.0F;797default:798break;799}800JSON_FAIL_MESSAGE("Value is not convertible to float.");801}802803bool Value::asBool() const {804switch (type()) {805case booleanValue:806return value_.bool_;807case nullValue:808return false;809case intValue:810return value_.int_ != 0;811case uintValue:812return value_.uint_ != 0;813case realValue: {814// According to JavaScript language zero or NaN is regarded as false815const auto value_classification = std::fpclassify(value_.real_);816return value_classification != FP_ZERO && value_classification != FP_NAN;817}818default:819break;820}821JSON_FAIL_MESSAGE("Value is not convertible to bool.");822}823824bool Value::isConvertibleTo(ValueType other) const {825switch (other) {826case nullValue:827return (isNumeric() && asDouble() == 0.0) ||828(type() == booleanValue && !value_.bool_) ||829(type() == stringValue && asString().empty()) ||830(type() == arrayValue && value_.map_->empty()) ||831(type() == objectValue && value_.map_->empty()) ||832type() == nullValue;833case intValue:834return isInt() ||835(type() == realValue && InRange(value_.real_, minInt, maxInt)) ||836type() == booleanValue || type() == nullValue;837case uintValue:838return isUInt() ||839(type() == realValue && InRange(value_.real_, 0, maxUInt)) ||840type() == booleanValue || type() == nullValue;841case realValue:842return isNumeric() || type() == booleanValue || type() == nullValue;843case booleanValue:844return isNumeric() || type() == booleanValue || type() == nullValue;845case stringValue:846return isNumeric() || type() == booleanValue || type() == stringValue ||847type() == nullValue;848case arrayValue:849return type() == arrayValue || type() == nullValue;850case objectValue:851return type() == objectValue || type() == nullValue;852}853JSON_ASSERT_UNREACHABLE;854return false;855}856857/// Number of values in array or object858ArrayIndex Value::size() const {859switch (type()) {860case nullValue:861case intValue:862case uintValue:863case realValue:864case booleanValue:865case stringValue:866return 0;867case arrayValue: // size of the array is highest index + 1868if (!value_.map_->empty()) {869ObjectValues::const_iterator itLast = value_.map_->end();870--itLast;871return (*itLast).first.index() + 1;872}873return 0;874case objectValue:875return ArrayIndex(value_.map_->size());876}877JSON_ASSERT_UNREACHABLE;878return 0; // unreachable;879}880881bool Value::empty() const {882if (isNull() || isArray() || isObject())883return size() == 0U;884return false;885}886887Value::operator bool() const { return !isNull(); }888889void Value::clear() {890JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue ||891type() == objectValue,892"in Json::Value::clear(): requires complex value");893start_ = 0;894limit_ = 0;895switch (type()) {896case arrayValue:897case objectValue:898value_.map_->clear();899break;900default:901break;902}903}904905void Value::resize(ArrayIndex newSize) {906JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,907"in Json::Value::resize(): requires arrayValue");908if (type() == nullValue)909*this = Value(arrayValue);910ArrayIndex oldSize = size();911if (newSize == 0)912clear();913else if (newSize > oldSize)914for (ArrayIndex i = oldSize; i < newSize; ++i)915(*this)[i];916else {917for (ArrayIndex index = newSize; index < oldSize; ++index) {918value_.map_->erase(index);919}920JSON_ASSERT(size() == newSize);921}922}923924Value& Value::operator[](ArrayIndex index) {925JSON_ASSERT_MESSAGE(926type() == nullValue || type() == arrayValue,927"in Json::Value::operator[](ArrayIndex): requires arrayValue");928if (type() == nullValue)929*this = Value(arrayValue);930CZString key(index);931auto it = value_.map_->lower_bound(key);932if (it != value_.map_->end() && (*it).first == key)933return (*it).second;934935ObjectValues::value_type defaultValue(key, nullSingleton());936it = value_.map_->insert(it, defaultValue);937return (*it).second;938}939940Value& Value::operator[](int index) {941JSON_ASSERT_MESSAGE(942index >= 0,943"in Json::Value::operator[](int index): index cannot be negative");944return (*this)[ArrayIndex(index)];945}946947const Value& Value::operator[](ArrayIndex index) const {948JSON_ASSERT_MESSAGE(949type() == nullValue || type() == arrayValue,950"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");951if (type() == nullValue)952return nullSingleton();953CZString key(index);954ObjectValues::const_iterator it = value_.map_->find(key);955if (it == value_.map_->end())956return nullSingleton();957return (*it).second;958}959960const Value& Value::operator[](int index) const {961JSON_ASSERT_MESSAGE(962index >= 0,963"in Json::Value::operator[](int index) const: index cannot be negative");964return (*this)[ArrayIndex(index)];965}966967void Value::initBasic(ValueType type, bool allocated) {968setType(type);969setIsAllocated(allocated);970comments_ = Comments{};971start_ = 0;972limit_ = 0;973}974975void Value::dupPayload(const Value& other) {976setType(other.type());977setIsAllocated(false);978switch (type()) {979case nullValue:980case intValue:981case uintValue:982case realValue:983case booleanValue:984value_ = other.value_;985break;986case stringValue:987if (other.value_.string_ && other.isAllocated()) {988unsigned len;989char const* str;990decodePrefixedString(other.isAllocated(), other.value_.string_, &len,991&str);992value_.string_ = duplicateAndPrefixStringValue(str, len);993setIsAllocated(true);994} else {995value_.string_ = other.value_.string_;996}997break;998case arrayValue:999case objectValue:1000value_.map_ = new ObjectValues(*other.value_.map_);1001break;1002default:1003JSON_ASSERT_UNREACHABLE;1004}1005}10061007void Value::releasePayload() {1008switch (type()) {1009case nullValue:1010case intValue:1011case uintValue:1012case realValue:1013case booleanValue:1014break;1015case stringValue:1016if (isAllocated())1017releasePrefixedStringValue(value_.string_);1018break;1019case arrayValue:1020case objectValue:1021delete value_.map_;1022break;1023default:1024JSON_ASSERT_UNREACHABLE;1025}1026}10271028void Value::dupMeta(const Value& other) {1029comments_ = other.comments_;1030start_ = other.start_;1031limit_ = other.limit_;1032}10331034// Access an object value by name, create a null member if it does not exist.1035// @pre Type of '*this' is object or null.1036// @param key is null-terminated.1037Value& Value::resolveReference(const char* key) {1038JSON_ASSERT_MESSAGE(1039type() == nullValue || type() == objectValue,1040"in Json::Value::resolveReference(): requires objectValue");1041if (type() == nullValue)1042*this = Value(objectValue);1043CZString actualKey(key, static_cast<unsigned>(strlen(key)),1044CZString::noDuplication); // NOTE!1045auto it = value_.map_->lower_bound(actualKey);1046if (it != value_.map_->end() && (*it).first == actualKey)1047return (*it).second;10481049ObjectValues::value_type defaultValue(actualKey, nullSingleton());1050it = value_.map_->insert(it, defaultValue);1051Value& value = (*it).second;1052return value;1053}10541055// @param key is not null-terminated.1056Value& Value::resolveReference(char const* key, char const* end) {1057JSON_ASSERT_MESSAGE(1058type() == nullValue || type() == objectValue,1059"in Json::Value::resolveReference(key, end): requires objectValue");1060if (type() == nullValue)1061*this = Value(objectValue);1062CZString actualKey(key, static_cast<unsigned>(end - key),1063CZString::duplicateOnCopy);1064auto it = value_.map_->lower_bound(actualKey);1065if (it != value_.map_->end() && (*it).first == actualKey)1066return (*it).second;10671068ObjectValues::value_type defaultValue(actualKey, nullSingleton());1069it = value_.map_->insert(it, defaultValue);1070Value& value = (*it).second;1071return value;1072}10731074Value Value::get(ArrayIndex index, const Value& defaultValue) const {1075const Value* value = &((*this)[index]);1076return value == &nullSingleton() ? defaultValue : *value;1077}10781079bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }10801081Value const* Value::find(char const* begin, char const* end) const {1082JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,1083"in Json::Value::find(begin, end): requires "1084"objectValue or nullValue");1085if (type() == nullValue)1086return nullptr;1087CZString actualKey(begin, static_cast<unsigned>(end - begin),1088CZString::noDuplication);1089ObjectValues::const_iterator it = value_.map_->find(actualKey);1090if (it == value_.map_->end())1091return nullptr;1092return &(*it).second;1093}1094Value const* Value::find(const String& key) const {1095return find(key.data(), key.data() + key.length());1096}1097Value* Value::demand(char const* begin, char const* end) {1098JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,1099"in Json::Value::demand(begin, end): requires "1100"objectValue or nullValue");1101return &resolveReference(begin, end);1102}1103const Value& Value::operator[](const char* key) const {1104Value const* found = find(key, key + strlen(key));1105if (!found)1106return nullSingleton();1107return *found;1108}1109Value const& Value::operator[](const String& key) const {1110Value const* found = find(key);1111if (!found)1112return nullSingleton();1113return *found;1114}11151116Value& Value::operator[](const char* key) {1117return resolveReference(key, key + strlen(key));1118}11191120Value& Value::operator[](const String& key) {1121return resolveReference(key.data(), key.data() + key.length());1122}11231124Value& Value::operator[](const StaticString& key) {1125return resolveReference(key.c_str());1126}11271128Value& Value::append(const Value& value) { return append(Value(value)); }11291130Value& Value::append(Value&& value) {1131JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,1132"in Json::Value::append: requires arrayValue");1133if (type() == nullValue) {1134*this = Value(arrayValue);1135}1136return this->value_.map_->emplace(size(), std::move(value)).first->second;1137}11381139bool Value::insert(ArrayIndex index, const Value& newValue) {1140return insert(index, Value(newValue));1141}11421143bool Value::insert(ArrayIndex index, Value&& newValue) {1144JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,1145"in Json::Value::insert: requires arrayValue");1146ArrayIndex length = size();1147if (index > length) {1148return false;1149}1150for (ArrayIndex i = length; i > index; i--) {1151(*this)[i] = std::move((*this)[i - 1]);1152}1153(*this)[index] = std::move(newValue);1154return true;1155}11561157Value Value::get(char const* begin, char const* end,1158Value const& defaultValue) const {1159Value const* found = find(begin, end);1160return !found ? defaultValue : *found;1161}1162Value Value::get(char const* key, Value const& defaultValue) const {1163return get(key, key + strlen(key), defaultValue);1164}1165Value Value::get(String const& key, Value const& defaultValue) const {1166return get(key.data(), key.data() + key.length(), defaultValue);1167}11681169bool Value::removeMember(const char* begin, const char* end, Value* removed) {1170if (type() != objectValue) {1171return false;1172}1173CZString actualKey(begin, static_cast<unsigned>(end - begin),1174CZString::noDuplication);1175auto it = value_.map_->find(actualKey);1176if (it == value_.map_->end())1177return false;1178if (removed)1179*removed = std::move(it->second);1180value_.map_->erase(it);1181return true;1182}1183bool Value::removeMember(const char* key, Value* removed) {1184return removeMember(key, key + strlen(key), removed);1185}1186bool Value::removeMember(String const& key, Value* removed) {1187return removeMember(key.data(), key.data() + key.length(), removed);1188}1189void Value::removeMember(const char* key) {1190JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,1191"in Json::Value::removeMember(): requires objectValue");1192if (type() == nullValue)1193return;11941195CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);1196value_.map_->erase(actualKey);1197}1198void Value::removeMember(const String& key) { removeMember(key.c_str()); }11991200bool Value::removeIndex(ArrayIndex index, Value* removed) {1201if (type() != arrayValue) {1202return false;1203}1204CZString key(index);1205auto it = value_.map_->find(key);1206if (it == value_.map_->end()) {1207return false;1208}1209if (removed)1210*removed = std::move(it->second);1211ArrayIndex oldSize = size();1212// shift left all items left, into the place of the "removed"1213for (ArrayIndex i = index; i < (oldSize - 1); ++i) {1214CZString keey(i);1215(*value_.map_)[keey] = (*this)[i + 1];1216}1217// erase the last one ("leftover")1218CZString keyLast(oldSize - 1);1219auto itLast = value_.map_->find(keyLast);1220value_.map_->erase(itLast);1221return true;1222}12231224bool Value::isMember(char const* begin, char const* end) const {1225Value const* value = find(begin, end);1226return nullptr != value;1227}1228bool Value::isMember(char const* key) const {1229return isMember(key, key + strlen(key));1230}1231bool Value::isMember(String const& key) const {1232return isMember(key.data(), key.data() + key.length());1233}12341235Value::Members Value::getMemberNames() const {1236JSON_ASSERT_MESSAGE(1237type() == nullValue || type() == objectValue,1238"in Json::Value::getMemberNames(), value must be objectValue");1239if (type() == nullValue)1240return Value::Members();1241Members members;1242members.reserve(value_.map_->size());1243ObjectValues::const_iterator it = value_.map_->begin();1244ObjectValues::const_iterator itEnd = value_.map_->end();1245for (; it != itEnd; ++it) {1246members.push_back(String((*it).first.data(), (*it).first.length()));1247}1248return members;1249}12501251static bool IsIntegral(double d) {1252double integral_part;1253return modf(d, &integral_part) == 0.0;1254}12551256bool Value::isNull() const { return type() == nullValue; }12571258bool Value::isBool() const { return type() == booleanValue; }12591260bool Value::isInt() const {1261switch (type()) {1262case intValue:1263#if defined(JSON_HAS_INT64)1264return value_.int_ >= minInt && value_.int_ <= maxInt;1265#else1266return true;1267#endif1268case uintValue:1269return value_.uint_ <= UInt(maxInt);1270case realValue:1271return value_.real_ >= minInt && value_.real_ <= maxInt &&1272IsIntegral(value_.real_);1273default:1274break;1275}1276return false;1277}12781279bool Value::isUInt() const {1280switch (type()) {1281case intValue:1282#if defined(JSON_HAS_INT64)1283return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);1284#else1285return value_.int_ >= 0;1286#endif1287case uintValue:1288#if defined(JSON_HAS_INT64)1289return value_.uint_ <= maxUInt;1290#else1291return true;1292#endif1293case realValue:1294return value_.real_ >= 0 && value_.real_ <= maxUInt &&1295IsIntegral(value_.real_);1296default:1297break;1298}1299return false;1300}13011302bool Value::isInt64() const {1303#if defined(JSON_HAS_INT64)1304switch (type()) {1305case intValue:1306return true;1307case uintValue:1308return value_.uint_ <= UInt64(maxInt64);1309case realValue:1310// Note that maxInt64 (= 2^63 - 1) is not exactly representable as a1311// double, so double(maxInt64) will be rounded up to 2^63. Therefore we1312// require the value to be strictly less than the limit.1313return value_.real_ >= double(minInt64) &&1314value_.real_ < double(maxInt64) && IsIntegral(value_.real_);1315default:1316break;1317}1318#endif // JSON_HAS_INT641319return false;1320}13211322bool Value::isUInt64() const {1323#if defined(JSON_HAS_INT64)1324switch (type()) {1325case intValue:1326return value_.int_ >= 0;1327case uintValue:1328return true;1329case realValue:1330// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a1331// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we1332// require the value to be strictly less than the limit.1333return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&1334IsIntegral(value_.real_);1335default:1336break;1337}1338#endif // JSON_HAS_INT641339return false;1340}13411342bool Value::isIntegral() const {1343switch (type()) {1344case intValue:1345case uintValue:1346return true;1347case realValue:1348#if defined(JSON_HAS_INT64)1349// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a1350// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we1351// require the value to be strictly less than the limit.1352return value_.real_ >= double(minInt64) &&1353value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);1354#else1355return value_.real_ >= minInt && value_.real_ <= maxUInt &&1356IsIntegral(value_.real_);1357#endif // JSON_HAS_INT641358default:1359break;1360}1361return false;1362}13631364bool Value::isDouble() const {1365return type() == intValue || type() == uintValue || type() == realValue;1366}13671368bool Value::isNumeric() const { return isDouble(); }13691370bool Value::isString() const { return type() == stringValue; }13711372bool Value::isArray() const { return type() == arrayValue; }13731374bool Value::isObject() const { return type() == objectValue; }13751376Value::Comments::Comments(const Comments& that)1377: ptr_{cloneUnique(that.ptr_)} {}13781379Value::Comments::Comments(Comments&& that) noexcept1380: ptr_{std::move(that.ptr_)} {}13811382Value::Comments& Value::Comments::operator=(const Comments& that) {1383ptr_ = cloneUnique(that.ptr_);1384return *this;1385}13861387Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {1388ptr_ = std::move(that.ptr_);1389return *this;1390}13911392bool Value::Comments::has(CommentPlacement slot) const {1393return ptr_ && !(*ptr_)[slot].empty();1394}13951396String Value::Comments::get(CommentPlacement slot) const {1397if (!ptr_)1398return {};1399return (*ptr_)[slot];1400}14011402void Value::Comments::set(CommentPlacement slot, String comment) {1403if (slot >= CommentPlacement::numberOfCommentPlacement)1404return;1405if (!ptr_)1406ptr_ = std::unique_ptr<Array>(new Array());1407(*ptr_)[slot] = std::move(comment);1408}14091410void Value::setComment(String comment, CommentPlacement placement) {1411if (!comment.empty() && (comment.back() == '\n')) {1412// Always discard trailing newline, to aid indentation.1413comment.pop_back();1414}1415JSON_ASSERT_MESSAGE(1416comment.empty() || comment[0] == '/',1417"in Json::Value::setComment(): Comments must start with /");1418comments_.set(placement, std::move(comment));1419}14201421bool Value::hasComment(CommentPlacement placement) const {1422return comments_.has(placement);1423}14241425String Value::getComment(CommentPlacement placement) const {1426return comments_.get(placement);1427}14281429void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }14301431void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }14321433ptrdiff_t Value::getOffsetStart() const { return start_; }14341435ptrdiff_t Value::getOffsetLimit() const { return limit_; }14361437String Value::toStyledString() const {1438StreamWriterBuilder builder;14391440String out = this->hasComment(commentBefore) ? "\n" : "";1441out += Json::writeString(builder, *this);1442out += '\n';14431444return out;1445}14461447Value::const_iterator Value::begin() const {1448switch (type()) {1449case arrayValue:1450case objectValue:1451if (value_.map_)1452return const_iterator(value_.map_->begin());1453break;1454default:1455break;1456}1457return {};1458}14591460Value::const_iterator Value::end() const {1461switch (type()) {1462case arrayValue:1463case objectValue:1464if (value_.map_)1465return const_iterator(value_.map_->end());1466break;1467default:1468break;1469}1470return {};1471}14721473Value::iterator Value::begin() {1474switch (type()) {1475case arrayValue:1476case objectValue:1477if (value_.map_)1478return iterator(value_.map_->begin());1479break;1480default:1481break;1482}1483return iterator();1484}14851486Value::iterator Value::end() {1487switch (type()) {1488case arrayValue:1489case objectValue:1490if (value_.map_)1491return iterator(value_.map_->end());1492break;1493default:1494break;1495}1496return iterator();1497}14981499// class PathArgument1500// //////////////////////////////////////////////////////////////////15011502PathArgument::PathArgument() = default;15031504PathArgument::PathArgument(ArrayIndex index)1505: index_(index), kind_(kindIndex) {}15061507PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}15081509PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}15101511// class Path1512// //////////////////////////////////////////////////////////////////15131514Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,1515const PathArgument& a3, const PathArgument& a4,1516const PathArgument& a5) {1517InArgs in;1518in.reserve(5);1519in.push_back(&a1);1520in.push_back(&a2);1521in.push_back(&a3);1522in.push_back(&a4);1523in.push_back(&a5);1524makePath(path, in);1525}15261527void Path::makePath(const String& path, const InArgs& in) {1528const char* current = path.c_str();1529const char* end = current + path.length();1530auto itInArg = in.begin();1531while (current != end) {1532if (*current == '[') {1533++current;1534if (*current == '%')1535addPathInArg(path, in, itInArg, PathArgument::kindIndex);1536else {1537ArrayIndex index = 0;1538for (; current != end && *current >= '0' && *current <= '9'; ++current)1539index = index * 10 + ArrayIndex(*current - '0');1540args_.push_back(index);1541}1542if (current == end || *++current != ']')1543invalidPath(path, int(current - path.c_str()));1544} else if (*current == '%') {1545addPathInArg(path, in, itInArg, PathArgument::kindKey);1546++current;1547} else if (*current == '.' || *current == ']') {1548++current;1549} else {1550const char* beginName = current;1551while (current != end && !strchr("[.", *current))1552++current;1553args_.push_back(String(beginName, current));1554}1555}1556}15571558void Path::addPathInArg(const String& /*path*/, const InArgs& in,1559InArgs::const_iterator& itInArg,1560PathArgument::Kind kind) {1561if (itInArg == in.end()) {1562// Error: missing argument %d1563} else if ((*itInArg)->kind_ != kind) {1564// Error: bad argument type1565} else {1566args_.push_back(**itInArg++);1567}1568}15691570void Path::invalidPath(const String& /*path*/, int /*location*/) {1571// Error: invalid path.1572}15731574const Value& Path::resolve(const Value& root) const {1575const Value* node = &root;1576for (const auto& arg : args_) {1577if (arg.kind_ == PathArgument::kindIndex) {1578if (!node->isArray() || !node->isValidIndex(arg.index_)) {1579// Error: unable to resolve path (array value expected at position... )1580return Value::nullSingleton();1581}1582node = &((*node)[arg.index_]);1583} else if (arg.kind_ == PathArgument::kindKey) {1584if (!node->isObject()) {1585// Error: unable to resolve path (object value expected at position...)1586return Value::nullSingleton();1587}1588node = &((*node)[arg.key_]);1589if (node == &Value::nullSingleton()) {1590// Error: unable to resolve path (object has no member named '' at1591// position...)1592return Value::nullSingleton();1593}1594}1595}1596return *node;1597}15981599Value Path::resolve(const Value& root, const Value& defaultValue) const {1600const Value* node = &root;1601for (const auto& arg : args_) {1602if (arg.kind_ == PathArgument::kindIndex) {1603if (!node->isArray() || !node->isValidIndex(arg.index_))1604return defaultValue;1605node = &((*node)[arg.index_]);1606} else if (arg.kind_ == PathArgument::kindKey) {1607if (!node->isObject())1608return defaultValue;1609node = &((*node)[arg.key_]);1610if (node == &Value::nullSingleton())1611return defaultValue;1612}1613}1614return *node;1615}16161617Value& Path::make(Value& root) const {1618Value* node = &root;1619for (const auto& arg : args_) {1620if (arg.kind_ == PathArgument::kindIndex) {1621if (!node->isArray()) {1622// Error: node is not an array at position ...1623}1624node = &((*node)[arg.index_]);1625} else if (arg.kind_ == PathArgument::kindKey) {1626if (!node->isObject()) {1627// Error: node is not an object at position...1628}1629node = &((*node)[arg.key_]);1630}1631}1632return *node;1633}16341635} // namespace Json163616371638