mirror of
https://github.com/Kitware/CMake.git
synced 2025-05-08 22:37:04 +08:00
Merge branch 'upstream-jsoncpp' into update-jsoncpp
* upstream-jsoncpp: jsoncpp 2024-09-09 (89e2973c)
This commit is contained in:
commit
af65a5d98b
@ -71,7 +71,9 @@ public:
|
|||||||
// Boilerplate
|
// Boilerplate
|
||||||
SecureAllocator() {}
|
SecureAllocator() {}
|
||||||
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
||||||
template <typename U> struct rebind { using other = SecureAllocator<U>; };
|
template <typename U> struct rebind {
|
||||||
|
using other = SecureAllocator<U>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
|
@ -53,12 +53,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Constructs a Reader allowing all features for parsing.
|
/** \brief Constructs a Reader allowing all features for parsing.
|
||||||
* deprecated Use CharReader and CharReaderBuilder.
|
* deprecated Use CharReader and CharReaderBuilder.
|
||||||
*/
|
*/
|
||||||
Reader();
|
Reader();
|
||||||
|
|
||||||
/** \brief Constructs a Reader allowing the specified feature set for parsing.
|
/** \brief Constructs a Reader allowing the specified feature set for parsing.
|
||||||
* deprecated Use CharReader and CharReaderBuilder.
|
* deprecated Use CharReader and CharReaderBuilder.
|
||||||
*/
|
*/
|
||||||
Reader(const Features& features);
|
Reader(const Features& features);
|
||||||
|
|
||||||
@ -192,6 +192,7 @@ private:
|
|||||||
using Errors = std::deque<ErrorInfo>;
|
using Errors = std::deque<ErrorInfo>;
|
||||||
|
|
||||||
bool readToken(Token& token);
|
bool readToken(Token& token);
|
||||||
|
bool readTokenSkippingComments(Token& token);
|
||||||
void skipSpaces();
|
void skipSpaces();
|
||||||
bool match(const Char* pattern, int patternLength);
|
bool match(const Char* pattern, int patternLength);
|
||||||
bool readComment();
|
bool readComment();
|
||||||
@ -223,7 +224,6 @@ private:
|
|||||||
int& column) const;
|
int& column) const;
|
||||||
String getLocationLineAndColumn(Location location) const;
|
String getLocationLineAndColumn(Location location) const;
|
||||||
void addComment(Location begin, Location end, CommentPlacement placement);
|
void addComment(Location begin, Location end, CommentPlacement placement);
|
||||||
void skipCommentTokens(Token& token);
|
|
||||||
|
|
||||||
static bool containsNewLine(Location begin, Location end);
|
static bool containsNewLine(Location begin, Location end);
|
||||||
static String normalizeEOL(Location begin, Location end);
|
static String normalizeEOL(Location begin, Location end);
|
||||||
@ -246,6 +246,12 @@ private:
|
|||||||
*/
|
*/
|
||||||
class JSON_API CharReader {
|
class JSON_API CharReader {
|
||||||
public:
|
public:
|
||||||
|
struct JSON_API StructuredError {
|
||||||
|
ptrdiff_t offset_start;
|
||||||
|
ptrdiff_t offset_limit;
|
||||||
|
String message;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~CharReader() = default;
|
virtual ~CharReader() = default;
|
||||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
* document. The document must be a UTF-8 encoded string containing the
|
* document. The document must be a UTF-8 encoded string containing the
|
||||||
@ -264,7 +270,12 @@ public:
|
|||||||
* error occurred.
|
* error occurred.
|
||||||
*/
|
*/
|
||||||
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
String* errs) = 0;
|
String* errs);
|
||||||
|
|
||||||
|
/** \brief Returns a vector of structured errors encountered while parsing.
|
||||||
|
* Each parse call resets the stored list of errors.
|
||||||
|
*/
|
||||||
|
std::vector<StructuredError> getStructuredErrors() const;
|
||||||
|
|
||||||
class JSON_API Factory {
|
class JSON_API Factory {
|
||||||
public:
|
public:
|
||||||
@ -274,7 +285,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual CharReader* newCharReader() const = 0;
|
virtual CharReader* newCharReader() const = 0;
|
||||||
}; // Factory
|
}; // Factory
|
||||||
}; // CharReader
|
|
||||||
|
protected:
|
||||||
|
class Impl {
|
||||||
|
public:
|
||||||
|
virtual ~Impl() = default;
|
||||||
|
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
|
String* errs) = 0;
|
||||||
|
virtual std::vector<StructuredError> getStructuredErrors() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit CharReader(std::unique_ptr<Impl> impl) : _impl(std::move(impl)) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Impl> _impl;
|
||||||
|
}; // CharReader
|
||||||
|
|
||||||
/** \brief Build a CharReader implementation.
|
/** \brief Build a CharReader implementation.
|
||||||
*
|
*
|
||||||
@ -362,6 +387,12 @@ public:
|
|||||||
* snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
* snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
||||||
*/
|
*/
|
||||||
static void strictMode(Json::Value* settings);
|
static void strictMode(Json::Value* settings);
|
||||||
|
/** ECMA-404 mode.
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderECMA404Mode
|
||||||
|
*/
|
||||||
|
static void ecma404Mode(Json::Value* settings);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Consume entire stream and use its begin/end.
|
/** Consume entire stream and use its begin/end.
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSON_H_INCLUDED
|
#ifndef JSON_VALUE_H_INCLUDED
|
||||||
#define JSON_H_INCLUDED
|
#define JSON_VALUE_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
#include "forwards.h"
|
#include "forwards.h"
|
||||||
@ -443,7 +443,7 @@ public:
|
|||||||
/// \post type() is arrayValue
|
/// \post type() is arrayValue
|
||||||
void resize(ArrayIndex newSize);
|
void resize(ArrayIndex newSize);
|
||||||
|
|
||||||
//@{
|
///@{
|
||||||
/// Access an array element (zero based index). If the array contains less
|
/// Access an array element (zero based index). If the array contains less
|
||||||
/// than index element, then null value are inserted in the array so that
|
/// than index element, then null value are inserted in the array so that
|
||||||
/// its size is index+1.
|
/// its size is index+1.
|
||||||
@ -451,15 +451,15 @@ public:
|
|||||||
/// this from the operator[] which takes a string.)
|
/// this from the operator[] which takes a string.)
|
||||||
Value& operator[](ArrayIndex index);
|
Value& operator[](ArrayIndex index);
|
||||||
Value& operator[](int index);
|
Value& operator[](int index);
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
//@{
|
///@{
|
||||||
/// Access an array element (zero based index).
|
/// Access an array element (zero based index).
|
||||||
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||||
/// this from the operator[] which takes a string.)
|
/// this from the operator[] which takes a string.)
|
||||||
const Value& operator[](ArrayIndex index) const;
|
const Value& operator[](ArrayIndex index) const;
|
||||||
const Value& operator[](int index) const;
|
const Value& operator[](int index) const;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// If the array contains at least index+1 elements, returns the element
|
/// If the array contains at least index+1 elements, returns the element
|
||||||
/// value, otherwise returns defaultValue.
|
/// value, otherwise returns defaultValue.
|
||||||
@ -519,6 +519,9 @@ public:
|
|||||||
/// and operator[]const
|
/// and operator[]const
|
||||||
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
Value const* find(char const* begin, char const* end) const;
|
Value const* find(char const* begin, char const* end) const;
|
||||||
|
/// Most general and efficient version of isMember()const, get()const,
|
||||||
|
/// and operator[]const
|
||||||
|
Value const* find(const String& key) const;
|
||||||
/// Most general and efficient version of object-mutators.
|
/// Most general and efficient version of object-mutators.
|
||||||
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
/// \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.
|
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
|
||||||
@ -591,6 +594,26 @@ public:
|
|||||||
iterator begin();
|
iterator begin();
|
||||||
iterator end();
|
iterator end();
|
||||||
|
|
||||||
|
/// \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.
|
||||||
|
const Value& front() 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.
|
||||||
|
Value& front();
|
||||||
|
|
||||||
|
/// \brief Returns a reference to the last element in the `Value`.
|
||||||
|
/// Requires that value holds an array or json object, with at least one
|
||||||
|
/// element.
|
||||||
|
const Value& back() const;
|
||||||
|
|
||||||
|
/// \brief Returns a reference to the last element in the `Value`.
|
||||||
|
/// Requires that this value holds an array or json object, with at least one
|
||||||
|
/// element.
|
||||||
|
Value& back();
|
||||||
|
|
||||||
// Accessors for the [start, limit) range of bytes within the JSON text from
|
// Accessors for the [start, limit) range of bytes within the JSON text from
|
||||||
// which this value was parsed, if any.
|
// which this value was parsed, if any.
|
||||||
void setOffsetStart(ptrdiff_t start);
|
void setOffsetStart(ptrdiff_t start);
|
||||||
@ -931,6 +954,14 @@ public:
|
|||||||
|
|
||||||
inline void swap(Value& a, Value& b) { a.swap(b); }
|
inline void swap(Value& a, Value& b) { a.swap(b); }
|
||||||
|
|
||||||
|
inline const Value& Value::front() const { return *begin(); }
|
||||||
|
|
||||||
|
inline Value& Value::front() { return *begin(); }
|
||||||
|
|
||||||
|
inline const Value& Value::back() const { return *(--end()); }
|
||||||
|
|
||||||
|
inline Value& Value::back() { return *(--end()); }
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
#if !defined(__SUNPRO_CC)
|
#if !defined(__SUNPRO_CC)
|
||||||
|
@ -9,19 +9,18 @@
|
|||||||
// 3. /CMakeLists.txt
|
// 3. /CMakeLists.txt
|
||||||
// IMPORTANT: also update the SOVERSION!!
|
// IMPORTANT: also update the SOVERSION!!
|
||||||
|
|
||||||
#define JSONCPP_VERSION_STRING "1.9.5"
|
#define JSONCPP_VERSION_STRING "1.9.6"
|
||||||
#define JSONCPP_VERSION_MAJOR 1
|
#define JSONCPP_VERSION_MAJOR 1
|
||||||
#define JSONCPP_VERSION_MINOR 9
|
#define JSONCPP_VERSION_MINOR 9
|
||||||
#define JSONCPP_VERSION_PATCH 5
|
#define JSONCPP_VERSION_PATCH 6
|
||||||
#define JSONCPP_VERSION_QUALIFIER
|
#define JSONCPP_VERSION_QUALIFIER
|
||||||
#define JSONCPP_VERSION_HEXA \
|
#define JSONCPP_VERSION_HEXA \
|
||||||
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||||
(JSONCPP_VERSION_PATCH << 8))
|
(JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
#ifdef JSONCPP_USING_SECURE_MEMORY
|
#if !defined(JSONCPP_USE_SECURE_MEMORY)
|
||||||
#undef JSONCPP_USING_SECURE_MEMORY
|
|
||||||
#endif
|
|
||||||
#define JSONCPP_USING_SECURE_MEMORY 0
|
#define JSONCPP_USING_SECURE_MEMORY 0
|
||||||
|
#endif
|
||||||
// If non-zero, the library zeroes any memory that it has allocated before
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
// it frees its memory.
|
// it frees its memory.
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual StreamWriter* newStreamWriter() const = 0;
|
virtual StreamWriter* newStreamWriter() const = 0;
|
||||||
}; // Factory
|
}; // Factory
|
||||||
}; // StreamWriter
|
}; // StreamWriter
|
||||||
|
|
||||||
/** \brief Write into stringstream, then return string, for convenience.
|
/** \brief Write into stringstream, then return string, for convenience.
|
||||||
* A StreamWriter will be created from the factory, used, and then deleted.
|
* A StreamWriter will be created from the factory, used, and then deleted.
|
||||||
@ -170,8 +170,7 @@ public:
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
#endif
|
#endif
|
||||||
class JSON_API FastWriter
|
class JSON_API FastWriter : public Writer {
|
||||||
: public Writer {
|
|
||||||
public:
|
public:
|
||||||
FastWriter();
|
FastWriter();
|
||||||
~FastWriter() override = default;
|
~FastWriter() override = default;
|
||||||
@ -230,8 +229,7 @@ private:
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
#endif
|
#endif
|
||||||
class JSON_API
|
class JSON_API StyledWriter : public Writer {
|
||||||
StyledWriter : public Writer {
|
|
||||||
public:
|
public:
|
||||||
StyledWriter();
|
StyledWriter();
|
||||||
~StyledWriter() override = default;
|
~StyledWriter() override = default;
|
||||||
@ -299,8 +297,7 @@ private:
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
#endif
|
#endif
|
||||||
class JSON_API
|
class JSON_API StyledStreamWriter {
|
||||||
StyledStreamWriter {
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* \param indentation Each level will be indented by this amount extra.
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
@ -356,6 +353,7 @@ String JSON_API valueToString(
|
|||||||
PrecisionType precisionType = PrecisionType::significantDigits);
|
PrecisionType precisionType = PrecisionType::significantDigits);
|
||||||
String JSON_API valueToString(bool value);
|
String JSON_API valueToString(bool value);
|
||||||
String JSON_API valueToQuotedString(const char* value);
|
String JSON_API valueToQuotedString(const char* value);
|
||||||
|
String JSON_API valueToQuotedString(const char* value, size_t length);
|
||||||
|
|
||||||
/// \brief Output using the StyledStreamWriter.
|
/// \brief Output using the StyledStreamWriter.
|
||||||
/// \see Json::operator>>()
|
/// \see Json::operator>>()
|
||||||
|
@ -129,7 +129,7 @@ bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
|||||||
|
|
||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
readTokenSkippingComments(token);
|
||||||
if (collectComments_ && !commentsBefore_.empty())
|
if (collectComments_ && !commentsBefore_.empty())
|
||||||
root.setComment(commentsBefore_, commentAfter);
|
root.setComment(commentsBefore_, commentAfter);
|
||||||
if (features_.strictRoot_) {
|
if (features_.strictRoot_) {
|
||||||
@ -157,7 +157,7 @@ bool Reader::readValue() {
|
|||||||
throwRuntimeError("Exceeded stackLimit in readValue().");
|
throwRuntimeError("Exceeded stackLimit in readValue().");
|
||||||
|
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
readTokenSkippingComments(token);
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
|
|
||||||
if (collectComments_ && !commentsBefore_.empty()) {
|
if (collectComments_ && !commentsBefore_.empty()) {
|
||||||
@ -225,14 +225,14 @@ bool Reader::readValue() {
|
|||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reader::skipCommentTokens(Token& token) {
|
bool Reader::readTokenSkippingComments(Token& token) {
|
||||||
|
bool success = readToken(token);
|
||||||
if (features_.allowComments_) {
|
if (features_.allowComments_) {
|
||||||
do {
|
while (success && token.type_ == tokenComment) {
|
||||||
readToken(token);
|
success = readToken(token);
|
||||||
} while (token.type_ == tokenComment);
|
}
|
||||||
} else {
|
|
||||||
readToken(token);
|
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::readToken(Token& token) {
|
bool Reader::readToken(Token& token) {
|
||||||
@ -446,12 +446,7 @@ bool Reader::readObject(Token& token) {
|
|||||||
Value init(objectValue);
|
Value init(objectValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(token.start_ - begin_);
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
while (readToken(tokenName)) {
|
while (readTokenSkippingComments(tokenName)) {
|
||||||
bool initialTokenOk = true;
|
|
||||||
while (tokenName.type_ == tokenComment && initialTokenOk)
|
|
||||||
initialTokenOk = readToken(tokenName);
|
|
||||||
if (!initialTokenOk)
|
|
||||||
break;
|
|
||||||
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
||||||
return true;
|
return true;
|
||||||
name.clear();
|
name.clear();
|
||||||
@ -480,15 +475,11 @@ bool Reader::readObject(Token& token) {
|
|||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
|
|
||||||
Token comma;
|
Token comma;
|
||||||
if (!readToken(comma) ||
|
if (!readTokenSkippingComments(comma) ||
|
||||||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
|
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator)) {
|
||||||
comma.type_ != tokenComment)) {
|
|
||||||
return addErrorAndRecover("Missing ',' or '}' in object declaration",
|
return addErrorAndRecover("Missing ',' or '}' in object declaration",
|
||||||
comma, tokenObjectEnd);
|
comma, tokenObjectEnd);
|
||||||
}
|
}
|
||||||
bool finalizeTokenOk = true;
|
|
||||||
while (comma.type_ == tokenComment && finalizeTokenOk)
|
|
||||||
finalizeTokenOk = readToken(comma);
|
|
||||||
if (comma.type_ == tokenObjectEnd)
|
if (comma.type_ == tokenObjectEnd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -518,10 +509,7 @@ bool Reader::readArray(Token& token) {
|
|||||||
|
|
||||||
Token currentToken;
|
Token currentToken;
|
||||||
// Accept Comment after last item in the array.
|
// Accept Comment after last item in the array.
|
||||||
ok = readToken(currentToken);
|
ok = readTokenSkippingComments(currentToken);
|
||||||
while (currentToken.type_ == tokenComment && ok) {
|
|
||||||
ok = readToken(currentToken);
|
|
||||||
}
|
|
||||||
bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
|
bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
|
||||||
currentToken.type_ != tokenArrayEnd);
|
currentToken.type_ != tokenArrayEnd);
|
||||||
if (!ok || badTokenType) {
|
if (!ok || badTokenType) {
|
||||||
@ -599,8 +587,7 @@ bool Reader::decodeDouble(Token& token) {
|
|||||||
|
|
||||||
bool Reader::decodeDouble(Token& token, Value& decoded) {
|
bool Reader::decodeDouble(Token& token, Value& decoded) {
|
||||||
double value = 0;
|
double value = 0;
|
||||||
String buffer(token.start_, token.end_);
|
IStringStream is(String(token.start_, token.end_));
|
||||||
IStringStream is(buffer);
|
|
||||||
if (!(is >> value)) {
|
if (!(is >> value)) {
|
||||||
if (value == std::numeric_limits<double>::max())
|
if (value == std::numeric_limits<double>::max())
|
||||||
value = std::numeric_limits<double>::infinity();
|
value = std::numeric_limits<double>::infinity();
|
||||||
@ -608,7 +595,7 @@ bool Reader::decodeDouble(Token& token, Value& decoded) {
|
|||||||
value = -std::numeric_limits<double>::infinity();
|
value = -std::numeric_limits<double>::infinity();
|
||||||
else if (!std::isinf(value))
|
else if (!std::isinf(value))
|
||||||
return addError(
|
return addError(
|
||||||
"'" + String(token.start_, token.end_) + "' is not a number.", token);
|
"'" + String(token.start_, token.end_) + "' is not a number.", token);
|
||||||
}
|
}
|
||||||
decoded = value;
|
decoded = value;
|
||||||
return true;
|
return true;
|
||||||
@ -773,7 +760,7 @@ void Reader::getLocationLineAndColumn(Location location, int& line,
|
|||||||
while (current < location && current != end_) {
|
while (current < location && current != end_) {
|
||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
if (*current == '\n')
|
if (current != end_ && *current == '\n')
|
||||||
++current;
|
++current;
|
||||||
lastLineStart = current;
|
lastLineStart = current;
|
||||||
++line;
|
++line;
|
||||||
@ -890,17 +877,12 @@ class OurReader {
|
|||||||
public:
|
public:
|
||||||
using Char = char;
|
using Char = char;
|
||||||
using Location = const Char*;
|
using Location = const Char*;
|
||||||
struct StructuredError {
|
|
||||||
ptrdiff_t offset_start;
|
|
||||||
ptrdiff_t offset_limit;
|
|
||||||
String message;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit OurReader(OurFeatures const& features);
|
explicit OurReader(OurFeatures const& features);
|
||||||
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||||
bool collectComments = true);
|
bool collectComments = true);
|
||||||
String getFormattedErrorMessages() const;
|
String getFormattedErrorMessages() const;
|
||||||
std::vector<StructuredError> getStructuredErrors() const;
|
std::vector<CharReader::StructuredError> getStructuredErrors() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OurReader(OurReader const&); // no impl
|
OurReader(OurReader const&); // no impl
|
||||||
@ -943,6 +925,7 @@ private:
|
|||||||
using Errors = std::deque<ErrorInfo>;
|
using Errors = std::deque<ErrorInfo>;
|
||||||
|
|
||||||
bool readToken(Token& token);
|
bool readToken(Token& token);
|
||||||
|
bool readTokenSkippingComments(Token& token);
|
||||||
void skipSpaces();
|
void skipSpaces();
|
||||||
void skipBom(bool skipBom);
|
void skipBom(bool skipBom);
|
||||||
bool match(const Char* pattern, int patternLength);
|
bool match(const Char* pattern, int patternLength);
|
||||||
@ -976,7 +959,6 @@ private:
|
|||||||
int& column) const;
|
int& column) const;
|
||||||
String getLocationLineAndColumn(Location location) const;
|
String getLocationLineAndColumn(Location location) const;
|
||||||
void addComment(Location begin, Location end, CommentPlacement placement);
|
void addComment(Location begin, Location end, CommentPlacement placement);
|
||||||
void skipCommentTokens(Token& token);
|
|
||||||
|
|
||||||
static String normalizeEOL(Location begin, Location end);
|
static String normalizeEOL(Location begin, Location end);
|
||||||
static bool containsNewLine(Location begin, Location end);
|
static bool containsNewLine(Location begin, Location end);
|
||||||
@ -1030,7 +1012,7 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
|||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
readTokenSkippingComments(token);
|
||||||
if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) {
|
if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) {
|
||||||
addError("Extra non-whitespace after JSON value.", token);
|
addError("Extra non-whitespace after JSON value.", token);
|
||||||
return false;
|
return false;
|
||||||
@ -1058,7 +1040,7 @@ bool OurReader::readValue() {
|
|||||||
if (nodes_.size() > features_.stackLimit_)
|
if (nodes_.size() > features_.stackLimit_)
|
||||||
throwRuntimeError("Exceeded stackLimit in readValue().");
|
throwRuntimeError("Exceeded stackLimit in readValue().");
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
readTokenSkippingComments(token);
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
|
|
||||||
if (collectComments_ && !commentsBefore_.empty()) {
|
if (collectComments_ && !commentsBefore_.empty()) {
|
||||||
@ -1145,14 +1127,14 @@ bool OurReader::readValue() {
|
|||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OurReader::skipCommentTokens(Token& token) {
|
bool OurReader::readTokenSkippingComments(Token& token) {
|
||||||
|
bool success = readToken(token);
|
||||||
if (features_.allowComments_) {
|
if (features_.allowComments_) {
|
||||||
do {
|
while (success && token.type_ == tokenComment) {
|
||||||
readToken(token);
|
success = readToken(token);
|
||||||
} while (token.type_ == tokenComment);
|
}
|
||||||
} else {
|
|
||||||
readToken(token);
|
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::readToken(Token& token) {
|
bool OurReader::readToken(Token& token) {
|
||||||
@ -1449,12 +1431,7 @@ bool OurReader::readObject(Token& token) {
|
|||||||
Value init(objectValue);
|
Value init(objectValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(token.start_ - begin_);
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
while (readToken(tokenName)) {
|
while (readTokenSkippingComments(tokenName)) {
|
||||||
bool initialTokenOk = true;
|
|
||||||
while (tokenName.type_ == tokenComment && initialTokenOk)
|
|
||||||
initialTokenOk = readToken(tokenName);
|
|
||||||
if (!initialTokenOk)
|
|
||||||
break;
|
|
||||||
if (tokenName.type_ == tokenObjectEnd &&
|
if (tokenName.type_ == tokenObjectEnd &&
|
||||||
(name.empty() ||
|
(name.empty() ||
|
||||||
features_.allowTrailingCommas_)) // empty object or trailing comma
|
features_.allowTrailingCommas_)) // empty object or trailing comma
|
||||||
@ -1491,15 +1468,11 @@ bool OurReader::readObject(Token& token) {
|
|||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
|
|
||||||
Token comma;
|
Token comma;
|
||||||
if (!readToken(comma) ||
|
if (!readTokenSkippingComments(comma) ||
|
||||||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
|
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator)) {
|
||||||
comma.type_ != tokenComment)) {
|
|
||||||
return addErrorAndRecover("Missing ',' or '}' in object declaration",
|
return addErrorAndRecover("Missing ',' or '}' in object declaration",
|
||||||
comma, tokenObjectEnd);
|
comma, tokenObjectEnd);
|
||||||
}
|
}
|
||||||
bool finalizeTokenOk = true;
|
|
||||||
while (comma.type_ == tokenComment && finalizeTokenOk)
|
|
||||||
finalizeTokenOk = readToken(comma);
|
|
||||||
if (comma.type_ == tokenObjectEnd)
|
if (comma.type_ == tokenObjectEnd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1533,10 +1506,7 @@ bool OurReader::readArray(Token& token) {
|
|||||||
|
|
||||||
Token currentToken;
|
Token currentToken;
|
||||||
// Accept Comment after last item in the array.
|
// Accept Comment after last item in the array.
|
||||||
ok = readToken(currentToken);
|
ok = readTokenSkippingComments(currentToken);
|
||||||
while (currentToken.type_ == tokenComment && ok) {
|
|
||||||
ok = readToken(currentToken);
|
|
||||||
}
|
|
||||||
bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
|
bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
|
||||||
currentToken.type_ != tokenArrayEnd);
|
currentToken.type_ != tokenArrayEnd);
|
||||||
if (!ok || badTokenType) {
|
if (!ok || badTokenType) {
|
||||||
@ -1651,8 +1621,7 @@ bool OurReader::decodeDouble(Token& token) {
|
|||||||
|
|
||||||
bool OurReader::decodeDouble(Token& token, Value& decoded) {
|
bool OurReader::decodeDouble(Token& token, Value& decoded) {
|
||||||
double value = 0;
|
double value = 0;
|
||||||
const String buffer(token.start_, token.end_);
|
IStringStream is(String(token.start_, token.end_));
|
||||||
IStringStream is(buffer);
|
|
||||||
if (!(is >> value)) {
|
if (!(is >> value)) {
|
||||||
if (value == std::numeric_limits<double>::max())
|
if (value == std::numeric_limits<double>::max())
|
||||||
value = std::numeric_limits<double>::infinity();
|
value = std::numeric_limits<double>::infinity();
|
||||||
@ -1660,7 +1629,7 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
|
|||||||
value = -std::numeric_limits<double>::infinity();
|
value = -std::numeric_limits<double>::infinity();
|
||||||
else if (!std::isinf(value))
|
else if (!std::isinf(value))
|
||||||
return addError(
|
return addError(
|
||||||
"'" + String(token.start_, token.end_) + "' is not a number.", token);
|
"'" + String(token.start_, token.end_) + "' is not a number.", token);
|
||||||
}
|
}
|
||||||
decoded = value;
|
decoded = value;
|
||||||
return true;
|
return true;
|
||||||
@ -1826,7 +1795,7 @@ void OurReader::getLocationLineAndColumn(Location location, int& line,
|
|||||||
while (current < location && current != end_) {
|
while (current < location && current != end_) {
|
||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
if (*current == '\n')
|
if (current != end_ && *current == '\n')
|
||||||
++current;
|
++current;
|
||||||
lastLineStart = current;
|
lastLineStart = current;
|
||||||
++line;
|
++line;
|
||||||
@ -1861,10 +1830,11 @@ String OurReader::getFormattedErrorMessages() const {
|
|||||||
return formattedMessage;
|
return formattedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
std::vector<CharReader::StructuredError>
|
||||||
std::vector<OurReader::StructuredError> allErrors;
|
OurReader::getStructuredErrors() const {
|
||||||
|
std::vector<CharReader::StructuredError> allErrors;
|
||||||
for (const auto& error : errors_) {
|
for (const auto& error : errors_) {
|
||||||
OurReader::StructuredError structured;
|
CharReader::StructuredError structured;
|
||||||
structured.offset_start = error.token_.start_ - begin_;
|
structured.offset_start = error.token_.start_ - begin_;
|
||||||
structured.offset_limit = error.token_.end_ - begin_;
|
structured.offset_limit = error.token_.end_ - begin_;
|
||||||
structured.message = error.message_;
|
structured.message = error.message_;
|
||||||
@ -1874,20 +1844,36 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OurCharReader : public CharReader {
|
class OurCharReader : public CharReader {
|
||||||
bool const collectComments_;
|
|
||||||
OurReader reader_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OurCharReader(bool collectComments, OurFeatures const& features)
|
OurCharReader(bool collectComments, OurFeatures const& features)
|
||||||
: collectComments_(collectComments), reader_(features) {}
|
: CharReader(
|
||||||
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
std::unique_ptr<OurImpl>(new OurImpl(collectComments, features))) {}
|
||||||
String* errs) override {
|
|
||||||
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
protected:
|
||||||
if (errs) {
|
class OurImpl : public Impl {
|
||||||
*errs = reader_.getFormattedErrorMessages();
|
public:
|
||||||
|
OurImpl(bool collectComments, OurFeatures const& features)
|
||||||
|
: collectComments_(collectComments), reader_(features) {}
|
||||||
|
|
||||||
|
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
|
String* errs) override {
|
||||||
|
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
||||||
|
if (errs) {
|
||||||
|
*errs = reader_.getFormattedErrorMessages();
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
return ok;
|
|
||||||
}
|
std::vector<CharReader::StructuredError>
|
||||||
|
getStructuredErrors() const override {
|
||||||
|
return reader_.getStructuredErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool const collectComments_;
|
||||||
|
OurReader reader_;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
||||||
@ -1976,6 +1962,32 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
|
|||||||
(*settings)["skipBom"] = true;
|
(*settings)["skipBom"] = true;
|
||||||
//! [CharReaderBuilderDefaults]
|
//! [CharReaderBuilderDefaults]
|
||||||
}
|
}
|
||||||
|
// static
|
||||||
|
void CharReaderBuilder::ecma404Mode(Json::Value* settings) {
|
||||||
|
//! [CharReaderBuilderECMA404Mode]
|
||||||
|
(*settings)["allowComments"] = false;
|
||||||
|
(*settings)["allowTrailingCommas"] = false;
|
||||||
|
(*settings)["strictRoot"] = false;
|
||||||
|
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||||
|
(*settings)["allowNumericKeys"] = false;
|
||||||
|
(*settings)["allowSingleQuotes"] = false;
|
||||||
|
(*settings)["stackLimit"] = 1000;
|
||||||
|
(*settings)["failIfExtra"] = true;
|
||||||
|
(*settings)["rejectDupKeys"] = false;
|
||||||
|
(*settings)["allowSpecialFloats"] = false;
|
||||||
|
(*settings)["skipBom"] = false;
|
||||||
|
//! [CharReaderBuilderECMA404Mode]
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CharReader::StructuredError>
|
||||||
|
CharReader::getStructuredErrors() const {
|
||||||
|
return _impl->getStructuredErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CharReader::parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
|
String* errs) {
|
||||||
|
return _impl->parse(beginDoc, endDoc, root, errs);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
// global functions
|
// global functions
|
||||||
@ -1984,7 +1996,7 @@ bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root,
|
|||||||
String* errs) {
|
String* errs) {
|
||||||
OStringStream ssin;
|
OStringStream ssin;
|
||||||
ssin << sin.rdbuf();
|
ssin << sin.rdbuf();
|
||||||
String doc = ssin.str();
|
String doc = std::move(ssin).str();
|
||||||
char const* begin = doc.data();
|
char const* begin = doc.data();
|
||||||
char const* end = begin + doc.size();
|
char const* end = begin + doc.size();
|
||||||
// Note that we do not actually need a null-terminator.
|
// Note that we do not actually need a null-terminator.
|
||||||
|
@ -1092,6 +1092,9 @@ Value const* Value::find(char const* begin, char const* end) const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
return &(*it).second;
|
return &(*it).second;
|
||||||
}
|
}
|
||||||
|
Value const* Value::find(const String& key) const {
|
||||||
|
return find(key.data(), key.data() + key.length());
|
||||||
|
}
|
||||||
Value* Value::demand(char const* begin, char const* end) {
|
Value* Value::demand(char const* begin, char const* end) {
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
||||||
"in Json::Value::demand(begin, end): requires "
|
"in Json::Value::demand(begin, end): requires "
|
||||||
@ -1105,7 +1108,7 @@ const Value& Value::operator[](const char* key) const {
|
|||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
Value const& Value::operator[](const String& key) const {
|
Value const& Value::operator[](const String& key) const {
|
||||||
Value const* found = find(key.data(), key.data() + key.length());
|
Value const* found = find(key);
|
||||||
if (!found)
|
if (!found)
|
||||||
return nullSingleton();
|
return nullSingleton();
|
||||||
return *found;
|
return *found;
|
||||||
@ -1205,7 +1208,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (removed)
|
if (removed)
|
||||||
*removed = it->second;
|
*removed = std::move(it->second);
|
||||||
ArrayIndex oldSize = size();
|
ArrayIndex oldSize = size();
|
||||||
// shift left all items left, into the place of the "removed"
|
// shift left all items left, into the place of the "removed"
|
||||||
for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
|
for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
|
||||||
@ -1410,9 +1413,8 @@ void Value::setComment(String comment, CommentPlacement placement) {
|
|||||||
// Always discard trailing newline, to aid indentation.
|
// Always discard trailing newline, to aid indentation.
|
||||||
comment.pop_back();
|
comment.pop_back();
|
||||||
}
|
}
|
||||||
JSON_ASSERT(!comment.empty());
|
|
||||||
JSON_ASSERT_MESSAGE(
|
JSON_ASSERT_MESSAGE(
|
||||||
comment[0] == '\0' || comment[0] == '/',
|
comment.empty() || comment[0] == '/',
|
||||||
"in Json::Value::setComment(): Comments must start with /");
|
"in Json::Value::setComment(): Comments must start with /");
|
||||||
comments_.set(placement, std::move(comment));
|
comments_.set(placement, std::move(comment));
|
||||||
}
|
}
|
||||||
|
@ -132,8 +132,9 @@ String valueToString(double value, bool useSpecialFloats,
|
|||||||
if (!isfinite(value)) {
|
if (!isfinite(value)) {
|
||||||
static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
|
static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
|
||||||
{"null", "-1e+9999", "1e+9999"}};
|
{"null", "-1e+9999", "1e+9999"}};
|
||||||
return reps[useSpecialFloats ? 0 : 1]
|
return reps[useSpecialFloats ? 0 : 1][isnan(value) ? 0
|
||||||
[isnan(value) ? 0 : (value < 0) ? 1 : 2];
|
: (value < 0) ? 1
|
||||||
|
: 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
String buffer(size_t(36), '\0');
|
String buffer(size_t(36), '\0');
|
||||||
@ -353,6 +354,10 @@ String valueToQuotedString(const char* value) {
|
|||||||
return valueToQuotedStringN(value, strlen(value));
|
return valueToQuotedStringN(value, strlen(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String valueToQuotedString(const char* value, size_t length) {
|
||||||
|
return valueToQuotedStringN(value, length);
|
||||||
|
}
|
||||||
|
|
||||||
// Class Writer
|
// Class Writer
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
Writer::~Writer() = default;
|
Writer::~Writer() = default;
|
||||||
@ -490,7 +495,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
const Value& childValue = value[name];
|
const Value& childValue = value[name];
|
||||||
writeCommentBeforeValue(childValue);
|
writeCommentBeforeValue(childValue);
|
||||||
writeWithIndent(valueToQuotedString(name.c_str()));
|
writeWithIndent(valueToQuotedString(name.c_str(), name.size()));
|
||||||
document_ += " : ";
|
document_ += " : ";
|
||||||
writeValue(childValue);
|
writeValue(childValue);
|
||||||
if (++it == members.end()) {
|
if (++it == members.end()) {
|
||||||
@ -708,7 +713,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
|||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
const Value& childValue = value[name];
|
const Value& childValue = value[name];
|
||||||
writeCommentBeforeValue(childValue);
|
writeCommentBeforeValue(childValue);
|
||||||
writeWithIndent(valueToQuotedString(name.c_str()));
|
writeWithIndent(valueToQuotedString(name.c_str(), name.size()));
|
||||||
*document_ << " : ";
|
*document_ << " : ";
|
||||||
writeValue(childValue);
|
writeValue(childValue);
|
||||||
if (++it == members.end()) {
|
if (++it == members.end()) {
|
||||||
@ -1246,7 +1251,7 @@ String writeString(StreamWriter::Factory const& factory, Value const& root) {
|
|||||||
OStringStream sout;
|
OStringStream sout;
|
||||||
StreamWriterPtr const writer(factory.newStreamWriter());
|
StreamWriterPtr const writer(factory.newStreamWriter());
|
||||||
writer->write(root, &sout);
|
writer->write(root, &sout);
|
||||||
return sout.str();
|
return std::move(sout).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
OStream& operator<<(OStream& sout, Value const& root) {
|
OStream& operator<<(OStream& sout, Value const& root) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user