12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634 |
- // Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
- // Distributed under MIT license, or public domain if desired and
- // recognized in your jurisdiction.
- // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
- #if !defined(JSON_IS_AMALGAMATION)
- #include <json/assertions.h>
- #include <json/value.h>
- #include <json/writer.h>
- #endif // if !defined(JSON_IS_AMALGAMATION)
- #include <algorithm>
- #include <cassert>
- #include <cmath>
- #include <cstddef>
- #include <cstring>
- #include <iostream>
- #include <sstream>
- #include <utility>
- // Provide implementation equivalent of std::snprintf for older _MSC compilers
- #if defined(_MSC_VER) && _MSC_VER < 1900
- #include <stdarg.h>
- static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size,
- const char* format, va_list ap) {
- int count = -1;
- if (size != 0)
- count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
- if (count == -1)
- count = _vscprintf(format, ap);
- return count;
- }
- int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
- const char* format, ...) {
- va_list ap;
- va_start(ap, format);
- const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap);
- va_end(ap);
- return count;
- }
- #endif
- // Disable warning C4702 : unreachable code
- #if defined(_MSC_VER)
- #pragma warning(disable : 4702)
- #endif
- #define JSON_ASSERT_UNREACHABLE assert(false)
- namespace Json {
- template <typename T>
- static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {
- std::unique_ptr<T> r;
- if (p) {
- r = std::unique_ptr<T>(new T(*p));
- }
- return r;
- }
- // This is a walkaround to avoid the static initialization of Value::null.
- // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
- // 8 (instead of 4) as a bit of future-proofing.
- #if defined(__ARMEL__)
- #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
- #else
- #define ALIGNAS(byte_alignment)
- #endif
- // static
- Value const& Value::nullSingleton() {
- static Value const nullStatic;
- return nullStatic;
- }
- #if JSON_USE_NULLREF
- // for backwards compatibility, we'll leave these global references around, but
- // DO NOT use them in JSONCPP library code any more!
- // static
- Value const& Value::null = Value::nullSingleton();
- // static
- Value const& Value::nullRef = Value::nullSingleton();
- #endif
- #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- template <typename T, typename U>
- static inline bool InRange(double d, T min, U max) {
- // The casts can lose precision, but we are looking only for
- // an approximate range. Might fail on edge cases though. ~cdunn
- return d >= static_cast<double>(min) && d <= static_cast<double>(max);
- }
- #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- static inline double integerToDouble(Json::UInt64 value) {
- return static_cast<double>(Int64(value / 2)) * 2.0 +
- static_cast<double>(Int64(value & 1));
- }
- template <typename T> static inline double integerToDouble(T value) {
- return static_cast<double>(value);
- }
- template <typename T, typename U>
- static inline bool InRange(double d, T min, U max) {
- return d >= integerToDouble(min) && d <= integerToDouble(max);
- }
- #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- /** Duplicates the specified string value.
- * @param value Pointer to the string to duplicate. Must be zero-terminated if
- * length is "unknown".
- * @param length Length of the value. if equals to unknown, then it will be
- * computed using strlen(value).
- * @return Pointer on the duplicate instance of string.
- */
- static inline char* duplicateStringValue(const char* value, size_t length) {
- // Avoid an integer overflow in the call to malloc below by limiting length
- // to a sane value.
- if (length >= static_cast<size_t>(Value::maxInt))
- length = Value::maxInt - 1;
- auto newString = static_cast<char*>(malloc(length + 1));
- if (newString == nullptr) {
- throwRuntimeError("in Json::Value::duplicateStringValue(): "
- "Failed to allocate string value buffer");
- }
- memcpy(newString, value, length);
- newString[length] = 0;
- return newString;
- }
- /* Record the length as a prefix.
- */
- static inline char* duplicateAndPrefixStringValue(const char* value,
- unsigned int length) {
- // Avoid an integer overflow in the call to malloc below by limiting length
- // to a sane value.
- JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -
- sizeof(unsigned) - 1U,
- "in Json::Value::duplicateAndPrefixStringValue(): "
- "length too big for prefixing");
- size_t actualLength = sizeof(length) + length + 1;
- auto newString = static_cast<char*>(malloc(actualLength));
- if (newString == nullptr) {
- throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
- "Failed to allocate string value buffer");
- }
- *reinterpret_cast<unsigned*>(newString) = length;
- memcpy(newString + sizeof(unsigned), value, length);
- newString[actualLength - 1U] =
- 0; // to avoid buffer over-run accidents by users later
- return newString;
- }
- inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
- unsigned* length, char const** value) {
- if (!isPrefixed) {
- *length = static_cast<unsigned>(strlen(prefixed));
- *value = prefixed;
- } else {
- *length = *reinterpret_cast<unsigned const*>(prefixed);
- *value = prefixed + sizeof(unsigned);
- }
- }
- /** Free the string duplicated by
- * duplicateStringValue()/duplicateAndPrefixStringValue().
- */
- #if JSONCPP_USING_SECURE_MEMORY
- static inline void releasePrefixedStringValue(char* value) {
- unsigned length = 0;
- char const* valueDecoded;
- decodePrefixedString(true, value, &length, &valueDecoded);
- size_t const size = sizeof(unsigned) + length + 1U;
- memset(value, 0, size);
- free(value);
- }
- static inline void releaseStringValue(char* value, unsigned length) {
- // length==0 => we allocated the strings memory
- size_t size = (length == 0) ? strlen(value) : length;
- memset(value, 0, size);
- free(value);
- }
- #else // !JSONCPP_USING_SECURE_MEMORY
- static inline void releasePrefixedStringValue(char* value) { free(value); }
- static inline void releaseStringValue(char* value, unsigned) { free(value); }
- #endif // JSONCPP_USING_SECURE_MEMORY
- } // namespace Json
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // ValueInternals...
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- #if !defined(JSON_IS_AMALGAMATION)
- #include "json_valueiterator.inl"
- #endif // if !defined(JSON_IS_AMALGAMATION)
- namespace Json {
- #if JSON_USE_EXCEPTION
- Exception::Exception(String msg) : msg_(std::move(msg)) {}
- Exception::~Exception() noexcept = default;
- char const* Exception::what() const noexcept { return msg_.c_str(); }
- RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
- LogicError::LogicError(String const& msg) : Exception(msg) {}
- JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
- throw RuntimeError(msg);
- }
- JSONCPP_NORETURN void throwLogicError(String const& msg) {
- throw LogicError(msg);
- }
- #else // !JSON_USE_EXCEPTION
- JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
- std::cerr << msg << std::endl;
- abort();
- }
- JSONCPP_NORETURN void throwLogicError(String const& msg) {
- std::cerr << msg << std::endl;
- abort();
- }
- #endif
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // class Value::CZString
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // Notes: policy_ indicates if the string was allocated when
- // a string is stored.
- Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
- Value::CZString::CZString(char const* str, unsigned length,
- DuplicationPolicy allocate)
- : cstr_(str) {
- // allocate != duplicate
- storage_.policy_ = allocate & 0x3;
- storage_.length_ = length & 0x3FFFFFFF;
- }
- Value::CZString::CZString(const CZString& other) {
- cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
- ? duplicateStringValue(other.cstr_, other.storage_.length_)
- : other.cstr_);
- storage_.policy_ =
- static_cast<unsigned>(
- other.cstr_
- ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
- noDuplication
- ? noDuplication
- : duplicate)
- : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
- 3U;
- storage_.length_ = other.storage_.length_;
- }
- Value::CZString::CZString(CZString&& other) noexcept
- : cstr_(other.cstr_), index_(other.index_) {
- other.cstr_ = nullptr;
- }
- Value::CZString::~CZString() {
- if (cstr_ && storage_.policy_ == duplicate) {
- releaseStringValue(const_cast<char*>(cstr_),
- storage_.length_ + 1U); // +1 for null terminating
- // character for sake of
- // completeness but not actually
- // necessary
- }
- }
- void Value::CZString::swap(CZString& other) {
- std::swap(cstr_, other.cstr_);
- std::swap(index_, other.index_);
- }
- Value::CZString& Value::CZString::operator=(const CZString& other) {
- cstr_ = other.cstr_;
- index_ = other.index_;
- return *this;
- }
- Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
- cstr_ = other.cstr_;
- index_ = other.index_;
- other.cstr_ = nullptr;
- return *this;
- }
- bool Value::CZString::operator<(const CZString& other) const {
- if (!cstr_)
- return index_ < other.index_;
- // return strcmp(cstr_, other.cstr_) < 0;
- // Assume both are strings.
- unsigned this_len = this->storage_.length_;
- unsigned other_len = other.storage_.length_;
- unsigned min_len = std::min<unsigned>(this_len, other_len);
- JSON_ASSERT(this->cstr_ && other.cstr_);
- int comp = memcmp(this->cstr_, other.cstr_, min_len);
- if (comp < 0)
- return true;
- if (comp > 0)
- return false;
- return (this_len < other_len);
- }
- bool Value::CZString::operator==(const CZString& other) const {
- if (!cstr_)
- return index_ == other.index_;
- // return strcmp(cstr_, other.cstr_) == 0;
- // Assume both are strings.
- unsigned this_len = this->storage_.length_;
- unsigned other_len = other.storage_.length_;
- if (this_len != other_len)
- return false;
- JSON_ASSERT(this->cstr_ && other.cstr_);
- int comp = memcmp(this->cstr_, other.cstr_, this_len);
- return comp == 0;
- }
- ArrayIndex Value::CZString::index() const { return index_; }
- // const char* Value::CZString::c_str() const { return cstr_; }
- const char* Value::CZString::data() const { return cstr_; }
- unsigned Value::CZString::length() const { return storage_.length_; }
- bool Value::CZString::isStaticString() const {
- return storage_.policy_ == noDuplication;
- }
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // class Value::Value
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- // //////////////////////////////////////////////////////////////////
- /*! \internal Default constructor initialization must be equivalent to:
- * memset( this, 0, sizeof(Value) )
- * This optimization is used in ValueInternalMap fast allocator.
- */
- Value::Value(ValueType type) {
- static char const emptyString[] = "";
- initBasic(type);
- switch (type) {
- case nullValue:
- break;
- case intValue:
- case uintValue:
- value_.int_ = 0;
- break;
- case realValue:
- value_.real_ = 0.0;
- break;
- case stringValue:
- // allocated_ == false, so this is safe.
- value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
- break;
- case arrayValue:
- case objectValue:
- value_.map_ = new ObjectValues();
- break;
- case booleanValue:
- value_.bool_ = false;
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- }
- Value::Value(Int value) {
- initBasic(intValue);
- value_.int_ = value;
- }
- Value::Value(UInt value) {
- initBasic(uintValue);
- value_.uint_ = value;
- }
- #if defined(JSON_HAS_INT64)
- Value::Value(Int64 value) {
- initBasic(intValue);
- value_.int_ = value;
- }
- Value::Value(UInt64 value) {
- initBasic(uintValue);
- value_.uint_ = value;
- }
- #endif // defined(JSON_HAS_INT64)
- Value::Value(double value) {
- initBasic(realValue);
- value_.real_ = value;
- }
- Value::Value(const char* value) {
- initBasic(stringValue, true);
- JSON_ASSERT_MESSAGE(value != nullptr,
- "Null Value Passed to Value Constructor");
- value_.string_ = duplicateAndPrefixStringValue(
- value, static_cast<unsigned>(strlen(value)));
- }
- Value::Value(const char* begin, const char* end) {
- initBasic(stringValue, true);
- value_.string_ =
- duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
- }
- Value::Value(const String& value) {
- initBasic(stringValue, true);
- value_.string_ = duplicateAndPrefixStringValue(
- value.data(), static_cast<unsigned>(value.length()));
- }
- Value::Value(const StaticString& value) {
- initBasic(stringValue);
- value_.string_ = const_cast<char*>(value.c_str());
- }
- Value::Value(bool value) {
- initBasic(booleanValue);
- value_.bool_ = value;
- }
- Value::Value(const Value& other) {
- dupPayload(other);
- dupMeta(other);
- }
- Value::Value(Value&& other) noexcept {
- initBasic(nullValue);
- swap(other);
- }
- Value::~Value() {
- releasePayload();
- value_.uint_ = 0;
- }
- Value& Value::operator=(const Value& other) {
- Value(other).swap(*this);
- return *this;
- }
- Value& Value::operator=(Value&& other) noexcept {
- other.swap(*this);
- return *this;
- }
- void Value::swapPayload(Value& other) {
- std::swap(bits_, other.bits_);
- std::swap(value_, other.value_);
- }
- void Value::copyPayload(const Value& other) {
- releasePayload();
- dupPayload(other);
- }
- void Value::swap(Value& other) {
- swapPayload(other);
- std::swap(comments_, other.comments_);
- std::swap(start_, other.start_);
- std::swap(limit_, other.limit_);
- }
- void Value::copy(const Value& other) {
- copyPayload(other);
- dupMeta(other);
- }
- ValueType Value::type() const {
- return static_cast<ValueType>(bits_.value_type_);
- }
- int Value::compare(const Value& other) const {
- if (*this < other)
- return -1;
- if (*this > other)
- return 1;
- return 0;
- }
- bool Value::operator<(const Value& other) const {
- int typeDelta = type() - other.type();
- if (typeDelta)
- return typeDelta < 0;
- switch (type()) {
- case nullValue:
- return false;
- case intValue:
- return value_.int_ < other.value_.int_;
- case uintValue:
- return value_.uint_ < other.value_.uint_;
- case realValue:
- return value_.real_ < other.value_.real_;
- case booleanValue:
- return value_.bool_ < other.value_.bool_;
- case stringValue: {
- if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
- return other.value_.string_ != nullptr;
- }
- unsigned this_len;
- unsigned other_len;
- char const* this_str;
- char const* other_str;
- decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
- &this_str);
- decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
- &other_str);
- unsigned min_len = std::min<unsigned>(this_len, other_len);
- JSON_ASSERT(this_str && other_str);
- int comp = memcmp(this_str, other_str, min_len);
- if (comp < 0)
- return true;
- if (comp > 0)
- return false;
- return (this_len < other_len);
- }
- case arrayValue:
- case objectValue: {
- auto thisSize = value_.map_->size();
- auto otherSize = other.value_.map_->size();
- if (thisSize != otherSize)
- return thisSize < otherSize;
- return (*value_.map_) < (*other.value_.map_);
- }
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return false; // unreachable
- }
- bool Value::operator<=(const Value& other) const { return !(other < *this); }
- bool Value::operator>=(const Value& other) const { return !(*this < other); }
- bool Value::operator>(const Value& other) const { return other < *this; }
- bool Value::operator==(const Value& other) const {
- if (type() != other.type())
- return false;
- switch (type()) {
- case nullValue:
- return true;
- case intValue:
- return value_.int_ == other.value_.int_;
- case uintValue:
- return value_.uint_ == other.value_.uint_;
- case realValue:
- return value_.real_ == other.value_.real_;
- case booleanValue:
- return value_.bool_ == other.value_.bool_;
- case stringValue: {
- if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
- return (value_.string_ == other.value_.string_);
- }
- unsigned this_len;
- unsigned other_len;
- char const* this_str;
- char const* other_str;
- decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
- &this_str);
- decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
- &other_str);
- if (this_len != other_len)
- return false;
- JSON_ASSERT(this_str && other_str);
- int comp = memcmp(this_str, other_str, this_len);
- return comp == 0;
- }
- case arrayValue:
- case objectValue:
- return value_.map_->size() == other.value_.map_->size() &&
- (*value_.map_) == (*other.value_.map_);
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- return false; // unreachable
- }
- bool Value::operator!=(const Value& other) const { return !(*this == other); }
- const char* Value::asCString() const {
- JSON_ASSERT_MESSAGE(type() == stringValue,
- "in Json::Value::asCString(): requires stringValue");
- if (value_.string_ == nullptr)
- return nullptr;
- unsigned this_len;
- char const* this_str;
- decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
- &this_str);
- return this_str;
- }
- #if JSONCPP_USING_SECURE_MEMORY
- unsigned Value::getCStringLength() const {
- JSON_ASSERT_MESSAGE(type() == stringValue,
- "in Json::Value::asCString(): requires stringValue");
- if (value_.string_ == 0)
- return 0;
- unsigned this_len;
- char const* this_str;
- decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
- &this_str);
- return this_len;
- }
- #endif
- bool Value::getString(char const** begin, char const** end) const {
- if (type() != stringValue)
- return false;
- if (value_.string_ == nullptr)
- return false;
- unsigned length;
- decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
- begin);
- *end = *begin + length;
- return true;
- }
- String Value::asString() const {
- switch (type()) {
- case nullValue:
- return "";
- case stringValue: {
- if (value_.string_ == nullptr)
- return "";
- unsigned this_len;
- char const* this_str;
- decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
- &this_str);
- return String(this_str, this_len);
- }
- case booleanValue:
- return value_.bool_ ? "true" : "false";
- case intValue:
- return valueToString(value_.int_);
- case uintValue:
- return valueToString(value_.uint_);
- case realValue:
- return valueToString(value_.real_);
- default:
- JSON_FAIL_MESSAGE("Type is not convertible to string");
- }
- }
- Value::Int Value::asInt() const {
- switch (type()) {
- case intValue:
- JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
- return Int(value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
- return Int(value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
- "double out of Int range");
- return Int(value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- default:
- break;
- }
- JSON_FAIL_MESSAGE("Value is not convertible to Int.");
- }
- Value::UInt Value::asUInt() const {
- switch (type()) {
- case intValue:
- JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
- return UInt(value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
- return UInt(value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
- "double out of UInt range");
- return UInt(value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- default:
- break;
- }
- JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
- }
- #if defined(JSON_HAS_INT64)
- Value::Int64 Value::asInt64() const {
- switch (type()) {
- case intValue:
- return Int64(value_.int_);
- case uintValue:
- JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
- return Int64(value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
- "double out of Int64 range");
- return Int64(value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- default:
- break;
- }
- JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
- }
- Value::UInt64 Value::asUInt64() const {
- switch (type()) {
- case intValue:
- JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
- return UInt64(value_.int_);
- case uintValue:
- return UInt64(value_.uint_);
- case realValue:
- JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
- "double out of UInt64 range");
- return UInt64(value_.real_);
- case nullValue:
- return 0;
- case booleanValue:
- return value_.bool_ ? 1 : 0;
- default:
- break;
- }
- JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
- }
- #endif // if defined(JSON_HAS_INT64)
- LargestInt Value::asLargestInt() const {
- #if defined(JSON_NO_INT64)
- return asInt();
- #else
- return asInt64();
- #endif
- }
- LargestUInt Value::asLargestUInt() const {
- #if defined(JSON_NO_INT64)
- return asUInt();
- #else
- return asUInt64();
- #endif
- }
- double Value::asDouble() const {
- switch (type()) {
- case intValue:
- return static_cast<double>(value_.int_);
- case uintValue:
- #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return static_cast<double>(value_.uint_);
- #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return integerToDouble(value_.uint_);
- #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- case realValue:
- return value_.real_;
- case nullValue:
- return 0.0;
- case booleanValue:
- return value_.bool_ ? 1.0 : 0.0;
- default:
- break;
- }
- JSON_FAIL_MESSAGE("Value is not convertible to double.");
- }
- float Value::asFloat() const {
- switch (type()) {
- case intValue:
- return static_cast<float>(value_.int_);
- case uintValue:
- #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return static_cast<float>(value_.uint_);
- #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- // This can fail (silently?) if the value is bigger than MAX_FLOAT.
- return static_cast<float>(integerToDouble(value_.uint_));
- #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- case realValue:
- return static_cast<float>(value_.real_);
- case nullValue:
- return 0.0;
- case booleanValue:
- return value_.bool_ ? 1.0F : 0.0F;
- default:
- break;
- }
- JSON_FAIL_MESSAGE("Value is not convertible to float.");
- }
- bool Value::asBool() const {
- switch (type()) {
- case booleanValue:
- return value_.bool_;
- case nullValue:
- return false;
- case intValue:
- return value_.int_ != 0;
- case uintValue:
- return value_.uint_ != 0;
- case realValue: {
- // According to JavaScript language zero or NaN is regarded as false
- const auto value_classification = std::fpclassify(value_.real_);
- return value_classification != FP_ZERO && value_classification != FP_NAN;
- }
- default:
- break;
- }
- JSON_FAIL_MESSAGE("Value is not convertible to bool.");
- }
- bool Value::isConvertibleTo(ValueType other) const {
- switch (other) {
- case nullValue:
- return (isNumeric() && asDouble() == 0.0) ||
- (type() == booleanValue && !value_.bool_) ||
- (type() == stringValue && asString().empty()) ||
- (type() == arrayValue && value_.map_->empty()) ||
- (type() == objectValue && value_.map_->empty()) ||
- type() == nullValue;
- case intValue:
- return isInt() ||
- (type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
- type() == booleanValue || type() == nullValue;
- case uintValue:
- return isUInt() ||
- (type() == realValue && InRange(value_.real_, 0, maxUInt)) ||
- type() == booleanValue || type() == nullValue;
- case realValue:
- return isNumeric() || type() == booleanValue || type() == nullValue;
- case booleanValue:
- return isNumeric() || type() == booleanValue || type() == nullValue;
- case stringValue:
- return isNumeric() || type() == booleanValue || type() == stringValue ||
- type() == nullValue;
- case arrayValue:
- return type() == arrayValue || type() == nullValue;
- case objectValue:
- return type() == objectValue || type() == nullValue;
- }
- JSON_ASSERT_UNREACHABLE;
- return false;
- }
- /// Number of values in array or object
- ArrayIndex Value::size() const {
- switch (type()) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- case stringValue:
- return 0;
- case arrayValue: // size of the array is highest index + 1
- if (!value_.map_->empty()) {
- ObjectValues::const_iterator itLast = value_.map_->end();
- --itLast;
- return (*itLast).first.index() + 1;
- }
- return 0;
- case objectValue:
- return ArrayIndex(value_.map_->size());
- }
- JSON_ASSERT_UNREACHABLE;
- return 0; // unreachable;
- }
- bool Value::empty() const {
- if (isNull() || isArray() || isObject())
- return size() == 0U;
- return false;
- }
- Value::operator bool() const { return !isNull(); }
- void Value::clear() {
- JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue ||
- type() == objectValue,
- "in Json::Value::clear(): requires complex value");
- start_ = 0;
- limit_ = 0;
- switch (type()) {
- case arrayValue:
- case objectValue:
- value_.map_->clear();
- break;
- default:
- break;
- }
- }
- void Value::resize(ArrayIndex newSize) {
- JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
- "in Json::Value::resize(): requires arrayValue");
- if (type() == nullValue)
- *this = Value(arrayValue);
- ArrayIndex oldSize = size();
- if (newSize == 0)
- clear();
- else if (newSize > oldSize)
- for (ArrayIndex i = oldSize; i < newSize; ++i)
- (*this)[i];
- else {
- for (ArrayIndex index = newSize; index < oldSize; ++index) {
- value_.map_->erase(index);
- }
- JSON_ASSERT(size() == newSize);
- }
- }
- Value& Value::operator[](ArrayIndex index) {
- JSON_ASSERT_MESSAGE(
- type() == nullValue || type() == arrayValue,
- "in Json::Value::operator[](ArrayIndex): requires arrayValue");
- if (type() == nullValue)
- *this = Value(arrayValue);
- CZString key(index);
- auto it = value_.map_->lower_bound(key);
- if (it != value_.map_->end() && (*it).first == key)
- return (*it).second;
- ObjectValues::value_type defaultValue(key, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
- return (*it).second;
- }
- Value& Value::operator[](int index) {
- JSON_ASSERT_MESSAGE(
- index >= 0,
- "in Json::Value::operator[](int index): index cannot be negative");
- return (*this)[ArrayIndex(index)];
- }
- const Value& Value::operator[](ArrayIndex index) const {
- JSON_ASSERT_MESSAGE(
- type() == nullValue || type() == arrayValue,
- "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
- if (type() == nullValue)
- return nullSingleton();
- CZString key(index);
- ObjectValues::const_iterator it = value_.map_->find(key);
- if (it == value_.map_->end())
- return nullSingleton();
- return (*it).second;
- }
- const Value& Value::operator[](int index) const {
- JSON_ASSERT_MESSAGE(
- index >= 0,
- "in Json::Value::operator[](int index) const: index cannot be negative");
- return (*this)[ArrayIndex(index)];
- }
- void Value::initBasic(ValueType type, bool allocated) {
- setType(type);
- setIsAllocated(allocated);
- comments_ = Comments{};
- start_ = 0;
- limit_ = 0;
- }
- void Value::dupPayload(const Value& other) {
- setType(other.type());
- setIsAllocated(false);
- switch (type()) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- value_ = other.value_;
- break;
- case stringValue:
- if (other.value_.string_ && other.isAllocated()) {
- unsigned len;
- char const* str;
- decodePrefixedString(other.isAllocated(), other.value_.string_, &len,
- &str);
- value_.string_ = duplicateAndPrefixStringValue(str, len);
- setIsAllocated(true);
- } else {
- value_.string_ = other.value_.string_;
- }
- break;
- case arrayValue:
- case objectValue:
- value_.map_ = new ObjectValues(*other.value_.map_);
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- }
- void Value::releasePayload() {
- switch (type()) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- break;
- case stringValue:
- if (isAllocated())
- releasePrefixedStringValue(value_.string_);
- break;
- case arrayValue:
- case objectValue:
- delete value_.map_;
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- }
- void Value::dupMeta(const Value& other) {
- comments_ = other.comments_;
- start_ = other.start_;
- limit_ = other.limit_;
- }
- // Access an object value by name, create a null member if it does not exist.
- // @pre Type of '*this' is object or null.
- // @param key is null-terminated.
- Value& Value::resolveReference(const char* key) {
- JSON_ASSERT_MESSAGE(
- type() == nullValue || type() == objectValue,
- "in Json::Value::resolveReference(): requires objectValue");
- if (type() == nullValue)
- *this = Value(objectValue);
- CZString actualKey(key, static_cast<unsigned>(strlen(key)),
- CZString::noDuplication); // NOTE!
- auto it = value_.map_->lower_bound(actualKey);
- if (it != value_.map_->end() && (*it).first == actualKey)
- return (*it).second;
- ObjectValues::value_type defaultValue(actualKey, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
- Value& value = (*it).second;
- return value;
- }
- // @param key is not null-terminated.
- Value& Value::resolveReference(char const* key, char const* end) {
- JSON_ASSERT_MESSAGE(
- type() == nullValue || type() == objectValue,
- "in Json::Value::resolveReference(key, end): requires objectValue");
- if (type() == nullValue)
- *this = Value(objectValue);
- CZString actualKey(key, static_cast<unsigned>(end - key),
- CZString::duplicateOnCopy);
- auto it = value_.map_->lower_bound(actualKey);
- if (it != value_.map_->end() && (*it).first == actualKey)
- return (*it).second;
- ObjectValues::value_type defaultValue(actualKey, nullSingleton());
- it = value_.map_->insert(it, defaultValue);
- Value& value = (*it).second;
- return value;
- }
- Value Value::get(ArrayIndex index, const Value& defaultValue) const {
- const Value* value = &((*this)[index]);
- return value == &nullSingleton() ? defaultValue : *value;
- }
- bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
- Value const* Value::find(char const* begin, char const* end) const {
- JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
- "in Json::Value::find(begin, end): requires "
- "objectValue or nullValue");
- if (type() == nullValue)
- return nullptr;
- CZString actualKey(begin, static_cast<unsigned>(end - begin),
- CZString::noDuplication);
- ObjectValues::const_iterator it = value_.map_->find(actualKey);
- if (it == value_.map_->end())
- return nullptr;
- return &(*it).second;
- }
- Value* Value::demand(char const* begin, char const* end) {
- JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
- "in Json::Value::demand(begin, end): requires "
- "objectValue or nullValue");
- return &resolveReference(begin, end);
- }
- const Value& Value::operator[](const char* key) const {
- Value const* found = find(key, key + strlen(key));
- if (!found)
- return nullSingleton();
- return *found;
- }
- Value const& Value::operator[](const String& key) const {
- Value const* found = find(key.data(), key.data() + key.length());
- if (!found)
- return nullSingleton();
- return *found;
- }
- Value& Value::operator[](const char* key) {
- return resolveReference(key, key + strlen(key));
- }
- Value& Value::operator[](const String& key) {
- return resolveReference(key.data(), key.data() + key.length());
- }
- Value& Value::operator[](const StaticString& key) {
- return resolveReference(key.c_str());
- }
- Value& Value::append(const Value& value) { return append(Value(value)); }
- Value& Value::append(Value&& value) {
- JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
- "in Json::Value::append: requires arrayValue");
- if (type() == nullValue) {
- *this = Value(arrayValue);
- }
- return this->value_.map_->emplace(size(), std::move(value)).first->second;
- }
- bool Value::insert(ArrayIndex index, const Value& newValue) {
- return insert(index, Value(newValue));
- }
- bool Value::insert(ArrayIndex index, Value&& newValue) {
- JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
- "in Json::Value::insert: requires arrayValue");
- ArrayIndex length = size();
- if (index > length) {
- return false;
- }
- for (ArrayIndex i = length; i > index; i--) {
- (*this)[i] = std::move((*this)[i - 1]);
- }
- (*this)[index] = std::move(newValue);
- return true;
- }
- Value Value::get(char const* begin, char const* end,
- Value const& defaultValue) const {
- Value const* found = find(begin, end);
- return !found ? defaultValue : *found;
- }
- Value Value::get(char const* key, Value const& defaultValue) const {
- return get(key, key + strlen(key), defaultValue);
- }
- Value Value::get(String const& key, Value const& defaultValue) const {
- return get(key.data(), key.data() + key.length(), defaultValue);
- }
- bool Value::removeMember(const char* begin, const char* end, Value* removed) {
- if (type() != objectValue) {
- return false;
- }
- CZString actualKey(begin, static_cast<unsigned>(end - begin),
- CZString::noDuplication);
- auto it = value_.map_->find(actualKey);
- if (it == value_.map_->end())
- return false;
- if (removed)
- *removed = std::move(it->second);
- value_.map_->erase(it);
- return true;
- }
- bool Value::removeMember(const char* key, Value* removed) {
- return removeMember(key, key + strlen(key), removed);
- }
- bool Value::removeMember(String const& key, Value* removed) {
- return removeMember(key.data(), key.data() + key.length(), removed);
- }
- void Value::removeMember(const char* key) {
- JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
- "in Json::Value::removeMember(): requires objectValue");
- if (type() == nullValue)
- return;
- CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
- value_.map_->erase(actualKey);
- }
- void Value::removeMember(const String& key) { removeMember(key.c_str()); }
- bool Value::removeIndex(ArrayIndex index, Value* removed) {
- if (type() != arrayValue) {
- return false;
- }
- CZString key(index);
- auto it = value_.map_->find(key);
- if (it == value_.map_->end()) {
- return false;
- }
- if (removed)
- *removed = it->second;
- ArrayIndex oldSize = size();
- // shift left all items left, into the place of the "removed"
- for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
- CZString keey(i);
- (*value_.map_)[keey] = (*this)[i + 1];
- }
- // erase the last one ("leftover")
- CZString keyLast(oldSize - 1);
- auto itLast = value_.map_->find(keyLast);
- value_.map_->erase(itLast);
- return true;
- }
- bool Value::isMember(char const* begin, char const* end) const {
- Value const* value = find(begin, end);
- return nullptr != value;
- }
- bool Value::isMember(char const* key) const {
- return isMember(key, key + strlen(key));
- }
- bool Value::isMember(String const& key) const {
- return isMember(key.data(), key.data() + key.length());
- }
- Value::Members Value::getMemberNames() const {
- JSON_ASSERT_MESSAGE(
- type() == nullValue || type() == objectValue,
- "in Json::Value::getMemberNames(), value must be objectValue");
- if (type() == nullValue)
- return Value::Members();
- Members members;
- members.reserve(value_.map_->size());
- ObjectValues::const_iterator it = value_.map_->begin();
- ObjectValues::const_iterator itEnd = value_.map_->end();
- for (; it != itEnd; ++it) {
- members.push_back(String((*it).first.data(), (*it).first.length()));
- }
- return members;
- }
- static bool IsIntegral(double d) {
- double integral_part;
- return modf(d, &integral_part) == 0.0;
- }
- bool Value::isNull() const { return type() == nullValue; }
- bool Value::isBool() const { return type() == booleanValue; }
- bool Value::isInt() const {
- switch (type()) {
- case intValue:
- #if defined(JSON_HAS_INT64)
- return value_.int_ >= minInt && value_.int_ <= maxInt;
- #else
- return true;
- #endif
- case uintValue:
- return value_.uint_ <= UInt(maxInt);
- case realValue:
- return value_.real_ >= minInt && value_.real_ <= maxInt &&
- IsIntegral(value_.real_);
- default:
- break;
- }
- return false;
- }
- bool Value::isUInt() const {
- switch (type()) {
- case intValue:
- #if defined(JSON_HAS_INT64)
- return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
- #else
- return value_.int_ >= 0;
- #endif
- case uintValue:
- #if defined(JSON_HAS_INT64)
- return value_.uint_ <= maxUInt;
- #else
- return true;
- #endif
- case realValue:
- return value_.real_ >= 0 && value_.real_ <= maxUInt &&
- IsIntegral(value_.real_);
- default:
- break;
- }
- return false;
- }
- bool Value::isInt64() const {
- #if defined(JSON_HAS_INT64)
- switch (type()) {
- case intValue:
- return true;
- case uintValue:
- return value_.uint_ <= UInt64(maxInt64);
- case realValue:
- // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
- // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
- // require the value to be strictly less than the limit.
- return value_.real_ >= double(minInt64) &&
- value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
- default:
- break;
- }
- #endif // JSON_HAS_INT64
- return false;
- }
- bool Value::isUInt64() const {
- #if defined(JSON_HAS_INT64)
- switch (type()) {
- case intValue:
- return value_.int_ >= 0;
- case uintValue:
- return true;
- case realValue:
- // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
- // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
- // require the value to be strictly less than the limit.
- return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
- IsIntegral(value_.real_);
- default:
- break;
- }
- #endif // JSON_HAS_INT64
- return false;
- }
- bool Value::isIntegral() const {
- switch (type()) {
- case intValue:
- case uintValue:
- return true;
- case realValue:
- #if defined(JSON_HAS_INT64)
- // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
- // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
- // require the value to be strictly less than the limit.
- return value_.real_ >= double(minInt64) &&
- value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
- #else
- return value_.real_ >= minInt && value_.real_ <= maxUInt &&
- IsIntegral(value_.real_);
- #endif // JSON_HAS_INT64
- default:
- break;
- }
- return false;
- }
- bool Value::isDouble() const {
- return type() == intValue || type() == uintValue || type() == realValue;
- }
- bool Value::isNumeric() const { return isDouble(); }
- bool Value::isString() const { return type() == stringValue; }
- bool Value::isArray() const { return type() == arrayValue; }
- bool Value::isObject() const { return type() == objectValue; }
- Value::Comments::Comments(const Comments& that)
- : ptr_{cloneUnique(that.ptr_)} {}
- Value::Comments::Comments(Comments&& that) noexcept
- : ptr_{std::move(that.ptr_)} {}
- Value::Comments& Value::Comments::operator=(const Comments& that) {
- ptr_ = cloneUnique(that.ptr_);
- return *this;
- }
- Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
- ptr_ = std::move(that.ptr_);
- return *this;
- }
- bool Value::Comments::has(CommentPlacement slot) const {
- return ptr_ && !(*ptr_)[slot].empty();
- }
- String Value::Comments::get(CommentPlacement slot) const {
- if (!ptr_)
- return {};
- return (*ptr_)[slot];
- }
- void Value::Comments::set(CommentPlacement slot, String comment) {
- if (slot >= CommentPlacement::numberOfCommentPlacement)
- return;
- if (!ptr_)
- ptr_ = std::unique_ptr<Array>(new Array());
- (*ptr_)[slot] = std::move(comment);
- }
- void Value::setComment(String comment, CommentPlacement placement) {
- if (!comment.empty() && (comment.back() == '\n')) {
- // Always discard trailing newline, to aid indentation.
- comment.pop_back();
- }
- JSON_ASSERT(!comment.empty());
- JSON_ASSERT_MESSAGE(
- comment[0] == '\0' || comment[0] == '/',
- "in Json::Value::setComment(): Comments must start with /");
- comments_.set(placement, std::move(comment));
- }
- bool Value::hasComment(CommentPlacement placement) const {
- return comments_.has(placement);
- }
- String Value::getComment(CommentPlacement placement) const {
- return comments_.get(placement);
- }
- void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
- void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
- ptrdiff_t Value::getOffsetStart() const { return start_; }
- ptrdiff_t Value::getOffsetLimit() const { return limit_; }
- String Value::toStyledString() const {
- StreamWriterBuilder builder;
- String out = this->hasComment(commentBefore) ? "\n" : "";
- out += Json::writeString(builder, *this);
- out += '\n';
- return out;
- }
- Value::const_iterator Value::begin() const {
- switch (type()) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return const_iterator(value_.map_->begin());
- break;
- default:
- break;
- }
- return {};
- }
- Value::const_iterator Value::end() const {
- switch (type()) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return const_iterator(value_.map_->end());
- break;
- default:
- break;
- }
- return {};
- }
- Value::iterator Value::begin() {
- switch (type()) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return iterator(value_.map_->begin());
- break;
- default:
- break;
- }
- return iterator();
- }
- Value::iterator Value::end() {
- switch (type()) {
- case arrayValue:
- case objectValue:
- if (value_.map_)
- return iterator(value_.map_->end());
- break;
- default:
- break;
- }
- return iterator();
- }
- // class PathArgument
- // //////////////////////////////////////////////////////////////////
- PathArgument::PathArgument() = default;
- PathArgument::PathArgument(ArrayIndex index)
- : index_(index), kind_(kindIndex) {}
- PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
- PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
- // class Path
- // //////////////////////////////////////////////////////////////////
- Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
- const PathArgument& a3, const PathArgument& a4,
- const PathArgument& a5) {
- InArgs in;
- in.reserve(5);
- in.push_back(&a1);
- in.push_back(&a2);
- in.push_back(&a3);
- in.push_back(&a4);
- in.push_back(&a5);
- makePath(path, in);
- }
- void Path::makePath(const String& path, const InArgs& in) {
- const char* current = path.c_str();
- const char* end = current + path.length();
- auto itInArg = in.begin();
- while (current != end) {
- if (*current == '[') {
- ++current;
- if (*current == '%')
- addPathInArg(path, in, itInArg, PathArgument::kindIndex);
- else {
- ArrayIndex index = 0;
- for (; current != end && *current >= '0' && *current <= '9'; ++current)
- index = index * 10 + ArrayIndex(*current - '0');
- args_.push_back(index);
- }
- if (current == end || *++current != ']')
- invalidPath(path, int(current - path.c_str()));
- } else if (*current == '%') {
- addPathInArg(path, in, itInArg, PathArgument::kindKey);
- ++current;
- } else if (*current == '.' || *current == ']') {
- ++current;
- } else {
- const char* beginName = current;
- while (current != end && !strchr("[.", *current))
- ++current;
- args_.push_back(String(beginName, current));
- }
- }
- }
- void Path::addPathInArg(const String& /*path*/, const InArgs& in,
- InArgs::const_iterator& itInArg,
- PathArgument::Kind kind) {
- if (itInArg == in.end()) {
- // Error: missing argument %d
- } else if ((*itInArg)->kind_ != kind) {
- // Error: bad argument type
- } else {
- args_.push_back(**itInArg++);
- }
- }
- void Path::invalidPath(const String& /*path*/, int /*location*/) {
- // Error: invalid path.
- }
- const Value& Path::resolve(const Value& root) const {
- const Value* node = &root;
- for (const auto& arg : args_) {
- if (arg.kind_ == PathArgument::kindIndex) {
- if (!node->isArray() || !node->isValidIndex(arg.index_)) {
- // Error: unable to resolve path (array value expected at position... )
- return Value::nullSingleton();
- }
- node = &((*node)[arg.index_]);
- } else if (arg.kind_ == PathArgument::kindKey) {
- if (!node->isObject()) {
- // Error: unable to resolve path (object value expected at position...)
- return Value::nullSingleton();
- }
- node = &((*node)[arg.key_]);
- if (node == &Value::nullSingleton()) {
- // Error: unable to resolve path (object has no member named '' at
- // position...)
- return Value::nullSingleton();
- }
- }
- }
- return *node;
- }
- Value Path::resolve(const Value& root, const Value& defaultValue) const {
- const Value* node = &root;
- for (const auto& arg : args_) {
- if (arg.kind_ == PathArgument::kindIndex) {
- if (!node->isArray() || !node->isValidIndex(arg.index_))
- return defaultValue;
- node = &((*node)[arg.index_]);
- } else if (arg.kind_ == PathArgument::kindKey) {
- if (!node->isObject())
- return defaultValue;
- node = &((*node)[arg.key_]);
- if (node == &Value::nullSingleton())
- return defaultValue;
- }
- }
- return *node;
- }
- Value& Path::make(Value& root) const {
- Value* node = &root;
- for (const auto& arg : args_) {
- if (arg.kind_ == PathArgument::kindIndex) {
- if (!node->isArray()) {
- // Error: node is not an array at position ...
- }
- node = &((*node)[arg.index_]);
- } else if (arg.kind_ == PathArgument::kindKey) {
- if (!node->isObject()) {
- // Error: node is not an object at position...
- }
- node = &((*node)[arg.key_]);
- }
- }
- return *node;
- }
- } // namespace Json
|