Update vendored jsoncpp to 1.9.8

This commit is contained in:
sfan5
2026-08-29 20:37:21 +02:00
parent 2b3ffa802d
commit 8b3d383a43
4 changed files with 419 additions and 142 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
#!/bin/sh
cd ..
git clone https://github.com/open-source-parsers/jsoncpp -b 1.9.6 --depth 1
git clone https://github.com/open-source-parsers/jsoncpp -b 1.9.8 --depth 1
cd jsoncpp
./amalgamate.py
cp -R dist/json ../json
cp dist/json/* ../json
cp dist/jsoncpp.cpp ..
+9 -4
View File
@@ -86,19 +86,19 @@ license you like.
#ifndef JSON_VERSION_H_INCLUDED
#define JSON_VERSION_H_INCLUDED
// Note: version must be updated in three places when doing a release. This
// Note: version must be updated in four places when doing a release. This
// annoying process ensures that amalgamate, CMake, and meson all report the
// correct version.
// 1. /meson.build
// 2. /include/json/version.h
// 3. /CMakeLists.txt
// 4. /MODULE.bazel
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.7"
#define JSONCPP_VERSION_STRING "1.9.8"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 7
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_PATCH 8
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
(JSONCPP_VERSION_PATCH << 8))
@@ -345,6 +345,7 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
JSON_API const char* version();
using Int = int;
using UInt = unsigned int;
#if defined(JSON_NO_INT64)
@@ -362,7 +363,9 @@ using UInt64 = uint64_t;
#endif // if defined(_MSC_VER)
using LargestInt = Int64;
using LargestUInt = UInt64;
#ifndef JSON_HAS_INT64
#define JSON_HAS_INT64
#endif // ifndef JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)
template <typename T>
@@ -441,6 +444,8 @@ class Value;
class ValueIteratorBase;
class ValueIterator;
class ValueConstIterator;
class ValueMembersView;
class ValueConstMembersView;
} // namespace Json
+245 -13
View File
@@ -85,19 +85,19 @@ license you like.
#ifndef JSON_VERSION_H_INCLUDED
#define JSON_VERSION_H_INCLUDED
// Note: version must be updated in three places when doing a release. This
// Note: version must be updated in four places when doing a release. This
// annoying process ensures that amalgamate, CMake, and meson all report the
// correct version.
// 1. /meson.build
// 2. /include/json/version.h
// 3. /CMakeLists.txt
// 4. /MODULE.bazel
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.7"
#define JSONCPP_VERSION_STRING "1.9.8"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 7
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_PATCH 8
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
(JSONCPP_VERSION_PATCH << 8))
@@ -344,6 +344,7 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
JSON_API const char* version();
using Int = int;
using UInt = unsigned int;
#if defined(JSON_NO_INT64)
@@ -361,7 +362,9 @@ using UInt64 = uint64_t;
#endif // if defined(_MSC_VER)
using LargestInt = Int64;
using LargestUInt = UInt64;
#ifndef JSON_HAS_INT64
#define JSON_HAS_INT64
#endif // ifndef JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)
template <typename T>
@@ -440,6 +443,8 @@ class Value;
class ValueIteratorBase;
class ValueIterator;
class ValueConstIterator;
class ValueMembersView;
class ValueConstMembersView;
} // namespace Json
@@ -575,6 +580,12 @@ public:
#endif
#endif
#ifndef JSONCPP_HAS_STRING_VIEW
#if __cplusplus >= 201703L
#define JSONCPP_HAS_STRING_VIEW 1
#endif
#endif
#include <array>
#include <exception>
#include <map>
@@ -582,6 +593,13 @@ public:
#include <string>
#include <vector>
// Forward declaration for testing.
struct ValueTest;
#ifdef JSONCPP_HAS_STRING_VIEW
#include <string_view>
#endif
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -729,6 +747,7 @@ private:
*/
class JSON_API Value {
friend class ValueIteratorBase;
friend struct ::ValueTest;
public:
using Members = std::vector<String>;
@@ -794,7 +813,7 @@ public:
private:
#endif
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
class CZString {
class JSON_API CZString {
public:
enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy };
CZString(ArrayIndex index);
@@ -878,6 +897,10 @@ public:
*/
Value(const StaticString& value);
Value(const String& value);
#ifdef JSONCPP_HAS_STRING_VIEW
inline Value(std::string_view value)
: Value(value.data(), value.data() + value.length()) {}
#endif
Value(bool value);
Value(std::nullptr_t ptr) = delete;
Value(const Value& other);
@@ -920,6 +943,19 @@ public:
* \return false if !string. (Seg-fault if str or end are NULL.)
*/
bool getString(char const** begin, char const** end) const;
#ifdef JSONCPP_HAS_STRING_VIEW
/** Get string_view of string-value.
* \return false if !string. (Seg-fault if str is NULL.)
*/
inline bool getString(std::string_view* str) const {
char const* begin;
char const* end;
if (!getString(&begin, &end))
return false;
*str = std::string_view(begin, static_cast<size_t>(end - begin));
return true;
}
#endif
Int asInt() const;
UInt asUInt() const;
#if defined(JSON_HAS_INT64)
@@ -1006,6 +1042,22 @@ public:
bool insert(ArrayIndex index, const Value& newValue);
bool insert(ArrayIndex index, Value&& newValue);
#ifdef JSONCPP_HAS_STRING_VIEW
/// Access an object value by name, create a null member if it does not exist.
/// \param key may contain embedded nulls.
inline Value& operator[](std::string_view key) {
return resolveReference(key.data(), key.data() + key.length());
}
/// Access an object value by name, returns null if there is no member with
/// that name.
/// \param key may contain embedded nulls.
inline const Value& operator[](std::string_view key) const {
Value const* found = find(key.data(), key.data() + key.length());
if (!found)
return nullSingleton();
return *found;
}
#endif
/// Access an object value by name, create a null member if it does not exist.
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
/// Exceeding that will cause an exception.
@@ -1033,18 +1085,25 @@ public:
* \endcode
*/
Value& operator[](const StaticString& key);
#ifdef JSONCPP_HAS_STRING_VIEW
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
inline Value get(std::string_view key, const Value& defaultValue) const {
return get(key.data(), key.data() + key.length(), defaultValue);
}
#endif
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const char* key, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \param key may contain embedded nulls.
Value get(const String& key, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \note key may contain embedded nulls.
Value get(const char* begin, const char* end,
const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \param key may contain embedded nulls.
Value get(const String& key, const Value& defaultValue) const;
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
@@ -1052,6 +1111,29 @@ public:
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
Value const* find(const String& key) const;
/// Calls find and only returns a valid pointer if the type is found
template <typename T, bool (T::*TMemFn)() const>
Value const* findValue(const String& key) const {
Value const* found = find(key);
if (!found || !(found->*TMemFn)())
return nullptr;
return found;
}
Value const* findNull(const String& key) const;
Value const* findBool(const String& key) const;
Value const* findInt(const String& key) const;
Value const* findInt64(const String& key) const;
Value const* findUInt(const String& key) const;
Value const* findUInt64(const String& key) const;
Value const* findIntegral(const String& key) const;
Value const* findDouble(const String& key) const;
Value const* findNumeric(const String& key) const;
Value const* findString(const String& key) const;
Value const* findArray(const String& key) const;
Value const* findObject(const String& key) const;
/// Most general and efficient version of object-mutators.
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
@@ -1061,20 +1143,30 @@ public:
/// Do nothing if it did not exist.
/// \pre type() is objectValue or nullValue
/// \post type() is unchanged
#if JSONCPP_HAS_STRING_VIEW
inline void removeMember(std::string_view key) {
removeMember(key.data(), key.data() + key.length(), nullptr);
}
#endif
void removeMember(const char* key);
/// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
void removeMember(const String& key);
/// Same as removeMember(const char* begin, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
/** \brief Remove the named map member.
*
* Update 'removed' iff removed.
* \param key may contain embedded nulls.
* \return true iff removed (no exceptions)
*/
#if JSONCPP_HAS_STRING_VIEW
inline bool removeMember(std::string_view key, Value* removed) {
return removeMember(key.data(), key.data() + key.length(), removed);
}
#endif
bool removeMember(String const& key, Value* removed);
/// Same as removeMember(const char* begin, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
/// Same as removeMember(String const& key, Value* removed)
bool removeMember(const char* begin, const char* end, Value* removed);
/** \brief Remove the indexed array element.
@@ -1085,6 +1177,13 @@ public:
*/
bool removeIndex(ArrayIndex index, Value* removed);
#ifdef JSONCPP_HAS_STRING_VIEW
/// Return true if the object has a member named key.
/// \param key may contain embedded nulls.
inline bool isMember(std::string_view key) const {
return isMember(key.data(), key.data() + key.length());
}
#endif
/// Return true if the object has a member named key.
/// \note 'key' must be null-terminated.
bool isMember(const char* key) const;
@@ -1124,6 +1223,11 @@ public:
iterator begin();
iterator end();
// \brief Returns a view of member pairs for range-based for loops.
ValueMembersView members();
// \brief Returns a view of member pairs for range-based for loops.
ValueConstMembersView members() const;
/// \brief Returns a reference to the first element in the `Value`.
/// Requires that this value holds an array or json object, with at least one
/// element.
@@ -1482,6 +1586,131 @@ public:
pointer operator->() const { return const_cast<pointer>(&deref()); }
};
/** \brief Proxy struct to enable range-based for loops over object members.
*/
struct MemberProxy {
const String name;
Value& value;
};
/** \brief Proxy struct to enable range-based for loops over const object
* members.
*/
struct ConstMemberProxy {
const String name;
const Value& value;
};
/** \brief Iterator adapter for range-based for loops.
*/
class ValueMembersIterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = MemberProxy;
using difference_type = int;
using pointer = MemberProxy*;
using reference = MemberProxy;
ValueMembersIterator() = default;
explicit ValueMembersIterator(ValueIterator const& iter) : it_(iter) {}
ValueMembersIterator& operator++() {
++it_;
return *this;
}
ValueMembersIterator operator++(int) {
ValueMembersIterator temp(*this);
++*this;
return temp;
}
bool operator==(ValueMembersIterator const& other) const {
return it_ == other.it_;
}
bool operator!=(ValueMembersIterator const& other) const {
return it_ != other.it_;
}
MemberProxy operator*() const { return MemberProxy{it_.name(), *it_}; }
private:
ValueIterator it_;
};
/** \brief Iterator adapter for range-based for loops.
*/
class ValueConstMembersIterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = ConstMemberProxy;
using difference_type = int;
using pointer = ConstMemberProxy*;
using reference = ConstMemberProxy;
ValueConstMembersIterator() = default;
explicit ValueConstMembersIterator(ValueConstIterator const& iter)
: it_(iter) {}
ValueConstMembersIterator& operator++() {
++it_;
return *this;
}
ValueConstMembersIterator operator++(int) {
ValueConstMembersIterator temp(*this);
++*this;
return temp;
}
bool operator==(ValueConstMembersIterator const& other) const {
return it_ == other.it_;
}
bool operator!=(ValueConstMembersIterator const& other) const {
return it_ != other.it_;
}
ConstMemberProxy operator*() const {
return ConstMemberProxy{it_.name(), *it_};
}
private:
ValueConstIterator it_;
};
/** \brief Range-based for loop adapter for object members.
*/
class ValueMembersView {
public:
ValueMembersView(ValueIterator begin, ValueIterator end)
: begin_(begin), end_(end) {}
ValueMembersIterator begin() const { return ValueMembersIterator(begin_); }
ValueMembersIterator end() const { return ValueMembersIterator(end_); }
private:
ValueIterator begin_;
ValueIterator end_;
};
/** \brief Range-based for loop adapter for object members.
*/
class ValueConstMembersView {
public:
ValueConstMembersView(ValueConstIterator begin, ValueConstIterator end)
: begin_(begin), end_(end) {}
ValueConstMembersIterator begin() const {
return ValueConstMembersIterator(begin_);
}
ValueConstMembersIterator end() const {
return ValueConstMembersIterator(end_);
}
private:
ValueConstIterator begin_;
ValueConstIterator end_;
};
inline ValueMembersView Value::members() {
return ValueMembersView(begin(), end());
}
inline ValueConstMembersView Value::members() const {
return ValueConstMembersView(begin(), end());
}
inline void swap(Value& a, Value& b) { a.swap(b); }
inline const Value& Value::front() const { return *begin(); }
@@ -1598,7 +1827,10 @@ public:
* document.
*
* \param beginDoc Pointer on the beginning of the UTF-8 encoded
* string of the document to read.
* string of the document to read. The pointed-to
* buffer must outlive this Reader if error
* methods (e.g. getFormattedErrorMessages()) are
* called after parse() returns.
* \param endDoc Pointer on the end of the UTF-8 encoded string
* of the document to read. Must be >= beginDoc.
* \param[out] root Contains the root value of the document if it
+163 -123
View File
@@ -254,6 +254,7 @@ Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
#include <cstring>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <memory>
#include <set>
@@ -261,13 +262,6 @@ Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
#include <utility>
#include <cstdio>
#if __cplusplus >= 201103L
#if !defined(sscanf)
#define sscanf std::sscanf
#endif
#endif //__cplusplus
#if defined(_MSC_VER)
#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
@@ -283,7 +277,7 @@ Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile
// time to change the stack limit
#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
#define JSONCPP_DEPRECATED_STACK_LIMIT 256
#endif
static size_t const stackLimit_g =
@@ -291,11 +285,7 @@ static size_t const stackLimit_g =
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
using CharReaderPtr = std::unique_ptr<CharReader>;
#else
using CharReaderPtr = std::auto_ptr<CharReader>;
#endif
// Implementation of class Features
// ////////////////////////////////
@@ -336,15 +326,10 @@ bool Reader::parse(const std::string& document, Value& root,
}
bool Reader::parse(std::istream& is, Value& root, bool collectComments) {
// std::istream_iterator<char> begin(is);
// std::istream_iterator<char> end;
// Those would allow streamed input from a file, if parse() were a
// template function.
// Since String is reference-counted, this at least does not
// create an extra copy.
String doc(std::istreambuf_iterator<char>(is), {});
return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
document_.assign(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>());
return parse(document_.data(), document_.data() + document_.size(), root,
collectComments);
}
bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
@@ -392,7 +377,12 @@ bool Reader::readValue() {
// after calling readValue(). parse() executes one nodes_.push(), so > instead
// of >=.
if (nodes_.size() > stackLimit_g)
#if JSON_USE_EXCEPTION
throwRuntimeError("Exceeded stackLimit in readValue().");
#else
// throwRuntimeError aborts. Don't abort here.
return false;
#endif
Token token;
readTokenSkippingComments(token);
@@ -826,6 +816,7 @@ bool Reader::decodeDouble(Token& token) {
bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
IStringStream is(String(token.start_, token.end_));
is.imbue(std::locale::classic());
if (!(is >> value)) {
if (value == std::numeric_limits<double>::max())
value = std::numeric_limits<double>::infinity();
@@ -897,6 +888,8 @@ bool Reader::decodeString(Token& token, String& decoded) {
return addError("Bad escape sequence in string", token, current);
}
} else {
if (static_cast<unsigned char>(c) < 0x20)
return addError("Control character in string", token, current - 1);
decoded += c;
}
}
@@ -1220,8 +1213,20 @@ private:
// complete copy of Read impl, for OurReader
// Test-only instrumentation: total bytes examined by
// OurReader::containsNewLine, so unit tests can assert that comment handling
// stays linear in the input rather than quadratic in the comment count (see
// CharReaderTest/parseCommentsAfterValueScansLinearly). thread_local so it
// never races during concurrent parsing; the increment is negligible and only
// runs while parsing comments. Not part of the supported public API.
JSON_API size_t& newlineScanByteCountForTesting() {
static thread_local size_t count = 0;
return count;
}
bool OurReader::containsNewLine(OurReader::Location begin,
OurReader::Location end) {
newlineScanByteCountForTesting() += static_cast<size_t>(end - begin);
return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
}
@@ -1541,9 +1546,13 @@ bool OurReader::readComment() {
if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
if (isCppStyleComment || !cStyleWithEmbeddedNewline) {
placement = commentAfterOnSameLine;
lastValueHasAComment_ = true;
}
}
// The gap between the last value and this comment only grows as more
// comments are consumed, so a later comment can never be on the same
// line as that value. Mark it handled to avoid re-scanning the same
// growing prefix for every following comment (quadratic behavior).
lastValueHasAComment_ = true;
}
addComment(commentBegin, current_, placement);
@@ -1860,6 +1869,7 @@ bool OurReader::decodeDouble(Token& token) {
bool OurReader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
IStringStream is(String(token.start_, token.end_));
is.imbue(std::locale::classic());
if (!(is >> value)) {
if (value == std::numeric_limits<double>::max())
value = std::numeric_limits<double>::infinity();
@@ -1931,6 +1941,8 @@ bool OurReader::decodeString(Token& token, String& decoded) {
return addError("Bad escape sequence in string", token, current);
}
} else {
if (static_cast<unsigned char>(c) < 0x20)
return addError("Control character in string", token, current - 1);
decoded += c;
}
}
@@ -2175,7 +2187,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings) {
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["allowSingleQuotes"] = false;
(*settings)["stackLimit"] = 1000;
(*settings)["stackLimit"] = 256;
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
@@ -2192,7 +2204,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["allowSingleQuotes"] = false;
(*settings)["stackLimit"] = 1000;
(*settings)["stackLimit"] = 256;
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
@@ -2208,7 +2220,7 @@ void CharReaderBuilder::ecma404Mode(Json::Value* settings) {
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["allowSingleQuotes"] = false;
(*settings)["stackLimit"] = 1000;
(*settings)["stackLimit"] = 256;
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
@@ -2390,8 +2402,8 @@ ValueConstIterator::ValueConstIterator(
ValueConstIterator::ValueConstIterator(ValueIterator const& other)
: ValueIteratorBase(other) {}
ValueConstIterator& ValueConstIterator::
operator=(const ValueIteratorBase& other) {
ValueConstIterator&
ValueConstIterator::operator=(const ValueIteratorBase& other) {
copy(other);
return *this;
}
@@ -2631,6 +2643,32 @@ static inline void releaseStringValue(char* value, unsigned) { free(value); }
// ValueInternals...
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
namespace Json {
static const char* valueTypeToString(ValueType type) {
switch (type) {
case nullValue:
return "nullValue";
case intValue:
return "intValue";
case uintValue:
return "uintValue";
case realValue:
return "realValue";
case stringValue:
return "stringValue";
case booleanValue:
return "booleanValue";
case arrayValue:
return "arrayValue";
case objectValue:
return "objectValue";
}
return "unknown";
}
} // namespace Json
// //////////////////////////////////////////////////////////////////
#if !defined(JSON_IS_AMALGAMATION)
@@ -2687,20 +2725,29 @@ 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_;
if (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_;
} else {
index_ = other.index_;
}
}
Value::CZString::CZString(CZString&& other) noexcept
: cstr_(other.cstr_), index_(other.index_) {
Value::CZString::CZString(CZString&& other) noexcept : cstr_(other.cstr_) {
if (other.cstr_) {
storage_.policy_ = other.storage_.policy_;
storage_.length_ = other.storage_.length_;
} else {
index_ = other.index_;
}
other.cstr_ = nullptr;
}
@@ -2726,8 +2773,16 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
}
Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
if (cstr_ && storage_.policy_ == duplicate) {
releasePrefixedStringValue(const_cast<char*>(cstr_));
}
cstr_ = other.cstr_;
index_ = other.index_;
if (other.cstr_) {
storage_.policy_ = other.storage_.policy_;
storage_.length_ = other.storage_.length_;
} else {
index_ = other.index_;
}
other.cstr_ = nullptr;
return *this;
}
@@ -3122,7 +3177,7 @@ Value::UInt Value::asUInt() const {
JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
return UInt(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt),
"double out of UInt range");
return UInt(value_.real_);
case nullValue:
@@ -3171,7 +3226,7 @@ Value::UInt64 Value::asUInt64() const {
case uintValue:
return UInt64(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt64),
"double out of UInt64 range");
return UInt64(value_.real_);
case nullValue:
@@ -3282,7 +3337,7 @@ bool Value::isConvertibleTo(ValueType other) const {
type() == booleanValue || type() == nullValue;
case uintValue:
return isUInt() ||
(type() == realValue && InRange(value_.real_, 0, maxUInt)) ||
(type() == realValue && InRange(value_.real_, 0u, maxUInt)) ||
type() == booleanValue || type() == nullValue;
case realValue:
return isNumeric() || type() == booleanValue || type() == nullValue;
@@ -3349,8 +3404,10 @@ void Value::clear() {
}
void Value::resize(ArrayIndex newSize) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::resize(): requires arrayValue");
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == arrayValue,
"in Json::Value::resize(): requires arrayValue, but found "
<< valueTypeToString(type()));
if (type() == nullValue)
*this = Value(arrayValue);
ArrayIndex oldSize = size();
@@ -3483,7 +3540,8 @@ void Value::dupMeta(const Value& other) {
Value& Value::resolveReference(const char* key) {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue,
"in Json::Value::resolveReference(): requires objectValue");
"in Json::Value::resolveReference(): requires objectValue, but found "
<< valueTypeToString(type()));
if (type() == nullValue)
*this = Value(objectValue);
CZString actualKey(key, static_cast<unsigned>(strlen(key)),
@@ -3500,9 +3558,10 @@ Value& Value::resolveReference(const char* key) {
// @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");
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
"in Json::Value::resolveReference(key, end): requires "
"objectValue, but found "
<< valueTypeToString(type()));
if (type() == nullValue)
*this = Value(objectValue);
CZString actualKey(key, static_cast<unsigned>(end - key),
@@ -3540,6 +3599,44 @@ Value const* Value::find(char const* begin, char const* end) const {
Value const* Value::find(const String& key) const {
return find(key.data(), key.data() + key.length());
}
Value const* Value::findNull(const String& key) const {
return findValue<Value, &Value::isNull>(key);
}
Value const* Value::findBool(const String& key) const {
return findValue<Value, &Value::isBool>(key);
}
Value const* Value::findInt(const String& key) const {
return findValue<Value, &Value::isInt>(key);
}
Value const* Value::findInt64(const String& key) const {
return findValue<Value, &Value::isInt64>(key);
}
Value const* Value::findUInt(const String& key) const {
return findValue<Value, &Value::isUInt>(key);
}
Value const* Value::findUInt64(const String& key) const {
return findValue<Value, &Value::isUInt64>(key);
}
Value const* Value::findIntegral(const String& key) const {
return findValue<Value, &Value::isIntegral>(key);
}
Value const* Value::findDouble(const String& key) const {
return findValue<Value, &Value::isDouble>(key);
}
Value const* Value::findNumeric(const String& key) const {
return findValue<Value, &Value::isNumeric>(key);
}
Value const* Value::findString(const String& key) const {
return findValue<Value, &Value::isString>(key);
}
Value const* Value::findArray(const String& key) const {
return findValue<Value, &Value::isArray>(key);
}
Value const* Value::findObject(const String& key) const {
return findValue<Value, &Value::isObject>(key);
}
Value* Value::demand(char const* begin, char const* end) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
"in Json::Value::demand(begin, end): requires "
@@ -3575,7 +3672,8 @@ 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");
"in Json::Value::append: requires arrayValue, but found "
<< valueTypeToString(type()));
if (type() == nullValue) {
*this = Value(arrayValue);
}
@@ -3632,9 +3730,12 @@ bool Value::removeMember(const char* key, Value* 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");
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue,
"in Json::Value::removeMember(): requires objectValue, but found "
<< valueTypeToString(type()));
if (type() == nullValue)
return;
@@ -4086,6 +4187,8 @@ Value& Path::make(Value& root) const {
return *node;
}
const char* version() { return JSONCPP_VERSION_STRING; }
} // namespace Json
// //////////////////////////////////////////////////////////////////////
@@ -4113,6 +4216,8 @@ Value& Path::make(Value& root) const {
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <memory>
@@ -4120,67 +4225,6 @@ Value& Path::make(Value& root) const {
#include <sstream>
#include <utility>
#if __cplusplus >= 201103L
#include <cmath>
#include <cstdio>
#if !defined(isnan)
#define isnan std::isnan
#endif
#if !defined(isfinite)
#define isfinite std::isfinite
#endif
#else
#include <cmath>
#include <cstdio>
#if defined(_MSC_VER)
#if !defined(isnan)
#include <float.h>
#define isnan _isnan
#endif
#if !defined(isfinite)
#include <float.h>
#define isfinite _finite
#endif
#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
#endif //_MSC_VER
#if defined(__sun) && defined(__SVR4) // Solaris
#if !defined(isfinite)
#include <ieeefp.h>
#define isfinite finite
#endif
#endif
#if defined(__hpux)
#if !defined(isfinite)
#if defined(__ia64) && !defined(finite)
#define isfinite(x) \
((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
#endif
#endif
#endif
#if !defined(isnan)
// IEEE standard states that NaN values will not compare to themselves
#define isnan(x) ((x) != (x))
#endif
#if !defined(__APPLE__)
#if !defined(isfinite)
#define isfinite finite
#endif
#endif
#endif
#if defined(_MSC_VER)
// Disable warning about strdup being deprecated.
#pragma warning(disable : 4996)
@@ -4188,11 +4232,7 @@ Value& Path::make(Value& root) const {
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
#else
using StreamWriterPtr = std::auto_ptr<StreamWriter>;
#endif
String valueToString(LargestInt value) {
UIntToStringBuffer buffer;
@@ -4232,12 +4272,12 @@ String valueToString(double value, bool useSpecialFloats,
// Print into the buffer. We need not request the alternative representation
// that always has a decimal point because JSON doesn't distinguish the
// concepts of reals and integers.
if (!isfinite(value)) {
static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
{"null", "-1e+9999", "1e+9999"}};
return reps[useSpecialFloats ? 0 : 1][isnan(value) ? 0
: (value < 0) ? 1
: 2];
if (!std::isfinite(value)) {
if (std::isnan(value))
return useSpecialFloats ? "NaN" : "null";
if (value < 0)
return useSpecialFloats ? "-Infinity" : "-1e+9999";
return useSpecialFloats ? "Infinity" : "1e+9999";
}
String buffer(size_t(36), '\0');