mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-05-18 19:37:35 +02:00
Rewrite and revert some code to build in pre-C++11
Rewerite and revert some code that this library can be built in pre-C++11 and C++11 env. Main Change List: 1. using -> typedef 2. not using auto & decltype 3. not using raw string literals 4. ..., other c++11 features will be chosen to compile, depending on env.
This commit is contained in:
parent
a4fb5db543
commit
d2c205206d
@ -1,4 +1,5 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
/** \brief Parse from stream, collect comments and capture error info.
|
/** \brief Parse from stream, collect comments and capture error info.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
/**
|
/**
|
||||||
* \brief Parse a raw string into Value object using the CharReaderBuilder
|
* \brief Parse a raw string into Value object using the CharReaderBuilder
|
||||||
@ -10,9 +11,9 @@
|
|||||||
* 20
|
* 20
|
||||||
*/
|
*/
|
||||||
int main() {
|
int main() {
|
||||||
const std::string rawJson = R"({"Age": 20, "Name": "colin"})";
|
const std::string rawJson = "{\"Age\": 20, \"Name\": \"colin\"}";
|
||||||
const auto rawJsonLength = static_cast<int>(rawJson.length());
|
const int rawJsonLength = static_cast<int>(rawJson.length());
|
||||||
constexpr bool shouldUseOldWay = false;
|
JSONCPP_CONST bool shouldUseOldWay = false;
|
||||||
JSONCPP_STRING err;
|
JSONCPP_STRING err;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
|
|
||||||
@ -21,12 +22,13 @@ int main() {
|
|||||||
reader.parse(rawJson, root);
|
reader.parse(rawJson, root);
|
||||||
} else {
|
} else {
|
||||||
Json::CharReaderBuilder builder;
|
Json::CharReaderBuilder builder;
|
||||||
const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
Json::CharReader* reader(builder.newCharReader());
|
||||||
if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root,
|
if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root,
|
||||||
&err)) {
|
&err)) {
|
||||||
std::cout << "error" << std::endl;
|
std::cout << "error" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
const std::string name = root["Name"].asString();
|
const std::string name = root["Name"].asString();
|
||||||
const int age = root["Age"].asInt();
|
const int age = root["Age"].asInt();
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
int main() {
|
int main() {
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
Json::StreamWriterBuilder builder;
|
Json::StreamWriterBuilder builder;
|
||||||
const std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
Json::StreamWriter* writer(builder.newStreamWriter());
|
||||||
|
|
||||||
root["Name"] = "robin";
|
root["Name"] = "robin";
|
||||||
root["Age"] = 20;
|
root["Age"] = 20;
|
||||||
writer->write(root, &std::cout);
|
writer->write(root, &std::cout);
|
||||||
|
delete writer;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
/** \brief Write a Value object to a string.
|
/** \brief Write a Value object to a string.
|
||||||
* Example Usage:
|
* Example Usage:
|
||||||
@ -15,7 +16,7 @@
|
|||||||
int main() {
|
int main() {
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
Json::Value data;
|
Json::Value data;
|
||||||
constexpr bool shouldUseOldWay = false;
|
JSONCPP_CONST bool shouldUseOldWay = false;
|
||||||
root["action"] = "run";
|
root["action"] = "run";
|
||||||
data["number"] = 1;
|
data["number"] = 1;
|
||||||
root["data"] = data;
|
root["data"] = data;
|
||||||
|
@ -58,4 +58,10 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
|
#define JSONCPP_STATIC_ASSERT static_assert
|
||||||
|
#else
|
||||||
|
#define JSONCPP_STATIC_ASSERT JSON_ASSERT_MESSAGE
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // JSON_ASSERTIONS_H_INCLUDED
|
#endif // JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
@ -5,14 +5,20 @@
|
|||||||
|
|
||||||
#ifndef JSON_CONFIG_H_INCLUDED
|
#ifndef JSON_CONFIG_H_INCLUDED
|
||||||
#define JSON_CONFIG_H_INCLUDED
|
#define JSON_CONFIG_H_INCLUDED
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
|
#include <cstddef> // typedef ptrdiff_t
|
||||||
|
#include <cstdint> // typedef int64_t, uint64_t
|
||||||
|
#else
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||||
// assertion macros. The default is to use exceptions.
|
// assertion macros. The default is to use exceptions.
|
||||||
@ -50,11 +56,6 @@
|
|||||||
#define JSON_API
|
#define JSON_API
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
|
||||||
#error \
|
|
||||||
"ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
// As recommended at
|
// As recommended at
|
||||||
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
|
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
|
||||||
@ -70,10 +71,41 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
|||||||
// Storages, and 64 bits integer support is disabled.
|
// Storages, and 64 bits integer support is disabled.
|
||||||
// #define JSON_NO_INT64 1
|
// #define JSON_NO_INT64 1
|
||||||
|
|
||||||
// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
|
#if __cplusplus >= 201103L || defined(_MSC_VER)
|
||||||
// C++11 should be used directly in JSONCPP.
|
#define JSONCPP_OP_EXPLICIT explicit
|
||||||
#define JSONCPP_OVERRIDE override
|
#else
|
||||||
|
#define JSONCPP_OP_EXPLICIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// These Macros are maintained for backwards compatibility of external tools.
|
||||||
|
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
|
||||||
|
(defined(__GNUC__) && __cplusplus >= 201103L) || \
|
||||||
|
(defined(__clang__) && __clang_major__ == 3 && __clang_minor__ >= 3)
|
||||||
|
|
||||||
|
#define JSONCPP_CXX_STD_11 1
|
||||||
|
#else
|
||||||
|
#define JSONCPP_CXX_STD_11 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
|
#define JSONCPP_NULL nullptr
|
||||||
|
#define JSONCPP_CONST constexpr
|
||||||
|
#define JSONCPP_CTOR_DELETE = delete
|
||||||
|
#define JSONCPP_NOEXCEPT noexcept
|
||||||
|
#define JSONCPP_OVERRIDE override
|
||||||
|
#define JSONCPP_MOVE(value) std::move(value)
|
||||||
|
#else
|
||||||
|
#define JSONCPP_NULL NULL
|
||||||
|
#define JSONCPP_CONST const
|
||||||
|
#define JSONCPP_CTOR_DELETE
|
||||||
|
#define JSONCPP_NOEXCEPT throw()
|
||||||
|
#define JSONCPP_OVERRIDE
|
||||||
|
#define JSONCPP_MOVE(value) value
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Define *deprecated* attribute
|
||||||
|
// [[deprecated]] is in C++14 or in Visual Studio 2015 and later
|
||||||
|
// For compatibility, [[deprecated]] is not used
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#if __has_extension(attribute_deprecated_with_message)
|
#if __has_extension(attribute_deprecated_with_message)
|
||||||
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
@ -98,33 +130,36 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
|
#endif
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
using Int = int;
|
|
||||||
using UInt = unsigned int;
|
typedef int Int;
|
||||||
|
typedef unsigned int UInt;
|
||||||
#if defined(JSON_NO_INT64)
|
#if defined(JSON_NO_INT64)
|
||||||
using LargestInt = int;
|
typedef int LargestInt;
|
||||||
using LargestUInt = unsigned int;
|
typedef unsigned int LargestUInt;
|
||||||
#undef JSON_HAS_INT64
|
#undef JSON_HAS_INT64
|
||||||
#else // if defined(JSON_NO_INT64)
|
#else // if defined(JSON_NO_INT64)
|
||||||
// For Microsoft Visual use specific types as long long is not supported
|
// For Microsoft Visual use specific types as long long is not supported
|
||||||
#if defined(_MSC_VER) // Microsoft Visual Studio
|
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||||
using Int64 = __int64;
|
typedef __int64 Int64;
|
||||||
using UInt64 = unsigned __int64;
|
typedef unsigned __int64 UInt64;
|
||||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||||
using Int64 = int64_t;
|
typedef int64_t Int64;
|
||||||
using UInt64 = uint64_t;
|
typedef uint64_t UInt64;
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
using LargestInt = Int64;
|
typedef Int64 LargestInt;
|
||||||
using LargestUInt = UInt64;
|
typedef UInt64 LargestUInt;
|
||||||
#define JSON_HAS_INT64
|
#define JSON_HAS_INT64
|
||||||
#endif // if defined(JSON_NO_INT64)
|
#endif // if defined(JSON_NO_INT64)
|
||||||
|
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Allocator =
|
using Allocator =
|
||||||
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
||||||
@ -138,13 +173,20 @@ using OStringStream =
|
|||||||
String::allocator_type>;
|
String::allocator_type>;
|
||||||
using IStream = std::istream;
|
using IStream = std::istream;
|
||||||
using OStream = std::ostream;
|
using OStream = std::ostream;
|
||||||
|
#else
|
||||||
|
typedef std::string String;
|
||||||
|
typedef std::istringstream IStringStream;
|
||||||
|
typedef std::ostringstream OStringStream;
|
||||||
|
typedef std::istream IStream;
|
||||||
|
typedef std::ostream OStream;
|
||||||
|
#endif // JSONCPP_CXX_STD_11
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
// Legacy names (formerly macros).
|
// Legacy names (formerly macros).
|
||||||
using JSONCPP_STRING = Json::String;
|
typedef Json::String JSONCPP_STRING;
|
||||||
using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
|
typedef Json::IStringStream JSONCPP_ISTRINGSTREAM;
|
||||||
using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
|
typedef Json::OStringStream JSONCPP_OSTRINGSTREAM;
|
||||||
using JSONCPP_ISTREAM = Json::IStream;
|
typedef Json::IStream JSONCPP_ISTREAM;
|
||||||
using JSONCPP_OSTREAM = Json::OStream;
|
typedef Json::OStream JSONCPP_OSTREAM;
|
||||||
|
|
||||||
#endif // JSON_CONFIG_H_INCLUDED
|
#endif // JSON_CONFIG_H_INCLUDED
|
||||||
|
@ -29,7 +29,7 @@ class CharReaderBuilder;
|
|||||||
class Features;
|
class Features;
|
||||||
|
|
||||||
// value.h
|
// value.h
|
||||||
using ArrayIndex = unsigned int;
|
typedef unsigned int ArrayIndex;
|
||||||
class StaticString;
|
class StaticString;
|
||||||
class Path;
|
class Path;
|
||||||
class PathArgument;
|
class PathArgument;
|
||||||
|
@ -41,17 +41,17 @@ public:
|
|||||||
Features();
|
Features();
|
||||||
|
|
||||||
/// \c true if comments are allowed. Default: \c true.
|
/// \c true if comments are allowed. Default: \c true.
|
||||||
bool allowComments_{true};
|
bool allowComments_;
|
||||||
|
|
||||||
/// \c true if root must be either an array or an object value. Default: \c
|
/// \c true if root must be either an array or an object value. Default: \c
|
||||||
/// false.
|
/// false.
|
||||||
bool strictRoot_{false};
|
bool strictRoot_;
|
||||||
|
|
||||||
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
||||||
bool allowDroppedNullPlaceholders_{false};
|
bool allowDroppedNullPlaceholders_;
|
||||||
|
|
||||||
/// \c true if numeric object key are allowed. Default: \c false.
|
/// \c true if numeric object key are allowed. Default: \c false.
|
||||||
bool allowNumericKeys_{false};
|
bool allowNumericKeys_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
@ -36,8 +36,8 @@ namespace Json {
|
|||||||
class JSONCPP_DEPRECATED(
|
class JSONCPP_DEPRECATED(
|
||||||
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
|
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
|
||||||
public:
|
public:
|
||||||
using Char = char;
|
typedef char Char;
|
||||||
using Location = const Char*;
|
typedef const Char* Location;
|
||||||
|
|
||||||
/** \brief An error tagged with where in the JSON text it was encountered.
|
/** \brief An error tagged with where in the JSON text it was encountered.
|
||||||
*
|
*
|
||||||
@ -187,7 +187,7 @@ private:
|
|||||||
Location extra_;
|
Location extra_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Errors = std::deque<ErrorInfo>;
|
typedef std::deque<ErrorInfo> Errors;
|
||||||
|
|
||||||
bool readToken(Token& token);
|
bool readToken(Token& token);
|
||||||
void skipSpaces();
|
void skipSpaces();
|
||||||
@ -210,7 +210,8 @@ private:
|
|||||||
unsigned int& unicode);
|
unsigned int& unicode);
|
||||||
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
||||||
Location end, unsigned int& unicode);
|
Location end, unsigned int& unicode);
|
||||||
bool addError(const String& message, Token& token, Location extra = nullptr);
|
bool addError(const String& message, Token& token,
|
||||||
|
Location extra = JSONCPP_NULL);
|
||||||
bool recoverFromError(TokenType skipUntilToken);
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
bool addErrorAndRecover(const String& message, Token& token,
|
bool addErrorAndRecover(const String& message, Token& token,
|
||||||
TokenType skipUntilToken);
|
TokenType skipUntilToken);
|
||||||
@ -226,25 +227,25 @@ private:
|
|||||||
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);
|
||||||
|
|
||||||
using Nodes = std::stack<Value*>;
|
typedef std::stack<Value*> Nodes;
|
||||||
Nodes nodes_;
|
Nodes nodes_;
|
||||||
Errors errors_;
|
Errors errors_;
|
||||||
String document_;
|
String document_;
|
||||||
Location begin_{};
|
Location begin_;
|
||||||
Location end_{};
|
Location end_;
|
||||||
Location current_{};
|
Location current_;
|
||||||
Location lastValueEnd_{};
|
Location lastValueEnd_;
|
||||||
Value* lastValue_{};
|
Value* lastValue_;
|
||||||
String commentsBefore_;
|
String commentsBefore_;
|
||||||
Features features_;
|
Features features_;
|
||||||
bool collectComments_{};
|
bool collectComments_;
|
||||||
}; // Reader
|
}; // Reader
|
||||||
|
|
||||||
/** Interface for reading JSON from a char array.
|
/** Interface for reading JSON from a char array.
|
||||||
*/
|
*/
|
||||||
class JSON_API CharReader {
|
class JSON_API CharReader {
|
||||||
public:
|
public:
|
||||||
virtual ~CharReader() = default;
|
virtual ~CharReader() {}
|
||||||
/** \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
|
||||||
* document to read.
|
* document to read.
|
||||||
@ -266,7 +267,7 @@ public:
|
|||||||
|
|
||||||
class JSON_API Factory {
|
class JSON_API Factory {
|
||||||
public:
|
public:
|
||||||
virtual ~Factory() = default;
|
virtual ~Factory() {}
|
||||||
/** \brief Allocate a CharReader via operator new().
|
/** \brief Allocate a CharReader via operator new().
|
||||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
*/
|
*/
|
||||||
@ -332,9 +333,9 @@ public:
|
|||||||
Json::Value settings_;
|
Json::Value settings_;
|
||||||
|
|
||||||
CharReaderBuilder();
|
CharReaderBuilder();
|
||||||
~CharReaderBuilder() override;
|
~CharReaderBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
CharReader* newCharReader() const override;
|
CharReader* newCharReader() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/** \return true if 'settings' are legal and consistent;
|
/** \return true if 'settings' are legal and consistent;
|
||||||
* otherwise, indicate bad settings via 'invalid'.
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
|
@ -13,13 +13,16 @@
|
|||||||
// Conditional NORETURN attribute on the throw functions would:
|
// Conditional NORETURN attribute on the throw functions would:
|
||||||
// a) suppress false positives from static code analysis
|
// a) suppress false positives from static code analysis
|
||||||
// b) possibly improve optimization opportunities.
|
// b) possibly improve optimization opportunities.
|
||||||
|
// For compatibility, [[noreturn]] is not used
|
||||||
#if !defined(JSONCPP_NORETURN)
|
#if !defined(JSONCPP_NORETURN)
|
||||||
#if defined(_MSC_VER) && _MSC_VER == 1800
|
#if defined(_MSC_VER)
|
||||||
#define JSONCPP_NORETURN __declspec(noreturn)
|
#define JSONCPP_NORETURN __declspec(noreturn)
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define JSONCPP_NORETURN __attribute__((noreturn))
|
||||||
#else
|
#else
|
||||||
#define JSONCPP_NORETURN [[noreturn]]
|
#define JSONCPP_NORETURN
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif // if !defined(JSONCPP_NORETURN)
|
||||||
|
|
||||||
// Support for '= delete' with template declarations was a late addition
|
// Support for '= delete' with template declarations was a late addition
|
||||||
// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
|
// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
|
||||||
@ -39,10 +42,15 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <array>
|
#if JSONCPP_CXX_STD_11
|
||||||
|
#else
|
||||||
|
#undef JSONCPP_TEMPLATE_DELETE
|
||||||
|
#define JSONCPP_TEMPLATE_DELETE
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -67,8 +75,8 @@ namespace Json {
|
|||||||
class JSON_API Exception : public std::exception {
|
class JSON_API Exception : public std::exception {
|
||||||
public:
|
public:
|
||||||
Exception(String msg);
|
Exception(String msg);
|
||||||
~Exception() noexcept override;
|
~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||||
char const* what() const noexcept override;
|
char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
String msg_;
|
String msg_;
|
||||||
@ -146,7 +154,7 @@ enum PrecisionType {
|
|||||||
*/
|
*/
|
||||||
class JSON_API StaticString {
|
class JSON_API StaticString {
|
||||||
public:
|
public:
|
||||||
explicit StaticString(const char* czstring) : c_str_(czstring) {}
|
JSONCPP_OP_EXPLICIT StaticString(const char* czstring) : c_str_(czstring) {}
|
||||||
|
|
||||||
operator const char*() const { return c_str_; }
|
operator const char*() const { return c_str_; }
|
||||||
|
|
||||||
@ -194,21 +202,21 @@ class JSON_API Value {
|
|||||||
friend class ValueIteratorBase;
|
friend class ValueIteratorBase;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Members = std::vector<String>;
|
typedef std::vector<String> Members;
|
||||||
using iterator = ValueIterator;
|
typedef ValueIterator iterator;
|
||||||
using const_iterator = ValueConstIterator;
|
typedef ValueConstIterator const_iterator;
|
||||||
using UInt = Json::UInt;
|
typedef Json::UInt UInt;
|
||||||
using Int = Json::Int;
|
typedef Json::Int Int;
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
using UInt64 = Json::UInt64;
|
typedef Json::UInt64 UInt64;
|
||||||
using Int64 = Json::Int64;
|
typedef Json::Int64 Int64;
|
||||||
#endif // defined(JSON_HAS_INT64)
|
#endif // defined(JSON_HAS_INT64)
|
||||||
using LargestInt = Json::LargestInt;
|
typedef Json::LargestInt LargestInt;
|
||||||
using LargestUInt = Json::LargestUInt;
|
typedef Json::LargestUInt LargestUInt;
|
||||||
using ArrayIndex = Json::ArrayIndex;
|
typedef Json::ArrayIndex ArrayIndex;
|
||||||
|
|
||||||
// Required for boost integration, e. g. BOOST_TEST
|
// Required for boost integration, e. g. BOOST_TEST
|
||||||
using value_type = std::string;
|
typedef std::string value_type;
|
||||||
|
|
||||||
#if JSON_USE_NULLREF
|
#if JSON_USE_NULLREF
|
||||||
// Binary compatibility kludges, do not use.
|
// Binary compatibility kludges, do not use.
|
||||||
@ -220,34 +228,35 @@ public:
|
|||||||
static Value const& nullSingleton();
|
static Value const& nullSingleton();
|
||||||
|
|
||||||
/// Minimum signed integer value that can be stored in a Json::Value.
|
/// Minimum signed integer value that can be stored in a Json::Value.
|
||||||
static constexpr LargestInt minLargestInt =
|
static JSONCPP_CONST LargestInt minLargestInt =
|
||||||
LargestInt(~(LargestUInt(-1) / 2));
|
LargestInt(~(LargestUInt(-1) / 2));
|
||||||
/// Maximum signed integer value that can be stored in a Json::Value.
|
/// Maximum signed integer value that can be stored in a Json::Value.
|
||||||
static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2);
|
static JSONCPP_CONST LargestInt maxLargestInt =
|
||||||
|
LargestInt(LargestUInt(-1) / 2);
|
||||||
/// Maximum unsigned integer value that can be stored in a Json::Value.
|
/// Maximum unsigned integer value that can be stored in a Json::Value.
|
||||||
static constexpr LargestUInt maxLargestUInt = LargestUInt(-1);
|
static JSONCPP_CONST LargestUInt maxLargestUInt = LargestUInt(-1);
|
||||||
|
|
||||||
/// Minimum signed int value that can be stored in a Json::Value.
|
/// Minimum signed int value that can be stored in a Json::Value.
|
||||||
static constexpr Int minInt = Int(~(UInt(-1) / 2));
|
static JSONCPP_CONST Int minInt = Int(~(UInt(-1) / 2));
|
||||||
/// Maximum signed int value that can be stored in a Json::Value.
|
/// Maximum signed int value that can be stored in a Json::Value.
|
||||||
static constexpr Int maxInt = Int(UInt(-1) / 2);
|
static JSONCPP_CONST Int maxInt = Int(UInt(-1) / 2);
|
||||||
/// Maximum unsigned int value that can be stored in a Json::Value.
|
/// Maximum unsigned int value that can be stored in a Json::Value.
|
||||||
static constexpr UInt maxUInt = UInt(-1);
|
static JSONCPP_CONST UInt maxUInt = UInt(-1);
|
||||||
|
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
|
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
|
||||||
static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2));
|
static JSONCPP_CONST Int64 minInt64 = Int64(~(UInt64(-1) / 2));
|
||||||
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
|
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
|
||||||
static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2);
|
static JSONCPP_CONST Int64 maxInt64 = Int64(UInt64(-1) / 2);
|
||||||
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
|
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
|
||||||
static constexpr UInt64 maxUInt64 = UInt64(-1);
|
static JSONCPP_CONST UInt64 maxUInt64 = UInt64(-1);
|
||||||
#endif // defined(JSON_HAS_INT64)
|
#endif // defined(JSON_HAS_INT64)
|
||||||
/// Default precision for real value for string representation.
|
/// Default precision for real value for string representation.
|
||||||
static constexpr UInt defaultRealPrecision = 17;
|
static JSONCPP_CONST UInt defaultRealPrecision = 17;
|
||||||
// The constant is hard-coded because some compiler have trouble
|
// The constant is hard-coded because some compiler have trouble
|
||||||
// converting Value::maxUInt64 to a double correctly (AIX/xlC).
|
// converting Value::maxUInt64 to a double correctly (AIX/xlC).
|
||||||
// Assumes that UInt64 is a 64 bits integer.
|
// Assumes that UInt64 is a 64 bits integer.
|
||||||
static constexpr double maxUInt64AsDouble = 18446744073709551615.0;
|
static JSONCPP_CONST double maxUInt64AsDouble = 18446744073709551615.0;
|
||||||
// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
|
// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
|
||||||
// when using gcc and clang backend compilers. CZString
|
// when using gcc and clang backend compilers. CZString
|
||||||
// cannot be defined as private. See issue #486
|
// cannot be defined as private. See issue #486
|
||||||
@ -263,11 +272,14 @@ private:
|
|||||||
CZString(ArrayIndex index);
|
CZString(ArrayIndex index);
|
||||||
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
||||||
CZString(CZString const& other);
|
CZString(CZString const& other);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
CZString(CZString&& other);
|
CZString(CZString&& other);
|
||||||
|
#endif
|
||||||
~CZString();
|
~CZString();
|
||||||
CZString& operator=(const CZString& other);
|
CZString& operator=(const CZString& other);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
CZString& operator=(CZString&& other);
|
CZString& operator=(CZString&& other);
|
||||||
|
#endif
|
||||||
bool operator<(CZString const& other) const;
|
bool operator<(CZString const& other) const;
|
||||||
bool operator==(CZString const& other) const;
|
bool operator==(CZString const& other) const;
|
||||||
ArrayIndex index() const;
|
ArrayIndex index() const;
|
||||||
@ -343,13 +355,17 @@ public:
|
|||||||
Value(const String& value);
|
Value(const String& value);
|
||||||
Value(bool value);
|
Value(bool value);
|
||||||
Value(const Value& other);
|
Value(const Value& other);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value(Value&& other);
|
Value(Value&& other);
|
||||||
|
#endif
|
||||||
~Value();
|
~Value();
|
||||||
|
|
||||||
/// \note Overwrite existing comments. To preserve comments, use
|
/// \note Overwrite existing comments. To preserve comments, use
|
||||||
/// #swapPayload().
|
/// #swapPayload().
|
||||||
Value& operator=(const Value& other);
|
Value& operator=(const Value& other);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value& operator=(Value&& other);
|
Value& operator=(Value&& other);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Swap everything.
|
/// Swap everything.
|
||||||
void swap(Value& other);
|
void swap(Value& other);
|
||||||
@ -421,7 +437,7 @@ public:
|
|||||||
bool empty() const;
|
bool empty() const;
|
||||||
|
|
||||||
/// Return !isNull()
|
/// Return !isNull()
|
||||||
explicit operator bool() const;
|
JSONCPP_OP_EXPLICIT operator bool() const;
|
||||||
|
|
||||||
/// Remove all object members and array elements.
|
/// Remove all object members and array elements.
|
||||||
/// \pre type() is arrayValue, objectValue, or nullValue
|
/// \pre type() is arrayValue, objectValue, or nullValue
|
||||||
@ -462,11 +478,15 @@ public:
|
|||||||
///
|
///
|
||||||
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
||||||
Value& append(const Value& value);
|
Value& append(const Value& value);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value& append(Value&& value);
|
Value& append(Value&& value);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Insert value in array at specific index
|
/// \brief Insert value in array at specific index
|
||||||
bool insert(ArrayIndex index, const Value& newValue);
|
bool insert(ArrayIndex index, const Value& newValue);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
bool insert(ArrayIndex index, Value&& newValue);
|
bool insert(ArrayIndex index, Value&& newValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Access an object value by name, create a null member if it does not exist.
|
/// 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.
|
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
||||||
@ -562,15 +582,11 @@ public:
|
|||||||
|
|
||||||
/// \deprecated Always pass len.
|
/// \deprecated Always pass len.
|
||||||
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
|
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
|
||||||
void setComment(const char* comment, CommentPlacement placement) {
|
void setComment(const char* comment, CommentPlacement placement);
|
||||||
setComment(String(comment, strlen(comment)), placement);
|
|
||||||
}
|
|
||||||
/// Comments must be //... or /* ... */
|
/// Comments must be //... or /* ... */
|
||||||
void setComment(const char* comment, size_t len, CommentPlacement placement) {
|
void setComment(const char* comment, size_t len, CommentPlacement placement);
|
||||||
setComment(String(comment, len), placement);
|
|
||||||
}
|
|
||||||
/// Comments must be //... or /* ... */
|
/// Comments must be //... or /* ... */
|
||||||
void setComment(String comment, CommentPlacement placement);
|
void setComment(const String& comment, CommentPlacement placement);
|
||||||
bool hasComment(CommentPlacement placement) const;
|
bool hasComment(CommentPlacement placement) const;
|
||||||
/// Include delimiters and embedded newlines.
|
/// Include delimiters and embedded newlines.
|
||||||
String getComment(CommentPlacement placement) const;
|
String getComment(CommentPlacement placement) const;
|
||||||
@ -632,18 +648,15 @@ private:
|
|||||||
|
|
||||||
class Comments {
|
class Comments {
|
||||||
public:
|
public:
|
||||||
Comments() = default;
|
Comments() {}
|
||||||
Comments(const Comments& that);
|
Comments(const Comments& that);
|
||||||
Comments(Comments&& that);
|
|
||||||
Comments& operator=(const Comments& that);
|
Comments& operator=(const Comments& that);
|
||||||
Comments& operator=(Comments&& that);
|
|
||||||
bool has(CommentPlacement slot) const;
|
bool has(CommentPlacement slot) const;
|
||||||
String get(CommentPlacement slot) const;
|
String get(CommentPlacement slot) const;
|
||||||
void set(CommentPlacement slot, String comment);
|
void set(CommentPlacement slot, String s);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Array = std::array<String, numberOfCommentPlacement>;
|
String ptr_[numberOfCommentPlacement];
|
||||||
std::unique_ptr<Array> ptr_;
|
|
||||||
};
|
};
|
||||||
Comments comments_;
|
Comments comments_;
|
||||||
|
|
||||||
@ -698,8 +711,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
enum Kind { kindNone = 0, kindIndex, kindKey };
|
enum Kind { kindNone = 0, kindIndex, kindKey };
|
||||||
String key_;
|
String key_;
|
||||||
ArrayIndex index_{};
|
ArrayIndex index_;
|
||||||
Kind kind_{kindNone};
|
Kind kind_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Experimental and untested: represents a "path" to access a node.
|
/** \brief Experimental and untested: represents a "path" to access a node.
|
||||||
@ -728,8 +741,8 @@ public:
|
|||||||
Value& make(Value& root) const;
|
Value& make(Value& root) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using InArgs = std::vector<const PathArgument*>;
|
typedef std::vector<const PathArgument*> InArgs;
|
||||||
using Args = std::vector<PathArgument>;
|
typedef std::vector<PathArgument> Args;
|
||||||
|
|
||||||
void makePath(const String& path, const InArgs& in);
|
void makePath(const String& path, const InArgs& in);
|
||||||
void addPathInArg(const String& path, const InArgs& in,
|
void addPathInArg(const String& path, const InArgs& in,
|
||||||
@ -744,10 +757,10 @@ private:
|
|||||||
*/
|
*/
|
||||||
class JSON_API ValueIteratorBase {
|
class JSON_API ValueIteratorBase {
|
||||||
public:
|
public:
|
||||||
using iterator_category = std::bidirectional_iterator_tag;
|
typedef std::bidirectional_iterator_tag iterator_category;
|
||||||
using size_t = unsigned int;
|
typedef unsigned int size_t;
|
||||||
using difference_type = int;
|
typedef int difference_type;
|
||||||
using SelfType = ValueIteratorBase;
|
typedef ValueIteratorBase SelfType;
|
||||||
|
|
||||||
bool operator==(const SelfType& other) const { return isEqual(other); }
|
bool operator==(const SelfType& other) const { return isEqual(other); }
|
||||||
|
|
||||||
@ -804,13 +817,14 @@ protected:
|
|||||||
private:
|
private:
|
||||||
Value::ObjectValues::iterator current_;
|
Value::ObjectValues::iterator current_;
|
||||||
// Indicates that iterator is for a null value.
|
// Indicates that iterator is for a null value.
|
||||||
bool isNull_{true};
|
bool isNull_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// For some reason, BORLAND needs these at the end, rather
|
// For some reason, BORLAND needs these at the end, rather
|
||||||
// than earlier. No idea why.
|
// than earlier. No idea why.
|
||||||
ValueIteratorBase();
|
ValueIteratorBase();
|
||||||
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
JSONCPP_OP_EXPLICIT
|
||||||
|
ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief const iterator for object and array value.
|
/** \brief const iterator for object and array value.
|
||||||
@ -820,12 +834,12 @@ class JSON_API ValueConstIterator : public ValueIteratorBase {
|
|||||||
friend class Value;
|
friend class Value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = const Value;
|
typedef const Value value_type;
|
||||||
// typedef unsigned int size_t;
|
// typedef unsigned int size_t;
|
||||||
// typedef int difference_type;
|
// typedef int difference_type;
|
||||||
using reference = const Value&;
|
typedef const Value& reference;
|
||||||
using pointer = const Value*;
|
typedef const Value* pointer;
|
||||||
using SelfType = ValueConstIterator;
|
typedef ValueConstIterator SelfType;
|
||||||
|
|
||||||
ValueConstIterator();
|
ValueConstIterator();
|
||||||
ValueConstIterator(ValueIterator const& other);
|
ValueConstIterator(ValueIterator const& other);
|
||||||
@ -833,7 +847,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
/*! \internal Use by Value to create an iterator.
|
/*! \internal Use by Value to create an iterator.
|
||||||
*/
|
*/
|
||||||
explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
|
JSONCPP_OP_EXPLICIT
|
||||||
|
ValueConstIterator(const Value::ObjectValues::iterator& current);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SelfType& operator=(const ValueIteratorBase& other);
|
SelfType& operator=(const ValueIteratorBase& other);
|
||||||
@ -871,21 +886,22 @@ class JSON_API ValueIterator : public ValueIteratorBase {
|
|||||||
friend class Value;
|
friend class Value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = Value;
|
typedef Value value_type;
|
||||||
using size_t = unsigned int;
|
typedef unsigned int size_t;
|
||||||
using difference_type = int;
|
typedef int difference_type;
|
||||||
using reference = Value&;
|
typedef Value& reference;
|
||||||
using pointer = Value*;
|
typedef Value* pointer;
|
||||||
using SelfType = ValueIterator;
|
typedef ValueIterator SelfType;
|
||||||
|
|
||||||
ValueIterator();
|
ValueIterator();
|
||||||
explicit ValueIterator(const ValueConstIterator& other);
|
JSONCPP_OP_EXPLICIT ValueIterator(const ValueConstIterator& other);
|
||||||
ValueIterator(const ValueIterator& other);
|
ValueIterator(const ValueIterator& other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*! \internal Use by Value to create an iterator.
|
/*! \internal Use by Value to create an iterator.
|
||||||
*/
|
*/
|
||||||
explicit ValueIterator(const Value::ObjectValues::iterator& current);
|
JSONCPP_OP_EXPLICIT
|
||||||
|
ValueIterator(const Value::ObjectValues::iterator& current);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SelfType& operator=(const SelfType& other);
|
SelfType& operator=(const SelfType& other);
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
// 3. /CMakeLists.txt
|
// 3. /CMakeLists.txt
|
||||||
// IMPORTANT: also update the SOVERSION!!
|
// IMPORTANT: also update the SOVERSION!!
|
||||||
|
|
||||||
#define JSONCPP_VERSION_STRING "1.9.3"
|
#define JSONCPP_VERSION_STRING "00.11.0"
|
||||||
#define JSONCPP_VERSION_MAJOR 1
|
#define JSONCPP_VERSION_MAJOR 00
|
||||||
#define JSONCPP_VERSION_MINOR 9
|
#define JSONCPP_VERSION_MINOR 11
|
||||||
#define JSONCPP_VERSION_PATCH 3
|
#define JSONCPP_VERSION_PATCH 0
|
||||||
#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) | \
|
||||||
|
@ -119,12 +119,12 @@ public:
|
|||||||
Json::Value settings_;
|
Json::Value settings_;
|
||||||
|
|
||||||
StreamWriterBuilder();
|
StreamWriterBuilder();
|
||||||
~StreamWriterBuilder() override;
|
~StreamWriterBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
*/
|
*/
|
||||||
StreamWriter* newStreamWriter() const override;
|
StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/** \return true if 'settings' are legal and consistent;
|
/** \return true if 'settings' are legal and consistent;
|
||||||
* otherwise, indicate bad settings via 'invalid'.
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
@ -169,7 +169,7 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter
|
|||||||
: public Writer {
|
: public Writer {
|
||||||
public:
|
public:
|
||||||
FastWriter();
|
FastWriter();
|
||||||
~FastWriter() override = default;
|
~FastWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
void enableYAMLCompatibility();
|
void enableYAMLCompatibility();
|
||||||
|
|
||||||
@ -183,15 +183,15 @@ public:
|
|||||||
void omitEndingLineFeed();
|
void omitEndingLineFeed();
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
String write(const Value& root) override;
|
String write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
|
|
||||||
String document_;
|
String document_;
|
||||||
bool yamlCompatibilityEnabled_{false};
|
bool yamlCompatibilityEnabled_;
|
||||||
bool dropNullPlaceholders_{false};
|
bool dropNullPlaceholders_;
|
||||||
bool omitEndingLineFeed_{false};
|
bool omitEndingLineFeed_;
|
||||||
};
|
};
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
@ -229,14 +229,14 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
|
|||||||
StyledWriter : public Writer {
|
StyledWriter : public Writer {
|
||||||
public:
|
public:
|
||||||
StyledWriter();
|
StyledWriter();
|
||||||
~StyledWriter() override = default;
|
~StyledWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
* \param root Value to serialize.
|
* \param root Value to serialize.
|
||||||
* \return String containing the JSON document that represents the root value.
|
* \return String containing the JSON document that represents the root value.
|
||||||
*/
|
*/
|
||||||
String write(const Value& root) override;
|
String write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
@ -252,14 +252,14 @@ private:
|
|||||||
static bool hasCommentForValue(const Value& value);
|
static bool hasCommentForValue(const Value& value);
|
||||||
static String normalizeEOL(const String& text);
|
static String normalizeEOL(const String& text);
|
||||||
|
|
||||||
using ChildValues = std::vector<String>;
|
typedef std::vector<String> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
String document_;
|
String document_;
|
||||||
String indentString_;
|
String indentString_;
|
||||||
unsigned int rightMargin_{74};
|
unsigned int rightMargin_;
|
||||||
unsigned int indentSize_{3};
|
unsigned int indentSize_;
|
||||||
bool addChildValues_{false};
|
bool addChildValues_;
|
||||||
};
|
};
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
@ -301,7 +301,7 @@ public:
|
|||||||
* \param indentation Each level will be indented by this amount extra.
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
*/
|
*/
|
||||||
StyledStreamWriter(String indentation = "\t");
|
StyledStreamWriter(String indentation = "\t");
|
||||||
~StyledStreamWriter() = default;
|
~StyledStreamWriter() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
@ -326,12 +326,12 @@ private:
|
|||||||
static bool hasCommentForValue(const Value& value);
|
static bool hasCommentForValue(const Value& value);
|
||||||
static String normalizeEOL(const String& text);
|
static String normalizeEOL(const String& text);
|
||||||
|
|
||||||
using ChildValues = std::vector<String>;
|
typedef std::vector<String> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
OStream* document_;
|
OStream* document_;
|
||||||
String indentString_;
|
String indentString_;
|
||||||
unsigned int rightMargin_{74};
|
unsigned int rightMargin_;
|
||||||
String indentation_;
|
String indentation_;
|
||||||
bool addChildValues_ : 1;
|
bool addChildValues_ : 1;
|
||||||
bool indented_ : 1;
|
bool indented_ : 1;
|
||||||
@ -348,7 +348,7 @@ String JSON_API valueToString(LargestInt value);
|
|||||||
String JSON_API valueToString(LargestUInt value);
|
String JSON_API valueToString(LargestUInt value);
|
||||||
String JSON_API valueToString(
|
String JSON_API valueToString(
|
||||||
double value, unsigned int precision = Value::defaultRealPrecision,
|
double value, unsigned int precision = Value::defaultRealPrecision,
|
||||||
PrecisionType precisionType = PrecisionType::significantDigits);
|
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);
|
||||||
|
|
||||||
|
@ -24,7 +24,9 @@ struct Options {
|
|||||||
Json::String path;
|
Json::String path;
|
||||||
Json::Features features;
|
Json::Features features;
|
||||||
bool parseOnly;
|
bool parseOnly;
|
||||||
using writeFuncType = Json::String (*)(Json::Value const&);
|
|
||||||
|
typedef Json::String (*writeFuncType)(Json::Value const&);
|
||||||
|
|
||||||
writeFuncType write;
|
writeFuncType write;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,11 +59,11 @@ static Json::String readInputTestFile(const char* path) {
|
|||||||
if (!file)
|
if (!file)
|
||||||
return "";
|
return "";
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
auto const size = ftell(file);
|
long const size = ftell(file);
|
||||||
auto const usize = static_cast<size_t>(size);
|
size_t const usize = static_cast<size_t>(size);
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
auto buffer = new char[size + 1];
|
char* buffer = new char[usize + 1];
|
||||||
buffer[size] = 0;
|
buffer[usize] = 0;
|
||||||
Json::String text;
|
Json::String text;
|
||||||
if (fread(buffer, 1, usize, file) == usize)
|
if (fread(buffer, 1, usize, file) == usize)
|
||||||
text = buffer;
|
text = buffer;
|
||||||
@ -111,7 +113,9 @@ static void printValueTree(FILE* fout, Json::Value& value,
|
|||||||
Json::Value::Members members(value.getMemberNames());
|
Json::Value::Members members(value.getMemberNames());
|
||||||
std::sort(members.begin(), members.end());
|
std::sort(members.begin(), members.end());
|
||||||
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
|
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
|
||||||
for (const auto& name : members) {
|
for (Json::Value::Members::const_iterator it = members.begin();
|
||||||
|
it != members.end(); it++) {
|
||||||
|
const Json::String& name = *it;
|
||||||
printValueTree(fout, value[name], path + suffix + name);
|
printValueTree(fout, value[name], path + suffix + name);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -138,7 +142,7 @@ static int parseAndSaveValueTree(const Json::String& input,
|
|||||||
features.allowDroppedNullPlaceholders_;
|
features.allowDroppedNullPlaceholders_;
|
||||||
builder.settings_["allowNumericKeys"] = features.allowNumericKeys_;
|
builder.settings_["allowNumericKeys"] = features.allowNumericKeys_;
|
||||||
|
|
||||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
Json::CharReader* reader(builder.newCharReader());
|
||||||
Json::String errors;
|
Json::String errors;
|
||||||
const bool parsingSuccessful =
|
const bool parsingSuccessful =
|
||||||
reader->parse(input.data(), input.data() + input.size(), root, &errors);
|
reader->parse(input.data(), input.data() + input.size(), root, &errors);
|
||||||
@ -148,7 +152,7 @@ static int parseAndSaveValueTree(const Json::String& input,
|
|||||||
<< errors << std::endl;
|
<< errors << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
// We may instead check the legacy implementation (to ensure it doesn't
|
// We may instead check the legacy implementation (to ensure it doesn't
|
||||||
// randomly get broken).
|
// randomly get broken).
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,18 +51,15 @@ static size_t const stackLimit_g =
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
typedef CharReader* CharReaderPtr;
|
||||||
using CharReaderPtr = std::unique_ptr<CharReader>;
|
|
||||||
#else
|
|
||||||
using CharReaderPtr = std::auto_ptr<CharReader>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Implementation of class Features
|
// Implementation of class Features
|
||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
|
|
||||||
Features::Features() = default;
|
Features::Features()
|
||||||
|
: allowComments_(true), strictRoot_(false),
|
||||||
Features Features::all() { return {}; }
|
allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
|
||||||
|
Features Features::all() { return Features(); }
|
||||||
|
|
||||||
Features Features::strictMode() {
|
Features Features::strictMode() {
|
||||||
Features features;
|
Features features;
|
||||||
@ -86,9 +83,15 @@ bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
|
|||||||
// Class Reader
|
// Class Reader
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Reader::Reader() : features_(Features::all()) {}
|
Reader::Reader()
|
||||||
|
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
|
||||||
|
lastValue_(), commentsBefore_(), features_(Features::all()),
|
||||||
|
collectComments_() {}
|
||||||
|
|
||||||
Reader::Reader(const Features& features) : features_(features) {}
|
Reader::Reader(const Features& features)
|
||||||
|
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
|
||||||
|
lastValue_(), commentsBefore_(), features_(features), collectComments_() {
|
||||||
|
}
|
||||||
|
|
||||||
bool Reader::parse(const std::string& document, Value& root,
|
bool Reader::parse(const std::string& document, Value& root,
|
||||||
bool collectComments) {
|
bool collectComments) {
|
||||||
@ -121,8 +124,8 @@ bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
|||||||
end_ = endDoc;
|
end_ = endDoc;
|
||||||
collectComments_ = collectComments;
|
collectComments_ = collectComments;
|
||||||
current_ = begin_;
|
current_ = begin_;
|
||||||
lastValueEnd_ = nullptr;
|
lastValueEnd_ = JSONCPP_NULL;
|
||||||
lastValue_ = nullptr;
|
lastValue_ = JSONCPP_NULL;
|
||||||
commentsBefore_.clear();
|
commentsBefore_.clear();
|
||||||
errors_.clear();
|
errors_.clear();
|
||||||
while (!nodes_.empty())
|
while (!nodes_.empty())
|
||||||
@ -376,7 +379,7 @@ void Reader::addComment(Location begin, Location end,
|
|||||||
assert(collectComments_);
|
assert(collectComments_);
|
||||||
const String& normalized = normalizeEOL(begin, end);
|
const String& normalized = normalizeEOL(begin, end);
|
||||||
if (placement == commentAfterOnSameLine) {
|
if (placement == commentAfterOnSameLine) {
|
||||||
assert(lastValue_ != nullptr);
|
assert(lastValue_ != JSONCPP_NULL);
|
||||||
lastValue_->setComment(normalized, placement);
|
lastValue_->setComment(normalized, placement);
|
||||||
} else {
|
} else {
|
||||||
commentsBefore_ += normalized;
|
commentsBefore_ += normalized;
|
||||||
@ -565,7 +568,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c < '0' || c > '9')
|
if (c < '0' || c > '9')
|
||||||
return decodeDouble(token, decoded);
|
return decodeDouble(token, decoded);
|
||||||
auto digit(static_cast<Value::UInt>(c - '0'));
|
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
|
||||||
if (value >= threshold) {
|
if (value >= threshold) {
|
||||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||||
// a) we've only just touched the limit, b) this is the last digit, and
|
// a) we've only just touched the limit, b) this is the last digit, and
|
||||||
@ -798,7 +801,9 @@ String Reader::getFormatedErrorMessages() const {
|
|||||||
|
|
||||||
String Reader::getFormattedErrorMessages() const {
|
String Reader::getFormattedErrorMessages() const {
|
||||||
String formattedMessage;
|
String formattedMessage;
|
||||||
for (const auto& error : errors_) {
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
|
itError != errors_.end(); ++itError) {
|
||||||
|
const ErrorInfo& error = *itError;
|
||||||
formattedMessage +=
|
formattedMessage +=
|
||||||
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
||||||
formattedMessage += " " + error.message_ + "\n";
|
formattedMessage += " " + error.message_ + "\n";
|
||||||
@ -811,7 +816,9 @@ String Reader::getFormattedErrorMessages() const {
|
|||||||
|
|
||||||
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
|
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
|
||||||
std::vector<Reader::StructuredError> allErrors;
|
std::vector<Reader::StructuredError> allErrors;
|
||||||
for (const auto& error : errors_) {
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
|
itError != errors_.end(); ++itError) {
|
||||||
|
const ErrorInfo& error = *itError;
|
||||||
Reader::StructuredError structured;
|
Reader::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_;
|
||||||
@ -832,7 +839,7 @@ bool Reader::pushError(const Value& value, const String& message) {
|
|||||||
ErrorInfo info;
|
ErrorInfo info;
|
||||||
info.token_ = token;
|
info.token_ = token;
|
||||||
info.message_ = message;
|
info.message_ = message;
|
||||||
info.extra_ = nullptr;
|
info.extra_ = JSONCPP_NULL;
|
||||||
errors_.push_back(info);
|
errors_.push_back(info);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -875,7 +882,7 @@ public:
|
|||||||
size_t stackLimit_;
|
size_t stackLimit_;
|
||||||
}; // OurFeatures
|
}; // OurFeatures
|
||||||
|
|
||||||
OurFeatures OurFeatures::all() { return {}; }
|
OurFeatures OurFeatures::all() { return OurFeatures(); }
|
||||||
|
|
||||||
// Implementation of class Reader
|
// Implementation of class Reader
|
||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
@ -884,15 +891,15 @@ OurFeatures OurFeatures::all() { return {}; }
|
|||||||
// for implementing JSON reading.
|
// for implementing JSON reading.
|
||||||
class OurReader {
|
class OurReader {
|
||||||
public:
|
public:
|
||||||
using Char = char;
|
typedef char Char;
|
||||||
using Location = const Char*;
|
typedef const Char* Location;
|
||||||
struct StructuredError {
|
struct StructuredError {
|
||||||
ptrdiff_t offset_start;
|
ptrdiff_t offset_start;
|
||||||
ptrdiff_t offset_limit;
|
ptrdiff_t offset_limit;
|
||||||
String message;
|
String message;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit OurReader(OurFeatures const& features);
|
JSONCPP_OP_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;
|
||||||
@ -936,7 +943,7 @@ private:
|
|||||||
Location extra_;
|
Location extra_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Errors = std::deque<ErrorInfo>;
|
typedef std::deque<ErrorInfo> Errors;
|
||||||
|
|
||||||
bool readToken(Token& token);
|
bool readToken(Token& token);
|
||||||
void skipSpaces();
|
void skipSpaces();
|
||||||
@ -961,7 +968,8 @@ private:
|
|||||||
unsigned int& unicode);
|
unsigned int& unicode);
|
||||||
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
||||||
Location end, unsigned int& unicode);
|
Location end, unsigned int& unicode);
|
||||||
bool addError(const String& message, Token& token, Location extra = nullptr);
|
bool addError(const String& message, Token& token,
|
||||||
|
Location extra = JSONCPP_NULL);
|
||||||
bool recoverFromError(TokenType skipUntilToken);
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
bool addErrorAndRecover(const String& message, Token& token,
|
bool addErrorAndRecover(const String& message, Token& token,
|
||||||
TokenType skipUntilToken);
|
TokenType skipUntilToken);
|
||||||
@ -977,21 +985,21 @@ private:
|
|||||||
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);
|
||||||
|
|
||||||
using Nodes = std::stack<Value*>;
|
typedef std::stack<Value*> Nodes;
|
||||||
|
|
||||||
Nodes nodes_{};
|
Nodes nodes_;
|
||||||
Errors errors_{};
|
Errors errors_;
|
||||||
String document_{};
|
String document_;
|
||||||
Location begin_ = nullptr;
|
Location begin_;
|
||||||
Location end_ = nullptr;
|
Location end_;
|
||||||
Location current_ = nullptr;
|
Location current_;
|
||||||
Location lastValueEnd_ = nullptr;
|
Location lastValueEnd_;
|
||||||
Value* lastValue_ = nullptr;
|
Value* lastValue_;
|
||||||
bool lastValueHasAComment_ = false;
|
bool lastValueHasAComment_;
|
||||||
String commentsBefore_{};
|
String commentsBefore_;
|
||||||
|
|
||||||
OurFeatures const features_;
|
OurFeatures const features_;
|
||||||
bool collectComments_ = false;
|
bool collectComments_;
|
||||||
}; // OurReader
|
}; // OurReader
|
||||||
|
|
||||||
// complete copy of Read impl, for OurReader
|
// complete copy of Read impl, for OurReader
|
||||||
@ -1004,7 +1012,11 @@ bool OurReader::containsNewLine(OurReader::Location begin,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
OurReader::OurReader(OurFeatures const& features) : features_(features) {}
|
OurReader::OurReader(OurFeatures const& features)
|
||||||
|
: errors_(), document_(), begin_(JSONCPP_NULL), end_(JSONCPP_NULL),
|
||||||
|
current_(JSONCPP_NULL), lastValueEnd_(JSONCPP_NULL),
|
||||||
|
lastValue_(JSONCPP_NULL), lastValueHasAComment_(false), commentsBefore_(),
|
||||||
|
features_(features), collectComments_(false) {}
|
||||||
|
|
||||||
bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||||
bool collectComments) {
|
bool collectComments) {
|
||||||
@ -1016,8 +1028,8 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
|||||||
end_ = endDoc;
|
end_ = endDoc;
|
||||||
collectComments_ = collectComments;
|
collectComments_ = collectComments;
|
||||||
current_ = begin_;
|
current_ = begin_;
|
||||||
lastValueEnd_ = nullptr;
|
lastValueEnd_ = JSONCPP_NULL;
|
||||||
lastValue_ = nullptr;
|
lastValue_ = JSONCPP_NULL;
|
||||||
commentsBefore_.clear();
|
commentsBefore_.clear();
|
||||||
errors_.clear();
|
errors_.clear();
|
||||||
while (!nodes_.empty())
|
while (!nodes_.empty())
|
||||||
@ -1352,7 +1364,7 @@ void OurReader::addComment(Location begin, Location end,
|
|||||||
assert(collectComments_);
|
assert(collectComments_);
|
||||||
const String& normalized = normalizeEOL(begin, end);
|
const String& normalized = normalizeEOL(begin, end);
|
||||||
if (placement == commentAfterOnSameLine) {
|
if (placement == commentAfterOnSameLine) {
|
||||||
assert(lastValue_ != nullptr);
|
assert(lastValue_ != JSONCPP_NULL);
|
||||||
lastValue_->setComment(normalized, placement);
|
lastValue_->setComment(normalized, placement);
|
||||||
} else {
|
} else {
|
||||||
commentsBefore_ += normalized;
|
commentsBefore_ += normalized;
|
||||||
@ -1568,32 +1580,36 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
// We assume we can represent the largest and smallest integer types as
|
// We assume we can represent the largest and smallest integer types as
|
||||||
// unsigned integers with separate sign. This is only true if they can fit
|
// unsigned integers with separate sign. This is only true if they can fit
|
||||||
// into an unsigned integer.
|
// into an unsigned integer.
|
||||||
static_assert(Value::maxLargestInt <= Value::maxLargestUInt,
|
JSONCPP_STATIC_ASSERT(LargestUInt(Value::maxLargestInt) <=
|
||||||
"Int must be smaller than UInt");
|
Value::maxLargestUInt,
|
||||||
|
"Int must be smaller than Uint");
|
||||||
// We need to convert minLargestInt into a positive number. The easiest way
|
// We need to convert minLargestInt into a positive number. The easiest way
|
||||||
// to do this conversion is to assume our "threshold" value of minLargestInt
|
// to do this conversion is to assume our "threshold" value of minLargestInt
|
||||||
// divided by 10 can fit in maxLargestInt when absolute valued. This should
|
// divided by 10 can fit in maxLargestInt when absolute valued. This should
|
||||||
// be a safe assumption.
|
// be a safe assumption.
|
||||||
static_assert(Value::minLargestInt <= -Value::maxLargestInt,
|
JSONCPP_STATIC_ASSERT(
|
||||||
"The absolute value of minLargestInt must be greater than or "
|
Value::minLargestInt <= -Value::maxLargestInt,
|
||||||
"equal to maxLargestInt");
|
"The absolute value of minLargestInt must ve greater than or"
|
||||||
static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt,
|
"equal to maxLargestInt");
|
||||||
"The absolute value of minLargestInt must be only 1 magnitude "
|
|
||||||
"larger than maxLargest Int");
|
|
||||||
|
|
||||||
static constexpr Value::LargestUInt positive_threshold =
|
JSONCPP_STATIC_ASSERT(
|
||||||
|
Value::minLargestInt / 10 >= -Value::maxLargestInt,
|
||||||
|
"The absolute value of minLargestInt must be only 1 magnitude"
|
||||||
|
"larger than maxLargestInt");
|
||||||
|
|
||||||
|
static JSONCPP_CONST Value::LargestUInt positive_threshold =
|
||||||
Value::maxLargestUInt / 10;
|
Value::maxLargestUInt / 10;
|
||||||
static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10;
|
static JSONCPP_CONST Value::UInt positive_last_digit =
|
||||||
|
Value::maxLargestUInt % 10;
|
||||||
|
|
||||||
// For the negative values, we have to be more careful. Since typically
|
// For the negative values, we have to be more careful. Since typically
|
||||||
// -Value::minLargestInt will cause an overflow, we first divide by 10 and
|
// -Value::minLargestInt will cause an overflow, we first divide by 10 and
|
||||||
// then take the inverse. This assumes that minLargestInt is only a single
|
// then take the inverse. This assumes that minLargestInt is only a single
|
||||||
// power of 10 different in magnitude, which we check above. For the last
|
// power of 10 different in magnitude, which we check above. For the last
|
||||||
// digit, we take the modulus before negating for the same reason.
|
// digit, we take the modulus before negating for the same reason.
|
||||||
static constexpr auto negative_threshold =
|
static JSONCPP_CONST Value::LargestUInt negative_threshold =
|
||||||
Value::LargestUInt(-(Value::minLargestInt / 10));
|
Value::LargestUInt(-(Value::minLargestInt / 10));
|
||||||
static constexpr auto negative_last_digit =
|
static JSONCPP_CONST Value::UInt negative_last_digit =
|
||||||
Value::UInt(-(Value::minLargestInt % 10));
|
Value::UInt(-(Value::minLargestInt % 10));
|
||||||
|
|
||||||
const Value::LargestUInt threshold =
|
const Value::LargestUInt threshold =
|
||||||
@ -1607,7 +1623,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
if (c < '0' || c > '9')
|
if (c < '0' || c > '9')
|
||||||
return decodeDouble(token, decoded);
|
return decodeDouble(token, decoded);
|
||||||
|
|
||||||
const auto digit(static_cast<Value::UInt>(c - '0'));
|
const Value::UInt digit(static_cast<Value::UInt>(c - '0'));
|
||||||
if (value >= threshold) {
|
if (value >= threshold) {
|
||||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||||
// a) we've only just touched the limit, meaing value == threshold,
|
// a) we've only just touched the limit, meaing value == threshold,
|
||||||
@ -1624,7 +1640,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
|
|
||||||
if (isNegative) {
|
if (isNegative) {
|
||||||
// We use the same magnitude assumption here, just in case.
|
// We use the same magnitude assumption here, just in case.
|
||||||
const auto last_digit = static_cast<Value::UInt>(value % 10);
|
const Value::UInt last_digit = static_cast<Value::UInt>(value % 10);
|
||||||
decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
|
decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
|
||||||
} else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
|
} else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
|
||||||
decoded = Value::LargestInt(value);
|
decoded = Value::LargestInt(value);
|
||||||
@ -1840,7 +1856,9 @@ String OurReader::getLocationLineAndColumn(Location location) const {
|
|||||||
|
|
||||||
String OurReader::getFormattedErrorMessages() const {
|
String OurReader::getFormattedErrorMessages() const {
|
||||||
String formattedMessage;
|
String formattedMessage;
|
||||||
for (const auto& error : errors_) {
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
|
itError != errors_.end(); ++itError) {
|
||||||
|
const ErrorInfo& error = *itError;
|
||||||
formattedMessage +=
|
formattedMessage +=
|
||||||
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
||||||
formattedMessage += " " + error.message_ + "\n";
|
formattedMessage += " " + error.message_ + "\n";
|
||||||
@ -1853,7 +1871,9 @@ String OurReader::getFormattedErrorMessages() const {
|
|||||||
|
|
||||||
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
||||||
std::vector<OurReader::StructuredError> allErrors;
|
std::vector<OurReader::StructuredError> allErrors;
|
||||||
for (const auto& error : errors_) {
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
|
itError != errors_.end(); ++itError) {
|
||||||
|
const ErrorInfo& error = *itError;
|
||||||
OurReader::StructuredError structured;
|
OurReader::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_;
|
||||||
@ -1871,7 +1891,7 @@ public:
|
|||||||
OurCharReader(bool collectComments, OurFeatures const& features)
|
OurCharReader(bool collectComments, OurFeatures const& features)
|
||||||
: collectComments_(collectComments), reader_(features) {}
|
: collectComments_(collectComments), reader_(features) {}
|
||||||
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
String* errs) override {
|
String* errs) JSONCPP_OVERRIDE {
|
||||||
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
||||||
if (errs) {
|
if (errs) {
|
||||||
*errs = reader_.getFormattedErrorMessages();
|
*errs = reader_.getFormattedErrorMessages();
|
||||||
@ -1881,7 +1901,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
||||||
CharReaderBuilder::~CharReaderBuilder() = default;
|
CharReaderBuilder::~CharReaderBuilder() {}
|
||||||
CharReader* CharReaderBuilder::newCharReader() const {
|
CharReader* CharReaderBuilder::newCharReader() const {
|
||||||
bool collectComments = settings_["collectComments"].asBool();
|
bool collectComments = settings_["collectComments"].asBool();
|
||||||
OurFeatures features = OurFeatures::all();
|
OurFeatures features = OurFeatures::all();
|
||||||
@ -1983,7 +2003,9 @@ bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root,
|
|||||||
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.
|
||||||
CharReaderPtr const reader(fact.newCharReader());
|
CharReaderPtr const reader(fact.newCharReader());
|
||||||
return reader->parse(begin, end, root, errs);
|
bool ret = reader->parse(begin, end, root, errs);
|
||||||
|
delete reader;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
IStream& operator>>(IStream& sin, Value& root) {
|
IStream& operator>>(IStream& sin, Value& root) {
|
||||||
|
@ -71,7 +71,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Defines a char buffer for use with uintToString().
|
// Defines a char buffer for use with uintToString().
|
||||||
using UIntToStringBuffer = char[uintToStringBufferSize];
|
typedef char UIntToStringBuffer[uintToStringBufferSize];
|
||||||
|
|
||||||
/** Converts an unsigned integer to string.
|
/** Converts an unsigned integer to string.
|
||||||
* @param value Unsigned integer to convert to string
|
* @param value Unsigned integer to convert to string
|
||||||
|
@ -48,14 +48,6 @@ int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
|||||||
#define JSON_ASSERT_UNREACHABLE assert(false)
|
#define JSON_ASSERT_UNREACHABLE assert(false)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
template <typename T>
|
|
||||||
static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {
|
|
||||||
std::unique_ptr<T> r;
|
|
||||||
if (p) {
|
|
||||||
r = std::unique_ptr<T>(new T(*p));
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a walkaround to avoid the static initialization of Value::null.
|
// This is a walkaround to avoid the static initialization of Value::null.
|
||||||
// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
|
// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
|
||||||
@ -118,8 +110,8 @@ static inline char* duplicateStringValue(const char* value, size_t length) {
|
|||||||
if (length >= static_cast<size_t>(Value::maxInt))
|
if (length >= static_cast<size_t>(Value::maxInt))
|
||||||
length = Value::maxInt - 1;
|
length = Value::maxInt - 1;
|
||||||
|
|
||||||
auto newString = static_cast<char*>(malloc(length + 1));
|
char* newString = static_cast<char*>(malloc(length + 1));
|
||||||
if (newString == nullptr) {
|
if (newString == JSONCPP_NULL) {
|
||||||
throwRuntimeError("in Json::Value::duplicateStringValue(): "
|
throwRuntimeError("in Json::Value::duplicateStringValue(): "
|
||||||
"Failed to allocate string value buffer");
|
"Failed to allocate string value buffer");
|
||||||
}
|
}
|
||||||
@ -139,8 +131,8 @@ static inline char* duplicateAndPrefixStringValue(const char* value,
|
|||||||
"in Json::Value::duplicateAndPrefixStringValue(): "
|
"in Json::Value::duplicateAndPrefixStringValue(): "
|
||||||
"length too big for prefixing");
|
"length too big for prefixing");
|
||||||
size_t actualLength = sizeof(length) + length + 1;
|
size_t actualLength = sizeof(length) + length + 1;
|
||||||
auto newString = static_cast<char*>(malloc(actualLength));
|
char* newString = static_cast<char*>(malloc(actualLength));
|
||||||
if (newString == nullptr) {
|
if (newString == JSONCPP_NULL) {
|
||||||
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
|
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
|
||||||
"Failed to allocate string value buffer");
|
"Failed to allocate string value buffer");
|
||||||
}
|
}
|
||||||
@ -200,9 +192,9 @@ static inline void releaseStringValue(char* value, unsigned) { free(value); }
|
|||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if JSON_USE_EXCEPTION
|
#if JSON_USE_EXCEPTION
|
||||||
Exception::Exception(String msg) : msg_(std::move(msg)) {}
|
Exception::Exception(String msg) : msg_(JSONCPP_MOVE(msg)) {}
|
||||||
Exception::~Exception() noexcept = default;
|
Exception::~Exception() JSONCPP_NOEXCEPT {}
|
||||||
char const* Exception::what() const noexcept { return msg_.c_str(); }
|
char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); }
|
||||||
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
|
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
|
||||||
LogicError::LogicError(String const& msg) : Exception(msg) {}
|
LogicError::LogicError(String const& msg) : Exception(msg) {}
|
||||||
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
|
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
|
||||||
@ -233,7 +225,8 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) {
|
|||||||
// Notes: policy_ indicates if the string was allocated when
|
// Notes: policy_ indicates if the string was allocated when
|
||||||
// a string is stored.
|
// a string is stored.
|
||||||
|
|
||||||
Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
|
Value::CZString::CZString(ArrayIndex index)
|
||||||
|
: cstr_(JSONCPP_NULL), index_(index) {}
|
||||||
|
|
||||||
Value::CZString::CZString(char const* str, unsigned length,
|
Value::CZString::CZString(char const* str, unsigned length,
|
||||||
DuplicationPolicy allocate)
|
DuplicationPolicy allocate)
|
||||||
@ -244,9 +237,10 @@ Value::CZString::CZString(char const* str, unsigned length,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Value::CZString::CZString(const CZString& other) {
|
Value::CZString::CZString(const CZString& other) {
|
||||||
cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
|
cstr_ =
|
||||||
? duplicateStringValue(other.cstr_, other.storage_.length_)
|
(other.storage_.policy_ != noDuplication && other.cstr_ != JSONCPP_NULL
|
||||||
: other.cstr_);
|
? duplicateStringValue(other.cstr_, other.storage_.length_)
|
||||||
|
: other.cstr_);
|
||||||
storage_.policy_ =
|
storage_.policy_ =
|
||||||
static_cast<unsigned>(
|
static_cast<unsigned>(
|
||||||
other.cstr_
|
other.cstr_
|
||||||
@ -258,12 +252,12 @@ Value::CZString::CZString(const CZString& other) {
|
|||||||
3U;
|
3U;
|
||||||
storage_.length_ = other.storage_.length_;
|
storage_.length_ = other.storage_.length_;
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value::CZString::CZString(CZString&& other)
|
Value::CZString::CZString(CZString&& other)
|
||||||
: cstr_(other.cstr_), index_(other.index_) {
|
: cstr_(other.cstr_), index_(other.index_) {
|
||||||
other.cstr_ = nullptr;
|
other.cstr_ = JSONCPP_NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
Value::CZString::~CZString() {
|
Value::CZString::~CZString() {
|
||||||
if (cstr_ && storage_.policy_ == duplicate) {
|
if (cstr_ && storage_.policy_ == duplicate) {
|
||||||
releaseStringValue(const_cast<char*>(cstr_),
|
releaseStringValue(const_cast<char*>(cstr_),
|
||||||
@ -284,14 +278,14 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
|
|||||||
index_ = other.index_;
|
index_ = other.index_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value::CZString& Value::CZString::operator=(CZString&& other) {
|
Value::CZString& Value::CZString::operator=(CZString&& other) {
|
||||||
cstr_ = other.cstr_;
|
cstr_ = other.cstr_;
|
||||||
index_ = other.index_;
|
index_ = other.index_;
|
||||||
other.cstr_ = nullptr;
|
other.cstr_ = JSONCPP_NULL;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
bool Value::CZString::operator<(const CZString& other) const {
|
bool Value::CZString::operator<(const CZString& other) const {
|
||||||
if (!cstr_)
|
if (!cstr_)
|
||||||
return index_ < other.index_;
|
return index_ < other.index_;
|
||||||
@ -400,7 +394,7 @@ Value::Value(double value) {
|
|||||||
|
|
||||||
Value::Value(const char* value) {
|
Value::Value(const char* value) {
|
||||||
initBasic(stringValue, true);
|
initBasic(stringValue, true);
|
||||||
JSON_ASSERT_MESSAGE(value != nullptr,
|
JSON_ASSERT_MESSAGE(value != JSONCPP_NULL,
|
||||||
"Null Value Passed to Value Constructor");
|
"Null Value Passed to Value Constructor");
|
||||||
value_.string_ = duplicateAndPrefixStringValue(
|
value_.string_ = duplicateAndPrefixStringValue(
|
||||||
value, static_cast<unsigned>(strlen(value)));
|
value, static_cast<unsigned>(strlen(value)));
|
||||||
@ -432,11 +426,12 @@ Value::Value(const Value& other) {
|
|||||||
dupPayload(other);
|
dupPayload(other);
|
||||||
dupMeta(other);
|
dupMeta(other);
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value::Value(Value&& other) {
|
Value::Value(Value&& other) {
|
||||||
initBasic(nullValue);
|
initBasic(nullValue);
|
||||||
swap(other);
|
swap(other);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Value::~Value() {
|
Value::~Value() {
|
||||||
releasePayload();
|
releasePayload();
|
||||||
@ -447,11 +442,12 @@ Value& Value::operator=(const Value& other) {
|
|||||||
Value(other).swap(*this);
|
Value(other).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value& Value::operator=(Value&& other) {
|
Value& Value::operator=(Value&& other) {
|
||||||
other.swap(*this);
|
other.swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Value::swapPayload(Value& other) {
|
void Value::swapPayload(Value& other) {
|
||||||
std::swap(bits_, other.bits_);
|
std::swap(bits_, other.bits_);
|
||||||
@ -503,8 +499,9 @@ bool Value::operator<(const Value& other) const {
|
|||||||
case booleanValue:
|
case booleanValue:
|
||||||
return value_.bool_ < other.value_.bool_;
|
return value_.bool_ < other.value_.bool_;
|
||||||
case stringValue: {
|
case stringValue: {
|
||||||
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
|
if ((value_.string_ == JSONCPP_NULL) ||
|
||||||
return other.value_.string_ != nullptr;
|
(other.value_.string_ == JSONCPP_NULL)) {
|
||||||
|
return other.value_.string_ != JSONCPP_NULL;
|
||||||
}
|
}
|
||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
unsigned other_len;
|
unsigned other_len;
|
||||||
@ -525,8 +522,8 @@ bool Value::operator<(const Value& other) const {
|
|||||||
}
|
}
|
||||||
case arrayValue:
|
case arrayValue:
|
||||||
case objectValue: {
|
case objectValue: {
|
||||||
auto thisSize = value_.map_->size();
|
long unsigned int thisSize = value_.map_->size();
|
||||||
auto otherSize = other.value_.map_->size();
|
long unsigned int otherSize = other.value_.map_->size();
|
||||||
if (thisSize != otherSize)
|
if (thisSize != otherSize)
|
||||||
return thisSize < otherSize;
|
return thisSize < otherSize;
|
||||||
return (*value_.map_) < (*other.value_.map_);
|
return (*value_.map_) < (*other.value_.map_);
|
||||||
@ -558,7 +555,8 @@ bool Value::operator==(const Value& other) const {
|
|||||||
case booleanValue:
|
case booleanValue:
|
||||||
return value_.bool_ == other.value_.bool_;
|
return value_.bool_ == other.value_.bool_;
|
||||||
case stringValue: {
|
case stringValue: {
|
||||||
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
|
if ((value_.string_ == JSONCPP_NULL) ||
|
||||||
|
(other.value_.string_ == JSONCPP_NULL)) {
|
||||||
return (value_.string_ == other.value_.string_);
|
return (value_.string_ == other.value_.string_);
|
||||||
}
|
}
|
||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
@ -590,8 +588,8 @@ bool Value::operator!=(const Value& other) const { return !(*this == other); }
|
|||||||
const char* Value::asCString() const {
|
const char* Value::asCString() const {
|
||||||
JSON_ASSERT_MESSAGE(type() == stringValue,
|
JSON_ASSERT_MESSAGE(type() == stringValue,
|
||||||
"in Json::Value::asCString(): requires stringValue");
|
"in Json::Value::asCString(): requires stringValue");
|
||||||
if (value_.string_ == nullptr)
|
if (value_.string_ == JSONCPP_NULL)
|
||||||
return nullptr;
|
return JSONCPP_NULL;
|
||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
char const* this_str;
|
char const* this_str;
|
||||||
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
|
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
|
||||||
@ -616,7 +614,7 @@ unsigned Value::getCStringLength() const {
|
|||||||
bool Value::getString(char const** begin, char const** end) const {
|
bool Value::getString(char const** begin, char const** end) const {
|
||||||
if (type() != stringValue)
|
if (type() != stringValue)
|
||||||
return false;
|
return false;
|
||||||
if (value_.string_ == nullptr)
|
if (value_.string_ == JSONCPP_NULL)
|
||||||
return false;
|
return false;
|
||||||
unsigned length;
|
unsigned length;
|
||||||
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
|
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
|
||||||
@ -630,7 +628,7 @@ String Value::asString() const {
|
|||||||
case nullValue:
|
case nullValue:
|
||||||
return "";
|
return "";
|
||||||
case stringValue: {
|
case stringValue: {
|
||||||
if (value_.string_ == nullptr)
|
if (value_.string_ == JSONCPP_NULL)
|
||||||
return "";
|
return "";
|
||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
char const* this_str;
|
char const* this_str;
|
||||||
@ -813,7 +811,7 @@ bool Value::asBool() const {
|
|||||||
return value_.uint_ != 0;
|
return value_.uint_ != 0;
|
||||||
case realValue: {
|
case realValue: {
|
||||||
// According to JavaScript language zero or NaN is regarded as false
|
// According to JavaScript language zero or NaN is regarded as false
|
||||||
const auto value_classification = std::fpclassify(value_.real_);
|
const int value_classification = std::fpclassify(value_.real_);
|
||||||
return value_classification != FP_ZERO && value_classification != FP_NAN;
|
return value_classification != FP_ZERO && value_classification != FP_NAN;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -928,7 +926,7 @@ Value& Value::operator[](ArrayIndex index) {
|
|||||||
if (type() == nullValue)
|
if (type() == nullValue)
|
||||||
*this = Value(arrayValue);
|
*this = Value(arrayValue);
|
||||||
CZString key(index);
|
CZString key(index);
|
||||||
auto it = value_.map_->lower_bound(key);
|
ObjectValues::iterator it = value_.map_->lower_bound(key);
|
||||||
if (it != value_.map_->end() && (*it).first == key)
|
if (it != value_.map_->end() && (*it).first == key)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
@ -967,7 +965,7 @@ const Value& Value::operator[](int index) const {
|
|||||||
void Value::initBasic(ValueType type, bool allocated) {
|
void Value::initBasic(ValueType type, bool allocated) {
|
||||||
setType(type);
|
setType(type);
|
||||||
setIsAllocated(allocated);
|
setIsAllocated(allocated);
|
||||||
comments_ = Comments{};
|
comments_ = Comments();
|
||||||
start_ = 0;
|
start_ = 0;
|
||||||
limit_ = 0;
|
limit_ = 0;
|
||||||
}
|
}
|
||||||
@ -1042,7 +1040,7 @@ Value& Value::resolveReference(const char* key) {
|
|||||||
*this = Value(objectValue);
|
*this = Value(objectValue);
|
||||||
CZString actualKey(key, static_cast<unsigned>(strlen(key)),
|
CZString actualKey(key, static_cast<unsigned>(strlen(key)),
|
||||||
CZString::noDuplication); // NOTE!
|
CZString::noDuplication); // NOTE!
|
||||||
auto it = value_.map_->lower_bound(actualKey);
|
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
|
||||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
@ -1061,7 +1059,7 @@ Value& Value::resolveReference(char const* key, char const* end) {
|
|||||||
*this = Value(objectValue);
|
*this = Value(objectValue);
|
||||||
CZString actualKey(key, static_cast<unsigned>(end - key),
|
CZString actualKey(key, static_cast<unsigned>(end - key),
|
||||||
CZString::duplicateOnCopy);
|
CZString::duplicateOnCopy);
|
||||||
auto it = value_.map_->lower_bound(actualKey);
|
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
|
||||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
@ -1083,12 +1081,12 @@ Value const* Value::find(char const* begin, char const* end) const {
|
|||||||
"in Json::Value::find(begin, end): requires "
|
"in Json::Value::find(begin, end): requires "
|
||||||
"objectValue or nullValue");
|
"objectValue or nullValue");
|
||||||
if (type() == nullValue)
|
if (type() == nullValue)
|
||||||
return nullptr;
|
return JSONCPP_NULL;
|
||||||
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
||||||
CZString::noDuplication);
|
CZString::noDuplication);
|
||||||
ObjectValues::const_iterator it = value_.map_->find(actualKey);
|
ObjectValues::const_iterator it = value_.map_->find(actualKey);
|
||||||
if (it == value_.map_->end())
|
if (it == value_.map_->end())
|
||||||
return nullptr;
|
return JSONCPP_NULL;
|
||||||
return &(*it).second;
|
return &(*it).second;
|
||||||
}
|
}
|
||||||
Value* Value::demand(char const* begin, char const* end) {
|
Value* Value::demand(char const* begin, char const* end) {
|
||||||
@ -1122,8 +1120,8 @@ Value& Value::operator[](const StaticString& key) {
|
|||||||
return resolveReference(key.c_str());
|
return resolveReference(key.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value& Value::append(const Value& value) { return append(Value(value)); }
|
Value& Value::append(const Value& value) { return append(Value(value)); }
|
||||||
|
|
||||||
Value& Value::append(Value&& value) {
|
Value& Value::append(Value&& value) {
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
||||||
"in Json::Value::append: requires arrayValue");
|
"in Json::Value::append: requires arrayValue");
|
||||||
@ -1132,12 +1130,19 @@ Value& Value::append(Value&& value) {
|
|||||||
}
|
}
|
||||||
return this->value_.map_->emplace(size(), std::move(value)).first->second;
|
return this->value_.map_->emplace(size(), std::move(value)).first->second;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
bool Value::insert(ArrayIndex index, const Value& newValue) {
|
bool Value::insert(ArrayIndex index, const Value& newValue) {
|
||||||
return insert(index, Value(newValue));
|
return insert(index, Value(newValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::insert(ArrayIndex index, Value&& newValue) {
|
bool Value::insert(ArrayIndex index, Value&& newValue) {
|
||||||
|
#else
|
||||||
|
bool Value::insert(ArrayIndex index, const Value& newValue) {
|
||||||
|
#endif
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
||||||
"in Json::Value::insert: requires arrayValue");
|
"in Json::Value::insert: requires arrayValue");
|
||||||
ArrayIndex length = size();
|
ArrayIndex length = size();
|
||||||
@ -1145,12 +1150,11 @@ bool Value::insert(ArrayIndex index, Value&& newValue) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (ArrayIndex i = length; i > index; i--) {
|
for (ArrayIndex i = length; i > index; i--) {
|
||||||
(*this)[i] = std::move((*this)[i - 1]);
|
(*this)[i] = JSONCPP_MOVE((*this)[i - 1]);
|
||||||
}
|
}
|
||||||
(*this)[index] = std::move(newValue);
|
(*this)[index] = JSONCPP_MOVE(newValue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Value::get(char const* begin, char const* end,
|
Value Value::get(char const* begin, char const* end,
|
||||||
Value const& defaultValue) const {
|
Value const& defaultValue) const {
|
||||||
Value const* found = find(begin, end);
|
Value const* found = find(begin, end);
|
||||||
@ -1169,11 +1173,11 @@ bool Value::removeMember(const char* begin, const char* end, Value* removed) {
|
|||||||
}
|
}
|
||||||
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
||||||
CZString::noDuplication);
|
CZString::noDuplication);
|
||||||
auto it = value_.map_->find(actualKey);
|
ObjectValues::iterator it = value_.map_->find(actualKey);
|
||||||
if (it == value_.map_->end())
|
if (it == value_.map_->end())
|
||||||
return false;
|
return false;
|
||||||
if (removed)
|
if (removed)
|
||||||
*removed = std::move(it->second);
|
*removed = JSONCPP_MOVE(it->second);
|
||||||
value_.map_->erase(it);
|
value_.map_->erase(it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1199,7 +1203,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CZString key(index);
|
CZString key(index);
|
||||||
auto it = value_.map_->find(key);
|
ObjectValues::iterator it = value_.map_->find(key);
|
||||||
if (it == value_.map_->end()) {
|
if (it == value_.map_->end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1213,14 +1217,14 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
|||||||
}
|
}
|
||||||
// erase the last one ("leftover")
|
// erase the last one ("leftover")
|
||||||
CZString keyLast(oldSize - 1);
|
CZString keyLast(oldSize - 1);
|
||||||
auto itLast = value_.map_->find(keyLast);
|
ObjectValues::iterator itLast = value_.map_->find(keyLast);
|
||||||
value_.map_->erase(itLast);
|
value_.map_->erase(itLast);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::isMember(char const* begin, char const* end) const {
|
bool Value::isMember(char const* begin, char const* end) const {
|
||||||
Value const* value = find(begin, end);
|
Value const* value = find(begin, end);
|
||||||
return nullptr != value;
|
return JSONCPP_NULL != value;
|
||||||
}
|
}
|
||||||
bool Value::isMember(char const* key) const {
|
bool Value::isMember(char const* key) const {
|
||||||
return isMember(key, key + strlen(key));
|
return isMember(key, key + strlen(key));
|
||||||
@ -1370,53 +1374,44 @@ bool Value::isArray() const { return type() == arrayValue; }
|
|||||||
|
|
||||||
bool Value::isObject() const { return type() == objectValue; }
|
bool Value::isObject() const { return type() == objectValue; }
|
||||||
|
|
||||||
Value::Comments::Comments(const Comments& that)
|
Value::Comments::Comments(const Comments& that) {
|
||||||
: ptr_{cloneUnique(that.ptr_)} {}
|
for (size_t i = 0; i < numberOfCommentPlacement; i++) {
|
||||||
|
ptr_[i] = that.ptr_[i];
|
||||||
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
|
}
|
||||||
|
}
|
||||||
Value::Comments& Value::Comments::operator=(const Comments& that) {
|
Value::Comments& Value::Comments::operator=(const Comments& that) {
|
||||||
ptr_ = cloneUnique(that.ptr_);
|
for (size_t i = 0; i < numberOfCommentPlacement; i++) {
|
||||||
|
ptr_[i] = that.ptr_[i];
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Comments& Value::Comments::operator=(Comments&& that) {
|
|
||||||
ptr_ = std::move(that.ptr_);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Value::Comments::has(CommentPlacement slot) const {
|
bool Value::Comments::has(CommentPlacement slot) const {
|
||||||
return ptr_ && !(*ptr_)[slot].empty();
|
return !ptr_[slot].empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
String Value::Comments::get(CommentPlacement slot) const {
|
String Value::Comments::get(CommentPlacement slot) const { return ptr_[slot]; }
|
||||||
if (!ptr_)
|
|
||||||
return {};
|
|
||||||
return (*ptr_)[slot];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Value::Comments::set(CommentPlacement slot, String comment) {
|
void Value::Comments::set(CommentPlacement slot, String comment) {
|
||||||
if (!ptr_) {
|
|
||||||
ptr_ = std::unique_ptr<Array>(new Array());
|
|
||||||
}
|
|
||||||
// check comments array boundry.
|
// check comments array boundry.
|
||||||
if (slot < CommentPlacement::numberOfCommentPlacement) {
|
if (slot < numberOfCommentPlacement) {
|
||||||
(*ptr_)[slot] = std::move(comment);
|
ptr_[slot] = comment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::setComment(String comment, CommentPlacement placement) {
|
void Value::setComment(const char* comment, CommentPlacement placement) {
|
||||||
if (!comment.empty() && (comment.back() == '\n')) {
|
setComment(comment, strlen(comment), placement);
|
||||||
|
}
|
||||||
|
void Value::setComment(const char* comment, size_t len,
|
||||||
|
CommentPlacement placement) {
|
||||||
|
if ((len > 0) && (comment[len - 1] == '\n')) {
|
||||||
// Always discard trailing newline, to aid indentation.
|
// Always discard trailing newline, to aid indentation.
|
||||||
comment.pop_back();
|
len -= 1;
|
||||||
}
|
}
|
||||||
JSON_ASSERT(!comment.empty());
|
comments_.set(placement, String(comment, len));
|
||||||
JSON_ASSERT_MESSAGE(
|
}
|
||||||
comment[0] == '\0' || comment[0] == '/',
|
void Value::setComment(const String& comment, CommentPlacement placement) {
|
||||||
"in Json::Value::setComment(): Comments must start with /");
|
setComment(comment.c_str(), comment.length(), placement);
|
||||||
comments_.set(placement, std::move(comment));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::hasComment(CommentPlacement placement) const {
|
bool Value::hasComment(CommentPlacement placement) const {
|
||||||
return comments_.has(placement);
|
return comments_.has(placement);
|
||||||
}
|
}
|
||||||
@ -1453,7 +1448,7 @@ Value::const_iterator Value::begin() const {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return {};
|
return const_iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::const_iterator Value::end() const {
|
Value::const_iterator Value::end() const {
|
||||||
@ -1466,7 +1461,7 @@ Value::const_iterator Value::end() const {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return {};
|
return const_iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::iterator Value::begin() {
|
Value::iterator Value::begin() {
|
||||||
@ -1498,14 +1493,15 @@ Value::iterator Value::end() {
|
|||||||
// class PathArgument
|
// class PathArgument
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PathArgument::PathArgument() = default;
|
PathArgument::PathArgument() {}
|
||||||
|
|
||||||
PathArgument::PathArgument(ArrayIndex index)
|
PathArgument::PathArgument(ArrayIndex index)
|
||||||
: index_(index), kind_(kindIndex) {}
|
: index_(index), kind_(kindIndex) {}
|
||||||
|
|
||||||
PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
|
PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
|
||||||
|
|
||||||
PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
|
PathArgument::PathArgument(String key)
|
||||||
|
: key_(JSONCPP_MOVE(key)), kind_(kindKey) {}
|
||||||
|
|
||||||
// class Path
|
// class Path
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
@ -1526,7 +1522,7 @@ Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
|
|||||||
void Path::makePath(const String& path, const InArgs& in) {
|
void Path::makePath(const String& path, const InArgs& in) {
|
||||||
const char* current = path.c_str();
|
const char* current = path.c_str();
|
||||||
const char* end = current + path.length();
|
const char* end = current + path.length();
|
||||||
auto itInArg = in.begin();
|
InArgs::const_iterator itInArg = in.begin();
|
||||||
while (current != end) {
|
while (current != end) {
|
||||||
if (*current == '[') {
|
if (*current == '[') {
|
||||||
++current;
|
++current;
|
||||||
@ -1572,7 +1568,9 @@ void Path::invalidPath(const String& /*path*/, int /*location*/) {
|
|||||||
|
|
||||||
const Value& Path::resolve(const Value& root) const {
|
const Value& Path::resolve(const Value& root) const {
|
||||||
const Value* node = &root;
|
const Value* node = &root;
|
||||||
for (const auto& arg : args_) {
|
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||||
|
++itArg) {
|
||||||
|
const PathArgument& arg = *itArg;
|
||||||
if (arg.kind_ == PathArgument::kindIndex) {
|
if (arg.kind_ == PathArgument::kindIndex) {
|
||||||
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
|
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
|
||||||
// Error: unable to resolve path (array value expected at position... )
|
// Error: unable to resolve path (array value expected at position... )
|
||||||
@ -1597,7 +1595,9 @@ const Value& Path::resolve(const Value& root) const {
|
|||||||
|
|
||||||
Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
||||||
const Value* node = &root;
|
const Value* node = &root;
|
||||||
for (const auto& arg : args_) {
|
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||||
|
++itArg) {
|
||||||
|
const PathArgument& arg = *itArg;
|
||||||
if (arg.kind_ == PathArgument::kindIndex) {
|
if (arg.kind_ == PathArgument::kindIndex) {
|
||||||
if (!node->isArray() || !node->isValidIndex(arg.index_))
|
if (!node->isArray() || !node->isValidIndex(arg.index_))
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
@ -1615,7 +1615,9 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
|||||||
|
|
||||||
Value& Path::make(Value& root) const {
|
Value& Path::make(Value& root) const {
|
||||||
Value* node = &root;
|
Value* node = &root;
|
||||||
for (const auto& arg : args_) {
|
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||||
|
++itArg) {
|
||||||
|
const PathArgument& arg = *itArg;
|
||||||
if (arg.kind_ == PathArgument::kindIndex) {
|
if (arg.kind_ == PathArgument::kindIndex) {
|
||||||
if (!node->isArray()) {
|
if (!node->isArray()) {
|
||||||
// Error: node is not an array at position ...
|
// Error: node is not an array at position ...
|
||||||
|
@ -15,7 +15,7 @@ namespace Json {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValueIteratorBase::ValueIteratorBase() : current_() {}
|
ValueIteratorBase::ValueIteratorBase() : current_(), isNull_(true) {}
|
||||||
|
|
||||||
ValueIteratorBase::ValueIteratorBase(
|
ValueIteratorBase::ValueIteratorBase(
|
||||||
const Value::ObjectValues::iterator& current)
|
const Value::ObjectValues::iterator& current)
|
||||||
@ -98,8 +98,8 @@ char const* ValueIteratorBase::memberName() const {
|
|||||||
char const* ValueIteratorBase::memberName(char const** end) const {
|
char const* ValueIteratorBase::memberName(char const** end) const {
|
||||||
const char* cname = (*current_).first.data();
|
const char* cname = (*current_).first.data();
|
||||||
if (!cname) {
|
if (!cname) {
|
||||||
*end = nullptr;
|
*end = JSONCPP_NULL;
|
||||||
return nullptr;
|
return JSONCPP_NULL;
|
||||||
}
|
}
|
||||||
*end = cname + (*current_).first.length();
|
*end = cname + (*current_).first.length();
|
||||||
return cname;
|
return cname;
|
||||||
@ -113,7 +113,7 @@ char const* ValueIteratorBase::memberName(char const** end) const {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValueConstIterator::ValueConstIterator() = default;
|
ValueConstIterator::ValueConstIterator() {}
|
||||||
|
|
||||||
ValueConstIterator::ValueConstIterator(
|
ValueConstIterator::ValueConstIterator(
|
||||||
const Value::ObjectValues::iterator& current)
|
const Value::ObjectValues::iterator& current)
|
||||||
@ -136,7 +136,7 @@ operator=(const ValueIteratorBase& other) {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValueIterator::ValueIterator() = default;
|
ValueIterator::ValueIterator() {}
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
||||||
: ValueIteratorBase(current) {}
|
: ValueIteratorBase(current) {}
|
||||||
@ -146,7 +146,8 @@ ValueIterator::ValueIterator(const ValueConstIterator& other)
|
|||||||
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const ValueIterator& other) = default;
|
ValueIterator::ValueIterator(const ValueIterator& other)
|
||||||
|
: ValueIteratorBase(other) {}
|
||||||
|
|
||||||
ValueIterator& ValueIterator::operator=(const SelfType& other) {
|
ValueIterator& ValueIterator::operator=(const SelfType& other) {
|
||||||
copy(other);
|
copy(other);
|
||||||
|
@ -83,11 +83,7 @@
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
typedef StreamWriter* StreamWriterPtr;
|
||||||
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
|
|
||||||
#else
|
|
||||||
using StreamWriterPtr = std::auto_ptr<StreamWriter>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
String valueToString(LargestInt value) {
|
String valueToString(LargestInt value) {
|
||||||
UIntToStringBuffer buffer;
|
UIntToStringBuffer buffer;
|
||||||
@ -136,12 +132,12 @@ String valueToString(double value, bool useSpecialFloats,
|
|||||||
|
|
||||||
String buffer(size_t(36), '\0');
|
String buffer(size_t(36), '\0');
|
||||||
while (true) {
|
while (true) {
|
||||||
int len = jsoncpp_snprintf(
|
int len =
|
||||||
&*buffer.begin(), buffer.size(),
|
jsoncpp_snprintf(&*buffer.begin(), buffer.size(),
|
||||||
(precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
|
(precisionType == significantDigits) ? "%.*g" : "%.*f",
|
||||||
precision, value);
|
precision, value);
|
||||||
assert(len >= 0);
|
assert(len >= 0);
|
||||||
auto wouldPrint = static_cast<size_t>(len);
|
size_t wouldPrint = static_cast<size_t>(len);
|
||||||
if (wouldPrint >= buffer.size()) {
|
if (wouldPrint >= buffer.size()) {
|
||||||
buffer.resize(wouldPrint + 1);
|
buffer.resize(wouldPrint + 1);
|
||||||
continue;
|
continue;
|
||||||
@ -153,7 +149,7 @@ String valueToString(double value, bool useSpecialFloats,
|
|||||||
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
|
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
|
||||||
|
|
||||||
// strip the zero padding from the right
|
// strip the zero padding from the right
|
||||||
if (precisionType == PrecisionType::decimalPlaces) {
|
if (precisionType == decimalPlaces) {
|
||||||
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
|
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +263,7 @@ static String toHex16Bit(unsigned int x) {
|
|||||||
|
|
||||||
static String valueToQuotedStringN(const char* value, unsigned length,
|
static String valueToQuotedStringN(const char* value, unsigned length,
|
||||||
bool emitUTF8 = false) {
|
bool emitUTF8 = false) {
|
||||||
if (value == nullptr)
|
if (value == JSONCPP_NULL)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
if (!isAnyCharRequiredQuoting(value, length))
|
if (!isAnyCharRequiredQuoting(value, length))
|
||||||
@ -351,14 +347,14 @@ String valueToQuotedString(const char* value) {
|
|||||||
|
|
||||||
// Class Writer
|
// Class Writer
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
Writer::~Writer() = default;
|
Writer::~Writer() {}
|
||||||
|
|
||||||
// Class FastWriter
|
// Class FastWriter
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FastWriter::FastWriter()
|
FastWriter::FastWriter()
|
||||||
|
: yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
|
||||||
= default;
|
omitEndingLineFeed_(false) {}
|
||||||
|
|
||||||
void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
|
void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
|
||||||
|
|
||||||
@ -414,7 +410,8 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
case objectValue: {
|
case objectValue: {
|
||||||
Value::Members members(value.getMemberNames());
|
Value::Members members(value.getMemberNames());
|
||||||
document_ += '{';
|
document_ += '{';
|
||||||
for (auto it = members.begin(); it != members.end(); ++it) {
|
for (Value::Members::const_iterator it = members.begin();
|
||||||
|
it != members.end(); ++it) {
|
||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
if (it != members.begin())
|
if (it != members.begin())
|
||||||
document_ += ',';
|
document_ += ',';
|
||||||
@ -431,7 +428,8 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
// Class StyledWriter
|
// Class StyledWriter
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
StyledWriter::StyledWriter() = default;
|
StyledWriter::StyledWriter()
|
||||||
|
: rightMargin_(74), indentSize_(3), addChildValues_() {}
|
||||||
|
|
||||||
String StyledWriter::write(const Value& root) {
|
String StyledWriter::write(const Value& root) {
|
||||||
document_.clear();
|
document_.clear();
|
||||||
@ -482,7 +480,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
else {
|
else {
|
||||||
writeWithIndent("{");
|
writeWithIndent("{");
|
||||||
indent();
|
indent();
|
||||||
auto it = members.begin();
|
Value::Members::const_iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
const Value& childValue = value[name];
|
const Value& childValue = value[name];
|
||||||
@ -644,8 +642,9 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
StyledStreamWriter::StyledStreamWriter(String indentation)
|
StyledStreamWriter::StyledStreamWriter(String indentation)
|
||||||
: document_(nullptr), indentation_(std::move(indentation)),
|
: document_(JSONCPP_NULL), rightMargin_(74),
|
||||||
addChildValues_(), indented_(false) {}
|
indentation_(JSONCPP_MOVE(indentation)), addChildValues_(),
|
||||||
|
indented_(false) {}
|
||||||
|
|
||||||
void StyledStreamWriter::write(OStream& out, const Value& root) {
|
void StyledStreamWriter::write(OStream& out, const Value& root) {
|
||||||
document_ = &out;
|
document_ = &out;
|
||||||
@ -659,7 +658,7 @@ void StyledStreamWriter::write(OStream& out, const Value& root) {
|
|||||||
writeValue(root);
|
writeValue(root);
|
||||||
writeCommentAfterValueOnSameLine(root);
|
writeCommentAfterValueOnSameLine(root);
|
||||||
*document_ << "\n";
|
*document_ << "\n";
|
||||||
document_ = nullptr; // Forget the stream, for safety.
|
document_ = JSONCPP_NULL; // Forget the stream, for safety.
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyledStreamWriter::writeValue(const Value& value) {
|
void StyledStreamWriter::writeValue(const Value& value) {
|
||||||
@ -700,7 +699,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
|||||||
else {
|
else {
|
||||||
writeWithIndent("{");
|
writeWithIndent("{");
|
||||||
indent();
|
indent();
|
||||||
auto it = members.begin();
|
Value::Members::const_iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
const Value& childValue = value[name];
|
const Value& childValue = value[name];
|
||||||
@ -878,7 +877,7 @@ struct BuiltStyledStreamWriter : public StreamWriter {
|
|||||||
String endingLineFeedSymbol, bool useSpecialFloats,
|
String endingLineFeedSymbol, bool useSpecialFloats,
|
||||||
bool emitUTF8, unsigned int precision,
|
bool emitUTF8, unsigned int precision,
|
||||||
PrecisionType precisionType);
|
PrecisionType precisionType);
|
||||||
int write(Value const& root, OStream* sout) override;
|
int write(Value const& root, OStream* sout) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(Value const& value);
|
void writeValue(Value const& value);
|
||||||
@ -893,7 +892,7 @@ private:
|
|||||||
void writeCommentAfterValueOnSameLine(Value const& root);
|
void writeCommentAfterValueOnSameLine(Value const& root);
|
||||||
static bool hasCommentForValue(const Value& value);
|
static bool hasCommentForValue(const Value& value);
|
||||||
|
|
||||||
using ChildValues = std::vector<String>;
|
typedef std::vector<String> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
String indentString_;
|
String indentString_;
|
||||||
@ -914,9 +913,10 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
|
|||||||
String indentation, CommentStyle::Enum cs, String colonSymbol,
|
String indentation, CommentStyle::Enum cs, String colonSymbol,
|
||||||
String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
|
String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
|
||||||
bool emitUTF8, unsigned int precision, PrecisionType precisionType)
|
bool emitUTF8, unsigned int precision, PrecisionType precisionType)
|
||||||
: rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
|
: rightMargin_(74), indentation_(JSONCPP_MOVE(indentation)), cs_(cs),
|
||||||
colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
|
colonSymbol_(JSONCPP_MOVE(colonSymbol)),
|
||||||
endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
|
nullSymbol_(JSONCPP_MOVE(nullSymbol)),
|
||||||
|
endingLineFeedSymbol_(JSONCPP_MOVE(endingLineFeedSymbol)),
|
||||||
addChildValues_(false), indented_(false),
|
addChildValues_(false), indented_(false),
|
||||||
useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
|
useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
|
||||||
precision_(precision), precisionType_(precisionType) {}
|
precision_(precision), precisionType_(precisionType) {}
|
||||||
@ -932,7 +932,7 @@ int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) {
|
|||||||
writeValue(root);
|
writeValue(root);
|
||||||
writeCommentAfterValueOnSameLine(root);
|
writeCommentAfterValueOnSameLine(root);
|
||||||
*sout_ << endingLineFeedSymbol_;
|
*sout_ << endingLineFeedSymbol_;
|
||||||
sout_ = nullptr;
|
sout_ = JSONCPP_NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||||
@ -975,7 +975,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
|||||||
else {
|
else {
|
||||||
writeWithIndent("{");
|
writeWithIndent("{");
|
||||||
indent();
|
indent();
|
||||||
auto it = members.begin();
|
Value::Members::const_iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
String const& name = *it;
|
String const& name = *it;
|
||||||
Value const& childValue = value[name];
|
Value const& childValue = value[name];
|
||||||
@ -1151,11 +1151,11 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
|
|||||||
///////////////
|
///////////////
|
||||||
// StreamWriter
|
// StreamWriter
|
||||||
|
|
||||||
StreamWriter::StreamWriter() : sout_(nullptr) {}
|
StreamWriter::StreamWriter() : sout_(JSONCPP_NULL) {}
|
||||||
StreamWriter::~StreamWriter() = default;
|
StreamWriter::~StreamWriter() {}
|
||||||
StreamWriter::Factory::~Factory() = default;
|
StreamWriter::Factory::~Factory() {}
|
||||||
StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
|
StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
|
||||||
StreamWriterBuilder::~StreamWriterBuilder() = default;
|
StreamWriterBuilder::~StreamWriterBuilder() {}
|
||||||
StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
||||||
const String indentation = settings_["indentation"].asString();
|
const String indentation = settings_["indentation"].asString();
|
||||||
const String cs_str = settings_["commentStyle"].asString();
|
const String cs_str = settings_["commentStyle"].asString();
|
||||||
@ -1175,9 +1175,9 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
|||||||
}
|
}
|
||||||
PrecisionType precisionType(significantDigits);
|
PrecisionType precisionType(significantDigits);
|
||||||
if (pt_str == "significant") {
|
if (pt_str == "significant") {
|
||||||
precisionType = PrecisionType::significantDigits;
|
precisionType = significantDigits;
|
||||||
} else if (pt_str == "decimal") {
|
} else if (pt_str == "decimal") {
|
||||||
precisionType = PrecisionType::decimalPlaces;
|
precisionType = decimalPlaces;
|
||||||
} else {
|
} else {
|
||||||
throwRuntimeError("precisionType must be 'significant' or 'decimal'");
|
throwRuntimeError("precisionType must be 'significant' or 'decimal'");
|
||||||
}
|
}
|
||||||
@ -1247,6 +1247,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);
|
||||||
|
delete writer;
|
||||||
return sout.str();
|
return sout.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1254,6 +1255,7 @@ OStream& operator<<(OStream& sout, Value const& root) {
|
|||||||
StreamWriterBuilder builder;
|
StreamWriterBuilder builder;
|
||||||
StreamWriterPtr const writer(builder.newStreamWriter());
|
StreamWriterPtr const writer(builder.newStreamWriter());
|
||||||
writer->write(root, &sout);
|
writer->write(root, &sout);
|
||||||
|
delete writer;
|
||||||
return sout;
|
return sout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "fuzz.h"
|
#include "fuzz.h"
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <json/config.h>
|
#include <json/config.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -41,14 +40,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|||||||
builder.settings_["collectComments"] = hash_settings & (1 << 9);
|
builder.settings_["collectComments"] = hash_settings & (1 << 9);
|
||||||
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
|
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
|
||||||
|
|
||||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
Json::CharReader* reader(builder.newCharReader());
|
||||||
|
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
const auto data_str = reinterpret_cast<const char*>(data);
|
const char* data_str = reinterpret_cast<const char*>(data);
|
||||||
try {
|
try {
|
||||||
reader->parse(data_str, data_str + size, &root, nullptr);
|
reader->parse(data_str, data_str + size, &root, JSONCPP_NULL);
|
||||||
} catch (Json::Exception const&) {
|
} catch (Json::Exception const&) {
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
// Whether it succeeded or not doesn't matter.
|
// Whether it succeeded or not doesn't matter.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -73,10 +73,11 @@ namespace JsonTest {
|
|||||||
// class TestResult
|
// class TestResult
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TestResult::TestResult() {
|
TestResult::TestResult()
|
||||||
|
: predicateId_(1), lastUsedPredicateId_(0), messageTarget_(JSONCPP_NULL) {
|
||||||
// The root predicate has id 0
|
// The root predicate has id 0
|
||||||
rootPredicateNode_.id_ = 0;
|
rootPredicateNode_.id_ = 0;
|
||||||
rootPredicateNode_.next_ = nullptr;
|
rootPredicateNode_.next_ = JSONCPP_NULL;
|
||||||
predicateStackTail_ = &rootPredicateNode_;
|
predicateStackTail_ = &rootPredicateNode_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,7 @@ TestResult& TestResult::addFailure(const char* file, unsigned int line,
|
|||||||
/// added.
|
/// added.
|
||||||
unsigned int nestingLevel = 0;
|
unsigned int nestingLevel = 0;
|
||||||
PredicateContext* lastNode = rootPredicateNode_.next_;
|
PredicateContext* lastNode = rootPredicateNode_.next_;
|
||||||
for (; lastNode != nullptr; lastNode = lastNode->next_) {
|
for (; lastNode != JSONCPP_NULL; lastNode = lastNode->next_) {
|
||||||
if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
|
if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
|
||||||
{
|
{
|
||||||
lastUsedPredicateId_ = lastNode->id_;
|
lastUsedPredicateId_ = lastNode->id_;
|
||||||
@ -121,17 +122,18 @@ void TestResult::addFailureInfo(const char* file, unsigned int line,
|
|||||||
|
|
||||||
TestResult& TestResult::popPredicateContext() {
|
TestResult& TestResult::popPredicateContext() {
|
||||||
PredicateContext* lastNode = &rootPredicateNode_;
|
PredicateContext* lastNode = &rootPredicateNode_;
|
||||||
while (lastNode->next_ != nullptr && lastNode->next_->next_ != nullptr) {
|
while (lastNode->next_ != JSONCPP_NULL &&
|
||||||
|
lastNode->next_->next_ != JSONCPP_NULL) {
|
||||||
lastNode = lastNode->next_;
|
lastNode = lastNode->next_;
|
||||||
}
|
}
|
||||||
// Set message target to popped failure
|
// Set message target to popped failure
|
||||||
PredicateContext* tail = lastNode->next_;
|
PredicateContext* tail = lastNode->next_;
|
||||||
if (tail != nullptr && tail->failure_ != nullptr) {
|
if (tail != JSONCPP_NULL && tail->failure_ != JSONCPP_NULL) {
|
||||||
messageTarget_ = tail->failure_;
|
messageTarget_ = tail->failure_;
|
||||||
}
|
}
|
||||||
// Remove tail from list
|
// Remove tail from list
|
||||||
predicateStackTail_ = lastNode;
|
predicateStackTail_ = lastNode;
|
||||||
lastNode->next_ = nullptr;
|
lastNode->next_ = JSONCPP_NULL;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +149,9 @@ void TestResult::printFailure(bool printTestName) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Print in reverse to display the callstack in the right order
|
// Print in reverse to display the callstack in the right order
|
||||||
for (const auto& failure : failures_) {
|
for (Failures::const_iterator it = failures_.begin(); it != failures_.end();
|
||||||
|
++it) {
|
||||||
|
const Failure& failure = *it;
|
||||||
Json::String indent(failure.nestingLevel_ * 2, ' ');
|
Json::String indent(failure.nestingLevel_ * 2, ' ');
|
||||||
if (failure.file_) {
|
if (failure.file_) {
|
||||||
printf("%s%s(%u): ", indent.c_str(), failure.file_, failure.line_);
|
printf("%s%s(%u): ", indent.c_str(), failure.file_, failure.line_);
|
||||||
@ -181,7 +185,7 @@ Json::String TestResult::indentText(const Json::String& text,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestResult& TestResult::addToLastFailure(const Json::String& message) {
|
TestResult& TestResult::addToLastFailure(const Json::String& message) {
|
||||||
if (messageTarget_ != nullptr) {
|
if (messageTarget_ != JSONCPP_NULL) {
|
||||||
messageTarget_->message_ += message;
|
messageTarget_->message_ += message;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@ -202,9 +206,9 @@ TestResult& TestResult::operator<<(bool value) {
|
|||||||
// class TestCase
|
// class TestCase
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TestCase::TestCase() = default;
|
TestCase::TestCase() : result_(JSONCPP_NULL) {}
|
||||||
|
|
||||||
TestCase::~TestCase() = default;
|
TestCase::~TestCase() {}
|
||||||
|
|
||||||
void TestCase::run(TestResult& result) {
|
void TestCase::run(TestResult& result) {
|
||||||
result_ = &result;
|
result_ = &result;
|
||||||
@ -214,7 +218,7 @@ void TestCase::run(TestResult& result) {
|
|||||||
// class Runner
|
// class Runner
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Runner::Runner() = default;
|
Runner::Runner() {}
|
||||||
|
|
||||||
Runner& Runner::add(TestCaseFactory factory) {
|
Runner& Runner::add(TestCaseFactory factory) {
|
||||||
tests_.push_back(factory);
|
tests_.push_back(factory);
|
||||||
@ -268,7 +272,8 @@ bool Runner::runAllTest(bool printSummary) const {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (auto& result : failures) {
|
for (size_t index = 0; index < failures.size(); ++index) {
|
||||||
|
TestResult& result = failures[index];
|
||||||
result.printFailure(count > 1);
|
result.printFailure(count > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
/// Must be a POD to allow inline initialisation without stepping
|
/// Must be a POD to allow inline initialisation without stepping
|
||||||
/// into the debugger.
|
/// into the debugger.
|
||||||
struct PredicateContext {
|
struct PredicateContext {
|
||||||
using Id = unsigned int;
|
typedef unsigned int Id;
|
||||||
Id id_;
|
Id id_;
|
||||||
const char* file_;
|
const char* file_;
|
||||||
unsigned int line_;
|
unsigned int line_;
|
||||||
@ -61,7 +61,7 @@ public:
|
|||||||
/// Not encapsulated to prevent step into when debugging failed assertions
|
/// Not encapsulated to prevent step into when debugging failed assertions
|
||||||
/// Incremented by one on assertion predicate entry, decreased by one
|
/// Incremented by one on assertion predicate entry, decreased by one
|
||||||
/// by addPredicateContext().
|
/// by addPredicateContext().
|
||||||
PredicateContext::Id predicateId_{1};
|
PredicateContext::Id predicateId_;
|
||||||
|
|
||||||
/// \internal Implementation detail for predicate macros
|
/// \internal Implementation detail for predicate macros
|
||||||
PredicateContext* predicateStackTail_;
|
PredicateContext* predicateStackTail_;
|
||||||
@ -70,7 +70,7 @@ public:
|
|||||||
|
|
||||||
/// Adds an assertion failure.
|
/// Adds an assertion failure.
|
||||||
TestResult& addFailure(const char* file, unsigned int line,
|
TestResult& addFailure(const char* file, unsigned int line,
|
||||||
const char* expr = nullptr);
|
const char* expr = JSONCPP_NULL);
|
||||||
|
|
||||||
/// Removes the last PredicateContext added to the predicate stack
|
/// Removes the last PredicateContext added to the predicate stack
|
||||||
/// chained list.
|
/// chained list.
|
||||||
@ -84,7 +84,9 @@ public:
|
|||||||
// Generic operator that will work with anything ostream can deal with.
|
// Generic operator that will work with anything ostream can deal with.
|
||||||
template <typename T> TestResult& operator<<(const T& value) {
|
template <typename T> TestResult& operator<<(const T& value) {
|
||||||
Json::OStringStream oss;
|
Json::OStringStream oss;
|
||||||
oss << std::setprecision(16) << std::hexfloat << value;
|
oss.precision(16);
|
||||||
|
oss.setf(std::ios_base::floatfield);
|
||||||
|
oss << value;
|
||||||
return addToLastFailure(oss.str());
|
return addToLastFailure(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,13 +104,13 @@ private:
|
|||||||
static Json::String indentText(const Json::String& text,
|
static Json::String indentText(const Json::String& text,
|
||||||
const Json::String& indent);
|
const Json::String& indent);
|
||||||
|
|
||||||
using Failures = std::deque<Failure>;
|
typedef std::deque<Failure> Failures;
|
||||||
Failures failures_;
|
Failures failures_;
|
||||||
Json::String name_;
|
Json::String name_;
|
||||||
PredicateContext rootPredicateNode_;
|
PredicateContext rootPredicateNode_;
|
||||||
PredicateContext::Id lastUsedPredicateId_{0};
|
PredicateContext::Id lastUsedPredicateId_;
|
||||||
/// Failure which is the target of the messages added using operator <<
|
/// Failure which is the target of the messages added using operator <<
|
||||||
Failure* messageTarget_{nullptr};
|
Failure* messageTarget_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestCase {
|
class TestCase {
|
||||||
@ -122,14 +124,14 @@ public:
|
|||||||
virtual const char* testName() const = 0;
|
virtual const char* testName() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TestResult* result_{nullptr};
|
TestResult* result_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void runTestCase() = 0;
|
virtual void runTestCase() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Function pointer type for TestCase factory
|
/// Function pointer type for TestCase factory
|
||||||
using TestCaseFactory = TestCase* (*)();
|
typedef TestCase* (*TestCaseFactory)();
|
||||||
|
|
||||||
class Runner {
|
class Runner {
|
||||||
public:
|
public:
|
||||||
@ -159,8 +161,8 @@ public:
|
|||||||
static void printUsage(const char* appName);
|
static void printUsage(const char* appName);
|
||||||
|
|
||||||
private: // prevents copy construction and assignment
|
private: // prevents copy construction and assignment
|
||||||
Runner(const Runner& other) = delete;
|
Runner(const Runner& other) JSONCPP_CTOR_DELETE;
|
||||||
Runner& operator=(const Runner& other) = delete;
|
Runner& operator=(const Runner& other) JSONCPP_CTOR_DELETE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void listTests() const;
|
void listTests() const;
|
||||||
@ -168,7 +170,7 @@ private:
|
|||||||
static void preventDialogOnCrash();
|
static void preventDialogOnCrash();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Factories = std::deque<TestCaseFactory>;
|
typedef std::deque<TestCaseFactory> Factories;
|
||||||
Factories tests_;
|
Factories tests_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -251,8 +253,10 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
public: /* overridden from TestCase */ \
|
public: /* overridden from TestCase */ \
|
||||||
const char* testName() const override { return #FixtureType "/" #name; } \
|
const char* testName() const JSONCPP_OVERRIDE { \
|
||||||
void runTestCase() override; \
|
return #FixtureType "/" #name; \
|
||||||
|
} \
|
||||||
|
void runTestCase() JSONCPP_OVERRIDE; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
void Test##FixtureType##name::runTestCase()
|
void Test##FixtureType##name::runTestCase()
|
||||||
@ -276,8 +280,10 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
public: /* overridden from TestCase */ \
|
public: /* overridden from TestCase */ \
|
||||||
const char* testName() const override { return #FixtureType "/" #name; } \
|
const char* testName() const JSONCPP_OVERRIDE { \
|
||||||
void runTestCase() override; \
|
return #FixtureType "/" #name; \
|
||||||
|
} \
|
||||||
|
void runTestCase() JSONCPP_OVERRIDE; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
static bool test##FixtureType##name##collect = \
|
static bool test##FixtureType##name##collect = \
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using CharReaderPtr = std::unique_ptr<Json::CharReader>;
|
typedef Json::CharReader* CharReaderPtr;
|
||||||
|
|
||||||
// Make numeric limits more convenient to talk about.
|
// Make numeric limits more convenient to talk about.
|
||||||
// Assumes int type in 32 bits.
|
// Assumes int type in 32 bits.
|
||||||
@ -65,22 +65,27 @@ static std::deque<JsonTest::TestCaseFactory> local_;
|
|||||||
|
|
||||||
struct ValueTest : JsonTest::TestCase {
|
struct ValueTest : JsonTest::TestCase {
|
||||||
Json::Value null_;
|
Json::Value null_;
|
||||||
Json::Value emptyArray_{Json::arrayValue};
|
Json::Value emptyArray_;
|
||||||
Json::Value emptyObject_{Json::objectValue};
|
Json::Value emptyObject_;
|
||||||
Json::Value integer_{123456789};
|
Json::Value integer_;
|
||||||
Json::Value unsignedInteger_{34567890};
|
Json::Value unsignedInteger_;
|
||||||
Json::Value smallUnsignedInteger_{Json::Value::UInt(Json::Value::maxInt)};
|
Json::Value smallUnsignedInteger_;
|
||||||
Json::Value real_{1234.56789};
|
Json::Value real_;
|
||||||
Json::Value float_{0.00390625f};
|
Json::Value float_;
|
||||||
Json::Value array1_;
|
Json::Value array1_;
|
||||||
Json::Value object1_;
|
Json::Value object1_;
|
||||||
Json::Value emptyString_{""};
|
Json::Value emptyString_;
|
||||||
Json::Value string1_{"a"};
|
Json::Value string1_;
|
||||||
Json::Value string_{"sometext with space"};
|
Json::Value string_;
|
||||||
Json::Value true_{true};
|
Json::Value true_;
|
||||||
Json::Value false_{false};
|
Json::Value false_;
|
||||||
|
|
||||||
ValueTest() {
|
ValueTest()
|
||||||
|
: emptyArray_(Json::arrayValue), emptyObject_(Json::objectValue),
|
||||||
|
integer_(123456789), unsignedInteger_(34567890u),
|
||||||
|
smallUnsignedInteger_(Json::Value::UInt(Json::Value::maxInt)),
|
||||||
|
real_(1234.56789), float_(0.00390625f), emptyString_(""), string1_("a"),
|
||||||
|
string_("sometext with space"), true_(true), false_(false) {
|
||||||
array1_.append(1234);
|
array1_.append(1234);
|
||||||
object1_["id"] = 1234;
|
object1_["id"] = 1234;
|
||||||
}
|
}
|
||||||
@ -89,19 +94,19 @@ struct ValueTest : JsonTest::TestCase {
|
|||||||
/// Initialize all checks to \c false by default.
|
/// Initialize all checks to \c false by default.
|
||||||
IsCheck();
|
IsCheck();
|
||||||
|
|
||||||
bool isObject_{false};
|
bool isObject_;
|
||||||
bool isArray_{false};
|
bool isArray_;
|
||||||
bool isBool_{false};
|
bool isBool_;
|
||||||
bool isString_{false};
|
bool isString_;
|
||||||
bool isNull_{false};
|
bool isNull_;
|
||||||
|
|
||||||
bool isInt_{false};
|
bool isInt_;
|
||||||
bool isInt64_{false};
|
bool isInt64_;
|
||||||
bool isUInt_{false};
|
bool isUInt_;
|
||||||
bool isUInt64_{false};
|
bool isUInt64_;
|
||||||
bool isIntegral_{false};
|
bool isIntegral_;
|
||||||
bool isDouble_{false};
|
bool isDouble_;
|
||||||
bool isNumeric_{false};
|
bool isNumeric_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void checkConstMemberCount(const Json::Value& value,
|
void checkConstMemberCount(const Json::Value& value,
|
||||||
@ -121,13 +126,14 @@ struct ValueTest : JsonTest::TestCase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Json::String ValueTest::normalizeFloatingPointStr(const Json::String& s) {
|
Json::String ValueTest::normalizeFloatingPointStr(const Json::String& s) {
|
||||||
auto index = s.find_last_of("eE");
|
std::string::size_type index = s.find_last_of("eE");
|
||||||
if (index == s.npos)
|
if (index == s.npos)
|
||||||
return s;
|
return s;
|
||||||
std::size_t signWidth = (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
|
std::size_t signWidth = (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
|
||||||
auto exponentStartIndex = index + 1 + signWidth;
|
std::string::size_type exponentStartIndex = index + 1 + signWidth;
|
||||||
Json::String normalized = s.substr(0, exponentStartIndex);
|
Json::String normalized = s.substr(0, exponentStartIndex);
|
||||||
auto indexDigit = s.find_first_not_of('0', exponentStartIndex);
|
std::string::size_type indexDigit =
|
||||||
|
s.find_first_not_of('0', exponentStartIndex);
|
||||||
Json::String exponent = "0";
|
Json::String exponent = "0";
|
||||||
if (indexDigit != s.npos) { // nonzero exponent
|
if (indexDigit != s.npos) { // nonzero exponent
|
||||||
exponent = s.substr(indexDigit);
|
exponent = s.substr(indexDigit);
|
||||||
@ -157,7 +163,9 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, checkNormalizeFloatingPointStr) {
|
|||||||
{"1234e+100", "1234e+100"},
|
{"1234e+100", "1234e+100"},
|
||||||
{"1234e-100", "1234e-100"},
|
{"1234e-100", "1234e-100"},
|
||||||
};
|
};
|
||||||
for (const auto& td : testData) {
|
for (unsigned int index = 0; index < sizeof(testData) / sizeof(testData[0]);
|
||||||
|
++index) {
|
||||||
|
const struct TestData td = testData[index];
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(normalizeFloatingPointStr(td.in), td.out);
|
JSONTEST_ASSERT_STRING_EQUAL(normalizeFloatingPointStr(td.in), td.out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,22 +223,22 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, objects) {
|
|||||||
// Access through find()
|
// Access through find()
|
||||||
const char idKey[] = "id";
|
const char idKey[] = "id";
|
||||||
const Json::Value* foundId = object1_.find(idKey, idKey + strlen(idKey));
|
const Json::Value* foundId = object1_.find(idKey, idKey + strlen(idKey));
|
||||||
JSONTEST_ASSERT(foundId != nullptr);
|
JSONTEST_ASSERT(foundId != JSONCPP_NULL);
|
||||||
JSONTEST_ASSERT_EQUAL(Json::Value(1234), *foundId);
|
JSONTEST_ASSERT_EQUAL(Json::Value(1234), *foundId);
|
||||||
|
|
||||||
const char unknownIdKey[] = "unknown id";
|
const char unknownIdKey[] = "unknown id";
|
||||||
const Json::Value* foundUnknownId =
|
const Json::Value* foundUnknownId =
|
||||||
object1_.find(unknownIdKey, unknownIdKey + strlen(unknownIdKey));
|
object1_.find(unknownIdKey, unknownIdKey + strlen(unknownIdKey));
|
||||||
JSONTEST_ASSERT_EQUAL(nullptr, foundUnknownId);
|
JSONTEST_ASSERT(JSONCPP_NULL == foundUnknownId);
|
||||||
|
|
||||||
// Access through demand()
|
// Access through demand()
|
||||||
const char yetAnotherIdKey[] = "yet another id";
|
const char yetAnotherIdKey[] = "yet another id";
|
||||||
const Json::Value* foundYetAnotherId =
|
const Json::Value* foundYetAnotherId =
|
||||||
object1_.find(yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
|
object1_.find(yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
|
||||||
JSONTEST_ASSERT_EQUAL(nullptr, foundYetAnotherId);
|
JSONTEST_ASSERT(JSONCPP_NULL == foundYetAnotherId);
|
||||||
Json::Value* demandedYetAnotherId = object1_.demand(
|
Json::Value* demandedYetAnotherId = object1_.demand(
|
||||||
yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
|
yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
|
||||||
JSONTEST_ASSERT(demandedYetAnotherId != nullptr);
|
JSONTEST_ASSERT(demandedYetAnotherId != JSONCPP_NULL);
|
||||||
*demandedYetAnotherId = "baz";
|
*demandedYetAnotherId = "baz";
|
||||||
|
|
||||||
JSONTEST_ASSERT_EQUAL(Json::Value("baz"), object1_["yet another id"]);
|
JSONTEST_ASSERT_EQUAL(Json::Value("baz"), object1_["yet another id"]);
|
||||||
@ -255,9 +263,9 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, objects) {
|
|||||||
JSONTEST_ASSERT_EQUAL(false, did);
|
JSONTEST_ASSERT_EQUAL(false, did);
|
||||||
|
|
||||||
object1_["some other id"] = "foo";
|
object1_["some other id"] = "foo";
|
||||||
Json::Value* gotPtr = nullptr;
|
Json::Value* gotPtr = JSONCPP_NULL;
|
||||||
did = object1_.removeMember("some other id", gotPtr);
|
did = object1_.removeMember("some other id", gotPtr);
|
||||||
JSONTEST_ASSERT_EQUAL(nullptr, gotPtr);
|
JSONTEST_ASSERT(JSONCPP_NULL == gotPtr);
|
||||||
JSONTEST_ASSERT_EQUAL(true, did);
|
JSONTEST_ASSERT_EQUAL(true, did);
|
||||||
|
|
||||||
// Using other removeMember interfaces, the test idea is the same as above.
|
// Using other removeMember interfaces, the test idea is the same as above.
|
||||||
@ -1182,7 +1190,7 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, integers) {
|
|||||||
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// 10^19
|
// 10^19
|
||||||
const auto ten_to_19 = static_cast<Json::UInt64>(1e19);
|
const Json::UInt64 ten_to_19 = static_cast<Json::UInt64>(1e19);
|
||||||
val = Json::Value(Json::UInt64(ten_to_19));
|
val = Json::Value(Json::UInt64(ten_to_19));
|
||||||
|
|
||||||
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
|
JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
|
||||||
@ -1476,7 +1484,11 @@ void ValueTest::checkMemberCount(Json::Value& value,
|
|||||||
JSONTEST_ASSERT_PRED(checkConstMemberCount(value, expectedCount));
|
JSONTEST_ASSERT_PRED(checkConstMemberCount(value, expectedCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueTest::IsCheck::IsCheck() = default;
|
ValueTest::IsCheck::IsCheck()
|
||||||
|
: isObject_(false), isArray_(false), isBool_(false), isString_(false),
|
||||||
|
isNull_(false), isInt_(false), isInt64_(false), isUInt_(false),
|
||||||
|
isUInt64_(false), isIntegral_(false), isDouble_(false),
|
||||||
|
isNumeric_(false) {}
|
||||||
|
|
||||||
void ValueTest::checkIs(const Json::Value& value, const IsCheck& check) {
|
void ValueTest::checkIs(const Json::Value& value, const IsCheck& check) {
|
||||||
JSONTEST_ASSERT_EQUAL(check.isObject_, value.isObject());
|
JSONTEST_ASSERT_EQUAL(check.isObject_, value.isObject());
|
||||||
@ -1661,19 +1673,19 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, CopyObject) {
|
|||||||
Json::Value srcObject, objectCopy, otherObject;
|
Json::Value srcObject, objectCopy, otherObject;
|
||||||
srcObject["key0"] = 10;
|
srcObject["key0"] = 10;
|
||||||
objectCopy.copy(srcObject);
|
objectCopy.copy(srcObject);
|
||||||
JSONTEST_ASSERT(srcObject["key0"] == 10);
|
JSONTEST_ASSERT(srcObject["key0"].asInt() == 10);
|
||||||
JSONTEST_ASSERT(objectCopy["key0"] == 10);
|
JSONTEST_ASSERT(objectCopy["key0"].asInt() == 10);
|
||||||
JSONTEST_ASSERT(srcObject.getMemberNames().size() == 1);
|
JSONTEST_ASSERT(srcObject.getMemberNames().size() == 1);
|
||||||
JSONTEST_ASSERT(objectCopy.getMemberNames().size() == 1);
|
JSONTEST_ASSERT(objectCopy.getMemberNames().size() == 1);
|
||||||
otherObject["key1"] = 15;
|
otherObject["key1"] = 15;
|
||||||
otherObject["key2"] = 16;
|
otherObject["key2"] = 16;
|
||||||
JSONTEST_ASSERT(otherObject.getMemberNames().size() == 2);
|
JSONTEST_ASSERT(otherObject.getMemberNames().size() == 2);
|
||||||
objectCopy.copy(otherObject);
|
objectCopy.copy(otherObject);
|
||||||
JSONTEST_ASSERT(objectCopy["key1"] == 15);
|
JSONTEST_ASSERT(objectCopy["key1"].asInt() == 15);
|
||||||
JSONTEST_ASSERT(objectCopy["key2"] == 16);
|
JSONTEST_ASSERT(objectCopy["key2"].asInt() == 16);
|
||||||
JSONTEST_ASSERT(objectCopy.getMemberNames().size() == 2);
|
JSONTEST_ASSERT(objectCopy.getMemberNames().size() == 2);
|
||||||
otherObject["key1"] = 20;
|
otherObject["key1"] = 20;
|
||||||
JSONTEST_ASSERT(objectCopy["key1"] == 15);
|
JSONTEST_ASSERT(objectCopy["key1"].asInt() == 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1817,7 +1829,7 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, StaticString) {
|
|||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ValueTest, WideString) {
|
JSONTEST_FIXTURE_LOCAL(ValueTest, WideString) {
|
||||||
// https://github.com/open-source-parsers/jsoncpp/issues/756
|
// https://github.com/open-source-parsers/jsoncpp/issues/756
|
||||||
const std::string uni = u8"\u5f0f\uff0c\u8fdb"; // "式,进"
|
const std::string uni = "\u5f0f\uff0c\u8fdb"; // "式,进"
|
||||||
std::string styled;
|
std::string styled;
|
||||||
{
|
{
|
||||||
Json::Value v;
|
Json::Value v;
|
||||||
@ -2592,7 +2604,7 @@ JSONTEST_FIXTURE_LOCAL(StreamWriterTest, indentation) {
|
|||||||
JSONTEST_FIXTURE_LOCAL(StreamWriterTest, writeZeroes) {
|
JSONTEST_FIXTURE_LOCAL(StreamWriterTest, writeZeroes) {
|
||||||
Json::String binary("hi", 3); // include trailing 0
|
Json::String binary("hi", 3); // include trailing 0
|
||||||
JSONTEST_ASSERT_EQUAL(3, binary.length());
|
JSONTEST_ASSERT_EQUAL(3, binary.length());
|
||||||
Json::String expected(R"("hi\u0000")"); // unicoded zero
|
Json::String expected("\"hi\\u0000\""); // unicoded zero
|
||||||
Json::StreamWriterBuilder b;
|
Json::StreamWriterBuilder b;
|
||||||
{
|
{
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
@ -2639,7 +2651,7 @@ JSONTEST_FIXTURE_LOCAL(StreamWriterTest, unicode) {
|
|||||||
"{\n\t\"test\" : "
|
"{\n\t\"test\" : "
|
||||||
"\"\\t\\n\\ud806\\udca1=\\u0133\\ud82c\\udd1b\\uff67\"\n}");
|
"\"\\t\\n\\ud806\\udca1=\\u0133\\ud82c\\udd1b\\uff67\"\n}");
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
struct ReaderTest : JsonTest::TestCase {
|
struct ReaderTest : JsonTest::TestCase {
|
||||||
void setStrictMode() {
|
void setStrictMode() {
|
||||||
reader = std::unique_ptr<Json::Reader>(
|
reader = std::unique_ptr<Json::Reader>(
|
||||||
@ -2688,43 +2700,43 @@ struct ReaderTest : JsonTest::TestCase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithNoErrors) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithNoErrors) {
|
||||||
checkParse(R"({ "property" : "value" })");
|
checkParse("{ \"property\" : \"value\" }");
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseObject) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseObject) {
|
||||||
checkParse(R"({"property"})",
|
checkParse("{\"property\"}",
|
||||||
{{11, 12, "Missing ':' after object member name"}},
|
{{11, 12, "Missing ':' after object member name"}},
|
||||||
"* Line 1, Column 12\n Missing ':' after object member name\n");
|
"* Line 1, Column 12\n Missing ':' after object member name\n");
|
||||||
checkParse(
|
checkParse(
|
||||||
R"({"property" : "value" )",
|
"{\"property\" : \"value\" ",
|
||||||
{{22, 22, "Missing ',' or '}' in object declaration"}},
|
{{22, 22, "Missing ',' or '}' in object declaration"}},
|
||||||
"* Line 1, Column 23\n Missing ',' or '}' in object declaration\n");
|
"* Line 1, Column 23\n Missing ',' or '}' in object declaration\n");
|
||||||
checkParse(R"({"property" : "value", )",
|
checkParse("{\"property\" : \"value\", ",
|
||||||
{{23, 23, "Missing '}' or object member name"}},
|
{{23, 23, "Missing '}' or object member name"}},
|
||||||
"* Line 1, Column 24\n Missing '}' or object member name\n");
|
"* Line 1, Column 24\n Missing '}' or object member name\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseArray) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseArray) {
|
||||||
checkParse(
|
checkParse(
|
||||||
R"([ "value" )", {{10, 10, "Missing ',' or ']' in array declaration"}},
|
"[ \"value\" ", {{10, 10, "Missing ',' or ']' in array declaration"}},
|
||||||
"* Line 1, Column 11\n Missing ',' or ']' in array declaration\n");
|
"* Line 1, Column 11\n Missing ',' or ']' in array declaration\n");
|
||||||
checkParse(
|
checkParse(
|
||||||
R"([ "value1" "value2" ] )",
|
"[ \"value1\" \"value2\" ] ",
|
||||||
{{11, 19, "Missing ',' or ']' in array declaration"}},
|
{{11, 19, "Missing ',' or ']' in array declaration"}},
|
||||||
"* Line 1, Column 12\n Missing ',' or ']' in array declaration\n");
|
"* Line 1, Column 12\n Missing ',' or ']' in array declaration\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseString) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseString) {
|
||||||
checkParse(R"([ "\u8a2a" ])");
|
checkParse("[ \"\u8a2a\" ]");
|
||||||
checkParse(
|
checkParse(
|
||||||
R"([ "\ud801" ])",
|
"[ \"\\ud801\" ]",
|
||||||
{{2, 10,
|
{{2, 10,
|
||||||
"additional six characters expected to parse unicode surrogate "
|
"additional six characters expected to parse unicode surrogate "
|
||||||
"pair."}},
|
"pair."}},
|
||||||
"* Line 1, Column 3\n"
|
"* Line 1, Column 3\n"
|
||||||
" additional six characters expected to parse unicode surrogate pair.\n"
|
" additional six characters expected to parse unicode surrogate pair.\n"
|
||||||
"See Line 1, Column 10 for detail.\n");
|
"See Line 1, Column 10 for detail.\n");
|
||||||
checkParse(R"([ "\ud801\d1234" ])",
|
checkParse("[ \"\\ud801\\d1234\" ]",
|
||||||
{{2, 16,
|
{{2, 16,
|
||||||
"expecting another \\u token to begin the "
|
"expecting another \\u token to begin the "
|
||||||
"second half of a unicode surrogate pair"}},
|
"second half of a unicode surrogate pair"}},
|
||||||
@ -2732,7 +2744,7 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, parseString) {
|
|||||||
" expecting another \\u token to begin the "
|
" expecting another \\u token to begin the "
|
||||||
"second half of a unicode surrogate pair\n"
|
"second half of a unicode surrogate pair\n"
|
||||||
"See Line 1, Column 12 for detail.\n");
|
"See Line 1, Column 12 for detail.\n");
|
||||||
checkParse(R"([ "\ua3t@" ])",
|
checkParse("[ \"\\ua3t@\" ]",
|
||||||
{{2, 10,
|
{{2, 10,
|
||||||
"Bad unicode escape sequence in string: "
|
"Bad unicode escape sequence in string: "
|
||||||
"hexadecimal digit expected."}},
|
"hexadecimal digit expected."}},
|
||||||
@ -2741,7 +2753,7 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, parseString) {
|
|||||||
"hexadecimal digit expected.\n"
|
"hexadecimal digit expected.\n"
|
||||||
"See Line 1, Column 9 for detail.\n");
|
"See Line 1, Column 9 for detail.\n");
|
||||||
checkParse(
|
checkParse(
|
||||||
R"([ "\ua3t" ])",
|
"[ \"\\ua3t\" ]",
|
||||||
{{2, 9, "Bad unicode escape sequence in string: four digits expected."}},
|
{{2, 9, "Bad unicode escape sequence in string: four digits expected."}},
|
||||||
"* Line 1, Column 3\n"
|
"* Line 1, Column 3\n"
|
||||||
" Bad unicode escape sequence in string: four digits expected.\n"
|
" Bad unicode escape sequence in string: four digits expected.\n"
|
||||||
@ -2750,29 +2762,29 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, parseString) {
|
|||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseComment) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseComment) {
|
||||||
checkParse(
|
checkParse(
|
||||||
R"({ /*commentBeforeValue*/ "property" : "value" }//commentAfterValue)"
|
"{ /*commentBeforeValue*/ \"property\" : \"value\" }//commentAfterValue"
|
||||||
"\n");
|
"\n");
|
||||||
checkParse(" true //comment1\n//comment2\r//comment3\r\n");
|
checkParse(" true //comment1\n//comment2\r//comment3\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, streamParseWithNoErrors) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, streamParseWithNoErrors) {
|
||||||
std::string styled = R"({ "property" : "value" })";
|
std::string styled = "{ \"property\" : \"value\" }";
|
||||||
std::istringstream iss(styled);
|
std::istringstream iss(styled);
|
||||||
checkParse(iss);
|
checkParse(iss);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithNoErrorsTestingOffsets) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithNoErrorsTestingOffsets) {
|
||||||
checkParse(R"({)"
|
checkParse("{"
|
||||||
R"( "property" : ["value", "value2"],)"
|
" \"property\" : [\"value\", \"value2\"],"
|
||||||
R"( "obj" : { "nested" : -6.2e+15, "bool" : true},)"
|
" \"obj\" : { \"nested\" : -6.2e+15, \"bool\" : true},"
|
||||||
R"( "null" : null,)"
|
" \"null\" : null,"
|
||||||
R"( "false" : false)"
|
" \"false\" : false"
|
||||||
R"( })");
|
"}");
|
||||||
auto checkOffsets = [&](const Json::Value& v, int start, int limit) {
|
auto checkOffsets = [&](const Json::Value& v, int start, int limit) {
|
||||||
JSONTEST_ASSERT_EQUAL(start, v.getOffsetStart());
|
JSONTEST_ASSERT_EQUAL(start, v.getOffsetStart());
|
||||||
JSONTEST_ASSERT_EQUAL(limit, v.getOffsetLimit());
|
JSONTEST_ASSERT_EQUAL(limit, v.getOffsetLimit());
|
||||||
};
|
};
|
||||||
checkOffsets(root, 0, 115);
|
checkOffsets(root, 0, 114);
|
||||||
checkOffsets(root["property"], 15, 34);
|
checkOffsets(root["property"], 15, 34);
|
||||||
checkOffsets(root["property"][0], 16, 23);
|
checkOffsets(root["property"][0], 16, 23);
|
||||||
checkOffsets(root["property"][1], 25, 33);
|
checkOffsets(root["property"][1], 25, 33);
|
||||||
@ -2784,7 +2796,7 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithNoErrorsTestingOffsets) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithOneError) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithOneError) {
|
||||||
checkParse(R"({ "property" :: "value" })",
|
checkParse("{ \"property\" :: \"value\" }",
|
||||||
{{14, 15, "Syntax error: value, object or array expected."}},
|
{{14, 15, "Syntax error: value, object or array expected."}},
|
||||||
"* Line 1, Column 15\n Syntax error: value, object or array "
|
"* Line 1, Column 15\n Syntax error: value, object or array "
|
||||||
"expected.\n");
|
"expected.\n");
|
||||||
@ -2794,11 +2806,11 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithOneError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseSpecialFloat) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseSpecialFloat) {
|
||||||
checkParse(R"({ "a" : Infi })",
|
checkParse("{ \"a\" : Infi }",
|
||||||
{{8, 9, "Syntax error: value, object or array expected."}},
|
{{8, 9, "Syntax error: value, object or array expected."}},
|
||||||
"* Line 1, Column 9\n Syntax error: value, object or array "
|
"* Line 1, Column 9\n Syntax error: value, object or array "
|
||||||
"expected.\n");
|
"expected.\n");
|
||||||
checkParse(R"({ "a" : Infiniaa })",
|
checkParse("{ \"a\" : Infiniaa }",
|
||||||
{{8, 9, "Syntax error: value, object or array expected."}},
|
{{8, 9, "Syntax error: value, object or array expected."}},
|
||||||
"* Line 1, Column 9\n Syntax error: value, object or array "
|
"* Line 1, Column 9\n Syntax error: value, object or array "
|
||||||
"expected.\n");
|
"expected.\n");
|
||||||
@ -2815,16 +2827,20 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, strictModeParseNumber) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseChineseWithOneError) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseChineseWithOneError) {
|
||||||
checkParse(R"({ "pr)"
|
checkParse("{ \"pr"
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
u8"\u4f50\u85e4" // 佐藤
|
u8"\u4f50\u85e4" // 佐藤
|
||||||
R"(erty" :: "value" })",
|
#else
|
||||||
|
"\u4f50\u85e4" // 佐藤
|
||||||
|
#endif
|
||||||
|
"erty\" :: \"value\" }",
|
||||||
{{18, 19, "Syntax error: value, object or array expected."}},
|
{{18, 19, "Syntax error: value, object or array expected."}},
|
||||||
"* Line 1, Column 19\n Syntax error: value, object or array "
|
"* Line 1, Column 19\n Syntax error: value, object or array "
|
||||||
"expected.\n");
|
"expected.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithDetailError) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithDetailError) {
|
||||||
checkParse(R"({ "property" : "v\alue" })",
|
checkParse("{ \"property\" : \"v\\alue\" }",
|
||||||
{{15, 23, "Bad escape sequence in string"}},
|
{{15, 23, "Bad escape sequence in string"}},
|
||||||
"* Line 1, Column 16\n"
|
"* Line 1, Column 16\n"
|
||||||
" Bad escape sequence in string\n"
|
" Bad escape sequence in string\n"
|
||||||
@ -2832,7 +2848,7 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithDetailError) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(ReaderTest, pushErrorTest) {
|
JSONTEST_FIXTURE_LOCAL(ReaderTest, pushErrorTest) {
|
||||||
checkParse(R"({ "AUTHOR" : 123 })");
|
checkParse("{ \"AUTHOR\" : 123 }");
|
||||||
if (!root["AUTHOR"].isString()) {
|
if (!root["AUTHOR"].isString()) {
|
||||||
JSONTEST_ASSERT(
|
JSONTEST_ASSERT(
|
||||||
reader->pushError(root["AUTHOR"], "AUTHOR must be a string"));
|
reader->pushError(root["AUTHOR"], "AUTHOR must be a string"));
|
||||||
@ -2841,7 +2857,7 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, pushErrorTest) {
|
|||||||
"* Line 1, Column 14\n"
|
"* Line 1, Column 14\n"
|
||||||
" AUTHOR must be a string\n");
|
" AUTHOR must be a string\n");
|
||||||
|
|
||||||
checkParse(R"({ "AUTHOR" : 123 })");
|
checkParse("{ \"AUTHOR\" : 123 }");
|
||||||
if (!root["AUTHOR"].isString()) {
|
if (!root["AUTHOR"].isString()) {
|
||||||
JSONTEST_ASSERT(reader->pushError(root["AUTHOR"], "AUTHOR must be a string",
|
JSONTEST_ASSERT(reader->pushError(root["AUTHOR"], "AUTHOR must be a string",
|
||||||
root["AUTHOR"]));
|
root["AUTHOR"]));
|
||||||
@ -2856,9 +2872,9 @@ JSONTEST_FIXTURE_LOCAL(ReaderTest, allowNumericKeysTest) {
|
|||||||
Json::Features features;
|
Json::Features features;
|
||||||
features.allowNumericKeys_ = true;
|
features.allowNumericKeys_ = true;
|
||||||
setFeatures(features);
|
setFeatures(features);
|
||||||
checkParse(R"({ 123 : "abc" })");
|
checkParse("{ 123 : \"abc\" }");
|
||||||
}
|
}
|
||||||
|
#endif // JSONCPP_CXX_STD_11
|
||||||
struct CharReaderTest : JsonTest::TestCase {};
|
struct CharReaderTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithNoErrors) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithNoErrors) {
|
||||||
@ -2866,10 +2882,11 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithNoErrors) {
|
|||||||
CharReaderPtr reader(b.newCharReader());
|
CharReaderPtr reader(b.newCharReader());
|
||||||
Json::String errs;
|
Json::String errs;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] = R"({ "property" : "value" })";
|
char const doc[] = "{ \"property\" : \"value\" }";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT(errs.empty());
|
JSONTEST_ASSERT(errs.empty());
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithNoErrorsTestingOffsets) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithNoErrorsTestingOffsets) {
|
||||||
@ -2883,6 +2900,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithNoErrorsTestingOffsets) {
|
|||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT(errs.empty());
|
JSONTEST_ASSERT(errs.empty());
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseNumber) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseNumber) {
|
||||||
@ -2899,6 +2917,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseNumber) {
|
|||||||
JSONTEST_ASSERT(errs.empty());
|
JSONTEST_ASSERT(errs.empty());
|
||||||
JSONTEST_ASSERT_EQUAL(1.1111111111111111e+020, root[0]);
|
JSONTEST_ASSERT_EQUAL(1.1111111111111111e+020, root[0]);
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseString) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseString) {
|
||||||
@ -2914,14 +2933,18 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseString) {
|
|||||||
JSONTEST_ASSERT_EQUAL("", root[0]);
|
JSONTEST_ASSERT_EQUAL("", root[0]);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char const doc[] = R"(["\u8A2a"])";
|
char const doc[] = "[\"\\u8A2a\"]";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT(errs.empty());
|
JSONTEST_ASSERT(errs.empty());
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
JSONTEST_ASSERT_EQUAL(u8"\u8A2a", root[0].asString()); // "訪"
|
JSONTEST_ASSERT_EQUAL(u8"\u8A2a", root[0].asString()); // "訪"
|
||||||
|
#else
|
||||||
|
JSONTEST_ASSERT_EQUAL("\u8A2a", root[0].asString()); // "訪"
|
||||||
|
#endif // JSONCPP_CXX_STD_11
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char const doc[] = R"([ "\uD801" ])";
|
char const doc[] = "[ \"\\uD801\" ]";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(errs == "* Line 1, Column 3\n"
|
JSONTEST_ASSERT(errs == "* Line 1, Column 3\n"
|
||||||
@ -2930,7 +2953,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseString) {
|
|||||||
"See Line 1, Column 10 for detail.\n");
|
"See Line 1, Column 10 for detail.\n");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char const doc[] = R"([ "\uD801\d1234" ])";
|
char const doc[] = "[ \"\\uD801\\d1234\" ]";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(errs == "* Line 1, Column 3\n"
|
JSONTEST_ASSERT(errs == "* Line 1, Column 3\n"
|
||||||
@ -2939,7 +2962,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseString) {
|
|||||||
"See Line 1, Column 12 for detail.\n");
|
"See Line 1, Column 12 for detail.\n");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char const doc[] = R"([ "\ua3t@" ])";
|
char const doc[] = "[ \"\\ua3t@\" ]";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(errs == "* Line 1, Column 3\n"
|
JSONTEST_ASSERT(errs == "* Line 1, Column 3\n"
|
||||||
@ -2948,7 +2971,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseString) {
|
|||||||
"See Line 1, Column 9 for detail.\n");
|
"See Line 1, Column 9 for detail.\n");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char const doc[] = R"([ "\ua3t" ])";
|
char const doc[] = "[ \"\\ua3t\" ]";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(
|
JSONTEST_ASSERT(
|
||||||
@ -2957,16 +2980,18 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseString) {
|
|||||||
" Bad unicode escape sequence in string: four digits expected.\n"
|
" Bad unicode escape sequence in string: four digits expected.\n"
|
||||||
"See Line 1, Column 6 for detail.\n");
|
"See Line 1, Column 6 for detail.\n");
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
{
|
{
|
||||||
b.settings_["allowSingleQuotes"] = true;
|
b.settings_["allowSingleQuotes"] = true;
|
||||||
CharReaderPtr charreader(b.newCharReader());
|
CharReaderPtr charReader(b.newCharReader());
|
||||||
char const doc[] = R"({'a': 'x\ty', "b":'x\\y'})";
|
char const doc[] = "{'a': 'x\\ty', \"b\":'x\\\\y'}";
|
||||||
bool ok = charreader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = charReader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
||||||
JSONTEST_ASSERT_EQUAL(2u, root.size());
|
JSONTEST_ASSERT_EQUAL(2u, root.size());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("x\ty", root["a"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("x\ty", root["a"].asString());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("x\\y", root["b"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("x\\y", root["b"].asString());
|
||||||
|
delete charReader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2999,6 +3024,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseComment) {
|
|||||||
JSONTEST_ASSERT_EQUAL("value", root[0]);
|
JSONTEST_ASSERT_EQUAL("value", root[0]);
|
||||||
JSONTEST_ASSERT_EQUAL(true, root[1]);
|
JSONTEST_ASSERT_EQUAL(true, root[1]);
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseObjectWithErrors) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseObjectWithErrors) {
|
||||||
@ -3007,7 +3033,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseObjectWithErrors) {
|
|||||||
Json::Value root;
|
Json::Value root;
|
||||||
Json::String errs;
|
Json::String errs;
|
||||||
{
|
{
|
||||||
char const doc[] = R"({ "property" : "value" )";
|
char const doc[] = "{ \"property\" : \"value\" ";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(errs == "* Line 1, Column 24\n"
|
JSONTEST_ASSERT(errs == "* Line 1, Column 24\n"
|
||||||
@ -3015,13 +3041,14 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseObjectWithErrors) {
|
|||||||
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char const doc[] = R"({ "property" : "value" ,)";
|
char const doc[] = "{ \"property\" : \"value\" ,";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(errs == "* Line 1, Column 25\n"
|
JSONTEST_ASSERT(errs == "* Line 1, Column 25\n"
|
||||||
" Missing '}' or object member name\n");
|
" Missing '}' or object member name\n");
|
||||||
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseArrayWithErrors) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseArrayWithErrors) {
|
||||||
@ -3038,13 +3065,14 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseArrayWithErrors) {
|
|||||||
JSONTEST_ASSERT_EQUAL("value", root[0]);
|
JSONTEST_ASSERT_EQUAL("value", root[0]);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
char const doc[] = R"([ "value1" "value2" ])";
|
char const doc[] = "[ \"value1\" \"value2\" ]";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(errs == "* Line 1, Column 12\n"
|
JSONTEST_ASSERT(errs == "* Line 1, Column 12\n"
|
||||||
" Missing ',' or ']' in array declaration\n");
|
" Missing ',' or ']' in array declaration\n");
|
||||||
JSONTEST_ASSERT_EQUAL("value1", root[0]);
|
JSONTEST_ASSERT_EQUAL("value1", root[0]);
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithOneError) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithOneError) {
|
||||||
@ -3052,12 +3080,13 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithOneError) {
|
|||||||
CharReaderPtr reader(b.newCharReader());
|
CharReaderPtr reader(b.newCharReader());
|
||||||
Json::String errs;
|
Json::String errs;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] = R"({ "property" :: "value" })";
|
char const doc[] = "{ \"property\" :: \"value\" }";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(errs ==
|
JSONTEST_ASSERT(errs ==
|
||||||
"* Line 1, Column 15\n Syntax error: value, object or array "
|
"* Line 1, Column 15\n Syntax error: value, object or array "
|
||||||
"expected.\n");
|
"expected.\n");
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseChineseWithOneError) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseChineseWithOneError) {
|
||||||
@ -3071,6 +3100,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseChineseWithOneError) {
|
|||||||
JSONTEST_ASSERT(errs ==
|
JSONTEST_ASSERT(errs ==
|
||||||
"* Line 1, Column 19\n Syntax error: value, object or array "
|
"* Line 1, Column 19\n Syntax error: value, object or array "
|
||||||
"expected.\n");
|
"expected.\n");
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithDetailError) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithDetailError) {
|
||||||
@ -3078,18 +3108,19 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithDetailError) {
|
|||||||
CharReaderPtr reader(b.newCharReader());
|
CharReaderPtr reader(b.newCharReader());
|
||||||
Json::String errs;
|
Json::String errs;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] = R"({ "property" : "v\alue" })";
|
char const doc[] = "{ \"property\" : \"v\\alue\" }";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(!ok);
|
JSONTEST_ASSERT(!ok);
|
||||||
JSONTEST_ASSERT(errs ==
|
JSONTEST_ASSERT(errs ==
|
||||||
"* Line 1, Column 16\n Bad escape sequence in string\nSee "
|
"* Line 1, Column 16\n Bad escape sequence in string\nSee "
|
||||||
"Line 1, Column 20 for detail.\n");
|
"Line 1, Column 20 for detail.\n");
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithStackLimit) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithStackLimit) {
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] = R"({ "property" : "value" })";
|
char const doc[] = "{ \"property\" : \"value\" }";
|
||||||
{
|
{
|
||||||
b.settings_["stackLimit"] = 2;
|
b.settings_["stackLimit"] = 2;
|
||||||
CharReaderPtr reader(b.newCharReader());
|
CharReaderPtr reader(b.newCharReader());
|
||||||
@ -3098,6 +3129,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithStackLimit) {
|
|||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT(errs.empty());
|
JSONTEST_ASSERT(errs.empty());
|
||||||
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
b.settings_["stackLimit"] = 1;
|
b.settings_["stackLimit"] = 1;
|
||||||
@ -3105,11 +3137,12 @@ JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithStackLimit) {
|
|||||||
Json::String errs;
|
Json::String errs;
|
||||||
JSONTEST_ASSERT_THROWS(
|
JSONTEST_ASSERT_THROWS(
|
||||||
reader->parse(doc, doc + std::strlen(doc), &root, &errs));
|
reader->parse(doc, doc + std::strlen(doc), &root, &errs));
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderTest, testOperator) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderTest, testOperator) {
|
||||||
const std::string styled = R"({ "property" : "value" })";
|
const std::string styled = "{ \"property\" : \"value\" }";
|
||||||
std::istringstream iss(styled);
|
std::istringstream iss(styled);
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
iss >> root;
|
iss >> root;
|
||||||
@ -3122,7 +3155,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderStrictModeTest, dupKeys) {
|
|||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] =
|
char const doc[] =
|
||||||
R"({ "property" : "value", "key" : "val1", "key" : "val2" })";
|
"{ \"property\" : \"value\", \"key\" : \"val1\", \"key\" : \"val2\" }";
|
||||||
{
|
{
|
||||||
b.strictMode(&b.settings_);
|
b.strictMode(&b.settings_);
|
||||||
CharReaderPtr reader(b.newCharReader());
|
CharReaderPtr reader(b.newCharReader());
|
||||||
@ -3133,6 +3166,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderStrictModeTest, dupKeys) {
|
|||||||
" Duplicate key: 'key'\n",
|
" Duplicate key: 'key'\n",
|
||||||
errs);
|
errs);
|
||||||
JSONTEST_ASSERT_EQUAL("val1", root["key"]); // so far
|
JSONTEST_ASSERT_EQUAL("val1", root["key"]); // so far
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
|
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
|
||||||
@ -3141,7 +3175,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, issue164) {
|
|||||||
// This is interpreted as a string value followed by a colon.
|
// This is interpreted as a string value followed by a colon.
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] = R"( "property" : "value" })";
|
char const doc[] = " \"property\" : \"value\" }";
|
||||||
{
|
{
|
||||||
b.settings_["failIfExtra"] = false;
|
b.settings_["failIfExtra"] = false;
|
||||||
CharReaderPtr reader(b.newCharReader());
|
CharReaderPtr reader(b.newCharReader());
|
||||||
@ -3150,6 +3184,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, issue164) {
|
|||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT(errs.empty());
|
JSONTEST_ASSERT(errs.empty());
|
||||||
JSONTEST_ASSERT_EQUAL("property", root);
|
JSONTEST_ASSERT_EQUAL("property", root);
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
b.settings_["failIfExtra"] = true;
|
b.settings_["failIfExtra"] = true;
|
||||||
@ -3161,6 +3196,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, issue164) {
|
|||||||
" Extra non-whitespace after JSON value.\n",
|
" Extra non-whitespace after JSON value.\n",
|
||||||
errs);
|
errs);
|
||||||
JSONTEST_ASSERT_EQUAL("property", root);
|
JSONTEST_ASSERT_EQUAL("property", root);
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
b.strictMode(&b.settings_);
|
b.strictMode(&b.settings_);
|
||||||
@ -3172,6 +3208,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, issue164) {
|
|||||||
" Extra non-whitespace after JSON value.\n",
|
" Extra non-whitespace after JSON value.\n",
|
||||||
errs);
|
errs);
|
||||||
JSONTEST_ASSERT_EQUAL("property", root);
|
JSONTEST_ASSERT_EQUAL("property", root);
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
b.strictMode(&b.settings_);
|
b.strictMode(&b.settings_);
|
||||||
@ -3185,6 +3222,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, issue164) {
|
|||||||
" A valid JSON document must be either an array or an object value.\n",
|
" A valid JSON document must be either an array or an object value.\n",
|
||||||
errs);
|
errs);
|
||||||
JSONTEST_ASSERT_EQUAL("property", root);
|
JSONTEST_ASSERT_EQUAL("property", root);
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3202,6 +3240,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, issue107) {
|
|||||||
" Extra non-whitespace after JSON value.\n",
|
" Extra non-whitespace after JSON value.\n",
|
||||||
errs);
|
errs);
|
||||||
JSONTEST_ASSERT_EQUAL(1, root.asInt());
|
JSONTEST_ASSERT_EQUAL(1, root.asInt());
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterObject) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterObject) {
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
@ -3215,6 +3254,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterObject) {
|
|||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
||||||
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
JSONTEST_ASSERT_EQUAL("value", root["property"]);
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterArray) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterArray) {
|
||||||
@ -3228,6 +3268,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterArray) {
|
|||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
||||||
JSONTEST_ASSERT_EQUAL("value", root[1u]);
|
JSONTEST_ASSERT_EQUAL("value", root[1u]);
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterBool) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterBool) {
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
@ -3240,6 +3281,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, commentAfterBool) {
|
|||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
||||||
JSONTEST_ASSERT_EQUAL(true, root.asBool());
|
JSONTEST_ASSERT_EQUAL(true, root.asBool());
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, parseComment) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, parseComment) {
|
||||||
@ -3273,11 +3315,12 @@ JSONTEST_FIXTURE_LOCAL(CharReaderFailIfExtraTest, parseComment) {
|
|||||||
errs);
|
errs);
|
||||||
JSONTEST_ASSERT_EQUAL(true, root.asBool());
|
JSONTEST_ASSERT_EQUAL(true, root.asBool());
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
struct CharReaderAllowDropNullTest : JsonTest::TestCase {
|
struct CharReaderAllowDropNullTest : JsonTest::TestCase {
|
||||||
using Value = Json::Value;
|
typedef Json::Value Value;
|
||||||
using ValueCheck = std::function<void(const Value&)>;
|
typedef std::function<void(const Value&)> ValueCheck;
|
||||||
|
|
||||||
Value nullValue = Value{Json::nullValue};
|
Value nullValue = Value{Json::nullValue};
|
||||||
Value emptyArray = Value{Json::arrayValue};
|
Value emptyArray = Value{Json::arrayValue};
|
||||||
@ -3303,19 +3346,19 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowDropNullTest, issue178) {
|
|||||||
ValueCheck onRoot;
|
ValueCheck onRoot;
|
||||||
};
|
};
|
||||||
const TestSpec specs[] = {
|
const TestSpec specs[] = {
|
||||||
{__LINE__, R"({"a":,"b":true})", 2, objGetAnd("a", checkEq(nullValue))},
|
{__LINE__, "{\"a\":,\"b\":true}", 2, objGetAnd("a", checkEq(nullValue))},
|
||||||
{__LINE__, R"({"a":,"b":true})", 2, objGetAnd("a", checkEq(nullValue))},
|
{__LINE__, "{\"a\":,\"b\":true}", 2, objGetAnd("a", checkEq(nullValue))},
|
||||||
{__LINE__, R"({"a":})", 1, objGetAnd("a", checkEq(nullValue))},
|
{__LINE__, "{\"a\":}", 1, objGetAnd("a", checkEq(nullValue))},
|
||||||
{__LINE__, "[]", 0, checkEq(emptyArray)},
|
{__LINE__, "[]", 0, checkEq(emptyArray)},
|
||||||
{__LINE__, "[null]", 1, nullptr},
|
{__LINE__, "[null]", 1, JSONCPP_NULL},
|
||||||
{__LINE__, "[,]", 2, nullptr},
|
{__LINE__, "[,]", 2, JSONCPP_NULL},
|
||||||
{__LINE__, "[,,,]", 4, nullptr},
|
{__LINE__, "[,,,]", 4, JSONCPP_NULL},
|
||||||
{__LINE__, "[null,]", 2, nullptr},
|
{__LINE__, "[null,]", 2, JSONCPP_NULL},
|
||||||
{__LINE__, "[,null]", 2, nullptr},
|
{__LINE__, "[,null]", 2, JSONCPP_NULL},
|
||||||
{__LINE__, "[,,]", 3, nullptr},
|
{__LINE__, "[,,]", 3, JSONCPP_NULL},
|
||||||
{__LINE__, "[null,,]", 3, nullptr},
|
{__LINE__, "[null,,]", 3, JSONCPP_NULL},
|
||||||
{__LINE__, "[,null,]", 3, nullptr},
|
{__LINE__, "[,null,]", 3, JSONCPP_NULL},
|
||||||
{__LINE__, "[,,null]", 3, nullptr},
|
{__LINE__, "[,,null]", 3, JSONCPP_NULL},
|
||||||
{__LINE__, "[[],,,]", 4, arrGetAnd(0, checkEq(emptyArray))},
|
{__LINE__, "[[],,,]", 4, arrGetAnd(0, checkEq(emptyArray))},
|
||||||
{__LINE__, "[,[],,]", 4, arrGetAnd(1, checkEq(emptyArray))},
|
{__LINE__, "[,[],,]", 4, arrGetAnd(1, checkEq(emptyArray))},
|
||||||
{__LINE__, "[,,,[]]", 4, arrGetAnd(3, checkEq(emptyArray))},
|
{__LINE__, "[,,,[]]", 4, arrGetAnd(3, checkEq(emptyArray))},
|
||||||
@ -3336,7 +3379,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowDropNullTest, issue178) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // JSONCPP_CXX_STD_11
|
||||||
struct CharReaderAllowNumericKeysTest : JsonTest::TestCase {};
|
struct CharReaderAllowNumericKeysTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderAllowNumericKeysTest, allowNumericKeys) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderAllowNumericKeysTest, allowNumericKeys) {
|
||||||
@ -3353,6 +3396,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowNumericKeysTest, allowNumericKeys) {
|
|||||||
JSONTEST_ASSERT_EQUAL(true, root.get("15", false));
|
JSONTEST_ASSERT_EQUAL(true, root.get("15", false));
|
||||||
JSONTEST_ASSERT_EQUAL(true, root.get("-16", false));
|
JSONTEST_ASSERT_EQUAL(true, root.get("-16", false));
|
||||||
JSONTEST_ASSERT_EQUAL(true, root.get("12.01", false));
|
JSONTEST_ASSERT_EQUAL(true, root.get("12.01", false));
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CharReaderAllowSingleQuotesTest : JsonTest::TestCase {};
|
struct CharReaderAllowSingleQuotesTest : JsonTest::TestCase {};
|
||||||
@ -3381,6 +3425,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowSingleQuotesTest, issue182) {
|
|||||||
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CharReaderAllowZeroesTest : JsonTest::TestCase {};
|
struct CharReaderAllowZeroesTest : JsonTest::TestCase {};
|
||||||
@ -3409,6 +3454,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowZeroesTest, issue176) {
|
|||||||
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CharReaderAllowSpecialFloatsTest : JsonTest::TestCase {};
|
struct CharReaderAllowSpecialFloatsTest : JsonTest::TestCase {};
|
||||||
@ -3436,6 +3482,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowSpecialFloatsTest, specialFloat) {
|
|||||||
" Syntax error: value, object or array expected.\n",
|
" Syntax error: value, object or array expected.\n",
|
||||||
errs);
|
errs);
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(CharReaderAllowSpecialFloatsTest, issue209) {
|
JSONTEST_FIXTURE_LOCAL(CharReaderAllowSpecialFloatsTest, issue209) {
|
||||||
@ -3445,7 +3492,8 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowSpecialFloatsTest, issue209) {
|
|||||||
Json::String errs;
|
Json::String errs;
|
||||||
CharReaderPtr reader(b.newCharReader());
|
CharReaderPtr reader(b.newCharReader());
|
||||||
{
|
{
|
||||||
char const doc[] = R"({"a":NaN,"b":Infinity,"c":-Infinity,"d":+Infinity})";
|
char const doc[] =
|
||||||
|
"{\"a\":NaN,\"b\":Infinity,\"c\":-Infinity,\"d\":+Infinity}";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
||||||
@ -3484,7 +3532,9 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowSpecialFloatsTest, issue209) {
|
|||||||
{__LINE__, true, "{\"a\":-Infinity}"}, //
|
{__LINE__, true, "{\"a\":-Infinity}"}, //
|
||||||
{__LINE__, true, "{\"a\":+Infinity}"} //
|
{__LINE__, true, "{\"a\":+Infinity}"} //
|
||||||
};
|
};
|
||||||
for (const auto& td : test_data) {
|
for (unsigned int index = 0; index < sizeof(test_data) / sizeof(test_data[0]);
|
||||||
|
++index) {
|
||||||
|
const struct TestData td = test_data[index];
|
||||||
bool ok = reader->parse(&*td.in.begin(), &*td.in.begin() + td.in.size(),
|
bool ok = reader->parse(&*td.in.begin(), &*td.in.begin() + td.in.size(),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
JSONTEST_ASSERT(td.ok == ok) << "line:" << td.line << "\n"
|
JSONTEST_ASSERT(td.ok == ok) << "line:" << td.line << "\n"
|
||||||
@ -3496,7 +3546,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowSpecialFloatsTest, issue209) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
char const doc[] = R"({"posInf": +Infinity, "NegInf": -Infinity})";
|
char const doc[] = "{\"posInf\": +Infinity, \"NegInf\": -Infinity}";
|
||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
||||||
@ -3506,6 +3556,7 @@ JSONTEST_FIXTURE_LOCAL(CharReaderAllowSpecialFloatsTest, issue209) {
|
|||||||
JSONTEST_ASSERT_EQUAL(-std::numeric_limits<double>::infinity(),
|
JSONTEST_ASSERT_EQUAL(-std::numeric_limits<double>::infinity(),
|
||||||
root["NegInf"].asDouble());
|
root["NegInf"].asDouble());
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EscapeSequenceTest : JsonTest::TestCase {};
|
struct EscapeSequenceTest : JsonTest::TestCase {};
|
||||||
@ -3533,6 +3584,7 @@ JSONTEST_FIXTURE_LOCAL(EscapeSequenceTest, charReaderParseEscapeSequence) {
|
|||||||
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
bool ok = reader->parse(doc, doc + std::strlen(doc), &root, &errs);
|
||||||
JSONTEST_ASSERT(ok);
|
JSONTEST_ASSERT(ok);
|
||||||
JSONTEST_ASSERT(errs.empty());
|
JSONTEST_ASSERT(errs.empty());
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(EscapeSequenceTest, writeEscapeSequence) {
|
JSONTEST_FIXTURE_LOCAL(EscapeSequenceTest, writeEscapeSequence) {
|
||||||
@ -3608,7 +3660,7 @@ struct IteratorTest : JsonTest::TestCase {};
|
|||||||
JSONTEST_FIXTURE_LOCAL(IteratorTest, convert) {
|
JSONTEST_FIXTURE_LOCAL(IteratorTest, convert) {
|
||||||
Json::Value j;
|
Json::Value j;
|
||||||
const Json::Value& cj = j;
|
const Json::Value& cj = j;
|
||||||
auto it = j.begin();
|
Json::Value::const_iterator it = j.begin();
|
||||||
Json::Value::const_iterator cit;
|
Json::Value::const_iterator cit;
|
||||||
cit = it;
|
cit = it;
|
||||||
JSONTEST_ASSERT(cit == cj.begin());
|
JSONTEST_ASSERT(cit == cj.begin());
|
||||||
@ -3619,11 +3671,17 @@ JSONTEST_FIXTURE_LOCAL(IteratorTest, decrement) {
|
|||||||
json["k1"] = "a";
|
json["k1"] = "a";
|
||||||
json["k2"] = "b";
|
json["k2"] = "b";
|
||||||
std::vector<std::string> values;
|
std::vector<std::string> values;
|
||||||
for (auto it = json.end(); it != json.begin();) {
|
std::vector<std::string> expected;
|
||||||
|
expected.push_back("b");
|
||||||
|
expected.push_back("a");
|
||||||
|
for (Json::Value::const_iterator it = json.end(); it != json.begin();) {
|
||||||
--it;
|
--it;
|
||||||
values.push_back(it->asString());
|
values.push_back(it->asString());
|
||||||
}
|
}
|
||||||
JSONTEST_ASSERT((values == std::vector<std::string>{"b", "a"}));
|
JSONTEST_ASSERT(values.size() == expected.size());
|
||||||
|
for (unsigned int i = 0; i < expected.size(); i++) {
|
||||||
|
JSONTEST_ASSERT(values.at(i) == expected.at(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(IteratorTest, reverseIterator) {
|
JSONTEST_FIXTURE_LOCAL(IteratorTest, reverseIterator) {
|
||||||
@ -3631,12 +3689,19 @@ JSONTEST_FIXTURE_LOCAL(IteratorTest, reverseIterator) {
|
|||||||
json["k1"] = "a";
|
json["k1"] = "a";
|
||||||
json["k2"] = "b";
|
json["k2"] = "b";
|
||||||
std::vector<std::string> values;
|
std::vector<std::string> values;
|
||||||
using Iter = decltype(json.begin());
|
typedef Json::Value::const_iterator Iter;
|
||||||
auto re = std::reverse_iterator<Iter>(json.begin());
|
std::reverse_iterator<Iter> re = std::reverse_iterator<Iter>(json.begin());
|
||||||
for (auto it = std::reverse_iterator<Iter>(json.end()); it != re; ++it) {
|
for (std::reverse_iterator<Iter> it = std::reverse_iterator<Iter>(json.end());
|
||||||
|
it != re; ++it) {
|
||||||
values.push_back(it->asString());
|
values.push_back(it->asString());
|
||||||
}
|
}
|
||||||
JSONTEST_ASSERT((values == std::vector<std::string>{"b", "a"}));
|
std::vector<std::string> expected;
|
||||||
|
expected.push_back("b");
|
||||||
|
expected.push_back("a");
|
||||||
|
JSONTEST_ASSERT(values.size() == expected.size());
|
||||||
|
for (unsigned int i = 0; i < expected.size(); i++) {
|
||||||
|
JSONTEST_ASSERT(values.at(i) == expected.at(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(IteratorTest, distance) {
|
JSONTEST_FIXTURE_LOCAL(IteratorTest, distance) {
|
||||||
@ -3645,9 +3710,9 @@ JSONTEST_FIXTURE_LOCAL(IteratorTest, distance) {
|
|||||||
json["k1"] = "a";
|
json["k1"] = "a";
|
||||||
json["k2"] = "b";
|
json["k2"] = "b";
|
||||||
int i = 0;
|
int i = 0;
|
||||||
auto it = json.begin();
|
Json::Value::const_iterator it = json.begin();
|
||||||
for (;; ++it, ++i) {
|
for (;; ++it, ++i) {
|
||||||
auto dist = it - json.begin();
|
Json::ValueIteratorBase::difference_type dist = it - json.begin();
|
||||||
JSONTEST_ASSERT_EQUAL(i, dist);
|
JSONTEST_ASSERT_EQUAL(i, dist);
|
||||||
if (it == json.end())
|
if (it == json.end())
|
||||||
break;
|
break;
|
||||||
@ -3663,8 +3728,8 @@ JSONTEST_FIXTURE_LOCAL(IteratorTest, distance) {
|
|||||||
JSONTEST_FIXTURE_LOCAL(IteratorTest, nullValues) {
|
JSONTEST_FIXTURE_LOCAL(IteratorTest, nullValues) {
|
||||||
{
|
{
|
||||||
Json::Value json;
|
Json::Value json;
|
||||||
auto end = json.end();
|
Json::Value::const_iterator end = json.end();
|
||||||
auto endCopy = end;
|
Json::Value::const_iterator endCopy = end;
|
||||||
JSONTEST_ASSERT(endCopy == end);
|
JSONTEST_ASSERT(endCopy == end);
|
||||||
endCopy = end;
|
endCopy = end;
|
||||||
JSONTEST_ASSERT(endCopy == end);
|
JSONTEST_ASSERT(endCopy == end);
|
||||||
@ -3672,8 +3737,8 @@ JSONTEST_FIXTURE_LOCAL(IteratorTest, nullValues) {
|
|||||||
{
|
{
|
||||||
// Same test, now with const Value.
|
// Same test, now with const Value.
|
||||||
const Json::Value json;
|
const Json::Value json;
|
||||||
auto end = json.end();
|
Json::Value::const_iterator end = json.end();
|
||||||
auto endCopy = end;
|
Json::Value::const_iterator endCopy = end;
|
||||||
JSONTEST_ASSERT(endCopy == end);
|
JSONTEST_ASSERT(endCopy == end);
|
||||||
endCopy = end;
|
endCopy = end;
|
||||||
JSONTEST_ASSERT(endCopy == end);
|
JSONTEST_ASSERT(endCopy == end);
|
||||||
@ -3744,10 +3809,10 @@ JSONTEST_FIXTURE_LOCAL(IteratorTest, constness) {
|
|||||||
for (; iter != value.end(); ++iter) {
|
for (; iter != value.end(); ++iter) {
|
||||||
out << *iter << ',';
|
out << *iter << ',';
|
||||||
}
|
}
|
||||||
Json::String expected = R"(" 9","10","11",)";
|
Json::String expected = "\" 9\",\"10\",\"11\",";
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(expected, out.str());
|
JSONTEST_ASSERT_STRING_EQUAL(expected, out.str());
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
struct RValueTest : JsonTest::TestCase {};
|
struct RValueTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(RValueTest, moveConstruction) {
|
JSONTEST_FIXTURE_LOCAL(RValueTest, moveConstruction) {
|
||||||
@ -3759,7 +3824,7 @@ JSONTEST_FIXTURE_LOCAL(RValueTest, moveConstruction) {
|
|||||||
JSONTEST_ASSERT_EQUAL(Json::objectValue, moved.type());
|
JSONTEST_ASSERT_EQUAL(Json::objectValue, moved.type());
|
||||||
JSONTEST_ASSERT_EQUAL(Json::stringValue, moved["key"].type());
|
JSONTEST_ASSERT_EQUAL(Json::stringValue, moved["key"].type());
|
||||||
}
|
}
|
||||||
|
#endif // JSONCPP_CXX_STD_11
|
||||||
struct FuzzTest : JsonTest::TestCase {};
|
struct FuzzTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
// Build and run the fuzz test without any fuzzer, so that it's guaranteed not
|
// Build and run the fuzz test without any fuzzer, so that it's guaranteed not
|
||||||
@ -3775,13 +3840,14 @@ JSONTEST_FIXTURE_LOCAL(FuzzTest, fuzzDoesntCrash) {
|
|||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
JsonTest::Runner runner;
|
JsonTest::Runner runner;
|
||||||
|
|
||||||
for (auto& local : local_) {
|
for (unsigned int index = 0; index < local_.size(); ++index) {
|
||||||
|
JsonTest::TestCaseFactory local = local_[index];
|
||||||
runner.add(local);
|
runner.add(local);
|
||||||
}
|
}
|
||||||
|
|
||||||
return runner.runCommandLine(argc, argv);
|
return runner.runCommandLine(argc, argv);
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
struct MemberTemplateAs : JsonTest::TestCase {
|
struct MemberTemplateAs : JsonTest::TestCase {
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
JsonTest::TestResult& EqEval(T v, F f) const {
|
JsonTest::TestResult& EqEval(T v, F f) const {
|
||||||
@ -3810,12 +3876,13 @@ JSONTEST_FIXTURE_LOCAL(MemberTemplateAs, BehavesSameAsNamedAs) {
|
|||||||
EqEval(false, [](const Json::Value& j) { return j.asBool(); });
|
EqEval(false, [](const Json::Value& j) { return j.asBool(); });
|
||||||
EqEval(true, [](const Json::Value& j) { return j.asBool(); });
|
EqEval(true, [](const Json::Value& j) { return j.asBool(); });
|
||||||
}
|
}
|
||||||
|
#endif // JSONCPP_CXX_STD_11
|
||||||
class MemberTemplateIs : public JsonTest::TestCase {};
|
class MemberTemplateIs : public JsonTest::TestCase {};
|
||||||
|
|
||||||
JSONTEST_FIXTURE_LOCAL(MemberTemplateIs, BehavesSameAsNamedIs) {
|
JSONTEST_FIXTURE_LOCAL(MemberTemplateIs, BehavesSameAsNamedIs) {
|
||||||
const Json::Value values[] = {true, 142, 40.63, "hello world"};
|
const Json::Value values[] = {true, 142, 40.63, "hello world"};
|
||||||
for (const Json::Value& j : values) {
|
for (size_t index = 0; index < sizeof(values) / sizeof(values[0]); index++) {
|
||||||
|
const Json::Value& j = values[index];
|
||||||
JSONTEST_ASSERT_EQUAL(j.is<bool>(), j.isBool());
|
JSONTEST_ASSERT_EQUAL(j.is<bool>(), j.isBool());
|
||||||
JSONTEST_ASSERT_EQUAL(j.is<Json::Int>(), j.isInt());
|
JSONTEST_ASSERT_EQUAL(j.is<Json::Int>(), j.isInt());
|
||||||
JSONTEST_ASSERT_EQUAL(j.is<Json::Int64>(), j.isInt64());
|
JSONTEST_ASSERT_EQUAL(j.is<Json::Int64>(), j.isInt64());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user