summaryrefslogtreecommitdiff
path: root/json
diff options
context:
space:
mode:
authorAndrew Lamoureux <andrew@vector35.com>2017-03-15 13:41:40 -0400
committerAndrew Lamoureux <andrew@vector35.com>2017-03-15 13:41:40 -0400
commit14fe0e379f5c9f10011750232c63d4f057dcf26d (patch)
tree0bfa07702311c257d8295d1301c07c72e54d8d07 /json
parent2f71ffd2a1ab18eeaf9c3c7821343c7a820679b9 (diff)
parent5a42aec73a77a3a54baf054cde9047533709be31 (diff)
Merge branch 'dev' of https://github.com/bambu/binaryninja-api into bambu-dev
Diffstat (limited to 'json')
-rw-r--r--json/json-forwards.h330
-rw-r--r--json/json.h450
-rw-r--r--json/jsoncpp.cpp1110
3 files changed, 1292 insertions, 598 deletions
diff --git a/json/json-forwards.h b/json/json-forwards.h
new file mode 100644
index 00000000..34243899
--- /dev/null
+++ b/json/json-forwards.h
@@ -0,0 +1,330 @@
+/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).
+/// It is intended to be used with #include "json/json-forwards.h"
+/// This header provides forward declaration for all JsonCpp types.
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+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,
+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
+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:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
+# define JSON_FORWARD_AMALGATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+#define JSON_IS_AMALGAMATION
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// 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
+
+#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
+
+/// If defined, indicates that json may leverage CppTL library
+//# define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of
+/// std::map
+/// as Value container.
+//# define JSON_USE_CPPTL_SMALLMAP 1
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgated header.
+// #define JSON_IS_AMALGAMATION
+
+#ifdef JSON_IN_CPPTL
+#include <cpptl/config.h>
+#ifndef JSON_USE_CPPTL
+#define JSON_USE_CPPTL 1
+#endif
+#endif
+
+#ifdef JSON_IN_CPPTL
+#define JSON_API CPPTL_API
+#elif defined(JSON_DLL_BUILD)
+#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) || defined(__MINGW32__)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_IN_CPPTL
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+#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
+
+#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;
+#if defined(JSON_NO_INT64)
+typedef int LargestInt;
+typedef unsigned int LargestUInt;
+#undef JSON_HAS_INT64
+#else // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else // if defined(_MSC_VER) // Other platforms, use long long
+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
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// 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
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class FastWriter;
+class StyledWriter;
+
+// reader.h
+class Reader;
+
+// features.h
+class Features;
+
+// value.h
+typedef unsigned int ArrayIndex;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
diff --git a/json/json.h b/json/json.h
index d2941c23..02a31f4a 100644
--- a/json/json.h
+++ b/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:
========================================================================
@@ -68,7 +68,9 @@ license you like.
// End of content of file: LICENSE
// //////////////////////////////////////////////////////////////////////
-#include <stdint.h>
+
+
+
#ifndef JSON_AMALGATED_H_INCLUDED
# define JSON_AMALGATED_H_INCLUDED
@@ -80,19 +82,25 @@ license you like.
// Beginning of content of file: include/json/version.h
// //////////////////////////////////////////////////////////////////////
-// DO NOT EDIT. This file is generated by CMake from "version"
-// and "version.h.in" files.
+// DO NOT EDIT. This file (and "version") is generated by CMake.
// Run CMake configure step to update it.
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED
-# define JSONCPP_VERSION_STRING "1.6.1"
+# define JSONCPP_VERSION_STRING "1.8.0"
# define JSONCPP_VERSION_MAJOR 1
-# define JSONCPP_VERSION_MINOR 6
-# define JSONCPP_VERSION_PATCH 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
// //////////////////////////////////////////////////////////////////////
@@ -115,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
@@ -147,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)
@@ -166,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) // 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)
-#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)))
+// 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;
@@ -214,6 +284,19 @@ 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
@@ -294,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.
@@ -338,6 +423,8 @@ public:
} // namespace Json
+#pragma pack(pop)
+
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
@@ -377,6 +464,19 @@ public:
#include <cpptl/forwards.h>
#endif
+//Conditional NORETURN attribute on the throw functions would:
+// a) suppress false positives from static code analysis
+// b) possibly improve optimization opportunities.
+#if !defined(JSONCPP_NORETURN)
+# if defined(_MSC_VER)
+# define JSONCPP_NORETURN __declspec(noreturn)
+# elif defined(__GNUC__)
+# define JSONCPP_NORETURN __attribute__ ((__noreturn__))
+# else
+# define JSONCPP_NORETURN
+# endif
+#endif
+
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -384,6 +484,8 @@ public:
#pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma pack(push, 8)
+
/** \brief JSON (JavaScript Object Notation).
*/
namespace Json {
@@ -392,26 +494,41 @@ namespace Json {
*
* We use nothing but these internally. Of course, STL can throw others.
*/
-class JSON_API Exception;
+class JSON_API Exception : public std::exception {
+public:
+ Exception(JSONCPP_STRING const& msg);
+ ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
+ char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
+protected:
+ 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;
+class JSON_API RuntimeError : public Exception {
+public:
+ 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;
+class JSON_API LogicError : public Exception {
+public:
+ LogicError(JSONCPP_STRING const& msg);
+};
/// used internally
-void throwRuntimeError(std::string const& msg);
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg);
/// used internally
-void throwLogicError(std::string const& msg);
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg);
/** \brief Type of the value held by a Value object.
*/
@@ -502,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;
@@ -517,6 +634,8 @@ public:
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.
@@ -552,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;
@@ -566,7 +688,7 @@ private:
void swap(CZString& other);
struct StringStorage {
- DuplicationPolicy policy_: 2;
+ unsigned policy_: 2;
unsigned length_: 30; // 1GB max
};
@@ -610,7 +732,7 @@ Json::Value obj_value(Json::objectValue); // {}
#endif // if defined(JSON_HAS_INT64)
Value(double value);
Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
- Value(const char* beginValue, const char* endValue); ///< Copy all, incl zeroes.
+ Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
/** \brief Constructs a value from a static string.
* Like other value string constructor but do not duplicate the string for
@@ -627,13 +749,17 @@ 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).
@@ -656,12 +782,15 @@ 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.)
*/
bool getString(
- char const** str, char const** end) const;
+ char const** begin, char const** end) const;
#ifdef JSON_USE_CPPTL
CppTL::ConstString asConstString() const;
#endif
@@ -760,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.
@@ -790,12 +919,12 @@ Json::Value obj_value(Json::objectValue); // {}
Value get(const char* key, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
- /// \param key may contain embedded nulls.
- Value get(const char* key, const char* end, const Value& defaultValue) const;
+ /// \note key may contain embedded nulls.
+ Value get(const char* begin, const char* end, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \param key may contain embedded nulls.
- Value get(const 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
@@ -803,12 +932,12 @@ Json::Value obj_value(Json::objectValue); // {}
#endif
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
- /// \note As stated elsewhere, behavior is undefined if (end-key) >= 2^30
- Value const* find(char const* key, char const* end) const;
+ /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+ Value const* find(char const* begin, char const* end) const;
/// Most general and efficient version of object-mutators.
- /// \note As stated elsewhere, behavior is undefined if (end-key) >= 2^30
+ /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
- Value const* demand(char const* key, char const* end);
+ Value const* demand(char const* begin, char const* end);
/// \brief Remove and return the named member.
///
/// Do nothing if it did not exist.
@@ -820,8 +949,8 @@ Json::Value obj_value(Json::objectValue); // {}
/// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
/// \deprecated
- Value removeMember(const std::string& key);
- /// Same as removeMember(const char* key, const char* end, Value* removed),
+ 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);
/** \brief Remove the named map member.
@@ -830,9 +959,9 @@ 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(const char* key, const char* end, 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.
O(n) expensive operations.
@@ -846,9 +975,9 @@ 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 char* key, const char* end) 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.
bool isMember(const CppTL::ConstString& key) const;
@@ -867,16 +996,17 @@ Json::Value obj_value(Json::objectValue); // {}
//# endif
/// \deprecated Always pass len.
+ 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;
@@ -886,10 +1016,10 @@ Json::Value obj_value(Json::objectValue); // {}
// Accessors for the [start, limit) range of bytes within the JSON text from
// which this value was parsed, if any.
- void setOffsetStart(size_t start);
- void setOffsetLimit(size_t limit);
- size_t getOffsetStart() const;
- size_t getOffsetLimit() const;
+ 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);
@@ -930,8 +1060,8 @@ private:
// [start, limit) byte offsets in the source JSON text from which this Value
// was extracted.
- size_t start_;
- size_t limit_;
+ ptrdiff_t start_;
+ ptrdiff_t limit_;
};
/** \brief Experimental and untested: represents an element of the "path" to
@@ -944,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 {
@@ -952,7 +1082,7 @@ private:
kindIndex,
kindKey
};
- std::string key_;
+ JSONCPP_STRING key_;
ArrayIndex index_;
Kind kind_;
};
@@ -970,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(),
@@ -987,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_;
};
@@ -1007,9 +1137,6 @@ public:
typedef int difference_type;
typedef ValueIteratorBase SelfType;
- ValueIteratorBase();
- explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
-
bool operator==(const SelfType& other) const { return isEqual(other); }
bool operator!=(const SelfType& other) const { return !isEqual(other); }
@@ -1028,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.
@@ -1057,6 +1184,12 @@ private:
Value::ObjectValues::iterator current_;
// Indicates that iterator is for a null value.
bool isNull_;
+
+public:
+ // For some reason, BORLAND needs these at the end, rather
+ // than earlier. No idea why.
+ ValueIteratorBase();
+ explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
};
/** \brief const iterator for object and array value.
@@ -1074,6 +1207,7 @@ public:
typedef ValueConstIterator SelfType;
ValueConstIterator();
+ ValueConstIterator(ValueIterator const& other);
private:
/*! \internal Use by Value to create an iterator.
@@ -1123,7 +1257,7 @@ public:
typedef ValueIterator SelfType;
ValueIterator();
- ValueIterator(const ValueConstIterator& other);
+ explicit ValueIterator(const ValueConstIterator& other);
ValueIterator(const ValueIterator& other);
private:
@@ -1169,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)
@@ -1214,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
@@ -1233,9 +1370,9 @@ public:
*
*/
struct StructuredError {
- size_t offset_start;
- size_t offset_limit;
- std::string message;
+ ptrdiff_t offset_start;
+ ptrdiff_t offset_limit;
+ JSONCPP_STRING message;
};
/** \brief Constructs a Reader allowing all features
@@ -1290,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.
@@ -1302,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.
@@ -1312,7 +1449,7 @@ 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
@@ -1329,7 +1466,7 @@ public:
* \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 std::string& message);
+ 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
@@ -1338,7 +1475,7 @@ public:
* \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 std::string& message, const Value& extra);
+ 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
@@ -1374,7 +1511,7 @@ private:
class ErrorInfo {
public:
Token token_;
- std::string message_;
+ JSONCPP_STRING message_;
Location extra_;
};
@@ -1394,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,
@@ -1405,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();
@@ -1415,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
@@ -1457,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().
@@ -1477,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
*/
@@ -1512,6 +1649,9 @@ public:
the JSON value in the input string.
- `"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
+ and their values are lossfree restorable.
You can examine 'settings_` yourself
to see the defaults. You can also write and read them just like any
@@ -1521,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'.
@@ -1532,18 +1672,18 @@ 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)
* \remark Defaults:
- * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
+ * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
*/
static void setDefaults(Json::Value* settings);
/** Same as old Features::strictMode().
* \pre 'settings' != NULL (but Json::null is fine)
* \remark Defaults:
- * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
+ * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
*/
static void strictMode(Json::Value* settings);
};
@@ -1554,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'.
@@ -1581,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)
@@ -1626,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;
@@ -1645,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();
@@ -1655,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.
*/
@@ -1672,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.
@@ -1705,6 +1849,10 @@ public:
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.
+ - "useSpecialFloats": false or true
+ - If true, outputs non-finite floating point values in the following way:
+ NaN values as "NaN", positive infinity as "Infinity", and negative infinity
+ as "-Infinity".
You can examine 'settings_` yourself
to see the defaults. You can also write and read them just like any
@@ -1714,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'.
@@ -1727,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)
@@ -1744,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
@@ -1760,7 +1908,7 @@ class JSON_API FastWriter : public Writer {
public:
FastWriter();
- virtual ~FastWriter() {}
+ ~FastWriter() JSONCPP_OVERRIDE {}
void enableYAMLCompatibility();
@@ -1774,12 +1922,12 @@ public:
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_;
@@ -1812,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_;
};
@@ -1873,7 +2021,7 @@ private:
*/
class JSON_API StyledStreamWriter {
public:
- StyledStreamWriter(std::string indentation = "\t");
+ StyledStreamWriter(JSONCPP_STRING indentation = "\t");
~StyledStreamWriter() {}
public:
@@ -1883,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)
@@ -1972,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(); \
}
@@ -1985,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/json/jsoncpp.cpp b/json/jsoncpp.cpp
index 21b87cd5..7634ed4f 100644
--- a/json/jsoncpp.cpp
+++ b/json/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:
========================================================================
@@ -73,7 +73,7 @@ license you like.
-#include "json.h"
+#include "json/json.h"
#ifndef JSON_IS_AMALGAMATION
#error "Compile with -I PATH_TO_JSON_DIRECTORY"
@@ -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
@@ -116,8 +134,8 @@ static inline std::string codePointToUTF8(unsigned int cp) {
} else if (cp <= 0xFFFF) {
result.resize(3);
result[2] = static_cast<char>(0x80 | (0x3f & cp));
- result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
- result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+ result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
} else if (cp <= 0x10FFFF) {
result.resize(4);
result[3] = static_cast<char>(0x80 | (0x3f & cp));
@@ -129,7 +147,7 @@ static inline std::string codePointToUTF8(unsigned int cp) {
return result;
}
-/// Returns true if ch is a control character (in range [0,32[).
+/// Returns true if ch is a control character (in range [1,31]).
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
enum {
@@ -149,7 +167,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
static inline void uintToString(LargestUInt value, char*& current) {
*--current = 0;
do {
- *--current = char(value % 10) + '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
@@ -204,22 +235,43 @@ static inline void fixNumericLocale(char* begin, char* end) {
#include <sstream>
#include <memory>
#include <set>
+#include <limits>
-#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
+#if defined(_MSC_VER)
+#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__) || 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 {
-#if __cplusplus >= 201103L
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<CharReader> CharReaderPtr;
#else
typedef std::auto_ptr<CharReader> CharReaderPtr;
@@ -268,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);
@@ -280,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,
@@ -307,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);
@@ -330,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);
@@ -409,7 +459,6 @@ bool Reader::readValue() {
lastValue_ = &currentValue();
}
- --stackDepth_g;
return successful;
}
@@ -538,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++;
@@ -560,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);
@@ -570,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;
@@ -599,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 == '\\')
@@ -630,7 +679,7 @@ bool Reader::readString() {
bool Reader::readObject(Token& tokenStart) {
Token tokenName;
- std::string name;
+ JSONCPP_STRING name;
Value init(objectValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
@@ -650,7 +699,7 @@ bool Reader::readObject(Token& tokenStart) {
Value numberName;
if (!decodeNumber(tokenName, numberName))
return recoverFromError(tokenObjectEnd);
- name = numberName.asString();
+ name = JSONCPP_STRING(numberName.asCString());
} else {
break;
}
@@ -689,7 +738,7 @@ bool Reader::readArray(Token& tokenStart) {
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces();
- if (*current_ == ']') // empty array
+ if (current_ != end_ && *current_ == ']') // empty array
{
Token endArray;
readToken(endArray);
@@ -742,7 +791,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
++current;
// TODO: Help the compiler do the div and mod at compile time or get rid of them.
Value::LargestUInt maxIntegerValue =
- isNegative ? Value::LargestUInt(-Value::minLargestInt)
+ isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
: Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
@@ -750,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
@@ -763,7 +812,9 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
}
value = value * 10 + digit;
}
- if (isNegative)
+ if (isNegative && value == maxIntegerValue)
+ decoded = Value::minLargestInt;
+ else if (isNegative)
decoded = -Value::LargestInt(value);
else if (value <= Value::LargestUInt(Value::maxInt))
decoded = Value::LargestInt(value);
@@ -784,34 +835,10 @@ bool Reader::decodeDouble(Token& token) {
bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
- const int bufferSize = 32;
- int count;
- int length = int(token.end_ - token.start_);
-
- // Sanity check to avoid buffer overflow exploits.
- if (length < 0) {
- return addError("Unable to parse token length", token);
- }
-
- // 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_, length);
- buffer[length] = 0;
- count = sscanf(buffer, format, &value);
- } else {
- std::string buffer(token.start_, token.end_);
- count = sscanf(buffer.c_str(), format, &value);
- }
-
- if (count != 1)
- return addError("'" + std::string(token.start_, token.end_) +
+ JSONCPP_STRING buffer(token.start_, token.end_);
+ JSONCPP_ISTRINGSTREAM is(buffer);
+ if (!(is >> value))
+ return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
"' is not a number.",
token);
decoded = value;
@@ -819,7 +846,7 @@ 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);
@@ -829,8 +856,8 @@ bool Reader::decodeString(Token& token) {
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) {
@@ -914,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;
@@ -936,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;
@@ -950,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))
@@ -962,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);
@@ -1000,29 +1028,21 @@ 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];
-#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
-#if defined(WINCE)
- _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#else
- sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#endif
-#else
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#endif
return buffer;
}
// 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) {
@@ -1052,8 +1072,8 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
return allErrors;
}
-bool Reader::pushError(const Value& value, const std::string& message) {
- size_t length = end_ - begin_;
+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;
@@ -1069,8 +1089,8 @@ bool Reader::pushError(const Value& value, const std::string& message) {
return true;
}
-bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
- size_t length = end_ - begin_;
+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)
@@ -1095,7 +1115,6 @@ bool Reader::good() const {
class OurFeatures {
public:
static OurFeatures all();
- OurFeatures();
bool allowComments_;
bool strictRoot_;
bool allowDroppedNullPlaceholders_;
@@ -1103,20 +1122,13 @@ public:
bool allowSingleQuotes_;
bool failIfExtra_;
bool rejectDupKeys_;
+ bool allowSpecialFloats_;
int stackLimit_;
}; // OurFeatures
// exact copy of Implementation of class Features
// ////////////////////////////////
-OurFeatures::OurFeatures()
- : allowComments_(true), strictRoot_(false)
- , allowDroppedNullPlaceholders_(false), allowNumericKeys_(false)
- , allowSingleQuotes_(false)
- , failIfExtra_(false)
-{
-}
-
OurFeatures OurFeatures::all() { return OurFeatures(); }
// Implementation of class Reader
@@ -1128,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);
@@ -1138,10 +1150,10 @@ 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 std::string& message);
- bool pushError(const Value& value, const std::string& message, const Value& extra);
+ 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:
@@ -1159,6 +1171,9 @@ private:
tokenTrue,
tokenFalse,
tokenNull,
+ tokenNaN,
+ tokenPosInf,
+ tokenNegInf,
tokenArraySeparator,
tokenMemberSeparator,
tokenComment,
@@ -1175,7 +1190,7 @@ private:
class ErrorInfo {
public:
Token token_;
- std::string message_;
+ JSONCPP_STRING message_;
Location extra_;
};
@@ -1189,14 +1204,14 @@ private:
bool readCppStyleComment();
bool readString();
bool readStringSingleQuote();
- void readNumber();
+ bool readNumber(bool checkInf);
bool readValue();
bool readObject(Token& token);
bool readArray(Token& token);
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,
@@ -1207,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();
@@ -1217,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_;
@@ -1241,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,
@@ -1264,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;
}
@@ -1293,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;
@@ -1343,6 +1357,30 @@ bool OurReader::readValue() {
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:
case tokenObjectEnd:
case tokenArrayEnd:
@@ -1367,7 +1405,6 @@ bool OurReader::readValue() {
lastValue_ = &currentValue();
}
- --stackDepth_;
return successful;
}
@@ -1423,9 +1460,16 @@ bool OurReader::readToken(Token& token) {
case '7':
case '8':
case '9':
- case '-':
token.type_ = tokenNumber;
- readNumber();
+ readNumber(false);
+ break;
+ case '-':
+ if (readNumber(true)) {
+ token.type_ = tokenNumber;
+ } else {
+ token.type_ = tokenNegInf;
+ ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+ }
break;
case 't':
token.type_ = tokenTrue;
@@ -1439,6 +1483,22 @@ bool OurReader::readToken(Token& token) {
token.type_ = tokenNull;
ok = match("ull", 3);
break;
+ case 'N':
+ if (features_.allowSpecialFloats_) {
+ token.type_ = tokenNaN;
+ ok = match("aN", 2);
+ } else {
+ ok = false;
+ }
+ break;
+ case 'I':
+ if (features_.allowSpecialFloats_) {
+ token.type_ = tokenPosInf;
+ ok = match("nfinity", 7);
+ } else {
+ ok = false;
+ }
+ break;
case ',':
token.type_ = tokenArraySeparator;
break;
@@ -1505,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);
@@ -1515,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;
@@ -1539,26 +1599,31 @@ bool OurReader::readCppStyleComment() {
return true;
}
-void OurReader::readNumber() {
+bool OurReader::readNumber(bool checkInf) {
const char *p = current_;
+ if (checkInf && p != end_ && *p == 'I') {
+ current_ = ++p;
+ return false;
+ }
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;
}
bool OurReader::readString() {
Char c = 0;
@@ -1587,7 +1652,7 @@ bool OurReader::readStringSingleQuote() {
bool OurReader::readObject(Token& tokenStart) {
Token tokenName;
- std::string name;
+ JSONCPP_STRING name;
Value init(objectValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
@@ -1619,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);
}
@@ -1652,7 +1717,7 @@ bool OurReader::readArray(Token& tokenStart) {
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces();
- if (*current_ == ']') // empty array
+ if (current_ != end_ && *current_ == ']') // empty array
{
Token endArray;
readToken(endArray);
@@ -1713,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
@@ -1749,12 +1814,13 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
const int bufferSize = 32;
int count;
- int length = int(token.end_ - token.start_);
+ 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
@@ -1765,16 +1831,17 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
if (length <= bufferSize) {
Char buffer[bufferSize + 1];
- memcpy(buffer, token.start_, length);
+ memcpy(buffer, token.start_, ulength);
buffer[length] = 0;
+ fixNumericLocaleInput(buffer, buffer + length);
count = sscanf(buffer, format, &value);
} else {
- std::string buffer(token.start_, token.end_);
+ JSONCPP_STRING buffer(token.start_, token.end_);
count = sscanf(buffer.c_str(), format, &value);
}
if (count != 1)
- return addError("'" + std::string(token.start_, token.end_) +
+ return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
"' is not a number.",
token);
decoded = value;
@@ -1782,7 +1849,7 @@ 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);
@@ -1792,8 +1859,8 @@ bool OurReader::decodeString(Token& token) {
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) {
@@ -1877,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;
@@ -1899,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;
@@ -1913,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))
@@ -1925,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);
@@ -1963,24 +2031,16 @@ 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];
-#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
-#if defined(WINCE)
- _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#else
- sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#endif
-#else
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#endif
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) {
@@ -2010,8 +2070,8 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
return allErrors;
}
-bool OurReader::pushError(const Value& value, const std::string& message) {
- size_t length = end_ - begin_;
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
+ ptrdiff_t length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length)
return false;
@@ -2027,8 +2087,8 @@ bool OurReader::pushError(const Value& value, const std::string& message) {
return true;
}
-bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) {
- size_t length = end_ - begin_;
+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)
@@ -2060,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();
@@ -2089,9 +2149,10 @@ CharReader* CharReaderBuilder::newCharReader() const
features.stackLimit_ = settings_["stackLimit"].asInt();
features.failIfExtra_ = settings_["failIfExtra"].asBool();
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
+ 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");
@@ -2103,25 +2164,26 @@ static void getValidReaderKeys(std::set<std::string>* valid_keys)
valid_keys->insert("stackLimit");
valid_keys->insert("failIfExtra");
valid_keys->insert("rejectDupKeys");
+ valid_keys->insert("allowSpecialFloats");
}
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];
}
@@ -2134,8 +2196,10 @@ 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;
//! [CharReaderBuilderStrictMode]
}
// static
@@ -2151,6 +2215,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
(*settings)["stackLimit"] = 1000;
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
+ (*settings)["allowSpecialFloats"] = false;
//! [CharReaderBuilderDefaults]
}
@@ -2158,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.
@@ -2171,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;
}
@@ -2294,27 +2359,27 @@ UInt ValueIteratorBase::index() const {
return Value::UInt(-1);
}
-std::string ValueIteratorBase::name() const {
- char const* key;
+JSONCPP_STRING ValueIteratorBase::name() const {
+ char const* keey;
char const* end;
- key = memberName(&end);
- if (!key) return std::string();
- return std::string(key, end);
+ keey = memberName(&end);
+ if (!keey) return JSONCPP_STRING();
+ return JSONCPP_STRING(keey, end);
}
char const* ValueIteratorBase::memberName() const {
- const char* name = (*current_).first.data();
- return name ? name : "";
+ const char* cname = (*current_).first.data();
+ return cname ? cname : "";
}
char const* ValueIteratorBase::memberName(char const** end) const {
- const char* name = (*current_).first.data();
- if (!name) {
+ const char* cname = (*current_).first.data();
+ if (!cname) {
*end = NULL;
return NULL;
}
- *end = name + (*current_).first.length();
- return name;
+ *end = cname + (*current_).first.length();
+ return cname;
}
// //////////////////////////////////////////////////////////////////
@@ -2331,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);
@@ -2351,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) {}
@@ -2409,10 +2479,22 @@ namespace Json {
#else
#define ALIGNAS(byte_alignment)
#endif
-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 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);
@@ -2433,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) {
@@ -2458,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));
@@ -2483,10 +2569,10 @@ 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 + sizeof(unsigned) + 1U;
+ unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
char* newString = static_cast<char*>(malloc(actualLength));
if (newString == 0) {
throwRuntimeError(
@@ -2503,7 +2589,7 @@ inline static void decodePrefixedString(
unsigned* length, char const** value)
{
if (!isPrefixed) {
- *length = strlen(prefixed);
+ *length = static_cast<unsigned>(strlen(prefixed));
*value = prefixed;
} else {
*length = *reinterpret_cast<unsigned const*>(prefixed);
@@ -2512,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
@@ -2530,43 +2638,26 @@ static inline void releaseStringValue(char* value) { free(value); }
namespace Json {
-class JSON_API Exception : public std::exception {
-public:
- Exception(std::string const& msg);
- virtual ~Exception() throw();
- virtual char const* what() const throw();
-protected:
- std::string const msg_;
-};
-class JSON_API RuntimeError : public Exception {
-public:
- RuntimeError(std::string const& msg);
-};
-class JSON_API LogicError : public Exception {
-public:
- LogicError(std::string const& msg);
-};
-
-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)
{}
-void throwRuntimeError(std::string const& msg)
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
{
throw RuntimeError(msg);
}
-void throwLogicError(std::string const& msg)
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
{
throw LogicError(msg);
}
@@ -2579,16 +2670,17 @@ 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);
@@ -2610,31 +2702,37 @@ void Value::CommentInfo::setComment(const char* text, size_t len) {
// Notes: policy_ indicates if the string was allocated when
// a string is stored.
-Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {}
+Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
-Value::CZString::CZString(char const* str, unsigned length, DuplicationPolicy allocate)
- : cstr_(str)
-{
+Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
+ : cstr_(str) {
// allocate != duplicate
- storage_.policy_ = allocate;
- storage_.length_ = length;
+ 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_
- ? (other.storage_.policy_ == noDuplication
+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)
- : 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) {
@@ -2653,7 +2751,8 @@ bool Value::CZString::operator<(const CZString& other) const {
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
- unsigned min_len = std::min(this_len, other_len);
+ unsigned min_len = std::min<unsigned>(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;
@@ -2667,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;
}
@@ -2690,9 +2790,10 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
* memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator.
*/
-Value::Value(ValueType type) {
- initBasic(type);
- switch (type) {
+Value::Value(ValueType vtype) {
+ static char const emptyString[] = "";
+ initBasic(vtype);
+ switch (vtype) {
case nullValue:
break;
case intValue:
@@ -2703,7 +2804,8 @@ Value::Value(ValueType type) {
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:
@@ -2744,6 +2846,7 @@ Value::Value(double value) {
Value::Value(const char* value) {
initBasic(stringValue, true);
+ JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
}
@@ -2753,7 +2856,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()));
@@ -2820,6 +2923,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:
@@ -2830,7 +2941,7 @@ Value::~Value() {
break;
case stringValue:
if (allocated_)
- releaseStringValue(value_.string_);
+ releasePrefixedStringValue(value_.string_);
break;
case arrayValue:
case objectValue:
@@ -2840,8 +2951,9 @@ Value::~Value() {
JSON_ASSERT_UNREACHABLE;
}
- if (comments_)
- delete[] comments_;
+ delete[] comments_;
+
+ value_.uint_ = 0;
}
Value& Value::operator=(Value other) {
@@ -2856,7 +2968,7 @@ void Value::swapPayload(Value& other) {
std::swap(value_, other.value_);
int temp2 = allocated_;
allocated_ = other.allocated_;
- other.allocated_ = temp2;
+ other.allocated_ = temp2 & 0x1;
}
void Value::swap(Value& other) {
@@ -2903,7 +3015,8 @@ bool Value::operator<(const Value& other) const {
char const* other_str;
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);
+ unsigned min_len = std::min<unsigned>(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;
@@ -2959,6 +3072,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;
}
@@ -2984,16 +3098,28 @@ const char* Value::asCString() const {
return this_str;
}
-bool Value::getString(char const** str, char const** end) const {
+#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;
unsigned length;
decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
- *end = *str + length;
+ *cend = *str + length;
return true;
}
-std::string Value::asString() const {
+JSONCPP_STRING Value::asString() const {
switch (type_) {
case nullValue:
return "";
@@ -3003,7 +3129,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";
@@ -3163,7 +3289,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_);
@@ -3188,7 +3315,8 @@ bool Value::asBool() const {
case uintValue:
return value_.uint_ ? true : false;
case realValue:
- return value_.real_ ? true : false;
+ // This is kind of strange. Not recommended.
+ return (value_.real_ != 0.0) ? true : false;
default:
break;
}
@@ -3291,7 +3419,7 @@ void Value::resize(ArrayIndex newSize) {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
value_.map_->erase(index);
}
- assert(size() == newSize);
+ JSON_ASSERT(size() == newSize);
}
}
@@ -3306,7 +3434,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;
}
@@ -3323,11 +3451,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;
}
@@ -3338,8 +3466,8 @@ const Value& Value::operator[](int index) const {
return (*this)[ArrayIndex(index)];
}
-void Value::initBasic(ValueType type, bool allocated) {
- type_ = type;
+void Value::initBasic(ValueType vtype, bool allocated) {
+ type_ = vtype;
allocated_ = allocated;
comments_ = 0;
start_ = 0;
@@ -3361,14 +3489,14 @@ 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;
}
// @param key is not null-terminated.
-Value& Value::resolveReference(char const* key, char const* end)
+Value& Value::resolveReference(char const* key, char const* cend)
{
JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue,
@@ -3376,12 +3504,12 @@ Value& Value::resolveReference(char const* key, char const* end)
if (type_ == nullValue)
*this = Value(objectValue);
CZString actualKey(
- key, static_cast<unsigned>(end-key), CZString::duplicateOnCopy);
+ key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
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;
@@ -3389,18 +3517,18 @@ Value& Value::resolveReference(char const* key, char const* end)
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(); }
-Value const* Value::find(char const* key, char const* end) const
+Value const* Value::find(char const* key, char const* cend) const
{
JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue,
"in Json::Value::find(key, end, found): requires objectValue or nullValue");
if (type_ == nullValue) return NULL;
- CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication);
+ CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end()) return NULL;
return &(*it).second;
@@ -3408,13 +3536,13 @@ Value const* Value::find(char const* key, char const* end) 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;
}
@@ -3422,7 +3550,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());
}
@@ -3437,34 +3565,34 @@ 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
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
-Value Value::get(char const* key, char const* end, Value const& defaultValue) const
+Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
{
- Value const* found = find(key, end);
+ Value const* found = find(key, cend);
return !found ? defaultValue : *found;
}
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);
}
-bool Value::removeMember(const char* key, const char* end, Value* removed)
+bool Value::removeMember(const char* key, const char* cend, Value* removed)
{
if (type_ != objectValue) {
return false;
}
- CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication);
+ CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
ObjectValues::iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return false;
@@ -3476,7 +3604,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);
}
@@ -3485,13 +3613,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());
}
@@ -3509,8 +3637,8 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
ArrayIndex oldSize = size();
// shift left all items left, into the place of the "removed"
for (ArrayIndex i = index; i < (oldSize - 1); ++i){
- CZString key(i);
- (*value_.map_)[key] = (*this)[i + 1];
+ CZString keey(i);
+ (*value_.map_)[keey] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
@@ -3526,16 +3654,16 @@ Value Value::get(const CppTL::ConstString& key,
}
#endif
-bool Value::isMember(char const* key, char const* end) const
+bool Value::isMember(char const* key, char const* cend) const
{
- Value const* value = find(key, end);
+ Value const* value = find(key, cend);
return NULL != value;
}
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());
}
@@ -3557,7 +3685,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;
@@ -3600,7 +3728,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:
@@ -3615,9 +3747,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_);
@@ -3675,9 +3815,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; }
@@ -3699,7 +3839,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);
}
@@ -3707,21 +3847,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 "";
}
-void Value::setOffsetStart(size_t start) { start_ = start; }
+void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
-void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
+void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
-size_t Value::getOffsetStart() const { return start_; }
+ptrdiff_t Value::getOffsetStart() const { return start_; }
-size_t Value::getOffsetLimit() const { return limit_; }
+ptrdiff_t Value::getOffsetLimit() const { return limit_; }
-std::string Value::toStyledString() const {
+JSONCPP_STRING Value::toStyledString() const {
StyledWriter writer;
return writer.write(*this);
}
@@ -3789,13 +3929,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,
@@ -3810,7 +3950,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();
@@ -3825,23 +3965,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) {
@@ -3850,11 +3990,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.
}
@@ -3865,16 +4005,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;
}
}
}
@@ -3893,7 +4036,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;
}
}
@@ -3956,18 +4099,53 @@ 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) && _MSC_VER < 1500 // VC++ 8.0 and below
+#if defined(_MSC_VER)
+#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__) || defined(__QNXNTO__)
+#define snprintf snprintf
#elif __cplusplus >= 201103L
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
#define snprintf std::snprintf
#endif
+#endif
+
+#if defined(__BORLANDC__)
+#include <float.h>
+#define isfinite _finite
+#define snprintf _snprintf
+#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
// Disable warning about strdup being deprecated.
@@ -3976,7 +4154,7 @@ Value& Path::make(Value& root) const {
namespace Json {
-#if __cplusplus >= 201103L
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
#else
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
@@ -4000,20 +4178,23 @@ 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);
- bool isNegative = value < 0;
- if (isNegative)
- value = -value;
- uintToString(LargestUInt(value), current);
- if (isNegative)
+ if (value == Value::minLargestInt) {
+ uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
+ *--current = '-';
+ } else if (value < 0) {
+ uintToString(LargestUInt(-value), current);
*--current = '-';
+ } else {
+ uintToString(LargestUInt(value), current);
+ }
assert(current >= buffer);
return current;
}
-std::string valueToString(LargestUInt value) {
+JSONCPP_STRING valueToString(LargestUInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
uintToString(value, current);
@@ -4023,68 +4204,71 @@ 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) {
+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;
-// Print into the buffer. We need not request the alternative representation
-// that always has a decimal point because JSON doesn't distingish the
-// concepts of reals and integers.
-#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with
- // visual studio 2005 to
- // avoid warning.
-#if defined(WINCE)
- len = _snprintf(buffer, sizeof(buffer), "%.17g", value);
-#else
- len = sprintf_s(buffer, sizeof(buffer), "%.17g", value);
-#endif
-#else
+ char formatString[6];
+ sprintf(formatString, "%%.%dg", precision);
+
+ // Print into the buffer. We need not request the alternative representation
+ // that always has a decimal point because JSON doesn't distingish the
+ // concepts of reals and integers.
if (isfinite(value)) {
- len = snprintf(buffer, sizeof(buffer), "%.17g", 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) {
- len = snprintf(buffer, sizeof(buffer), "null");
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
} else if (value < 0) {
- len = snprintf(buffer, sizeof(buffer), "-1e+9999");
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
} else {
- len = snprintf(buffer, sizeof(buffer), "1e+9999");
+ len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
}
// For those, we do not need to call fixNumLoc, but it is fast.
}
-#endif
assert(len >= 0);
fixNumericLocale(buffer, buffer + len);
return buffer;
}
+}
+
+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) {
@@ -4120,7 +4304,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();
@@ -4149,19 +4333,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;
@@ -4198,7 +4382,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();
@@ -4229,7 +4413,7 @@ void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
-std::string FastWriter::write(const Value& root) {
+JSONCPP_STRING FastWriter::write(const Value& root) {
document_ = "";
writeValue(root);
if (!omitEndingLineFeed_)
@@ -4253,15 +4437,21 @@ void FastWriter::writeValue(const Value& value) {
document_ += valueToString(value.asDouble());
break;
case stringValue:
- document_ += valueToQuotedString(value.asCString());
+ {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
break;
+ }
case booleanValue:
document_ += valueToString(value.asBool());
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]);
@@ -4273,10 +4463,10 @@ 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(), name.length());
+ document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
document_ += yamlCompatiblityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
@@ -4291,7 +4481,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_ = "";
@@ -4318,7 +4508,7 @@ void StyledWriter::writeValue(const Value& value) {
break;
case stringValue:
{
- // Is NULL is possible for value.string_?
+ // Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
@@ -4341,7 +4531,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()));
@@ -4405,26 +4595,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_;
@@ -4432,7 +4621,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
@@ -4450,15 +4639,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_);
}
@@ -4468,8 +4657,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' &&
@@ -4502,11 +4691,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_ = "";
@@ -4535,8 +4724,15 @@ void StyledStreamWriter::writeValue(const Value& value) {
pushValue(valueToString(value.asDouble()));
break;
case stringValue:
- pushValue(valueToQuotedString(value.asCString()));
+ {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+ else pushValue("");
break;
+ }
case booleanValue:
pushValue(valueToString(value.asBool()));
break;
@@ -4552,7 +4748,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()));
@@ -4618,26 +4814,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_;
@@ -4645,7 +4840,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
@@ -4660,7 +4855,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;
@@ -4678,8 +4873,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' &&
@@ -4724,44 +4919,50 @@ 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);
- virtual int write(Value const& root, std::ostream* sout);
+ JSONCPP_STRING const& colonSymbol,
+ JSONCPP_STRING const& nullSymbol,
+ JSONCPP_STRING const& endingLineFeedSymbol,
+ bool useSpecialFloats,
+ unsigned int precision);
+ 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)
, indentation_(indentation)
, cs_(cs)
@@ -4770,9 +4971,11 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
, endingLineFeedSymbol_(endingLineFeedSymbol)
, addChildValues_(false)
, indented_(false)
+ , useSpecialFloats_(useSpecialFloats)
+ , precision_(precision)
{
}
-int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
+int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
{
sout_ = sout;
addChildValues_ = false;
@@ -4799,11 +5002,11 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
pushValue(valueToString(value.asLargestUInt()));
break;
case realValue:
- pushValue(valueToString(value.asDouble()));
+ pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
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);
@@ -4826,10 +5029,10 @@ 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(), name.length()));
+ writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
*sout_ << colonSymbol_;
writeValue(childValue);
if (++it == members.end()) {
@@ -4884,7 +5087,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_ << " ";
@@ -4894,26 +5097,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_;
@@ -4921,7 +5123,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
@@ -4940,7 +5142,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;
@@ -4959,8 +5161,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' &&
@@ -5010,10 +5212,12 @@ 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();
+ unsigned int pre = settings_["precision"].asUInt();
CommentStyle::Enum cs = CommentStyle::All;
if (cs_str == "All") {
cs = CommentStyle::All;
@@ -5022,47 +5226,50 @@ 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 = "";
}
- std::string endingLineFeedSymbol = "";
+ if (pre > 17) pre = 17;
+ JSONCPP_STRING endingLineFeedSymbol = "";
return new BuiltStyledStreamWriter(
indentation, cs,
- colonSymbol, nullSymbol, endingLineFeedSymbol);
+ 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");
valid_keys->insert("commentStyle");
valid_keys->insert("enableYAMLCompatibility");
valid_keys->insert("dropNullPlaceholders");
+ valid_keys->insert("useSpecialFloats");
+ valid_keys->insert("precision");
}
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];
}
@@ -5074,17 +5281,19 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings)
(*settings)["indentation"] = "\t";
(*settings)["enableYAMLCompatibility"] = false;
(*settings)["dropNullPlaceholders"] = false;
+ (*settings)["useSpecialFloats"] = false;
+ (*settings)["precision"] = 17;
//! [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);
@@ -5096,3 +5305,8 @@ std::ostream& operator<<(std::ostream& sout, Value const& root) {
// //////////////////////////////////////////////////////////////////////
// End of content of file: src/lib_json/json_writer.cpp
// //////////////////////////////////////////////////////////////////////
+
+
+
+
+