aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoic Blot <loic.blot@unix-experience.fr>2017-05-26 17:04:10 +0200
committerLoïc Blot <nerzhul@users.noreply.github.com>2017-06-04 09:57:08 +0200
commit2362d3f926e2702585f60011d4cea90b4faf4bd6 (patch)
tree326cdbbd96f62004df96e922dda0c5978a534e49
parentbf6569b57019d070246d947ed929cb2b5eb67faf (diff)
downloadminetest-2362d3f926e2702585f60011d4cea90b4faf4bd6.tar.gz
minetest-2362d3f926e2702585f60011d4cea90b4faf4bd6.tar.bz2
minetest-2362d3f926e2702585f60011d4cea90b4faf4bd6.zip
JsonCPP update from 0.10.6 to 1.8.0
-rw-r--r--lib/jsoncpp/json/json.h466
-rw-r--r--lib/jsoncpp/jsoncpp.cpp1020
2 files changed, 1020 insertions, 466 deletions
diff --git a/lib/jsoncpp/json/json.h b/lib/jsoncpp/json/json.h
index e9b696c01..02a31f4a0 100644
--- a/lib/jsoncpp/json/json.h
+++ b/lib/jsoncpp/json/json.h
@@ -6,28 +6,28 @@
// //////////////////////////////////////////////////////////////////////
/*
-The JsonCpp library's source code, including accompanying documentation,
+The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
-The author (Baptiste Lepilleur) explicitly disclaims copyright in all
-jurisdictions which recognize such a disclaimer. In such jurisdictions,
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all
+jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
released under the terms of the MIT License (see below).
-In jurisdictions which recognize Public Domain property, the user of this
-software may choose to accept it either as 1) Public Domain, 2) under the
-conditions of the MIT License (see below), or 3) under the terms of dual
+In jurisdictions which recognize Public Domain property, the user of this
+software may choose to accept it either as 1) Public Domain, 2) under the
+conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
-
+
The full text of the MIT License follows:
========================================================================
@@ -77,7 +77,7 @@ license you like.
/// If defined, indicates that the source file is amalgated
/// to prevent private header inclusion.
#define JSON_IS_AMALGAMATION
-#define JSONCPP_STRING
+
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/version.h
// //////////////////////////////////////////////////////////////////////
@@ -87,13 +87,20 @@ license you like.
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED
-# define JSONCPP_VERSION_STRING "0.10.6"
-# define JSONCPP_VERSION_MAJOR 0
-# define JSONCPP_VERSION_MINOR 10
-# define JSONCPP_VERSION_PATCH 6
+# define JSONCPP_VERSION_STRING "1.8.0"
+# define JSONCPP_VERSION_MAJOR 1
+# define JSONCPP_VERSION_MINOR 8
+# define JSONCPP_VERSION_PATCH 0
# define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY 0
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
#endif // JSON_VERSION_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
@@ -116,6 +123,9 @@ license you like.
#ifndef JSON_CONFIG_H_INCLUDED
#define JSON_CONFIG_H_INCLUDED
+#include <stddef.h>
+#include <string> //typedef String
+#include <stdint.h> //typedef int64_t, uint64_t
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
@@ -148,12 +158,12 @@ license you like.
#ifdef JSON_IN_CPPTL
#define JSON_API CPPTL_API
#elif defined(JSON_DLL_BUILD)
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#elif defined(JSON_DLL)
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
@@ -167,34 +177,93 @@ license you like.
// Storages, and 64 bits integer support is disabled.
// #define JSON_NO_INT64 1
-#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
-// Microsoft Visual Studio 6 only support conversion from __int64 to double
-// (no conversion from unsigned __int64).
-#define JSON_USE_INT64_DOUBLE_CONVERSION 1
-// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
-// characters in the debug information)
-// All projects I've ever seen with VS6 were using this globally (not bothering
-// with pragma push/pop).
-#pragma warning(disable : 4786)
-#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6
-
-#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
-/// Indicates that the following function is deprecated.
-#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
-#elif defined(__clang__) && defined(__has_feature)
-#if __has_feature(attribute_deprecated_with_message)
-#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
+#if defined(_MSC_VER) // MSVC
+# if _MSC_VER <= 1200 // MSVC 6
+ // Microsoft Visual Studio 6 only support conversion from __int64 to double
+ // (no conversion from unsigned __int64).
+# define JSON_USE_INT64_DOUBLE_CONVERSION 1
+ // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
+ // characters in the debug information)
+ // All projects I've ever seen with VS6 were using this globally (not bothering
+ // with pragma push/pop).
+# pragma warning(disable : 4786)
+# endif // MSVC 6
+
+# if _MSC_VER >= 1500 // MSVC 2008
+ /// Indicates that the following function is deprecated.
+# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+# endif
+
+#endif // defined(_MSC_VER)
+
+// In c++11 the override keyword allows you to explicity define that a function
+// is intended to override the base-class version. This makes the code more
+// managable and fixes a set of common hard-to-find bugs.
+#if __cplusplus >= 201103L
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT noexcept
+#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT throw()
+#elif defined(_MSC_VER) && _MSC_VER >= 1900
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT noexcept
+#else
+# define JSONCPP_OVERRIDE
+# define JSONCPP_NOEXCEPT throw()
#endif
-#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
-#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
-#elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
-#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // MSVC >= 2010
+
+#ifdef __clang__
+#if __has_feature(cxx_rvalue_references)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // has_feature
+
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // GXX_EXPERIMENTAL
+
+#endif // __clang__ || __GNUC__
+
+#endif // not defined JSON_HAS_RVALUE_REFERENCES
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+#define JSON_HAS_RVALUE_REFERENCES 0
#endif
+#ifdef __clang__
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
+# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
+# endif // GNUC version
+#endif // __clang__ || __GNUC__
+
#if !defined(JSONCPP_DEPRECATED)
#define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED)
+#if __GNUC__ >= 6
+# define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif
+
+#if !defined(JSON_IS_AMALGAMATION)
+
+# include "version.h"
+
+# if JSONCPP_USING_SECURE_MEMORY
+# include "allocator.h" //typedef Allocator
+# endif
+
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
namespace Json {
typedef int Int;
typedef unsigned int UInt;
@@ -208,13 +277,26 @@ typedef unsigned int LargestUInt;
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#else // if defined(_MSC_VER) // Other platforms, use long long
-typedef long long int Int64;
-typedef unsigned long long int UInt64;
+typedef int64_t Int64;
+typedef uint64_t UInt64;
#endif // if defined(_MSC_VER)
typedef Int64 LargestInt;
typedef UInt64 LargestUInt;
#define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)
+#if JSONCPP_USING_SECURE_MEMORY
+#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
+#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_ISTREAM std::istream
+#else
+#define JSONCPP_STRING std::string
+#define JSONCPP_OSTRINGSTREAM std::ostringstream
+#define JSONCPP_OSTREAM std::ostream
+#define JSONCPP_ISTRINGSTREAM std::istringstream
+#define JSONCPP_ISTREAM std::istream
+#endif // if JSONCPP_USING_SECURE_MEMORY
} // end namespace Json
#endif // JSON_CONFIG_H_INCLUDED
@@ -295,6 +377,8 @@ class ValueConstIterator;
#include "forwards.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
+#pragma pack(push, 8)
+
namespace Json {
/** \brief Configuration passed to reader and writer.
@@ -329,10 +413,18 @@ public:
/// \c true if root must be either an array or an object value. Default: \c
/// false.
bool strictRoot_;
+
+ /// \c true if dropped null placeholders are allowed. Default: \c false.
+ bool allowDroppedNullPlaceholders_;
+
+ /// \c true if numeric object key are allowed. Default: \c false.
+ bool allowNumericKeys_;
};
} // namespace Json
+#pragma pack(pop)
+
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
@@ -372,15 +464,8 @@ public:
#include <cpptl/forwards.h>
#endif
-// Disable warning C4251: <data member>: <type> needs to have dll-interface to
-// be used by...
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#pragma warning(push)
-#pragma warning(disable : 4251)
-#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-
//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.
#if !defined(JSONCPP_NORETURN)
# if defined(_MSC_VER)
@@ -392,6 +477,15 @@ public:
# endif
#endif
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#pragma pack(push, 8)
+
/** \brief JSON (JavaScript Object Notation).
*/
namespace Json {
@@ -402,39 +496,39 @@ namespace Json {
*/
class JSON_API Exception : public std::exception {
public:
- Exception(std::string const& msg);
- virtual ~Exception() throw();
- virtual char const* what() const throw();
+ Exception(JSONCPP_STRING const& msg);
+ ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
+ char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
protected:
- std::string const msg_;
+ JSONCPP_STRING msg_;
};
/** Exceptions which the user cannot easily avoid.
*
* E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
- *
+ *
* \remark derived from Json::Exception
*/
class JSON_API RuntimeError : public Exception {
public:
- RuntimeError(std::string const& msg);
+ RuntimeError(JSONCPP_STRING const& msg);
};
/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
*
* These are precondition-violations (user bugs) and internal errors (our bugs).
- *
+ *
* \remark derived from Json::Exception
*/
class JSON_API LogicError : public Exception {
public:
- LogicError(std::string const& msg);
+ LogicError(JSONCPP_STRING const& msg);
};
/// used internally
-JSONCPP_NORETURN void throwRuntimeError(std::string const& msg);
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg);
/// used internally
-JSONCPP_NORETURN void throwLogicError(std::string const& msg);
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg);
/** \brief Type of the value held by a Value object.
*/
@@ -525,7 +619,7 @@ private:
class JSON_API Value {
friend class ValueIteratorBase;
public:
- typedef std::vector<std::string> Members;
+ typedef std::vector<JSONCPP_STRING> Members;
typedef ValueIterator iterator;
typedef ValueConstIterator const_iterator;
typedef Json::UInt UInt;
@@ -538,11 +632,10 @@ public:
typedef Json::LargestUInt LargestUInt;
typedef Json::ArrayIndex ArrayIndex;
- static const Value& nullRef;
-#if !defined(__ARMEL__)
- /// \deprecated This exists for binary compatibility only. Use nullRef.
- static const Value null;
-#endif
+ static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
+ static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
+ static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
+
/// Minimum signed integer value that can be stored in a Json::Value.
static const LargestInt minLargestInt;
/// Maximum signed integer value that can be stored in a Json::Value.
@@ -578,6 +671,9 @@ private:
CZString(ArrayIndex index);
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
CZString(CZString const& other);
+#if JSON_HAS_RVALUE_REFERENCES
+ CZString(CZString&& other);
+#endif
~CZString();
CZString& operator=(CZString other);
bool operator<(CZString const& other) const;
@@ -653,18 +749,22 @@ Json::Value obj_value(Json::objectValue); // {}
* \endcode
*/
Value(const StaticString& value);
- Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too.
+ Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too.
#ifdef JSON_USE_CPPTL
Value(const CppTL::ConstString& value);
#endif
Value(bool value);
/// Deep copy.
Value(const Value& other);
+#if JSON_HAS_RVALUE_REFERENCES
+ /// Move constructor
+ Value(Value&& other);
+#endif
~Value();
/// Deep copy, then swap(other).
/// \note Over-write existing comments. To preserve comments, use #swapPayload().
- Value &operator=(const Value &other);
+ Value& operator=(Value other);
/// Swap everything.
void swap(Value& other);
/// Swap values but leave comments and source offsets in place.
@@ -682,7 +782,10 @@ Json::Value obj_value(Json::objectValue); // {}
int compare(const Value& other) const;
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
- std::string asString() const; ///< Embedded zeroes are possible.
+#if JSONCPP_USING_SECURE_MEMORY
+ unsigned getCStringLength() const; //Allows you to understand the length of the CString
+#endif
+ JSONCPP_STRING asString() const; ///< Embedded zeroes are possible.
/** Get raw char* of string-value.
* \return false if !string. (Seg-fault if str or end are NULL.)
*/
@@ -786,11 +889,11 @@ Json::Value obj_value(Json::objectValue); // {}
const Value& operator[](const char* key) const;
/// Access an object value by name, create a null member if it does not exist.
/// \param key may contain embedded nulls.
- Value& operator[](const std::string& key);
+ Value& operator[](const JSONCPP_STRING& key);
/// Access an object value by name, returns null if there is no member with
/// that name.
/// \param key may contain embedded nulls.
- const Value& operator[](const std::string& key) const;
+ const Value& operator[](const JSONCPP_STRING& key) const;
/** \brief Access an object value by name, create a null member if it does not
exist.
@@ -821,7 +924,7 @@ Json::Value obj_value(Json::objectValue); // {}
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \param key may contain embedded nulls.
- Value get(const std::string& key, const Value& defaultValue) const;
+ Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
#ifdef JSON_USE_CPPTL
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
@@ -846,7 +949,7 @@ Json::Value obj_value(Json::objectValue); // {}
/// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
/// \deprecated
- Value removeMember(const std::string& key);
+ Value removeMember(const JSONCPP_STRING& key);
/// Same as removeMember(const char* begin, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
@@ -856,8 +959,8 @@ Json::Value obj_value(Json::objectValue); // {}
\param key may contain embedded nulls.
\return true iff removed (no exceptions)
*/
- bool removeMember(std::string const& key, Value* removed);
- /// Same as removeMember(std::string const& key, Value* removed)
+ bool removeMember(JSONCPP_STRING const& key, Value* removed);
+ /// Same as removeMember(JSONCPP_STRING const& key, Value* removed)
bool removeMember(const char* begin, const char* end, Value* removed);
/** \brief Remove the indexed array element.
@@ -872,8 +975,8 @@ Json::Value obj_value(Json::objectValue); // {}
bool isMember(const char* key) const;
/// Return true if the object has a member named key.
/// \param key may contain embedded nulls.
- bool isMember(const std::string& key) const;
- /// Same as isMember(std::string const& key)const
+ bool isMember(const JSONCPP_STRING& key) const;
+ /// Same as isMember(JSONCPP_STRING const& key)const
bool isMember(const char* begin, const char* end) const;
#ifdef JSON_USE_CPPTL
/// Return true if the object has a member named key.
@@ -893,17 +996,17 @@ Json::Value obj_value(Json::objectValue); // {}
//# endif
/// \deprecated Always pass len.
- JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.")
+ JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
void setComment(const char* comment, CommentPlacement placement);
/// Comments must be //... or /* ... */
void setComment(const char* comment, size_t len, CommentPlacement placement);
/// Comments must be //... or /* ... */
- void setComment(const std::string& comment, CommentPlacement placement);
+ void setComment(const JSONCPP_STRING& comment, CommentPlacement placement);
bool hasComment(CommentPlacement placement) const;
/// Include delimiters and embedded newlines.
- std::string getComment(CommentPlacement placement) const;
+ JSONCPP_STRING getComment(CommentPlacement placement) const;
- std::string toStyledString() const;
+ JSONCPP_STRING toStyledString() const;
const_iterator begin() const;
const_iterator end() const;
@@ -911,6 +1014,13 @@ Json::Value obj_value(Json::objectValue); // {}
iterator begin();
iterator end();
+ // Accessors for the [start, limit) range of bytes within the JSON text from
+ // which this value was parsed, if any.
+ void setOffsetStart(ptrdiff_t start);
+ void setOffsetLimit(ptrdiff_t limit);
+ ptrdiff_t getOffsetStart() const;
+ ptrdiff_t getOffsetLimit() const;
+
private:
void initBasic(ValueType type, bool allocated = false);
@@ -947,6 +1057,11 @@ private:
unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
// If not allocated_, string_ must be null-terminated.
CommentInfo* comments_;
+
+ // [start, limit) byte offsets in the source JSON text from which this Value
+ // was extracted.
+ ptrdiff_t start_;
+ ptrdiff_t limit_;
};
/** \brief Experimental and untested: represents an element of the "path" to
@@ -959,7 +1074,7 @@ public:
PathArgument();
PathArgument(ArrayIndex index);
PathArgument(const char* key);
- PathArgument(const std::string& key);
+ PathArgument(const JSONCPP_STRING& key);
private:
enum Kind {
@@ -967,7 +1082,7 @@ private:
kindIndex,
kindKey
};
- std::string key_;
+ JSONCPP_STRING key_;
ArrayIndex index_;
Kind kind_;
};
@@ -985,7 +1100,7 @@ private:
*/
class JSON_API Path {
public:
- Path(const std::string& path,
+ Path(const JSONCPP_STRING& path,
const PathArgument& a1 = PathArgument(),
const PathArgument& a2 = PathArgument(),
const PathArgument& a3 = PathArgument(),
@@ -1002,12 +1117,12 @@ private:
typedef std::vector<const PathArgument*> InArgs;
typedef std::vector<PathArgument> Args;
- void makePath(const std::string& path, const InArgs& in);
- void addPathInArg(const std::string& path,
+ void makePath(const JSONCPP_STRING& path, const InArgs& in);
+ void addPathInArg(const JSONCPP_STRING& path,
const InArgs& in,
InArgs::const_iterator& itInArg,
PathArgument::Kind kind);
- void invalidPath(const std::string& path, int location);
+ void invalidPath(const JSONCPP_STRING& path, int location);
Args args_;
};
@@ -1040,7 +1155,7 @@ public:
/// Return the member name of the referenced Value, or "" if it is not an
/// objectValue.
/// \note Avoid `c_str()` on result, as embedded zeroes are possible.
- std::string name() const;
+ JSONCPP_STRING name() const;
/// Return the member name of the referenced Value. "" if it is not an
/// objectValue.
@@ -1092,6 +1207,7 @@ public:
typedef ValueConstIterator SelfType;
ValueConstIterator();
+ ValueConstIterator(ValueIterator const& other);
private:
/*! \internal Use by Value to create an iterator.
@@ -1141,7 +1257,7 @@ public:
typedef ValueIterator SelfType;
ValueIterator();
- ValueIterator(const ValueConstIterator& other);
+ explicit ValueIterator(const ValueConstIterator& other);
ValueIterator(const ValueIterator& other);
private:
@@ -1187,6 +1303,7 @@ template<>
inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
}
+#pragma pack(pop)
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(pop)
@@ -1232,6 +1349,8 @@ inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
#pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma pack(push, 8)
+
namespace Json {
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
@@ -1244,6 +1363,18 @@ public:
typedef char Char;
typedef const Char* Location;
+ /** \brief An error tagged with where in the JSON text it was encountered.
+ *
+ * The offsets give the [start, limit) range of bytes within the text. Note
+ * that this is bytes, not codepoints.
+ *
+ */
+ struct StructuredError {
+ ptrdiff_t offset_start;
+ ptrdiff_t offset_limit;
+ JSONCPP_STRING message;
+ };
+
/** \brief Constructs a Reader allowing all features
* for parsing.
*/
@@ -1296,7 +1427,7 @@ public:
/// \brief Parse from input stream.
/// \see Json::operator>>(std::istream&, Json::Value&).
- bool parse(std::istream& is, Value& root, bool collectComments = true);
+ bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
/** \brief Returns a user friendly string that list errors in the parsed
* document.
@@ -1308,7 +1439,7 @@ public:
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
*/
JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
- std::string getFormatedErrorMessages() const;
+ JSONCPP_STRING getFormatedErrorMessages() const;
/** \brief Returns a user friendly string that list errors in the parsed
* document.
@@ -1318,7 +1449,39 @@ public:
* occurred
* during parsing.
*/
- std::string getFormattedErrorMessages() const;
+ JSONCPP_STRING getFormattedErrorMessages() const;
+
+ /** \brief Returns a vector of structured erros encounted while parsing.
+ * \return A (possibly empty) vector of StructuredError objects. Currently
+ * only one error can be returned, but the caller should tolerate
+ * multiple
+ * errors. This can occur if the parser recovers from a non-fatal
+ * parse error and then encounters additional errors.
+ */
+ std::vector<StructuredError> getStructuredErrors() const;
+
+ /** \brief Add a semantic error message.
+ * \param value JSON Value location associated with the error
+ * \param message The error message.
+ * \return \c true if the error was successfully added, \c false if the
+ * Value offset exceeds the document size.
+ */
+ bool pushError(const Value& value, const JSONCPP_STRING& message);
+
+ /** \brief Add a semantic error message with extra context.
+ * \param value JSON Value location associated with the error
+ * \param message The error message.
+ * \param extra Additional JSON Value location to contextualize the error
+ * \return \c true if the error was successfully added, \c false if either
+ * Value offset exceeds the document size.
+ */
+ bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
+
+ /** \brief Return whether there are any errors.
+ * \return \c true if there are no errors to report \c false if
+ * errors have occurred.
+ */
+ bool good() const;
private:
enum TokenType {
@@ -1348,7 +1511,7 @@ private:
class ErrorInfo {
public:
Token token_;
- std::string message_;
+ JSONCPP_STRING message_;
Location extra_;
};
@@ -1368,7 +1531,7 @@ private:
bool decodeNumber(Token& token);
bool decodeNumber(Token& token, Value& decoded);
bool decodeString(Token& token);
- bool decodeString(Token& token, std::string& decoded);
+ bool decodeString(Token& token, JSONCPP_STRING& decoded);
bool decodeDouble(Token& token);
bool decodeDouble(Token& token, Value& decoded);
bool decodeUnicodeCodePoint(Token& token,
@@ -1379,9 +1542,9 @@ private:
Location& current,
Location end,
unsigned int& unicode);
- bool addError(const std::string& message, Token& token, Location extra = 0);
+ bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
bool recoverFromError(TokenType skipUntilToken);
- bool addErrorAndRecover(const std::string& message,
+ bool addErrorAndRecover(const JSONCPP_STRING& message,
Token& token,
TokenType skipUntilToken);
void skipUntilSpace();
@@ -1389,20 +1552,20 @@ private:
Char getNextChar();
void
getLocationLineAndColumn(Location location, int& line, int& column) const;
- std::string getLocationLineAndColumn(Location location) const;
+ JSONCPP_STRING getLocationLineAndColumn(Location location) const;
void addComment(Location begin, Location end, CommentPlacement placement);
void skipCommentTokens(Token& token);
typedef std::stack<Value*> Nodes;
Nodes nodes_;
Errors errors_;
- std::string document_;
+ JSONCPP_STRING document_;
Location begin_;
Location end_;
Location current_;
Location lastValueEnd_;
Value* lastValue_;
- std::string commentsBefore_;
+ JSONCPP_STRING commentsBefore_;
Features features_;
bool collectComments_;
}; // Reader
@@ -1431,9 +1594,9 @@ public:
*/
virtual bool parse(
char const* beginDoc, char const* endDoc,
- Value* root, std::string* errs) = 0;
+ Value* root, JSONCPP_STRING* errs) = 0;
- class Factory {
+ class JSON_API Factory {
public:
virtual ~Factory() {}
/** \brief Allocate a CharReader via operator new().
@@ -1451,7 +1614,7 @@ Usage:
CharReaderBuilder builder;
builder["collectComments"] = false;
Value value;
- std::string errs;
+ JSONCPP_STRING errs;
bool ok = parseFromStream(builder, std::cin, &value, &errs);
\endcode
*/
@@ -1487,7 +1650,7 @@ public:
- `"rejectDupKeys": false or true`
- If true, `parse()` returns false when a key is duplicated within an object.
- `"allowSpecialFloats": false or true`
- - If true, special float values (NaNs and infinities) are allowed
+ - If true, special float values (NaNs and infinities) are allowed
and their values are lossfree restorable.
You can examine 'settings_` yourself
@@ -1498,9 +1661,9 @@ public:
Json::Value settings_;
CharReaderBuilder();
- virtual ~CharReaderBuilder();
+ ~CharReaderBuilder() JSONCPP_OVERRIDE;
- virtual CharReader* newCharReader() const;
+ CharReader* newCharReader() const JSONCPP_OVERRIDE;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
@@ -1509,7 +1672,7 @@ public:
/** A simple way to update a specific setting.
*/
- Value& operator[](std::string key);
+ Value& operator[](JSONCPP_STRING key);
/** Called by ctor, but you can use this to reset settings_.
* \pre 'settings' != NULL (but Json::null is fine)
@@ -1531,7 +1694,7 @@ public:
*/
bool JSON_API parseFromStream(
CharReader::Factory const&,
- std::istream&,
+ JSONCPP_ISTREAM&,
Value* root, std::string* errs);
/** \brief Read from 'sin' into 'root'.
@@ -1558,10 +1721,12 @@ bool JSON_API parseFromStream(
\throw std::exception on parse error.
\see Json::operator<<()
*/
-JSON_API std::istream& operator>>(std::istream&, Value&);
+JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
} // namespace Json
+#pragma pack(pop)
+
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -1603,6 +1768,8 @@ JSON_API std::istream& operator>>(std::istream&, Value&);
#pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma pack(push, 8)
+
namespace Json {
class Value;
@@ -1622,7 +1789,7 @@ Usage:
*/
class JSON_API StreamWriter {
protected:
- std::ostream* sout_; // not owned; will not delete
+ JSONCPP_OSTREAM* sout_; // not owned; will not delete
public:
StreamWriter();
virtual ~StreamWriter();
@@ -1632,7 +1799,7 @@ public:
\return zero on success (For now, we always return zero, so check the stream instead.)
\throw std::exception possibly, depending on configuration
*/
- virtual int write(Value const& root, std::ostream* sout) = 0;
+ virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
/** \brief A simple abstract factory.
*/
@@ -1649,7 +1816,7 @@ public:
/** \brief Write into stringstream, then return string, for convenience.
* A StreamWriter will be created from the factory, used, and then deleted.
*/
-std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
+JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
/** \brief Build a StreamWriter implementation.
@@ -1695,12 +1862,12 @@ public:
Json::Value settings_;
StreamWriterBuilder();
- virtual ~StreamWriterBuilder();
+ ~StreamWriterBuilder() JSONCPP_OVERRIDE;
/**
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
- virtual StreamWriter* newStreamWriter() const;
+ StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
@@ -1708,7 +1875,7 @@ public:
bool validate(Json::Value* invalid) const;
/** A simple way to update a specific setting.
*/
- Value& operator[](std::string key);
+ Value& operator[](JSONCPP_STRING key);
/** Called by ctor, but you can use this to reset settings_.
* \pre 'settings' != NULL (but Json::null is fine)
@@ -1725,7 +1892,7 @@ class JSON_API Writer {
public:
virtual ~Writer();
- virtual std::string write(const Value& root) = 0;
+ virtual JSONCPP_STRING write(const Value& root) = 0;
};
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
@@ -1741,18 +1908,29 @@ class JSON_API FastWriter : public Writer {
public:
FastWriter();
- virtual ~FastWriter() {}
+ ~FastWriter() JSONCPP_OVERRIDE {}
void enableYAMLCompatibility();
+ /** \brief Drop the "null" string from the writer's output for nullValues.
+ * Strictly speaking, this is not valid JSON. But when the output is being
+ * fed to a browser's Javascript, it makes for smaller output and the
+ * browser can handle the output just fine.
+ */
+ void dropNullPlaceholders();
+
+ void omitEndingLineFeed();
+
public: // overridden from Writer
- virtual std::string write(const Value& root);
+ JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
private:
void writeValue(const Value& value);
- std::string document_;
+ JSONCPP_STRING document_;
bool yamlCompatiblityEnabled_;
+ bool dropNullPlaceholders_;
+ bool omitEndingLineFeed_;
};
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
@@ -1782,36 +1960,36 @@ private:
class JSON_API StyledWriter : public Writer {
public:
StyledWriter();
- virtual ~StyledWriter() {}
+ ~StyledWriter() JSONCPP_OVERRIDE {}
public: // overridden from Writer
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
* \param root Value to serialize.
* \return String containing the JSON document that represents the root value.
*/
- virtual std::string write(const Value& root);
+ JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
private:
void writeValue(const Value& value);
void writeArrayValue(const Value& value);
bool isMultineArray(const Value& value);
- void pushValue(const std::string& value);
+ void pushValue(const JSONCPP_STRING& value);
void writeIndent();
- void writeWithIndent(const std::string& value);
+ void writeWithIndent(const JSONCPP_STRING& value);
void indent();
void unindent();
void writeCommentBeforeValue(const Value& root);
void writeCommentAfterValueOnSameLine(const Value& root);
bool hasCommentForValue(const Value& value);
- static std::string normalizeEOL(const std::string& text);
+ static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
- typedef std::vector<std::string> ChildValues;
+ typedef std::vector<JSONCPP_STRING> ChildValues;
ChildValues childValues_;
- std::string document_;
- std::string indentString_;
- int rightMargin_;
- int indentSize_;
+ JSONCPP_STRING document_;
+ JSONCPP_STRING indentString_;
+ unsigned int rightMargin_;
+ unsigned int indentSize_;
bool addChildValues_;
};
@@ -1843,7 +2021,7 @@ private:
*/
class JSON_API StyledStreamWriter {
public:
- StyledStreamWriter(std::string indentation = "\t");
+ StyledStreamWriter(JSONCPP_STRING indentation = "\t");
~StyledStreamWriter() {}
public:
@@ -1853,49 +2031,51 @@ public:
* \note There is no point in deriving from Writer, since write() should not
* return a value.
*/
- void write(std::ostream& out, const Value& root);
+ void write(JSONCPP_OSTREAM& out, const Value& root);
private:
void writeValue(const Value& value);
void writeArrayValue(const Value& value);
bool isMultineArray(const Value& value);
- void pushValue(const std::string& value);
+ void pushValue(const JSONCPP_STRING& value);
void writeIndent();
- void writeWithIndent(const std::string& value);
+ void writeWithIndent(const JSONCPP_STRING& value);
void indent();
void unindent();
void writeCommentBeforeValue(const Value& root);
void writeCommentAfterValueOnSameLine(const Value& root);
bool hasCommentForValue(const Value& value);
- static std::string normalizeEOL(const std::string& text);
+ static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
- typedef std::vector<std::string> ChildValues;
+ typedef std::vector<JSONCPP_STRING> ChildValues;
ChildValues childValues_;
- std::ostream* document_;
- std::string indentString_;
- int rightMargin_;
- std::string indentation_;
+ JSONCPP_OSTREAM* document_;
+ JSONCPP_STRING indentString_;
+ unsigned int rightMargin_;
+ JSONCPP_STRING indentation_;
bool addChildValues_ : 1;
bool indented_ : 1;
};
#if defined(JSON_HAS_INT64)
-std::string JSON_API valueToString(Int value);
-std::string JSON_API valueToString(UInt value);
+JSONCPP_STRING JSON_API valueToString(Int value);
+JSONCPP_STRING JSON_API valueToString(UInt value);
#endif // if defined(JSON_HAS_INT64)
-std::string JSON_API valueToString(LargestInt value);
-std::string JSON_API valueToString(LargestUInt value);
-std::string JSON_API valueToString(double value);
-std::string JSON_API valueToString(bool value);
-std::string JSON_API valueToQuotedString(const char* value);
+JSONCPP_STRING JSON_API valueToString(LargestInt value);
+JSONCPP_STRING JSON_API valueToString(LargestUInt value);
+JSONCPP_STRING JSON_API valueToString(double value);
+JSONCPP_STRING JSON_API valueToString(bool value);
+JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
/// \brief Output using the StyledStreamWriter.
/// \see Json::operator>>()
-JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
+JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
} // namespace Json
+#pragma pack(pop)
+
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -1942,7 +2122,7 @@ JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
# define JSON_FAIL_MESSAGE(message) \
{ \
- std::ostringstream oss; oss << message; \
+ JSONCPP_OSTRINGSTREAM oss; oss << message; \
Json::throwLogicError(oss.str()); \
abort(); \
}
@@ -1955,7 +2135,7 @@ JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
// release builds we abort, for a core-dump or debugger.
# define JSON_FAIL_MESSAGE(message) \
{ \
- std::ostringstream oss; oss << message; \
+ JSONCPP_OSTRINGSTREAM oss; oss << message; \
assert(false && oss.str().c_str()); \
abort(); \
}
diff --git a/lib/jsoncpp/jsoncpp.cpp b/lib/jsoncpp/jsoncpp.cpp
index 618191612..c373405f0 100644
--- a/lib/jsoncpp/jsoncpp.cpp
+++ b/lib/jsoncpp/jsoncpp.cpp
@@ -6,28 +6,28 @@
// //////////////////////////////////////////////////////////////////////
/*
-The JsonCpp library's source code, including accompanying documentation,
+The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
-The author (Baptiste Lepilleur) explicitly disclaims copyright in all
-jurisdictions which recognize such a disclaimer. In such jurisdictions,
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all
+jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
released under the terms of the MIT License (see below).
-In jurisdictions which recognize Public Domain property, the user of this
-software may choose to accept it either as 1) Public Domain, 2) under the
-conditions of the MIT License (see below), or 3) under the terms of dual
+In jurisdictions which recognize Public Domain property, the user of this
+software may choose to accept it either as 1) Public Domain, 2) under the
+conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
-
+
The full text of the MIT License follows:
========================================================================
@@ -92,6 +92,16 @@ license you like.
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+// Also support old flag NO_LOCALE_SUPPORT
+#ifdef NO_LOCALE_SUPPORT
+#define JSONCPP_NO_LOCALE_SUPPORT
+#endif
+
+#ifndef JSONCPP_NO_LOCALE_SUPPORT
+#include <clocale>
+#endif
+
/* This header provides common string manipulation support, such as UTF-8,
* portable conversion from/to string...
*
@@ -99,10 +109,18 @@ license you like.
*/
namespace Json {
+static char getDecimalPoint() {
+#ifdef JSONCPP_NO_LOCALE_SUPPORT
+ return '\0';
+#else
+ struct lconv* lc = localeconv();
+ return lc ? *(lc->decimal_point) : '\0';
+#endif
+}
/// Converts a unicode code-point to UTF-8.
-static inline std::string codePointToUTF8(unsigned int cp) {
- std::string result;
+static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
+ JSONCPP_STRING result;
// based on description from http://en.wikipedia.org/wiki/UTF-8
@@ -149,7 +167,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
static inline void uintToString(LargestUInt value, char*& current) {
*--current = 0;
do {
- *--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0'));
+ *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
value /= 10;
} while (value != 0);
}
@@ -168,6 +186,18 @@ static inline void fixNumericLocale(char* begin, char* end) {
}
}
+static inline void fixNumericLocaleInput(char* begin, char* end) {
+ char decimalPoint = getDecimalPoint();
+ if (decimalPoint != '\0' && decimalPoint != '.') {
+ while (begin < end) {
+ if (*begin == '.') {
+ *begin = decimalPoint;
+ }
+ ++begin;
+ }
+ }
+}
+
} // namespace Json {
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
@@ -186,6 +216,7 @@ static inline void fixNumericLocale(char* begin, char* end) {
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2011 Baptiste Lepilleur
+// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -207,43 +238,60 @@ static inline void fixNumericLocale(char* begin, char* end) {
#include <limits>
#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
#define snprintf sprintf_s
#elif _MSC_VER >= 1900 // VC++ 14.0 and above
#define snprintf std::snprintf
#else
#define snprintf _snprintf
#endif
-#elif defined(__ANDROID__)
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
#define snprintf snprintf
#elif __cplusplus >= 201103L
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
#define snprintf std::snprintf
#endif
+#endif
+
+#if defined(__QNXNTO__)
+#define sscanf std::sscanf
+#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
// Disable warning about strdup being deprecated.
#pragma warning(disable : 4996)
#endif
-static int const stackLimit_g = 1000;
-static int stackDepth_g = 0; // see readValue()
+// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
+#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
+#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
+#endif
+
+static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
namespace Json {
-typedef std::auto_ptr<CharReader> CharReaderPtr;
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<CharReader> CharReaderPtr;
+#else
+typedef std::auto_ptr<CharReader> CharReaderPtr;
+#endif
// Implementation of class Features
// ////////////////////////////////
Features::Features()
- : allowComments_(true), strictRoot_(false)
-{}
+ : allowComments_(true), strictRoot_(false),
+ allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
+
Features Features::all() { return Features(); }
Features Features::strictMode() {
Features features;
features.allowComments_ = false;
features.strictRoot_ = true;
+ features.allowDroppedNullPlaceholders_ = false;
+ features.allowNumericKeys_ = false;
return features;
}
@@ -272,7 +320,8 @@ Reader::Reader(const Features& features)
bool
Reader::parse(const std::string& document, Value& root, bool collectComments) {
- document_ = document;
+ JSONCPP_STRING documentCopy(document.data(), document.data() + document.capacity());
+ std::swap(documentCopy, document_);
const char* begin = document_.c_str();
const char* end = begin + document_.length();
return parse(begin, end, root, collectComments);
@@ -284,11 +333,11 @@ bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
// Those would allow streamed input from a file, if parse() were a
// template function.
- // Since std::string is reference-counted, this at least does not
+ // Since JSONCPP_STRING is reference-counted, this at least does not
// create an extra copy.
- std::string doc;
+ JSONCPP_STRING doc;
std::getline(sin, doc, (char)EOF);
- return parse(doc, root, collectComments);
+ return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
}
bool Reader::parse(const char* beginDoc,
@@ -311,7 +360,6 @@ bool Reader::parse(const char* beginDoc,
nodes_.pop();
nodes_.push(&root);
- stackDepth_g = 0; // Yes, this is bad coding, but options are limited.
bool successful = readValue();
Token token;
skipCommentTokens(token);
@@ -334,12 +382,10 @@ bool Reader::parse(const char* beginDoc,
}
bool Reader::readValue() {
- // This is a non-reentrant way to support a stackLimit. Terrible!
- // But this deprecated class has a security problem: Bad input can
- // cause a seg-fault. This seems like a fair, binary-compatible way
- // to prevent the problem.
- if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
- ++stackDepth_g;
+ // readValue() may call itself only if it calls readObject() or ReadArray().
+ // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue().
+ // parse() executes one nodes_.push(), so > instead of >=.
+ if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
skipCommentTokens(token);
@@ -353,9 +399,11 @@ bool Reader::readValue() {
switch (token.type_) {
case tokenObjectBegin:
successful = readObject(token);
+ currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenArrayBegin:
successful = readArray(token);
+ currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenNumber:
successful = decodeNumber(token);
@@ -367,22 +415,42 @@ bool Reader::readValue() {
{
Value v(true);
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenFalse:
{
Value v(false);
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenNull:
{
Value v;
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
- // Else, fall through...
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ current_--;
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(current_ - begin_ - 1);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ } // Else, fall through...
default:
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return addError("Syntax error: value, object or array expected.", token);
}
@@ -391,7 +459,6 @@ bool Reader::readValue() {
lastValue_ = &currentValue();
}
- --stackDepth_g;
return successful;
}
@@ -520,9 +587,9 @@ bool Reader::readComment() {
return true;
}
-static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
- std::string normalized;
- normalized.reserve(end - begin);
+static JSONCPP_STRING normalizeEOL(Reader::Location begin, Reader::Location end) {
+ JSONCPP_STRING normalized;
+ normalized.reserve(static_cast<size_t>(end - begin));
Reader::Location current = begin;
while (current != end) {
char c = *current++;
@@ -542,7 +609,7 @@ static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
void
Reader::addComment(Location begin, Location end, CommentPlacement placement) {
assert(collectComments_);
- const std::string& normalized = normalizeEOL(begin, end);
+ const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
assert(lastValue_ != 0);
lastValue_->setComment(normalized, placement);
@@ -552,7 +619,7 @@ Reader::addComment(Location begin, Location end, CommentPlacement placement) {
}
bool Reader::readCStyleComment() {
- while (current_ != end_) {
+ while ((current_ + 1) < end_) {
Char c = getNextChar();
if (c == '*' && *current_ == '/')
break;
@@ -581,25 +648,25 @@ void Reader::readNumber() {
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
// fractional part
if (c == '.') {
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
}
// exponential part
if (c == 'e' || c == 'E') {
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
if (c == '+' || c == '-')
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
}
}
bool Reader::readString() {
- Char c = 0;
+ Char c = '\0';
while (current_ != end_) {
c = getNextChar();
if (c == '\\')
@@ -610,11 +677,12 @@ bool Reader::readString() {
return c == '"';
}
-bool Reader::readObject(Token& /*tokenStart*/) {
+bool Reader::readObject(Token& tokenStart) {
Token tokenName;
- std::string name;
+ JSONCPP_STRING name;
Value init(objectValue);
currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
while (readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
@@ -627,6 +695,11 @@ bool Reader::readObject(Token& /*tokenStart*/) {
if (tokenName.type_ == tokenString) {
if (!decodeString(tokenName, name))
return recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ Value numberName;
+ if (!decodeNumber(tokenName, numberName))
+ return recoverFromError(tokenObjectEnd);
+ name = JSONCPP_STRING(numberName.asCString());
} else {
break;
}
@@ -660,11 +733,12 @@ bool Reader::readObject(Token& /*tokenStart*/) {
"Missing '}' or object member name", tokenName, tokenObjectEnd);
}
-bool Reader::readArray(Token& /*tokenStart*/) {
+bool Reader::readArray(Token& tokenStart) {
Value init(arrayValue);
currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces();
- if (*current_ == ']') // empty array
+ if (current_ != end_ && *current_ == ']') // empty array
{
Token endArray;
readToken(endArray);
@@ -702,6 +776,8 @@ bool Reader::decodeNumber(Token& token) {
if (!decodeNumber(token, decoded))
return false;
currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
@@ -723,7 +799,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
Char c = *current++;
if (c < '0' || c > '9')
return decodeDouble(token, decoded);
- Value::UInt digit(c - '0');
+ Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// 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
@@ -752,15 +828,17 @@ bool Reader::decodeDouble(Token& token) {
if (!decodeDouble(token, decoded))
return false;
currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
- std::string buffer(token.start_, token.end_);
- std::istringstream is(buffer);
+ JSONCPP_STRING buffer(token.start_, token.end_);
+ JSONCPP_ISTRINGSTREAM is(buffer);
if (!(is >> value))
- return addError("'" + std::string(token.start_, token.end_) +
+ return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
"' is not a number.",
token);
decoded = value;
@@ -768,16 +846,18 @@ bool Reader::decodeDouble(Token& token, Value& decoded) {
}
bool Reader::decodeString(Token& token) {
- std::string decoded_string;
+ JSONCPP_STRING decoded_string;
if (!decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
-bool Reader::decodeString(Token& token, std::string& decoded) {
- decoded.reserve(token.end_ - token.start_ - 2);
+bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+ decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
while (current != end) {
@@ -861,13 +941,13 @@ bool Reader::decodeUnicodeCodePoint(Token& token,
bool Reader::decodeUnicodeEscapeSequence(Token& token,
Location& current,
Location end,
- unsigned int& unicode) {
+ unsigned int& ret_unicode) {
if (end - current < 4)
return addError(
"Bad unicode escape sequence in string: four digits expected.",
token,
current);
- unicode = 0;
+ int unicode = 0;
for (int index = 0; index < 4; ++index) {
Char c = *current++;
unicode *= 16;
@@ -883,11 +963,12 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token,
token,
current);
}
+ ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
bool
-Reader::addError(const std::string& message, Token& token, Location extra) {
+Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
ErrorInfo info;
info.token_ = token;
info.message_ = message;
@@ -897,7 +978,7 @@ Reader::addError(const std::string& message, Token& token, Location extra) {
}
bool Reader::recoverFromError(TokenType skipUntilToken) {
- int errorCount = int(errors_.size());
+ size_t const errorCount = errors_.size();
Token skip;
for (;;) {
if (!readToken(skip))
@@ -909,7 +990,7 @@ bool Reader::recoverFromError(TokenType skipUntilToken) {
return false;
}
-bool Reader::addErrorAndRecover(const std::string& message,
+bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
Token& token,
TokenType skipUntilToken) {
addError(message, token);
@@ -947,7 +1028,7 @@ void Reader::getLocationLineAndColumn(Location location,
++line;
}
-std::string Reader::getLocationLineAndColumn(Location location) const {
+JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
int line, column;
getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
@@ -956,12 +1037,12 @@ std::string Reader::getLocationLineAndColumn(Location location) const {
}
// Deprecated. Preserved for backward compatibility
-std::string Reader::getFormatedErrorMessages() const {
+JSONCPP_STRING Reader::getFormatedErrorMessages() const {
return getFormattedErrorMessages();
}
-std::string Reader::getFormattedErrorMessages() const {
- std::string formattedMessage;
+JSONCPP_STRING Reader::getFormattedErrorMessages() const {
+ JSONCPP_STRING formattedMessage;
for (Errors::const_iterator itError = errors_.begin();
itError != errors_.end();
++itError) {
@@ -976,14 +1057,64 @@ std::string Reader::getFormattedErrorMessages() const {
return formattedMessage;
}
-// Reader
-/////////////////////////
+std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
+ std::vector<Reader::StructuredError> allErrors;
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
+ const ErrorInfo& error = *itError;
+ Reader::StructuredError structured;
+ structured.offset_start = error.token_.start_ - begin_;
+ structured.offset_limit = error.token_.end_ - begin_;
+ structured.message = error.message_;
+ allErrors.push_back(structured);
+ }
+ return allErrors;
+}
+
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
+ ptrdiff_t const length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = end_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = 0;
+ errors_.push_back(info);
+ return true;
+}
+
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+ ptrdiff_t const length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length
+ || extra.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = begin_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = begin_ + extra.getOffsetStart();
+ errors_.push_back(info);
+ return true;
+}
+
+bool Reader::good() const {
+ return !errors_.size();
+}
// exact copy of Features
class OurFeatures {
public:
static OurFeatures all();
- OurFeatures();
bool allowComments_;
bool strictRoot_;
bool allowDroppedNullPlaceholders_;
@@ -998,15 +1129,6 @@ public:
// exact copy of Implementation of class Features
// ////////////////////////////////
-OurFeatures::OurFeatures()
- : allowComments_(true), strictRoot_(false)
- , allowDroppedNullPlaceholders_(false), allowNumericKeys_(false)
- , allowSingleQuotes_(false)
- , failIfExtra_(false)
- , allowSpecialFloats_(false)
-{
-}
-
OurFeatures OurFeatures::all() { return OurFeatures(); }
// Implementation of class Reader
@@ -1018,9 +1140,9 @@ public:
typedef char Char;
typedef const Char* Location;
struct StructuredError {
- size_t offset_start;
- size_t offset_limit;
- std::string message;
+ ptrdiff_t offset_start;
+ ptrdiff_t offset_limit;
+ JSONCPP_STRING message;
};
OurReader(OurFeatures const& features);
@@ -1028,7 +1150,11 @@ public:
const char* endDoc,
Value& root,
bool collectComments = true);
- std::string getFormattedErrorMessages() const;
+ JSONCPP_STRING getFormattedErrorMessages() const;
+ std::vector<StructuredError> getStructuredErrors() const;
+ bool pushError(const Value& value, const JSONCPP_STRING& message);
+ bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
+ bool good() const;
private:
OurReader(OurReader const&); // no impl
@@ -1064,7 +1190,7 @@ private:
class ErrorInfo {
public:
Token token_;
- std::string message_;
+ JSONCPP_STRING message_;
Location extra_;
};
@@ -1085,7 +1211,7 @@ private:
bool decodeNumber(Token& token);
bool decodeNumber(Token& token, Value& decoded);
bool decodeString(Token& token);
- bool decodeString(Token& token, std::string& decoded);
+ bool decodeString(Token& token, JSONCPP_STRING& decoded);
bool decodeDouble(Token& token);
bool decodeDouble(Token& token, Value& decoded);
bool decodeUnicodeCodePoint(Token& token,
@@ -1096,9 +1222,9 @@ private:
Location& current,
Location end,
unsigned int& unicode);
- bool addError(const std::string& message, Token& token, Location extra = 0);
+ bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
bool recoverFromError(TokenType skipUntilToken);
- bool addErrorAndRecover(const std::string& message,
+ bool addErrorAndRecover(const JSONCPP_STRING& message,
Token& token,
TokenType skipUntilToken);
void skipUntilSpace();
@@ -1106,21 +1232,20 @@ private:
Char getNextChar();
void
getLocationLineAndColumn(Location location, int& line, int& column) const;
- std::string getLocationLineAndColumn(Location location) const;
+ JSONCPP_STRING getLocationLineAndColumn(Location location) const;
void addComment(Location begin, Location end, CommentPlacement placement);
void skipCommentTokens(Token& token);
typedef std::stack<Value*> Nodes;
Nodes nodes_;
Errors errors_;
- std::string document_;
+ JSONCPP_STRING document_;
Location begin_;
Location end_;
Location current_;
Location lastValueEnd_;
Value* lastValue_;
- std::string commentsBefore_;
- int stackDepth_;
+ JSONCPP_STRING commentsBefore_;
OurFeatures const features_;
bool collectComments_;
@@ -1130,7 +1255,8 @@ private:
OurReader::OurReader(OurFeatures const& features)
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
- lastValue_(), commentsBefore_(), features_(features), collectComments_() {
+ lastValue_(), commentsBefore_(),
+ features_(features), collectComments_() {
}
bool OurReader::parse(const char* beginDoc,
@@ -1153,12 +1279,11 @@ bool OurReader::parse(const char* beginDoc,
nodes_.pop();
nodes_.push(&root);
- stackDepth_ = 0;
bool successful = readValue();
Token token;
skipCommentTokens(token);
if (features_.failIfExtra_) {
- if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
+ if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
addError("Extra non-whitespace after JSON value.", token);
return false;
}
@@ -1182,8 +1307,8 @@ bool OurReader::parse(const char* beginDoc,
}
bool OurReader::readValue() {
- if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
- ++stackDepth_;
+ // To preserve the old behaviour we cast size_t to int.
+ if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
skipCommentTokens(token);
bool successful = true;
@@ -1196,9 +1321,11 @@ bool OurReader::readValue() {
switch (token.type_) {
case tokenObjectBegin:
successful = readObject(token);
+ currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenArrayBegin:
successful = readArray(token);
+ currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenNumber:
successful = decodeNumber(token);
@@ -1210,36 +1337,48 @@ bool OurReader::readValue() {
{
Value v(true);
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenFalse:
{
Value v(false);
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenNull:
{
Value v;
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenNaN:
{
Value v(std::numeric_limits<double>::quiet_NaN());
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenPosInf:
{
Value v(std::numeric_limits<double>::infinity());
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenNegInf:
{
Value v(-std::numeric_limits<double>::infinity());
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenArraySeparator:
@@ -1251,9 +1390,13 @@ bool OurReader::readValue() {
current_--;
Value v;
currentValue().swapPayload(v);
+ currentValue().setOffsetStart(current_ - begin_ - 1);
+ currentValue().setOffsetLimit(current_ - begin_);
break;
} // else, fall through ...
default:
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return addError("Syntax error: value, object or array expected.", token);
}
@@ -1262,7 +1405,6 @@ bool OurReader::readValue() {
lastValue_ = &currentValue();
}
- --stackDepth_;
return successful;
}
@@ -1423,7 +1565,7 @@ bool OurReader::readComment() {
void
OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
assert(collectComments_);
- const std::string& normalized = normalizeEOL(begin, end);
+ const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
assert(lastValue_ != 0);
lastValue_->setComment(normalized, placement);
@@ -1433,7 +1575,7 @@ OurReader::addComment(Location begin, Location end, CommentPlacement placement)
}
bool OurReader::readCStyleComment() {
- while (current_ != end_) {
+ while ((current_ + 1) < end_) {
Char c = getNextChar();
if (c == '*' && *current_ == '/')
break;
@@ -1466,20 +1608,20 @@ bool OurReader::readNumber(bool checkInf) {
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
// fractional part
if (c == '.') {
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
}
// exponential part
if (c == 'e' || c == 'E') {
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
if (c == '+' || c == '-')
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
while (c >= '0' && c <= '9')
- c = (current_ = p) < end_ ? *p++ : 0;
+ c = (current_ = p) < end_ ? *p++ : '\0';
}
return true;
}
@@ -1508,11 +1650,12 @@ bool OurReader::readStringSingleQuote() {
return c == '\'';
}
-bool OurReader::readObject(Token& /*tokenStart*/) {
+bool OurReader::readObject(Token& tokenStart) {
Token tokenName;
- std::string name;
+ JSONCPP_STRING name;
Value init(objectValue);
currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
while (readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
@@ -1541,7 +1684,7 @@ bool OurReader::readObject(Token& /*tokenStart*/) {
}
if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
- std::string msg = "Duplicate key: '" + name + "'";
+ JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
return addErrorAndRecover(
msg, tokenName, tokenObjectEnd);
}
@@ -1569,11 +1712,12 @@ bool OurReader::readObject(Token& /*tokenStart*/) {
"Missing '}' or object member name", tokenName, tokenObjectEnd);
}
-bool OurReader::readArray(Token& /*tokenStart*/) {
+bool OurReader::readArray(Token& tokenStart) {
Value init(arrayValue);
currentValue().swapPayload(init);
+ currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces();
- if (*current_ == ']') // empty array
+ if (current_ != end_ && *current_ == ']') // empty array
{
Token endArray;
readToken(endArray);
@@ -1611,6 +1755,8 @@ bool OurReader::decodeNumber(Token& token) {
if (!decodeNumber(token, decoded))
return false;
currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
@@ -1632,7 +1778,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
Char c = *current++;
if (c < '0' || c > '9')
return decodeDouble(token, decoded);
- Value::UInt digit(c - '0');
+ Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// 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
@@ -1659,15 +1805,43 @@ bool OurReader::decodeDouble(Token& token) {
if (!decodeDouble(token, decoded))
return false;
currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
bool OurReader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
- std::string buffer( token.start_, token.end_ );
- std::istringstream is(buffer);
- if (!(is >> value))
- return addError("'" + std::string(token.start_, token.end_) +
+ const int bufferSize = 32;
+ int count;
+ ptrdiff_t const length = token.end_ - token.start_;
+
+ // Sanity check to avoid buffer overflow exploits.
+ if (length < 0) {
+ return addError("Unable to parse token length", token);
+ }
+ size_t const ulength = static_cast<size_t>(length);
+
+ // Avoid using a string constant for the format control string given to
+ // sscanf, as this can cause hard to debug crashes on OS X. See here for more
+ // info:
+ //
+ // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
+ char format[] = "%lf";
+
+ if (length <= bufferSize) {
+ Char buffer[bufferSize + 1];
+ memcpy(buffer, token.start_, ulength);
+ buffer[length] = 0;
+ fixNumericLocaleInput(buffer, buffer + length);
+ count = sscanf(buffer, format, &value);
+ } else {
+ JSONCPP_STRING buffer(token.start_, token.end_);
+ count = sscanf(buffer.c_str(), format, &value);
+ }
+
+ if (count != 1)
+ return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
"' is not a number.",
token);
decoded = value;
@@ -1675,16 +1849,18 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
}
bool OurReader::decodeString(Token& token) {
- std::string decoded_string;
+ JSONCPP_STRING decoded_string;
if (!decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
-bool OurReader::decodeString(Token& token, std::string& decoded) {
- decoded.reserve(token.end_ - token.start_ - 2);
+bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+ decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
while (current != end) {
@@ -1768,13 +1944,13 @@ bool OurReader::decodeUnicodeCodePoint(Token& token,
bool OurReader::decodeUnicodeEscapeSequence(Token& token,
Location& current,
Location end,
- unsigned int& unicode) {
+ unsigned int& ret_unicode) {
if (end - current < 4)
return addError(
"Bad unicode escape sequence in string: four digits expected.",
token,
current);
- unicode = 0;
+ int unicode = 0;
for (int index = 0; index < 4; ++index) {
Char c = *current++;
unicode *= 16;
@@ -1790,11 +1966,12 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token,
token,
current);
}
+ ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
bool
-OurReader::addError(const std::string& message, Token& token, Location extra) {
+OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
ErrorInfo info;
info.token_ = token;
info.message_ = message;
@@ -1804,7 +1981,7 @@ OurReader::addError(const std::string& message, Token& token, Location extra) {
}
bool OurReader::recoverFromError(TokenType skipUntilToken) {
- int errorCount = int(errors_.size());
+ size_t errorCount = errors_.size();
Token skip;
for (;;) {
if (!readToken(skip))
@@ -1816,7 +1993,7 @@ bool OurReader::recoverFromError(TokenType skipUntilToken) {
return false;
}
-bool OurReader::addErrorAndRecover(const std::string& message,
+bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
Token& token,
TokenType skipUntilToken) {
addError(message, token);
@@ -1854,7 +2031,7 @@ void OurReader::getLocationLineAndColumn(Location location,
++line;
}
-std::string OurReader::getLocationLineAndColumn(Location location) const {
+JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
int line, column;
getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
@@ -1862,8 +2039,8 @@ std::string OurReader::getLocationLineAndColumn(Location location) const {
return buffer;
}
-std::string OurReader::getFormattedErrorMessages() const {
- std::string formattedMessage;
+JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
+ JSONCPP_STRING formattedMessage;
for (Errors::const_iterator itError = errors_.begin();
itError != errors_.end();
++itError) {
@@ -1878,6 +2055,60 @@ std::string OurReader::getFormattedErrorMessages() const {
return formattedMessage;
}
+std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
+ std::vector<OurReader::StructuredError> allErrors;
+ for (Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError) {
+ const ErrorInfo& error = *itError;
+ OurReader::StructuredError structured;
+ structured.offset_start = error.token_.start_ - begin_;
+ structured.offset_limit = error.token_.end_ - begin_;
+ structured.message = error.message_;
+ allErrors.push_back(structured);
+ }
+ return allErrors;
+}
+
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
+ ptrdiff_t length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = end_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = 0;
+ errors_.push_back(info);
+ return true;
+}
+
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+ ptrdiff_t length = end_ - begin_;
+ if(value.getOffsetStart() > length
+ || value.getOffsetLimit() > length
+ || extra.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = begin_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = begin_ + extra.getOffsetStart();
+ errors_.push_back(info);
+ return true;
+}
+
+bool OurReader::good() const {
+ return !errors_.size();
+}
+
class OurCharReader : public CharReader {
bool const collectComments_;
@@ -1889,9 +2120,9 @@ public:
: collectComments_(collectComments)
, reader_(features)
{}
- virtual bool parse(
+ bool parse(
char const* beginDoc, char const* endDoc,
- Value* root, std::string* errs) {
+ Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
if (errs) {
*errs = reader_.getFormattedErrorMessages();
@@ -1921,7 +2152,7 @@ CharReader* CharReaderBuilder::newCharReader() const
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
return new OurCharReader(collectComments, features);
}
-static void getValidReaderKeys(std::set<std::string>* valid_keys)
+static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
{
valid_keys->clear();
valid_keys->insert("collectComments");
@@ -1940,19 +2171,19 @@ bool CharReaderBuilder::validate(Json::Value* invalid) const
Json::Value my_invalid;
if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
Json::Value& inv = *invalid;
- std::set<std::string> valid_keys;
+ std::set<JSONCPP_STRING> valid_keys;
getValidReaderKeys(&valid_keys);
Value::Members keys = settings_.getMemberNames();
size_t n = keys.size();
for (size_t i = 0; i < n; ++i) {
- std::string const& key = keys[i];
+ JSONCPP_STRING const& key = keys[i];
if (valid_keys.find(key) == valid_keys.end()) {
inv[key] = settings_[key];
}
}
return 0u == inv.size();
}
-Value& CharReaderBuilder::operator[](std::string key)
+Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
{
return settings_[key];
}
@@ -1965,6 +2196,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["allowSingleQuotes"] = false;
+ (*settings)["stackLimit"] = 1000;
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
@@ -1991,12 +2223,12 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
// global functions
bool parseFromStream(
- CharReader::Factory const& fact, std::istream& sin,
- Value* root, std::string* errs)
+ CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
+ Value* root, JSONCPP_STRING* errs)
{
- std::ostringstream ssin;
+ JSONCPP_OSTRINGSTREAM ssin;
ssin << sin.rdbuf();
- std::string doc = ssin.str();
+ JSONCPP_STRING doc = ssin.str();
char const* begin = doc.data();
char const* end = begin + doc.size();
// Note that we do not actually need a null-terminator.
@@ -2004,16 +2236,16 @@ bool parseFromStream(
return reader->parse(begin, end, root, errs);
}
-std::istream& operator>>(std::istream& sin, Value& root) {
+JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
CharReaderBuilder b;
- std::string errs;
+ JSONCPP_STRING errs;
bool ok = parseFromStream(b, sin, &root, &errs);
if (!ok) {
fprintf(stderr,
"Error from reader: %s",
errs.c_str());
- throwRuntimeError("reader error");
+ throwRuntimeError(errs);
}
return sin;
}
@@ -2127,12 +2359,12 @@ UInt ValueIteratorBase::index() const {
return Value::UInt(-1);
}
-std::string ValueIteratorBase::name() const {
+JSONCPP_STRING ValueIteratorBase::name() const {
char const* keey;
char const* end;
keey = memberName(&end);
- if (!keey) return std::string();
- return std::string(keey, end);
+ if (!keey) return JSONCPP_STRING();
+ return JSONCPP_STRING(keey, end);
}
char const* ValueIteratorBase::memberName() const {
@@ -2164,6 +2396,9 @@ ValueConstIterator::ValueConstIterator(
const Value::ObjectValues::iterator& current)
: ValueIteratorBase(current) {}
+ValueConstIterator::ValueConstIterator(ValueIterator const& other)
+ : ValueIteratorBase(other) {}
+
ValueConstIterator& ValueConstIterator::
operator=(const ValueIteratorBase& other) {
copy(other);
@@ -2184,7 +2419,9 @@ ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
: ValueIteratorBase(current) {}
ValueIterator::ValueIterator(const ValueConstIterator& other)
- : ValueIteratorBase(other) {}
+ : ValueIteratorBase(other) {
+ throwRuntimeError("ConstIterator to Iterator should never be allowed.");
+}
ValueIterator::ValueIterator(const ValueIterator& other)
: ValueIteratorBase(other) {}
@@ -2240,13 +2477,24 @@ namespace Json {
#if defined(__ARMEL__)
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#else
-// This exists for binary compatibility only. Use nullRef.
-const Value Value::null;
#define ALIGNAS(byte_alignment)
#endif
-static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
-const unsigned char& kNullRef = kNull[0];
-const Value& Value::nullRef = reinterpret_cast<const Value&>(kNullRef);
+//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
+//const unsigned char& kNullRef = kNull[0];
+//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+//const Value& Value::nullRef = null;
+
+// static
+Value const& Value::nullSingleton()
+{
+ static Value const nullStatic;
+ return nullStatic;
+}
+
+// for backwards compatibility, we'll leave these global references around, but DO NOT
+// use them in JSONCPP library code any more!
+Value const& Value::null = Value::nullSingleton();
+Value const& Value::nullRef = Value::nullSingleton();
const Int Value::minInt = Int(~(UInt(-1) / 2));
const Int Value::maxInt = Int(UInt(-1) / 2);
@@ -2267,11 +2515,14 @@ const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
template <typename T, typename U>
static inline bool InRange(double d, T min, U max) {
+ // The casts can lose precision, but we are looking only for
+ // an approximate range. Might fail on edge cases though. ~cdunn
+ //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
return d >= min && d <= max;
}
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
static inline double integerToDouble(Json::UInt64 value) {
- return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
+ return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
}
template <typename T> static inline double integerToDouble(T value) {
@@ -2292,10 +2543,11 @@ static inline bool InRange(double d, T min, U max) {
* @return Pointer on the duplicate instance of string.
*/
static inline char* duplicateStringValue(const char* value,
- size_t length) {
+ size_t length)
+{
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
- if (length >= (size_t)Value::maxInt)
+ if (length >= static_cast<size_t>(Value::maxInt))
length = Value::maxInt - 1;
char* newString = static_cast<char*>(malloc(length + 1));
@@ -2317,7 +2569,7 @@ static inline char* duplicateAndPrefixStringValue(
{
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
- JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
+ JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
@@ -2346,7 +2598,29 @@ inline static void decodePrefixedString(
}
/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
*/
-static inline void releaseStringValue(char* value) { free(value); }
+#if JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) {
+ unsigned length = 0;
+ char const* valueDecoded;
+ decodePrefixedString(true, value, &length, &valueDecoded);
+ size_t const size = sizeof(unsigned) + length + 1U;
+ memset(value, 0, size);
+ free(value);
+}
+static inline void releaseStringValue(char* value, unsigned length) {
+ // length==0 => we allocated the strings memory
+ size_t size = (length==0) ? strlen(value) : length;
+ memset(value, 0, size);
+ free(value);
+}
+#else // !JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) {
+ free(value);
+}
+static inline void releaseStringValue(char* value, unsigned) {
+ free(value);
+}
+#endif // JSONCPP_USING_SECURE_MEMORY
} // namespace Json
@@ -2364,26 +2638,26 @@ static inline void releaseStringValue(char* value) { free(value); }
namespace Json {
-Exception::Exception(std::string const& msg)
+Exception::Exception(JSONCPP_STRING const& msg)
: msg_(msg)
{}
-Exception::~Exception() throw()
+Exception::~Exception() JSONCPP_NOEXCEPT
{}
-char const* Exception::what() const throw()
+char const* Exception::what() const JSONCPP_NOEXCEPT
{
return msg_.c_str();
}
-RuntimeError::RuntimeError(std::string const& msg)
+RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
: Exception(msg)
{}
-LogicError::LogicError(std::string const& msg)
+LogicError::LogicError(JSONCPP_STRING const& msg)
: Exception(msg)
{}
-JSONCPP_NORETURN void throwRuntimeError(std::string const& msg)
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
{
throw RuntimeError(msg);
}
-JSONCPP_NORETURN void throwLogicError(std::string const& msg)
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
{
throw LogicError(msg);
}
@@ -2396,16 +2670,17 @@ JSONCPP_NORETURN void throwLogicError(std::string const& msg)
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
-Value::CommentInfo::CommentInfo() : comment_(0) {}
+Value::CommentInfo::CommentInfo() : comment_(0)
+{}
Value::CommentInfo::~CommentInfo() {
if (comment_)
- releaseStringValue(comment_);
+ releaseStringValue(comment_, 0u);
}
void Value::CommentInfo::setComment(const char* text, size_t len) {
if (comment_) {
- releaseStringValue(comment_);
+ releaseStringValue(comment_, 0u);
comment_ = 0;
}
JSON_ASSERT(text != 0);
@@ -2430,28 +2705,34 @@ void Value::CommentInfo::setComment(const char* text, size_t len) {
Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
- : cstr_(str)
-{
+ : cstr_(str) {
// allocate != duplicate
storage_.policy_ = allocate & 0x3;
storage_.length_ = ulength & 0x3FFFFFFF;
}
-Value::CZString::CZString(const CZString& other)
- : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0
- ? duplicateStringValue(other.cstr_, other.storage_.length_)
- : other.cstr_)
-{
- storage_.policy_ = (other.cstr_
+Value::CZString::CZString(const CZString& other) {
+ cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
+ ? duplicateStringValue(other.cstr_, other.storage_.length_)
+ : other.cstr_);
+ storage_.policy_ = static_cast<unsigned>(other.cstr_
? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
? noDuplication : duplicate)
- : static_cast<DuplicationPolicy>(other.storage_.policy_));
+ : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
storage_.length_ = other.storage_.length_;
}
+#if JSON_HAS_RVALUE_REFERENCES
+Value::CZString::CZString(CZString&& other)
+ : cstr_(other.cstr_), index_(other.index_) {
+ other.cstr_ = nullptr;
+}
+#endif
+
Value::CZString::~CZString() {
- if (cstr_ && storage_.policy_ == duplicate)
- releaseStringValue(const_cast<char*>(cstr_));
+ if (cstr_ && storage_.policy_ == duplicate) {
+ releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
+ }
}
void Value::CZString::swap(CZString& other) {
@@ -2471,6 +2752,7 @@ bool Value::CZString::operator<(const CZString& other) const {
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
unsigned min_len = std::min(this_len, other_len);
+ JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, min_len);
if (comp < 0) return true;
if (comp > 0) return false;
@@ -2484,6 +2766,7 @@ bool Value::CZString::operator==(const CZString& other) const {
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
if (this_len != other_len) return false;
+ JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, this_len);
return comp == 0;
}
@@ -2508,6 +2791,7 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
* This optimization is used in ValueInternalMap fast allocator.
*/
Value::Value(ValueType vtype) {
+ static char const emptyString[] = "";
initBasic(vtype);
switch (vtype) {
case nullValue:
@@ -2520,7 +2804,8 @@ Value::Value(ValueType vtype) {
value_.real_ = 0.0;
break;
case stringValue:
- value_.string_ = 0;
+ // allocated_ == false, so this is safe.
+ value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
break;
case arrayValue:
case objectValue:
@@ -2570,7 +2855,7 @@ Value::Value(const char* beginValue, const char* endValue) {
duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
}
-Value::Value(const std::string& value) {
+Value::Value(const JSONCPP_STRING& value) {
initBasic(stringValue, true);
value_.string_ =
duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
@@ -2596,7 +2881,7 @@ Value::Value(bool value) {
Value::Value(Value const& other)
: type_(other.type_), allocated_(false)
,
- comments_(0)
+ comments_(0), start_(other.start_), limit_(other.limit_)
{
switch (type_) {
case nullValue:
@@ -2637,6 +2922,14 @@ Value::Value(Value const& other)
}
}
+#if JSON_HAS_RVALUE_REFERENCES
+// Move constructor
+Value::Value(Value&& other) {
+ initBasic(nullValue);
+ swap(other);
+}
+#endif
+
Value::~Value() {
switch (type_) {
case nullValue:
@@ -2647,7 +2940,7 @@ Value::~Value() {
break;
case stringValue:
if (allocated_)
- releaseStringValue(value_.string_);
+ releasePrefixedStringValue(value_.string_);
break;
case arrayValue:
case objectValue:
@@ -2657,13 +2950,13 @@ Value::~Value() {
JSON_ASSERT_UNREACHABLE;
}
- if (comments_)
- delete[] comments_;
+ delete[] comments_;
+
+ value_.uint_ = 0;
}
-Value &Value::operator=(const Value &other) {
- Value temp(other);
- swap(temp);
+Value& Value::operator=(Value other) {
+ swap(other);
return *this;
}
@@ -2680,6 +2973,8 @@ void Value::swapPayload(Value& other) {
void Value::swap(Value& other) {
swapPayload(other);
std::swap(comments_, other.comments_);
+ std::swap(start_, other.start_);
+ std::swap(limit_, other.limit_);
}
ValueType Value::type() const { return type_; }
@@ -2720,6 +3015,7 @@ bool Value::operator<(const Value& other) const {
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
unsigned min_len = std::min(this_len, other_len);
+ JSON_ASSERT(this_str && other_str);
int comp = memcmp(this_str, other_str, min_len);
if (comp < 0) return true;
if (comp > 0) return false;
@@ -2775,6 +3071,7 @@ bool Value::operator==(const Value& other) const {
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
if (this_len != other_len) return false;
+ JSON_ASSERT(this_str && other_str);
int comp = memcmp(this_str, other_str, this_len);
return comp == 0;
}
@@ -2800,6 +3097,18 @@ const char* Value::asCString() const {
return this_str;
}
+#if JSONCPP_USING_SECURE_MEMORY
+unsigned Value::getCStringLength() const {
+ JSON_ASSERT_MESSAGE(type_ == stringValue,
+ "in Json::Value::asCString(): requires stringValue");
+ if (value_.string_ == 0) return 0;
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ return this_len;
+}
+#endif
+
bool Value::getString(char const** str, char const** cend) const {
if (type_ != stringValue) return false;
if (value_.string_ == 0) return false;
@@ -2809,7 +3118,7 @@ bool Value::getString(char const** str, char const** cend) const {
return true;
}
-std::string Value::asString() const {
+JSONCPP_STRING Value::asString() const {
switch (type_) {
case nullValue:
return "";
@@ -2819,7 +3128,7 @@ std::string Value::asString() const {
unsigned this_len;
char const* this_str;
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
- return std::string(this_str, this_len);
+ return JSONCPP_STRING(this_str, this_len);
}
case booleanValue:
return value_.bool_ ? "true" : "false";
@@ -2979,7 +3288,8 @@ float Value::asFloat() const {
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
return static_cast<float>(value_.uint_);
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
- return integerToDouble(value_.uint_);
+ // This can fail (silently?) if the value is bigger than MAX_FLOAT.
+ return static_cast<float>(integerToDouble(value_.uint_));
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
case realValue:
return static_cast<float>(value_.real_);
@@ -3082,6 +3392,8 @@ void Value::clear() {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
type_ == objectValue,
"in Json::Value::clear(): requires complex value");
+ start_ = 0;
+ limit_ = 0;
switch (type_) {
case arrayValue:
case objectValue:
@@ -3106,7 +3418,7 @@ void Value::resize(ArrayIndex newSize) {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
value_.map_->erase(index);
}
- assert(size() == newSize);
+ JSON_ASSERT(size() == newSize);
}
}
@@ -3121,7 +3433,7 @@ Value& Value::operator[](ArrayIndex index) {
if (it != value_.map_->end() && (*it).first == key)
return (*it).second;
- ObjectValues::value_type defaultValue(key, nullRef);
+ ObjectValues::value_type defaultValue(key, nullSingleton());
it = value_.map_->insert(it, defaultValue);
return (*it).second;
}
@@ -3138,11 +3450,11 @@ const Value& Value::operator[](ArrayIndex index) const {
type_ == nullValue || type_ == arrayValue,
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
if (type_ == nullValue)
- return nullRef;
+ return nullSingleton();
CZString key(index);
ObjectValues::const_iterator it = value_.map_->find(key);
if (it == value_.map_->end())
- return nullRef;
+ return nullSingleton();
return (*it).second;
}
@@ -3157,6 +3469,8 @@ void Value::initBasic(ValueType vtype, bool allocated) {
type_ = vtype;
allocated_ = allocated;
comments_ = 0;
+ start_ = 0;
+ limit_ = 0;
}
// Access an object value by name, create a null member if it does not exist.
@@ -3174,7 +3488,7 @@ Value& Value::resolveReference(const char* key) {
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
- ObjectValues::value_type defaultValue(actualKey, nullRef);
+ ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
@@ -3194,7 +3508,7 @@ Value& Value::resolveReference(char const* key, char const* cend)
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
- ObjectValues::value_type defaultValue(actualKey, nullRef);
+ ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
@@ -3202,7 +3516,7 @@ Value& Value::resolveReference(char const* key, char const* cend)
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
const Value* value = &((*this)[index]);
- return value == &nullRef ? defaultValue : *value;
+ return value == &nullSingleton() ? defaultValue : *value;
}
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
@@ -3221,13 +3535,13 @@ Value const* Value::find(char const* key, char const* cend) const
const Value& Value::operator[](const char* key) const
{
Value const* found = find(key, key + strlen(key));
- if (!found) return nullRef;
+ if (!found) return nullSingleton();
return *found;
}
-Value const& Value::operator[](std::string const& key) const
+Value const& Value::operator[](JSONCPP_STRING const& key) const
{
Value const* found = find(key.data(), key.data() + key.length());
- if (!found) return nullRef;
+ if (!found) return nullSingleton();
return *found;
}
@@ -3235,7 +3549,7 @@ Value& Value::operator[](const char* key) {
return resolveReference(key, key + strlen(key));
}
-Value& Value::operator[](const std::string& key) {
+Value& Value::operator[](const JSONCPP_STRING& key) {
return resolveReference(key.data(), key.data() + key.length());
}
@@ -3250,7 +3564,7 @@ Value& Value::operator[](const CppTL::ConstString& key) {
Value const& Value::operator[](CppTL::ConstString const& key) const
{
Value const* found = find(key.c_str(), key.end_c_str());
- if (!found) return nullRef;
+ if (!found) return nullSingleton();
return *found;
}
#endif
@@ -3266,7 +3580,7 @@ Value Value::get(char const* key, Value const& defaultValue) const
{
return get(key, key + strlen(key), defaultValue);
}
-Value Value::get(std::string const& key, Value const& defaultValue) const
+Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
{
return get(key.data(), key.data() + key.length(), defaultValue);
}
@@ -3289,7 +3603,7 @@ bool Value::removeMember(const char* key, Value* removed)
{
return removeMember(key, key + strlen(key), removed);
}
-bool Value::removeMember(std::string const& key, Value* removed)
+bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
{
return removeMember(key.data(), key.data() + key.length(), removed);
}
@@ -3298,13 +3612,13 @@ Value Value::removeMember(const char* key)
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue)
- return nullRef;
+ return nullSingleton();
Value removed; // null
removeMember(key, key + strlen(key), &removed);
return removed; // still null if removeMember() did nothing
}
-Value Value::removeMember(const std::string& key)
+Value Value::removeMember(const JSONCPP_STRING& key)
{
return removeMember(key.c_str());
}
@@ -3348,7 +3662,7 @@ bool Value::isMember(char const* key) const
{
return isMember(key, key + strlen(key));
}
-bool Value::isMember(std::string const& key) const
+bool Value::isMember(JSONCPP_STRING const& key) const
{
return isMember(key.data(), key.data() + key.length());
}
@@ -3370,7 +3684,7 @@ Value::Members Value::getMemberNames() const {
ObjectValues::const_iterator it = value_.map_->begin();
ObjectValues::const_iterator itEnd = value_.map_->end();
for (; it != itEnd; ++it) {
- members.push_back(std::string((*it).first.data(),
+ members.push_back(JSONCPP_STRING((*it).first.data(),
(*it).first.length()));
}
return members;
@@ -3413,7 +3727,11 @@ bool Value::isBool() const { return type_ == booleanValue; }
bool Value::isInt() const {
switch (type_) {
case intValue:
+#if defined(JSON_HAS_INT64)
return value_.int_ >= minInt && value_.int_ <= maxInt;
+#else
+ return true;
+#endif
case uintValue:
return value_.uint_ <= UInt(maxInt);
case realValue:
@@ -3428,9 +3746,17 @@ bool Value::isInt() const {
bool Value::isUInt() const {
switch (type_) {
case intValue:
+#if defined(JSON_HAS_INT64)
return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+#else
+ return value_.int_ >= 0;
+#endif
case uintValue:
+#if defined(JSON_HAS_INT64)
return value_.uint_ <= maxUInt;
+#else
+ return true;
+#endif
case realValue:
return value_.real_ >= 0 && value_.real_ <= maxUInt &&
IsIntegral(value_.real_);
@@ -3488,9 +3814,9 @@ bool Value::isIntegral() const {
#endif
}
-bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
+bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
-bool Value::isNumeric() const { return isIntegral() || isDouble(); }
+bool Value::isNumeric() const { return isDouble(); }
bool Value::isString() const { return type_ == stringValue; }
@@ -3512,7 +3838,7 @@ void Value::setComment(const char* comment, CommentPlacement placement) {
setComment(comment, strlen(comment), placement);
}
-void Value::setComment(const std::string& comment, CommentPlacement placement) {
+void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
setComment(comment.c_str(), comment.length(), placement);
}
@@ -3520,13 +3846,21 @@ bool Value::hasComment(CommentPlacement placement) const {
return comments_ != 0 && comments_[placement].comment_ != 0;
}
-std::string Value::getComment(CommentPlacement placement) const {
+JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
if (hasComment(placement))
return comments_[placement].comment_;
return "";
}
-std::string Value::toStyledString() const {
+void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
+
+void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
+
+ptrdiff_t Value::getOffsetStart() const { return start_; }
+
+ptrdiff_t Value::getOffsetLimit() const { return limit_; }
+
+JSONCPP_STRING Value::toStyledString() const {
StyledWriter writer;
return writer.write(*this);
}
@@ -3594,13 +3928,13 @@ PathArgument::PathArgument(ArrayIndex index)
PathArgument::PathArgument(const char* key)
: key_(key), index_(), kind_(kindKey) {}
-PathArgument::PathArgument(const std::string& key)
+PathArgument::PathArgument(const JSONCPP_STRING& key)
: key_(key.c_str()), index_(), kind_(kindKey) {}
// class Path
// //////////////////////////////////////////////////////////////////
-Path::Path(const std::string& path,
+Path::Path(const JSONCPP_STRING& path,
const PathArgument& a1,
const PathArgument& a2,
const PathArgument& a3,
@@ -3615,7 +3949,7 @@ Path::Path(const std::string& path,
makePath(path, in);
}
-void Path::makePath(const std::string& path, const InArgs& in) {
+void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
const char* current = path.c_str();
const char* end = current + path.length();
InArgs::const_iterator itInArg = in.begin();
@@ -3630,23 +3964,23 @@ void Path::makePath(const std::string& path, const InArgs& in) {
index = index * 10 + ArrayIndex(*current - '0');
args_.push_back(index);
}
- if (current == end || *current++ != ']')
+ if (current == end || *++current != ']')
invalidPath(path, int(current - path.c_str()));
} else if (*current == '%') {
addPathInArg(path, in, itInArg, PathArgument::kindKey);
++current;
- } else if (*current == '.') {
+ } else if (*current == '.' || *current == ']') {
++current;
} else {
const char* beginName = current;
while (current != end && !strchr("[.", *current))
++current;
- args_.push_back(std::string(beginName, current));
+ args_.push_back(JSONCPP_STRING(beginName, current));
}
}
}
-void Path::addPathInArg(const std::string& /*path*/,
+void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
const InArgs& in,
InArgs::const_iterator& itInArg,
PathArgument::Kind kind) {
@@ -3655,11 +3989,11 @@ void Path::addPathInArg(const std::string& /*path*/,
} else if ((*itInArg)->kind_ != kind) {
// Error: bad argument type
} else {
- args_.push_back(**itInArg);
+ args_.push_back(**itInArg++);
}
}
-void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
+void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
// Error: invalid path.
}
@@ -3670,16 +4004,19 @@ const Value& Path::resolve(const Value& root) const {
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
// Error: unable to resolve path (array value expected at position...
+ return Value::null;
}
node = &((*node)[arg.index_]);
} else if (arg.kind_ == PathArgument::kindKey) {
if (!node->isObject()) {
// Error: unable to resolve path (object value expected at position...)
+ return Value::null;
}
node = &((*node)[arg.key_]);
- if (node == &Value::nullRef) {
+ if (node == &Value::nullSingleton()) {
// Error: unable to resolve path (object has no member named '' at
// position...)
+ return Value::null;
}
}
}
@@ -3698,7 +4035,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
if (!node->isObject())
return defaultValue;
node = &((*node)[arg.key_]);
- if (node == &Value::nullRef)
+ if (node == &Value::nullSingleton())
return defaultValue;
}
}
@@ -3761,12 +4098,31 @@ Value& Path::make(Value& root) const {
#include <float.h>
#define isfinite _finite
#elif defined(__sun) && defined(__SVR4) //Solaris
+#if !defined(isfinite)
#include <ieeefp.h>
#define isfinite finite
+#endif
+#elif defined(_AIX)
+#if !defined(isfinite)
+#include <math.h>
+#define isfinite finite
+#endif
+#elif defined(__hpux)
+#if !defined(isfinite)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
+ _Isfinitef(x) : _IsFinite(x)))
+#else
+#include <math.h>
+#define isfinite finite
+#endif
+#endif
#else
#include <cmath>
+#if !(defined(__QNXNTO__)) // QNX already defines isfinite
#define isfinite std::isfinite
#endif
+#endif
#if defined(_MSC_VER)
#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
@@ -3776,13 +4132,15 @@ Value& Path::make(Value& root) const {
#else
#define snprintf _snprintf
#endif
-#elif defined(__ANDROID__)
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
#define snprintf snprintf
#elif __cplusplus >= 201103L
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
#define snprintf std::snprintf
#endif
+#endif
-#if defined(__BORLANDC__)
+#if defined(__BORLANDC__)
#include <float.h>
#define isfinite _finite
#define snprintf _snprintf
@@ -3795,7 +4153,11 @@ Value& Path::make(Value& root) const {
namespace Json {
-typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
+#else
+typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
+#endif
static bool containsControlCharacter(const char* str) {
while (*str) {
@@ -3815,7 +4177,7 @@ static bool containsControlCharacter0(const char* str, unsigned len) {
return false;
}
-std::string valueToString(LargestInt value) {
+JSONCPP_STRING valueToString(LargestInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
if (value == Value::minLargestInt) {
@@ -3831,7 +4193,7 @@ std::string valueToString(LargestInt value) {
return current;
}
-std::string valueToString(LargestUInt value) {
+JSONCPP_STRING valueToString(LargestUInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
uintToString(value, current);
@@ -3841,20 +4203,21 @@ std::string valueToString(LargestUInt value) {
#if defined(JSON_HAS_INT64)
-std::string valueToString(Int value) {
+JSONCPP_STRING valueToString(Int value) {
return valueToString(LargestInt(value));
}
-std::string valueToString(UInt value) {
+JSONCPP_STRING valueToString(UInt value) {
return valueToString(LargestUInt(value));
}
#endif // # if defined(JSON_HAS_INT64)
-std::string valueToString(double value, bool useSpecialFloats, unsigned int precision) {
+namespace {
+JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
// Allocate a buffer that is more than large enough to store the 16 digits of
// precision requested below.
- char buffer[32];
+ char buffer[36];
int len = -1;
char formatString[6];
@@ -3865,6 +4228,12 @@ std::string valueToString(double value, bool useSpecialFloats, unsigned int prec
// concepts of reals and integers.
if (isfinite(value)) {
len = snprintf(buffer, sizeof(buffer), formatString, value);
+
+ // try to ensure we preserve the fact that this was given to us as a double on input
+ if (!strstr(buffer, ".") && !strstr(buffer, "e")) {
+ strcat(buffer, ".0");
+ }
+
} else {
// IEEE standard states that NaN values will not compare to themselves
if (value != value) {
@@ -3880,24 +4249,25 @@ std::string valueToString(double value, bool useSpecialFloats, unsigned int prec
fixNumericLocale(buffer, buffer + len);
return buffer;
}
+}
-std::string valueToString(double value) { return valueToString(value, false, 17); }
+JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
-std::string valueToString(bool value) { return value ? "true" : "false"; }
+JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
-std::string valueToQuotedString(const char* value) {
+JSONCPP_STRING valueToQuotedString(const char* value) {
if (value == NULL)
return "";
// Not sure how to handle unicode...
if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
!containsControlCharacter(value))
- return std::string("\"") + value + "\"";
+ return JSONCPP_STRING("\"") + value + "\"";
// We have to walk value and escape any special characters.
- // Appending to std::string is not efficient, but this should be rare.
+ // Appending to JSONCPP_STRING is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
- std::string::size_type maxsize =
+ JSONCPP_STRING::size_type maxsize =
strlen(value) * 2 + 3; // allescaped+quotes+NULL
- std::string result;
+ JSONCPP_STRING result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
for (const char* c = value; *c != 0; ++c) {
@@ -3933,7 +4303,7 @@ std::string valueToQuotedString(const char* value) {
// sequence from occurring.
default:
if (isControlCharacter(*c)) {
- std::ostringstream oss;
+ JSONCPP_OSTRINGSTREAM oss;
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
<< std::setw(4) << static_cast<int>(*c);
result += oss.str();
@@ -3962,19 +4332,19 @@ static char const* strnpbrk(char const* s, char const* accept, size_t n) {
}
return NULL;
}
-static std::string valueToQuotedStringN(const char* value, unsigned length) {
+static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
if (value == NULL)
return "";
// Not sure how to handle unicode...
if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
!containsControlCharacter0(value, length))
- return std::string("\"") + value + "\"";
+ return JSONCPP_STRING("\"") + value + "\"";
// We have to walk value and escape any special characters.
- // Appending to std::string is not efficient, but this should be rare.
+ // Appending to JSONCPP_STRING is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
- std::string::size_type maxsize =
+ JSONCPP_STRING::size_type maxsize =
length * 2 + 3; // allescaped+quotes+NULL
- std::string result;
+ JSONCPP_STRING result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
char const* end = value + length;
@@ -4011,7 +4381,7 @@ static std::string valueToQuotedStringN(const char* value, unsigned length) {
// sequence from occurring.
default:
if ((isControlCharacter(*c)) || (*c == 0)) {
- std::ostringstream oss;
+ JSONCPP_OSTRINGSTREAM oss;
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
<< std::setw(4) << static_cast<int>(*c);
result += oss.str();
@@ -4033,21 +4403,28 @@ Writer::~Writer() {}
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
- : yamlCompatiblityEnabled_(false) {}
+ : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
+ omitEndingLineFeed_(false) {}
void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
-std::string FastWriter::write(const Value& root) {
+void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
+
+void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
+
+JSONCPP_STRING FastWriter::write(const Value& root) {
document_ = "";
writeValue(root);
- document_ += "\n";
+ if (!omitEndingLineFeed_)
+ document_ += "\n";
return document_;
}
void FastWriter::writeValue(const Value& value) {
switch (value.type()) {
case nullValue:
- document_ += "null";
+ if (!dropNullPlaceholders_)
+ document_ += "null";
break;
case intValue:
document_ += valueToString(value.asLargestInt());
@@ -4060,7 +4437,7 @@ void FastWriter::writeValue(const Value& value) {
break;
case stringValue:
{
- // Is NULL possible for value.string_?
+ // Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
@@ -4072,8 +4449,8 @@ void FastWriter::writeValue(const Value& value) {
break;
case arrayValue: {
document_ += '[';
- int size = value.size();
- for (int index = 0; index < size; ++index) {
+ ArrayIndex size = value.size();
+ for (ArrayIndex index = 0; index < size; ++index) {
if (index > 0)
document_ += ',';
writeValue(value[index]);
@@ -4085,7 +4462,7 @@ void FastWriter::writeValue(const Value& value) {
document_ += '{';
for (Value::Members::iterator it = members.begin(); it != members.end();
++it) {
- const std::string& name = *it;
+ const JSONCPP_STRING& name = *it;
if (it != members.begin())
document_ += ',';
document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
@@ -4103,7 +4480,7 @@ void FastWriter::writeValue(const Value& value) {
StyledWriter::StyledWriter()
: rightMargin_(74), indentSize_(3), addChildValues_() {}
-std::string StyledWriter::write(const Value& root) {
+JSONCPP_STRING StyledWriter::write(const Value& root) {
document_ = "";
addChildValues_ = false;
indentString_ = "";
@@ -4130,7 +4507,7 @@ void StyledWriter::writeValue(const Value& value) {
break;
case stringValue:
{
- // Is NULL possible for value.string_?
+ // Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
@@ -4153,7 +4530,7 @@ void StyledWriter::writeValue(const Value& value) {
indent();
Value::Members::iterator it = members.begin();
for (;;) {
- const std::string& name = *it;
+ const JSONCPP_STRING& name = *it;
const Value& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedString(name.c_str()));
@@ -4217,26 +4594,25 @@ void StyledWriter::writeArrayValue(const Value& value) {
}
bool StyledWriter::isMultineArray(const Value& value) {
- int size = value.size();
+ ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
- for (int index = 0; index < size && !isMultiLine; ++index) {
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
- isMultiLine =
- isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
childValues_.reserve(size);
addChildValues_ = true;
- int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
- for (int index = 0; index < size; ++index) {
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
writeValue(value[index]);
- lineLength += int(childValues_[index].length());
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
addChildValues_ = false;
isMultiLine = isMultiLine || lineLength >= rightMargin_;
@@ -4244,7 +4620,7 @@ bool StyledWriter::isMultineArray(const Value& value) {
return isMultiLine;
}
-void StyledWriter::pushValue(const std::string& value) {
+void StyledWriter::pushValue(const JSONCPP_STRING& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -4262,15 +4638,15 @@ void StyledWriter::writeIndent() {
document_ += indentString_;
}
-void StyledWriter::writeWithIndent(const std::string& value) {
+void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
writeIndent();
document_ += value;
}
-void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
+void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
void StyledWriter::unindent() {
- assert(int(indentString_.size()) >= indentSize_);
+ assert(indentString_.size() >= indentSize_);
indentString_.resize(indentString_.size() - indentSize_);
}
@@ -4280,8 +4656,8 @@ void StyledWriter::writeCommentBeforeValue(const Value& root) {
document_ += "\n";
writeIndent();
- const std::string& comment = root.getComment(commentBefore);
- std::string::const_iterator iter = comment.begin();
+ const JSONCPP_STRING& comment = root.getComment(commentBefore);
+ JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
document_ += *iter;
if (*iter == '\n' &&
@@ -4314,11 +4690,11 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
// Class StyledStreamWriter
// //////////////////////////////////////////////////////////////////
-StyledStreamWriter::StyledStreamWriter(std::string indentation)
+StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
: document_(NULL), rightMargin_(74), indentation_(indentation),
addChildValues_() {}
-void StyledStreamWriter::write(std::ostream& out, const Value& root) {
+void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
document_ = &out;
addChildValues_ = false;
indentString_ = "";
@@ -4348,7 +4724,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
break;
case stringValue:
{
- // Is NULL possible for value.string_?
+ // Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
@@ -4371,7 +4747,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
indent();
Value::Members::iterator it = members.begin();
for (;;) {
- const std::string& name = *it;
+ const JSONCPP_STRING& name = *it;
const Value& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedString(name.c_str()));
@@ -4437,26 +4813,25 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
}
bool StyledStreamWriter::isMultineArray(const Value& value) {
- int size = value.size();
+ ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
- for (int index = 0; index < size && !isMultiLine; ++index) {
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
- isMultiLine =
- isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
childValues_.reserve(size);
addChildValues_ = true;
- int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
- for (int index = 0; index < size; ++index) {
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
writeValue(value[index]);
- lineLength += int(childValues_[index].length());
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
addChildValues_ = false;
isMultiLine = isMultiLine || lineLength >= rightMargin_;
@@ -4464,7 +4839,7 @@ bool StyledStreamWriter::isMultineArray(const Value& value) {
return isMultiLine;
}
-void StyledStreamWriter::pushValue(const std::string& value) {
+void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -4479,7 +4854,7 @@ void StyledStreamWriter::writeIndent() {
*document_ << '\n' << indentString_;
}
-void StyledStreamWriter::writeWithIndent(const std::string& value) {
+void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
if (!indented_) writeIndent();
*document_ << value;
indented_ = false;
@@ -4497,8 +4872,8 @@ void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
return;
if (!indented_) writeIndent();
- const std::string& comment = root.getComment(commentBefore);
- std::string::const_iterator iter = comment.begin();
+ const JSONCPP_STRING& comment = root.getComment(commentBefore);
+ JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
*document_ << *iter;
if (*iter == '\n' &&
@@ -4543,48 +4918,48 @@ struct CommentStyle {
struct BuiltStyledStreamWriter : public StreamWriter
{
BuiltStyledStreamWriter(
- std::string const& indentation,
+ JSONCPP_STRING const& indentation,
CommentStyle::Enum cs,
- std::string const& colonSymbol,
- std::string const& nullSymbol,
- std::string const& endingLineFeedSymbol,
+ JSONCPP_STRING const& colonSymbol,
+ JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol,
bool useSpecialFloats,
unsigned int precision);
- virtual int write(Value const& root, std::ostream* sout);
+ int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
private:
void writeValue(Value const& value);
void writeArrayValue(Value const& value);
bool isMultineArray(Value const& value);
- void pushValue(std::string const& value);
+ void pushValue(JSONCPP_STRING const& value);
void writeIndent();
- void writeWithIndent(std::string const& value);
+ void writeWithIndent(JSONCPP_STRING const& value);
void indent();
void unindent();
void writeCommentBeforeValue(Value const& root);
void writeCommentAfterValueOnSameLine(Value const& root);
static bool hasCommentForValue(const Value& value);
- typedef std::vector<std::string> ChildValues;
+ typedef std::vector<JSONCPP_STRING> ChildValues;
ChildValues childValues_;
- std::string indentString_;
- int rightMargin_;
- std::string indentation_;
+ JSONCPP_STRING indentString_;
+ unsigned int rightMargin_;
+ JSONCPP_STRING indentation_;
CommentStyle::Enum cs_;
- std::string colonSymbol_;
- std::string nullSymbol_;
- std::string endingLineFeedSymbol_;
+ JSONCPP_STRING colonSymbol_;
+ JSONCPP_STRING nullSymbol_;
+ JSONCPP_STRING endingLineFeedSymbol_;
bool addChildValues_ : 1;
bool indented_ : 1;
bool useSpecialFloats_ : 1;
unsigned int precision_;
};
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
- std::string const& indentation,
+ JSONCPP_STRING const& indentation,
CommentStyle::Enum cs,
- std::string const& colonSymbol,
- std::string const& nullSymbol,
- std::string const& endingLineFeedSymbol,
+ JSONCPP_STRING const& colonSymbol,
+ JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol,
bool useSpecialFloats,
unsigned int precision)
: rightMargin_(74)
@@ -4599,7 +4974,7 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
, precision_(precision)
{
}
-int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
+int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
{
sout_ = sout;
addChildValues_ = false;
@@ -4630,7 +5005,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
break;
case stringValue:
{
- // Is NULL is possible for value.string_?
+ // Is NULL is possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
@@ -4653,7 +5028,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
indent();
Value::Members::iterator it = members.begin();
for (;;) {
- std::string const& name = *it;
+ JSONCPP_STRING const& name = *it;
Value const& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
@@ -4711,7 +5086,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
if (!indentation_.empty()) *sout_ << " ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
- *sout_ << ", ";
+ *sout_ << ((!indentation_.empty()) ? ", " : ",");
*sout_ << childValues_[index];
}
if (!indentation_.empty()) *sout_ << " ";
@@ -4721,26 +5096,25 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
}
bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
- int size = value.size();
+ ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
- for (int index = 0; index < size && !isMultiLine; ++index) {
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
Value const& childValue = value[index];
- isMultiLine =
- isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
childValues_.reserve(size);
addChildValues_ = true;
- int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
- for (int index = 0; index < size; ++index) {
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
writeValue(value[index]);
- lineLength += int(childValues_[index].length());
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
addChildValues_ = false;
isMultiLine = isMultiLine || lineLength >= rightMargin_;
@@ -4748,7 +5122,7 @@ bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
return isMultiLine;
}
-void BuiltStyledStreamWriter::pushValue(std::string const& value) {
+void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -4767,7 +5141,7 @@ void BuiltStyledStreamWriter::writeIndent() {
}
}
-void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) {
+void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
if (!indented_) writeIndent();
*sout_ << value;
indented_ = false;
@@ -4786,8 +5160,8 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
return;
if (!indented_) writeIndent();
- const std::string& comment = root.getComment(commentBefore);
- std::string::const_iterator iter = comment.begin();
+ const JSONCPP_STRING& comment = root.getComment(commentBefore);
+ JSONCPP_STRING::const_iterator iter = comment.begin();
while (iter != comment.end()) {
*sout_ << *iter;
if (*iter == '\n' &&
@@ -4837,11 +5211,11 @@ StreamWriterBuilder::~StreamWriterBuilder()
{}
StreamWriter* StreamWriterBuilder::newStreamWriter() const
{
- std::string indentation = settings_["indentation"].asString();
- std::string cs_str = settings_["commentStyle"].asString();
+ JSONCPP_STRING indentation = settings_["indentation"].asString();
+ JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
bool eyc = settings_["enableYAMLCompatibility"].asBool();
bool dnp = settings_["dropNullPlaceholders"].asBool();
- bool usf = settings_["useSpecialFloats"].asBool();
+ bool usf = settings_["useSpecialFloats"].asBool();
unsigned int pre = settings_["precision"].asUInt();
CommentStyle::Enum cs = CommentStyle::All;
if (cs_str == "All") {
@@ -4851,23 +5225,23 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const
} else {
throwRuntimeError("commentStyle must be 'All' or 'None'");
}
- std::string colonSymbol = " : ";
+ JSONCPP_STRING colonSymbol = " : ";
if (eyc) {
colonSymbol = ": ";
} else if (indentation.empty()) {
colonSymbol = ":";
}
- std::string nullSymbol = "null";
+ JSONCPP_STRING nullSymbol = "null";
if (dnp) {
nullSymbol = "";
}
if (pre > 17) pre = 17;
- std::string endingLineFeedSymbol = "";
+ JSONCPP_STRING endingLineFeedSymbol = "";
return new BuiltStyledStreamWriter(
indentation, cs,
colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
}
-static void getValidWriterKeys(std::set<std::string>* valid_keys)
+static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
{
valid_keys->clear();
valid_keys->insert("indentation");
@@ -4882,19 +5256,19 @@ bool StreamWriterBuilder::validate(Json::Value* invalid) const
Json::Value my_invalid;
if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
Json::Value& inv = *invalid;
- std::set<std::string> valid_keys;
+ std::set<JSONCPP_STRING> valid_keys;
getValidWriterKeys(&valid_keys);
Value::Members keys = settings_.getMemberNames();
size_t n = keys.size();
for (size_t i = 0; i < n; ++i) {
- std::string const& key = keys[i];
+ JSONCPP_STRING const& key = keys[i];
if (valid_keys.find(key) == valid_keys.end()) {
inv[key] = settings_[key];
}
}
return 0u == inv.size();
}
-Value& StreamWriterBuilder::operator[](std::string key)
+Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
{
return settings_[key];
}
@@ -4911,14 +5285,14 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings)
//! [StreamWriterBuilderDefaults]
}
-std::string writeString(StreamWriter::Factory const& builder, Value const& root) {
- std::ostringstream sout;
+JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
+ JSONCPP_OSTRINGSTREAM sout;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);
return sout.str();
}
-std::ostream& operator<<(std::ostream& sout, Value const& root) {
+JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
StreamWriterBuilder builder;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);