mirror of
https://github.com/luanti-org/luanti.git
synced 2026-10-12 02:18:30 +00:00
Update vendored jsoncpp to 1.9.8
This commit is contained in:
@@ -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 ..
|
||||
|
||||
@@ -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
@@ -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
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user