mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-05-03 15:58:22 +02:00
Ran clang-format over all .h and .cpp files.
clang-format -i $(find . -name '*.h' -or -name '*.cpp')
This commit is contained in:
parent
1b137a3802
commit
9fa4e849a1
@ -4,29 +4,38 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
||||||
# define CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
# include <json/config.h>
|
#include <json/config.h>
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
#if JSON_USE_EXCEPTION
|
#if JSON_USE_EXCEPTION
|
||||||
# include <stdexcept>
|
#include <stdexcept>
|
||||||
#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
|
#define JSON_ASSERT(condition) \
|
||||||
#define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message );
|
assert(condition); // @todo <= change this into an exception throw
|
||||||
#else // JSON_USE_EXCEPTION
|
#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message);
|
||||||
#define JSON_ASSERT( condition ) assert( condition );
|
#else // JSON_USE_EXCEPTION
|
||||||
|
#define JSON_ASSERT(condition) assert(condition);
|
||||||
|
|
||||||
// The call to assert() will show the failure message in debug builds. In
|
// The call to assert() will show the failure message in debug builds. In
|
||||||
// release bugs we write to invalid memory in order to crash hard, so that a
|
// release bugs we write to invalid memory in order to crash hard, so that a
|
||||||
// debugger or crash reporter gets the chance to take over. We still call exit()
|
// debugger or crash reporter gets the chance to take over. We still call exit()
|
||||||
// afterward in order to tell the compiler that this macro doesn't return.
|
// afterward in order to tell the compiler that this macro doesn't return.
|
||||||
#define JSON_FAIL_MESSAGE( message ) { assert(false && message); strcpy(reinterpret_cast<char*>(666), message); exit(123); }
|
#define JSON_FAIL_MESSAGE(message) \
|
||||||
|
{ \
|
||||||
|
assert(false &&message); \
|
||||||
|
strcpy(reinterpret_cast<char *>(666), message); \
|
||||||
|
exit(123); \
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) { JSON_FAIL_MESSAGE( message ) }
|
#define JSON_ASSERT_MESSAGE(condition, message) \
|
||||||
|
if (!(condition)) { \
|
||||||
|
JSON_FAIL_MESSAGE(message) \
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
@ -4,21 +4,22 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSON_AUTOLINK_H_INCLUDED
|
#ifndef JSON_AUTOLINK_H_INCLUDED
|
||||||
# define JSON_AUTOLINK_H_INCLUDED
|
#define JSON_AUTOLINK_H_INCLUDED
|
||||||
|
|
||||||
# include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
# ifdef JSON_IN_CPPTL
|
#ifdef JSON_IN_CPPTL
|
||||||
# include <cpptl/cpptl_autolink.h>
|
#include <cpptl/cpptl_autolink.h>
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
|
#if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \
|
||||||
# define CPPTL_AUTOLINK_NAME "json"
|
!defined(JSON_IN_CPPTL)
|
||||||
# undef CPPTL_AUTOLINK_DLL
|
#define CPPTL_AUTOLINK_NAME "json"
|
||||||
# ifdef JSON_DLL
|
#undef CPPTL_AUTOLINK_DLL
|
||||||
# define CPPTL_AUTOLINK_DLL
|
#ifdef JSON_DLL
|
||||||
# endif
|
#define CPPTL_AUTOLINK_DLL
|
||||||
# include "autolink.h"
|
#endif
|
||||||
# endif
|
#include "autolink.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // JSON_AUTOLINK_H_INCLUDED
|
#endif // JSON_AUTOLINK_H_INCLUDED
|
||||||
|
@ -4,105 +4,109 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSON_CONFIG_H_INCLUDED
|
#ifndef JSON_CONFIG_H_INCLUDED
|
||||||
# define JSON_CONFIG_H_INCLUDED
|
#define JSON_CONFIG_H_INCLUDED
|
||||||
|
|
||||||
/// If defined, indicates that json library is embedded in CppTL library.
|
/// If defined, indicates that json library is embedded in CppTL library.
|
||||||
//# define JSON_IN_CPPTL 1
|
//# define JSON_IN_CPPTL 1
|
||||||
|
|
||||||
/// If defined, indicates that json may leverage CppTL library
|
/// If defined, indicates that json may leverage CppTL library
|
||||||
//# define JSON_USE_CPPTL 1
|
//# define JSON_USE_CPPTL 1
|
||||||
/// If defined, indicates that cpptl vector based map should be used instead of std::map
|
/// If defined, indicates that cpptl vector based map should be used instead of
|
||||||
|
/// std::map
|
||||||
/// as Value container.
|
/// as Value container.
|
||||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||||
/// If defined, indicates that Json specific container should be used
|
/// If defined, indicates that Json specific container should be used
|
||||||
/// (hash table & simple deque container with customizable allocator).
|
/// (hash table & simple deque container with customizable allocator).
|
||||||
/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
|
/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
|
||||||
//# define JSON_VALUE_USE_INTERNAL_MAP 1
|
//# define JSON_VALUE_USE_INTERNAL_MAP 1
|
||||||
/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
|
/// Force usage of standard new/malloc based allocator instead of memory pool
|
||||||
/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
|
/// based allocator.
|
||||||
|
/// The memory pools allocator used optimization (initializing Value and
|
||||||
|
/// ValueInternalLink
|
||||||
/// as if it was a POD) that may cause some validation tool to report errors.
|
/// as if it was a POD) that may cause some validation tool to report errors.
|
||||||
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
|
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
|
||||||
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
|
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
|
||||||
|
|
||||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||||
// assertion macros. The default is to use exceptions.
|
// assertion macros. The default is to use exceptions.
|
||||||
# ifndef JSON_USE_EXCEPTION
|
#ifndef JSON_USE_EXCEPTION
|
||||||
# define JSON_USE_EXCEPTION 1
|
#define JSON_USE_EXCEPTION 1
|
||||||
# endif
|
#endif
|
||||||
|
|
||||||
/// If defined, indicates that the source file is amalgated
|
/// If defined, indicates that the source file is amalgated
|
||||||
/// to prevent private header inclusion.
|
/// to prevent private header inclusion.
|
||||||
/// Remarks: it is automatically defined in the generated amalgated header.
|
/// Remarks: it is automatically defined in the generated amalgated header.
|
||||||
// #define JSON_IS_AMALGAMATION
|
// #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
|
#ifdef JSON_IN_CPPTL
|
||||||
# include <cpptl/config.h>
|
#define JSON_API CPPTL_API
|
||||||
# ifndef JSON_USE_CPPTL
|
#elif defined(JSON_DLL_BUILD)
|
||||||
# define JSON_USE_CPPTL 1
|
#if defined(_MSC_VER)
|
||||||
# endif
|
#define JSON_API __declspec(dllexport)
|
||||||
# endif
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
|
#endif // if defined(_MSC_VER)
|
||||||
|
#elif defined(JSON_DLL)
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#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
|
||||||
|
|
||||||
# ifdef JSON_IN_CPPTL
|
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
|
||||||
# define JSON_API CPPTL_API
|
// integer
|
||||||
# elif defined(JSON_DLL_BUILD)
|
|
||||||
# if defined(_MSC_VER)
|
|
||||||
# define JSON_API __declspec(dllexport)
|
|
||||||
# define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
|
||||||
# endif // if defined(_MSC_VER)
|
|
||||||
# elif defined(JSON_DLL)
|
|
||||||
# if defined(_MSC_VER)
|
|
||||||
# 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.
|
// Storages, and 64 bits integer support is disabled.
|
||||||
// #define JSON_NO_INT64 1
|
// #define JSON_NO_INT64 1
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
|
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
|
||||||
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
||||||
// (no conversion from unsigned __int64).
|
// (no conversion from unsigned __int64).
|
||||||
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
#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)
|
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
||||||
// All projects I've ever seen with VS6 were using this globally (not bothering with pragma push/pop).
|
// 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)
|
#pragma warning(disable : 4786)
|
||||||
#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6
|
#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
|
#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
|
||||||
/// Indicates that the following function is deprecated.
|
/// Indicates that the following function is deprecated.
|
||||||
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(JSONCPP_DEPRECATED)
|
#if !defined(JSONCPP_DEPRECATED)
|
||||||
# define JSONCPP_DEPRECATED(message)
|
#define JSONCPP_DEPRECATED(message)
|
||||||
#endif // if !defined(JSONCPP_DEPRECATED)
|
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
typedef int Int;
|
typedef int Int;
|
||||||
typedef unsigned int UInt;
|
typedef unsigned int UInt;
|
||||||
# if defined(JSON_NO_INT64)
|
#if defined(JSON_NO_INT64)
|
||||||
typedef int LargestInt;
|
typedef int LargestInt;
|
||||||
typedef unsigned int LargestUInt;
|
typedef unsigned int LargestUInt;
|
||||||
# undef JSON_HAS_INT64
|
#undef JSON_HAS_INT64
|
||||||
# else // if defined(JSON_NO_INT64)
|
#else // if defined(JSON_NO_INT64)
|
||||||
// For Microsoft Visual use specific types as long long is not supported
|
// For Microsoft Visual use specific types as long long is not supported
|
||||||
# if defined(_MSC_VER) // Microsoft Visual Studio
|
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||||
typedef __int64 Int64;
|
typedef __int64 Int64;
|
||||||
typedef unsigned __int64 UInt64;
|
typedef unsigned __int64 UInt64;
|
||||||
# else // if defined(_MSC_VER) // Other platforms, use long long
|
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||||
typedef long long int Int64;
|
typedef long long int Int64;
|
||||||
typedef unsigned long long int UInt64;
|
typedef unsigned long long int UInt64;
|
||||||
# endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
typedef Int64 LargestInt;
|
typedef Int64 LargestInt;
|
||||||
typedef UInt64 LargestUInt;
|
typedef UInt64 LargestUInt;
|
||||||
# define JSON_HAS_INT64
|
#define JSON_HAS_INT64
|
||||||
# endif // if defined(JSON_NO_INT64)
|
#endif // if defined(JSON_NO_INT64)
|
||||||
} // end namespace Json
|
} // end namespace Json
|
||||||
|
|
||||||
|
|
||||||
#endif // JSON_CONFIG_H_INCLUDED
|
#endif // JSON_CONFIG_H_INCLUDED
|
||||||
|
@ -4,51 +4,53 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
||||||
# define CPPTL_JSON_FEATURES_H_INCLUDED
|
#define CPPTL_JSON_FEATURES_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
# include "forwards.h"
|
#include "forwards.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
/** \brief Configuration passed to reader and writer.
|
/** \brief Configuration passed to reader and writer.
|
||||||
* This configuration object can be used to force the Reader or Writer
|
* This configuration object can be used to force the Reader or Writer
|
||||||
* to behave in a standard conforming way.
|
* to behave in a standard conforming way.
|
||||||
*/
|
*/
|
||||||
class JSON_API Features
|
class JSON_API Features {
|
||||||
{
|
public:
|
||||||
public:
|
/** \brief A configuration that allows all features and assumes all strings
|
||||||
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
|
* are UTF-8.
|
||||||
* - C & C++ comments are allowed
|
* - C & C++ comments are allowed
|
||||||
* - Root object can be any JSON value
|
* - Root object can be any JSON value
|
||||||
* - Assumes Value strings are encoded in UTF-8
|
* - Assumes Value strings are encoded in UTF-8
|
||||||
*/
|
*/
|
||||||
static Features all();
|
static Features all();
|
||||||
|
|
||||||
/** \brief A configuration that is strictly compatible with the JSON specification.
|
/** \brief A configuration that is strictly compatible with the JSON
|
||||||
* - Comments are forbidden.
|
* specification.
|
||||||
* - Root object must be either an array or an object value.
|
* - Comments are forbidden.
|
||||||
* - Assumes Value strings are encoded in UTF-8
|
* - Root object must be either an array or an object value.
|
||||||
*/
|
* - Assumes Value strings are encoded in UTF-8
|
||||||
static Features strictMode();
|
*/
|
||||||
|
static Features strictMode();
|
||||||
|
|
||||||
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
/** \brief Initialize the configuration like JsonConfig::allFeatures;
|
||||||
*/
|
*/
|
||||||
Features();
|
Features();
|
||||||
|
|
||||||
/// \c true if comments are allowed. Default: \c true.
|
/// \c true if comments are allowed. Default: \c true.
|
||||||
bool allowComments_;
|
bool allowComments_;
|
||||||
|
|
||||||
/// \c true if root must be either an array or an object value. Default: \c false.
|
/// \c true if root must be either an array or an object value. Default: \c
|
||||||
bool strictRoot_;
|
/// false.
|
||||||
|
bool strictRoot_;
|
||||||
|
|
||||||
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
||||||
bool allowDroppedNullPlaceholders_;
|
bool allowDroppedNullPlaceholders_;
|
||||||
|
|
||||||
/// \c true if numeric object key are allowed. Default: \c false.
|
/// \c true if numeric object key are allowed. Default: \c false.
|
||||||
bool allowNumericKeys_;
|
bool allowNumericKeys_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
@ -4,41 +4,40 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||||
# define JSON_FORWARDS_H_INCLUDED
|
#define JSON_FORWARDS_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
# include "config.h"
|
#include "config.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
// writer.h
|
// writer.h
|
||||||
class FastWriter;
|
class FastWriter;
|
||||||
class StyledWriter;
|
class StyledWriter;
|
||||||
|
|
||||||
// reader.h
|
// reader.h
|
||||||
class Reader;
|
class Reader;
|
||||||
|
|
||||||
// features.h
|
// features.h
|
||||||
class Features;
|
class Features;
|
||||||
|
|
||||||
// value.h
|
// value.h
|
||||||
typedef unsigned int ArrayIndex;
|
typedef unsigned int ArrayIndex;
|
||||||
class StaticString;
|
class StaticString;
|
||||||
class Path;
|
class Path;
|
||||||
class PathArgument;
|
class PathArgument;
|
||||||
class Value;
|
class Value;
|
||||||
class ValueIteratorBase;
|
class ValueIteratorBase;
|
||||||
class ValueIterator;
|
class ValueIterator;
|
||||||
class ValueConstIterator;
|
class ValueConstIterator;
|
||||||
#ifdef JSON_VALUE_USE_INTERNAL_MAP
|
#ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||||
class ValueMapAllocator;
|
class ValueMapAllocator;
|
||||||
class ValueInternalLink;
|
class ValueInternalLink;
|
||||||
class ValueInternalArray;
|
class ValueInternalArray;
|
||||||
class ValueInternalMap;
|
class ValueInternalMap;
|
||||||
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
|
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
|
||||||
#endif // JSON_FORWARDS_H_INCLUDED
|
#endif // JSON_FORWARDS_H_INCLUDED
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSON_JSON_H_INCLUDED
|
#ifndef JSON_JSON_H_INCLUDED
|
||||||
# define JSON_JSON_H_INCLUDED
|
#define JSON_JSON_H_INCLUDED
|
||||||
|
|
||||||
# include "autolink.h"
|
#include "autolink.h"
|
||||||
# include "value.h"
|
#include "value.h"
|
||||||
# include "reader.h"
|
#include "reader.h"
|
||||||
# include "writer.h"
|
#include "writer.h"
|
||||||
# include "features.h"
|
#include "features.h"
|
||||||
|
|
||||||
#endif // JSON_JSON_H_INCLUDED
|
#endif // JSON_JSON_H_INCLUDED
|
||||||
|
@ -4,246 +4,250 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
||||||
# define CPPTL_JSON_READER_H_INCLUDED
|
#define CPPTL_JSON_READER_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
# include "features.h"
|
#include "features.h"
|
||||||
# include "value.h"
|
#include "value.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
# include <deque>
|
#include <deque>
|
||||||
# include <iosfwd>
|
#include <iosfwd>
|
||||||
# include <stack>
|
#include <stack>
|
||||||
# include <string>
|
#include <string>
|
||||||
|
|
||||||
// Disable warning C4251: <data member>: <type> needs to have dll-interface to be used by...
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
|
// be used by...
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
# pragma warning(push)
|
#pragma warning(push)
|
||||||
# pragma warning(disable:4251)
|
#pragma warning(disable : 4251)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
|
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
|
||||||
*
|
*Value.
|
||||||
*/
|
*
|
||||||
class JSON_API Reader
|
*/
|
||||||
{
|
class JSON_API Reader {
|
||||||
public:
|
public:
|
||||||
typedef char Char;
|
typedef char Char;
|
||||||
typedef const Char *Location;
|
typedef const Char *Location;
|
||||||
|
|
||||||
/** \brief An error tagged with where in the JSON text it was encountered.
|
/** \brief An error tagged with where in the JSON text it was encountered.
|
||||||
*
|
*
|
||||||
* The offsets give the [start, limit) range of bytes within the text. Note
|
* The offsets give the [start, limit) range of bytes within the text. Note
|
||||||
* that this is bytes, not codepoints.
|
* that this is bytes, not codepoints.
|
||||||
*
|
*
|
||||||
*/
|
|
||||||
struct StructuredError
|
|
||||||
{
|
|
||||||
size_t offset_start;
|
|
||||||
size_t offset_limit;
|
|
||||||
std::string message;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Constructs a Reader allowing all features
|
|
||||||
* for parsing.
|
|
||||||
*/
|
|
||||||
Reader();
|
|
||||||
|
|
||||||
/** \brief Constructs a Reader allowing the specified feature set
|
|
||||||
* for parsing.
|
|
||||||
*/
|
|
||||||
Reader( const Features &features );
|
|
||||||
|
|
||||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
|
||||||
* \param document UTF-8 encoded string containing the document to read.
|
|
||||||
* \param root [out] Contains the root value of the document if it was
|
|
||||||
* successfully parsed.
|
|
||||||
* \param collectComments \c true to collect comment and allow writing them back during
|
|
||||||
* serialization, \c false to discard comments.
|
|
||||||
* This parameter is ignored if Features::allowComments_
|
|
||||||
* is \c false.
|
|
||||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
|
||||||
*/
|
|
||||||
bool parse( const std::string &document,
|
|
||||||
Value &root,
|
|
||||||
bool collectComments = true );
|
|
||||||
|
|
||||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
|
|
||||||
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read.
|
|
||||||
* \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read.
|
|
||||||
\ Must be >= beginDoc.
|
|
||||||
* \param root [out] Contains the root value of the document if it was
|
|
||||||
* successfully parsed.
|
|
||||||
* \param collectComments \c true to collect comment and allow writing them back during
|
|
||||||
* serialization, \c false to discard comments.
|
|
||||||
* This parameter is ignored if Features::allowComments_
|
|
||||||
* is \c false.
|
|
||||||
* \return \c true if the document was successfully parsed, \c false if an error occurred.
|
|
||||||
*/
|
|
||||||
bool parse( const char *beginDoc, const char *endDoc,
|
|
||||||
Value &root,
|
|
||||||
bool collectComments = true );
|
|
||||||
|
|
||||||
/// \brief Parse from input stream.
|
|
||||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
|
||||||
bool parse( std::istream &is,
|
|
||||||
Value &root,
|
|
||||||
bool collectComments = true );
|
|
||||||
|
|
||||||
/** \brief Returns a user friendly string that list errors in the parsed document.
|
|
||||||
* \return Formatted error message with the list of errors with their location in
|
|
||||||
* the parsed document. An empty string is returned if no error occurred
|
|
||||||
* during parsing.
|
|
||||||
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
|
|
||||||
*/
|
|
||||||
JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
|
|
||||||
std::string getFormatedErrorMessages() const;
|
|
||||||
|
|
||||||
/** \brief Returns a user friendly string that list errors in the parsed document.
|
|
||||||
* \return Formatted error message with the list of errors with their location in
|
|
||||||
* the parsed document. An empty string is returned if no error occurred
|
|
||||||
* during parsing.
|
|
||||||
*/
|
|
||||||
std::string getFormattedErrorMessages() const;
|
|
||||||
|
|
||||||
/** \brief Returns a vector of structured erros encounted while parsing.
|
|
||||||
* \return A (possibly empty) vector of StructuredError objects. Currently
|
|
||||||
* only one error can be returned, but the caller should tolerate multiple
|
|
||||||
* errors. This can occur if the parser recovers from a non-fatal
|
|
||||||
* parse error and then encounters additional errors.
|
|
||||||
*/
|
|
||||||
std::vector<StructuredError> getStructuredErrors() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum TokenType
|
|
||||||
{
|
|
||||||
tokenEndOfStream = 0,
|
|
||||||
tokenObjectBegin,
|
|
||||||
tokenObjectEnd,
|
|
||||||
tokenArrayBegin,
|
|
||||||
tokenArrayEnd,
|
|
||||||
tokenString,
|
|
||||||
tokenNumber,
|
|
||||||
tokenTrue,
|
|
||||||
tokenFalse,
|
|
||||||
tokenNull,
|
|
||||||
tokenArraySeparator,
|
|
||||||
tokenMemberSeparator,
|
|
||||||
tokenComment,
|
|
||||||
tokenError
|
|
||||||
};
|
|
||||||
|
|
||||||
class Token
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TokenType type_;
|
|
||||||
Location start_;
|
|
||||||
Location end_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ErrorInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Token token_;
|
|
||||||
std::string message_;
|
|
||||||
Location extra_;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::deque<ErrorInfo> Errors;
|
|
||||||
|
|
||||||
bool expectToken( TokenType type, Token &token, const char *message );
|
|
||||||
bool readToken( Token &token );
|
|
||||||
void skipSpaces();
|
|
||||||
bool match( Location pattern,
|
|
||||||
int patternLength );
|
|
||||||
bool readComment();
|
|
||||||
bool readCStyleComment();
|
|
||||||
bool readCppStyleComment();
|
|
||||||
bool readString();
|
|
||||||
void readNumber();
|
|
||||||
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 decodeDouble( Token &token );
|
|
||||||
bool decodeDouble( Token &token, Value &decoded );
|
|
||||||
bool decodeUnicodeCodePoint( Token &token,
|
|
||||||
Location ¤t,
|
|
||||||
Location end,
|
|
||||||
unsigned int &unicode );
|
|
||||||
bool decodeUnicodeEscapeSequence( Token &token,
|
|
||||||
Location ¤t,
|
|
||||||
Location end,
|
|
||||||
unsigned int &unicode );
|
|
||||||
bool addError( const std::string &message,
|
|
||||||
Token &token,
|
|
||||||
Location extra = 0 );
|
|
||||||
bool recoverFromError( TokenType skipUntilToken );
|
|
||||||
bool addErrorAndRecover( const std::string &message,
|
|
||||||
Token &token,
|
|
||||||
TokenType skipUntilToken );
|
|
||||||
void skipUntilSpace();
|
|
||||||
Value ¤tValue();
|
|
||||||
Char getNextChar();
|
|
||||||
void getLocationLineAndColumn( Location location,
|
|
||||||
int &line,
|
|
||||||
int &column ) const;
|
|
||||||
std::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_;
|
|
||||||
Location begin_;
|
|
||||||
Location end_;
|
|
||||||
Location current_;
|
|
||||||
Location lastValueEnd_;
|
|
||||||
Value *lastValue_;
|
|
||||||
std::string commentsBefore_;
|
|
||||||
Features features_;
|
|
||||||
bool collectComments_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Read from 'sin' into 'root'.
|
|
||||||
|
|
||||||
Always keep comments from the input JSON.
|
|
||||||
|
|
||||||
This can be used to read a file into a particular sub-object.
|
|
||||||
For example:
|
|
||||||
\code
|
|
||||||
Json::Value root;
|
|
||||||
cin >> root["dir"]["file"];
|
|
||||||
cout << root;
|
|
||||||
\endcode
|
|
||||||
Result:
|
|
||||||
\verbatim
|
|
||||||
{
|
|
||||||
"dir": {
|
|
||||||
"file": {
|
|
||||||
// The input stream JSON would be nested here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
\endverbatim
|
|
||||||
\throw std::exception on parse error.
|
|
||||||
\see Json::operator<<()
|
|
||||||
*/
|
*/
|
||||||
JSON_API std::istream& operator>>( std::istream&, Value& );
|
struct StructuredError {
|
||||||
|
size_t offset_start;
|
||||||
|
size_t offset_limit;
|
||||||
|
std::string message;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Constructs a Reader allowing all features
|
||||||
|
* for parsing.
|
||||||
|
*/
|
||||||
|
Reader();
|
||||||
|
|
||||||
|
/** \brief Constructs a Reader allowing the specified feature set
|
||||||
|
* for parsing.
|
||||||
|
*/
|
||||||
|
Reader(const Features &features);
|
||||||
|
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
* document.
|
||||||
|
* \param document UTF-8 encoded string containing the document to read.
|
||||||
|
* \param root [out] Contains the root value of the document if it was
|
||||||
|
* successfully parsed.
|
||||||
|
* \param collectComments \c true to collect comment and allow writing them
|
||||||
|
* back during
|
||||||
|
* serialization, \c false to discard comments.
|
||||||
|
* This parameter is ignored if
|
||||||
|
* Features::allowComments_
|
||||||
|
* is \c false.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
* error occurred.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
parse(const std::string &document, Value &root, bool collectComments = true);
|
||||||
|
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
document.
|
||||||
|
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
|
||||||
|
document to read.
|
||||||
|
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
|
||||||
|
document to read.
|
||||||
|
\ Must be >= beginDoc.
|
||||||
|
* \param root [out] Contains the root value of the document if it was
|
||||||
|
* successfully parsed.
|
||||||
|
* \param collectComments \c true to collect comment and allow writing them
|
||||||
|
back during
|
||||||
|
* serialization, \c false to discard comments.
|
||||||
|
* This parameter is ignored if
|
||||||
|
Features::allowComments_
|
||||||
|
* is \c false.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
error occurred.
|
||||||
|
*/
|
||||||
|
bool parse(const char *beginDoc,
|
||||||
|
const char *endDoc,
|
||||||
|
Value &root,
|
||||||
|
bool collectComments = true);
|
||||||
|
|
||||||
|
/// \brief Parse from input stream.
|
||||||
|
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||||
|
bool parse(std::istream &is, Value &root, bool collectComments = true);
|
||||||
|
|
||||||
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
|
* document.
|
||||||
|
* \return Formatted error message with the list of errors with their location
|
||||||
|
* in
|
||||||
|
* the parsed document. An empty string is returned if no error
|
||||||
|
* occurred
|
||||||
|
* during parsing.
|
||||||
|
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
|
||||||
|
*/
|
||||||
|
JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
|
||||||
|
std::string getFormatedErrorMessages() const;
|
||||||
|
|
||||||
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
|
* document.
|
||||||
|
* \return Formatted error message with the list of errors with their location
|
||||||
|
* in
|
||||||
|
* the parsed document. An empty string is returned if no error
|
||||||
|
* occurred
|
||||||
|
* during parsing.
|
||||||
|
*/
|
||||||
|
std::string getFormattedErrorMessages() const;
|
||||||
|
|
||||||
|
/** \brief Returns a vector of structured erros encounted while parsing.
|
||||||
|
* \return A (possibly empty) vector of StructuredError objects. Currently
|
||||||
|
* only one error can be returned, but the caller should tolerate
|
||||||
|
* multiple
|
||||||
|
* errors. This can occur if the parser recovers from a non-fatal
|
||||||
|
* parse error and then encounters additional errors.
|
||||||
|
*/
|
||||||
|
std::vector<StructuredError> getStructuredErrors() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum TokenType {
|
||||||
|
tokenEndOfStream = 0,
|
||||||
|
tokenObjectBegin,
|
||||||
|
tokenObjectEnd,
|
||||||
|
tokenArrayBegin,
|
||||||
|
tokenArrayEnd,
|
||||||
|
tokenString,
|
||||||
|
tokenNumber,
|
||||||
|
tokenTrue,
|
||||||
|
tokenFalse,
|
||||||
|
tokenNull,
|
||||||
|
tokenArraySeparator,
|
||||||
|
tokenMemberSeparator,
|
||||||
|
tokenComment,
|
||||||
|
tokenError
|
||||||
|
};
|
||||||
|
|
||||||
|
class Token {
|
||||||
|
public:
|
||||||
|
TokenType type_;
|
||||||
|
Location start_;
|
||||||
|
Location end_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ErrorInfo {
|
||||||
|
public:
|
||||||
|
Token token_;
|
||||||
|
std::string message_;
|
||||||
|
Location extra_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::deque<ErrorInfo> Errors;
|
||||||
|
|
||||||
|
bool expectToken(TokenType type, Token &token, const char *message);
|
||||||
|
bool readToken(Token &token);
|
||||||
|
void skipSpaces();
|
||||||
|
bool match(Location pattern, int patternLength);
|
||||||
|
bool readComment();
|
||||||
|
bool readCStyleComment();
|
||||||
|
bool readCppStyleComment();
|
||||||
|
bool readString();
|
||||||
|
void readNumber();
|
||||||
|
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 decodeDouble(Token &token);
|
||||||
|
bool decodeDouble(Token &token, Value &decoded);
|
||||||
|
bool decodeUnicodeCodePoint(Token &token,
|
||||||
|
Location ¤t,
|
||||||
|
Location end,
|
||||||
|
unsigned int &unicode);
|
||||||
|
bool decodeUnicodeEscapeSequence(Token &token,
|
||||||
|
Location ¤t,
|
||||||
|
Location end,
|
||||||
|
unsigned int &unicode);
|
||||||
|
bool addError(const std::string &message, Token &token, Location extra = 0);
|
||||||
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
|
bool addErrorAndRecover(const std::string &message,
|
||||||
|
Token &token,
|
||||||
|
TokenType skipUntilToken);
|
||||||
|
void skipUntilSpace();
|
||||||
|
Value ¤tValue();
|
||||||
|
Char getNextChar();
|
||||||
|
void
|
||||||
|
getLocationLineAndColumn(Location location, int &line, int &column) const;
|
||||||
|
std::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_;
|
||||||
|
Location begin_;
|
||||||
|
Location end_;
|
||||||
|
Location current_;
|
||||||
|
Location lastValueEnd_;
|
||||||
|
Value *lastValue_;
|
||||||
|
std::string commentsBefore_;
|
||||||
|
Features features_;
|
||||||
|
bool collectComments_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Read from 'sin' into 'root'.
|
||||||
|
|
||||||
|
Always keep comments from the input JSON.
|
||||||
|
|
||||||
|
This can be used to read a file into a particular sub-object.
|
||||||
|
For example:
|
||||||
|
\code
|
||||||
|
Json::Value root;
|
||||||
|
cin >> root["dir"]["file"];
|
||||||
|
cout << root;
|
||||||
|
\endcode
|
||||||
|
Result:
|
||||||
|
\verbatim
|
||||||
|
{
|
||||||
|
"dir": {
|
||||||
|
"file": {
|
||||||
|
// The input stream JSON would be nested here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
\throw std::exception on parse error.
|
||||||
|
\see Json::operator<<()
|
||||||
|
*/
|
||||||
|
JSON_API std::istream &operator>>(std::istream &, Value &);
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
# pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
|
||||||
#endif // CPPTL_JSON_READER_H_INCLUDED
|
#endif // CPPTL_JSON_READER_H_INCLUDED
|
||||||
|
1922
include/json/value.h
1922
include/json/value.h
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,16 @@
|
|||||||
// DO NOT EDIT. This file is generated by CMake from "version"
|
// DO NOT EDIT. This file is generated by CMake from "version"
|
||||||
// and "version.h.in" files.
|
// and "version.h.in" files.
|
||||||
// Run CMake configure step to update it.
|
// Run CMake configure step to update it.
|
||||||
#ifndef JSON_VERSION_H_INCLUDED
|
#ifndef JSON_VERSION_H_INCLUDED
|
||||||
# define JSON_VERSION_H_INCLUDED
|
#define JSON_VERSION_H_INCLUDED
|
||||||
|
|
||||||
# define JSONCPP_VERSION_STRING "0.6.0-dev"
|
#define JSONCPP_VERSION_STRING "0.6.0-dev"
|
||||||
# define JSONCPP_VERSION_MAJOR 0
|
#define JSONCPP_VERSION_MAJOR 0
|
||||||
# define JSONCPP_VERSION_MINOR 6
|
#define JSONCPP_VERSION_MINOR 6
|
||||||
# define JSONCPP_VERSION_PATCH 0
|
#define JSONCPP_VERSION_PATCH 0
|
||||||
# define JSONCPP_VERSION_QUALIFIER -dev
|
#define JSONCPP_VERSION_QUALIFIER -dev
|
||||||
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
#define JSONCPP_VERSION_HEXA \
|
||||||
|
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||||
|
(JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
#endif // JSON_VERSION_H_INCLUDED
|
#endif // JSON_VERSION_H_INCLUDED
|
||||||
|
@ -4,200 +4,207 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSON_WRITER_H_INCLUDED
|
#ifndef JSON_WRITER_H_INCLUDED
|
||||||
# define JSON_WRITER_H_INCLUDED
|
#define JSON_WRITER_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
# include "value.h"
|
#include "value.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
# include <vector>
|
#include <vector>
|
||||||
# include <string>
|
#include <string>
|
||||||
|
|
||||||
// Disable warning C4251: <data member>: <type> needs to have dll-interface to be used by...
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
|
// be used by...
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
# pragma warning(push)
|
#pragma warning(push)
|
||||||
# pragma warning(disable:4251)
|
#pragma warning(disable : 4251)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
class Value;
|
class Value;
|
||||||
|
|
||||||
/** \brief Abstract class for writers.
|
/** \brief Abstract class for writers.
|
||||||
*/
|
*/
|
||||||
class JSON_API Writer
|
class JSON_API Writer {
|
||||||
{
|
public:
|
||||||
public:
|
virtual ~Writer();
|
||||||
virtual ~Writer();
|
|
||||||
|
|
||||||
virtual std::string write( const Value &root ) = 0;
|
virtual std::string write(const Value &root) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
|
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
||||||
*
|
*without formatting (not human friendly).
|
||||||
* The JSON document is written in a single line. It is not intended for 'human' consumption,
|
*
|
||||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
* The JSON document is written in a single line. It is not intended for 'human'
|
||||||
* \sa Reader, Value
|
*consumption,
|
||||||
*/
|
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||||
class JSON_API FastWriter : public Writer
|
* \sa Reader, Value
|
||||||
{
|
*/
|
||||||
public:
|
class JSON_API FastWriter : public Writer {
|
||||||
FastWriter();
|
public:
|
||||||
virtual ~FastWriter(){}
|
FastWriter();
|
||||||
|
virtual ~FastWriter() {}
|
||||||
|
|
||||||
void enableYAMLCompatibility();
|
void enableYAMLCompatibility();
|
||||||
|
|
||||||
/** \brief Drop the "null" string from the writer's output for nullValues.
|
/** \brief Drop the "null" string from the writer's output for nullValues.
|
||||||
* Strictly speaking, this is not valid JSON. But when the output is being
|
* 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
|
* fed to a browser's Javascript, it makes for smaller output and the
|
||||||
* browser can handle the output just fine.
|
* browser can handle the output just fine.
|
||||||
*/
|
*/
|
||||||
void dropNullPlaceholders();
|
void dropNullPlaceholders();
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
virtual std::string write( const Value &root );
|
virtual std::string write(const Value &root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue( const Value &value );
|
void writeValue(const Value &value);
|
||||||
|
|
||||||
std::string document_;
|
std::string document_;
|
||||||
bool yamlCompatiblityEnabled_;
|
bool yamlCompatiblityEnabled_;
|
||||||
bool dropNullPlaceholders_;
|
bool dropNullPlaceholders_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
|
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||||
*
|
*human friendly way.
|
||||||
* The rules for line break and indent are as follow:
|
*
|
||||||
* - Object value:
|
* The rules for line break and indent are as follow:
|
||||||
* - if empty then print {} without indent and line break
|
* - Object value:
|
||||||
* - if not empty the print '{', line break & indent, print one value per line
|
* - if empty then print {} without indent and line break
|
||||||
* and then unindent and line break and print '}'.
|
* - if not empty the print '{', line break & indent, print one value per
|
||||||
* - Array value:
|
*line
|
||||||
* - if empty then print [] without indent and line break
|
* and then unindent and line break and print '}'.
|
||||||
* - if the array contains no object value, empty array or some other value types,
|
* - Array value:
|
||||||
* and all the values fit on one lines, then print the array on a single line.
|
* - if empty then print [] without indent and line break
|
||||||
* - otherwise, it the values do not fit on one line, or the array contains
|
* - if the array contains no object value, empty array or some other value
|
||||||
* object or non empty array, then print one value per line.
|
*types,
|
||||||
*
|
* and all the values fit on one lines, then print the array on a single
|
||||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
*line.
|
||||||
*
|
* - otherwise, it the values do not fit on one line, or the array contains
|
||||||
* \sa Reader, Value, Value::setComment()
|
* object or non empty array, then print one value per line.
|
||||||
*/
|
*
|
||||||
class JSON_API StyledWriter: public Writer
|
* If the Value have comments then they are outputed according to their
|
||||||
{
|
*#CommentPlacement.
|
||||||
public:
|
*
|
||||||
StyledWriter();
|
* \sa Reader, Value, Value::setComment()
|
||||||
virtual ~StyledWriter(){}
|
*/
|
||||||
|
class JSON_API StyledWriter : public Writer {
|
||||||
|
public:
|
||||||
|
StyledWriter();
|
||||||
|
virtual ~StyledWriter() {}
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
* \param root Value to serialize.
|
* \param root Value to serialize.
|
||||||
* \return String containing the JSON document that represents the root value.
|
* \return String containing the JSON document that represents the root value.
|
||||||
*/
|
*/
|
||||||
virtual std::string write( const Value &root );
|
virtual std::string write(const Value &root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue( const Value &value );
|
void writeValue(const Value &value);
|
||||||
void writeArrayValue( const Value &value );
|
void writeArrayValue(const Value &value);
|
||||||
bool isMultineArray( const Value &value );
|
bool isMultineArray(const Value &value);
|
||||||
void pushValue( const std::string &value );
|
void pushValue(const std::string &value);
|
||||||
void writeIndent();
|
void writeIndent();
|
||||||
void writeWithIndent( const std::string &value );
|
void writeWithIndent(const std::string &value);
|
||||||
void indent();
|
void indent();
|
||||||
void unindent();
|
void unindent();
|
||||||
void writeCommentBeforeValue( const Value &root );
|
void writeCommentBeforeValue(const Value &root);
|
||||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
void writeCommentAfterValueOnSameLine(const Value &root);
|
||||||
bool hasCommentForValue( const Value &value );
|
bool hasCommentForValue(const Value &value);
|
||||||
static std::string normalizeEOL( const std::string &text );
|
static std::string normalizeEOL(const std::string &text);
|
||||||
|
|
||||||
typedef std::vector<std::string> ChildValues;
|
typedef std::vector<std::string> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
std::string document_;
|
std::string document_;
|
||||||
std::string indentString_;
|
std::string indentString_;
|
||||||
int rightMargin_;
|
int rightMargin_;
|
||||||
int indentSize_;
|
int indentSize_;
|
||||||
bool addChildValues_;
|
bool addChildValues_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
|
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
|
||||||
to a stream rather than to a string.
|
human friendly way,
|
||||||
*
|
to a stream rather than to a string.
|
||||||
* The rules for line break and indent are as follow:
|
*
|
||||||
* - Object value:
|
* The rules for line break and indent are as follow:
|
||||||
* - if empty then print {} without indent and line break
|
* - Object value:
|
||||||
* - if not empty the print '{', line break & indent, print one value per line
|
* - if empty then print {} without indent and line break
|
||||||
* and then unindent and line break and print '}'.
|
* - if not empty the print '{', line break & indent, print one value per
|
||||||
* - Array value:
|
line
|
||||||
* - if empty then print [] without indent and line break
|
* and then unindent and line break and print '}'.
|
||||||
* - if the array contains no object value, empty array or some other value types,
|
* - Array value:
|
||||||
* and all the values fit on one lines, then print the array on a single line.
|
* - if empty then print [] without indent and line break
|
||||||
* - otherwise, it the values do not fit on one line, or the array contains
|
* - if the array contains no object value, empty array or some other value
|
||||||
* object or non empty array, then print one value per line.
|
types,
|
||||||
*
|
* and all the values fit on one lines, then print the array on a single
|
||||||
* If the Value have comments then they are outputed according to their #CommentPlacement.
|
line.
|
||||||
*
|
* - otherwise, it the values do not fit on one line, or the array contains
|
||||||
* \param indentation Each level will be indented by this amount extra.
|
* object or non empty array, then print one value per line.
|
||||||
* \sa Reader, Value, Value::setComment()
|
*
|
||||||
*/
|
* If the Value have comments then they are outputed according to their
|
||||||
class JSON_API StyledStreamWriter
|
#CommentPlacement.
|
||||||
{
|
*
|
||||||
public:
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
StyledStreamWriter( std::string indentation="\t" );
|
* \sa Reader, Value, Value::setComment()
|
||||||
~StyledStreamWriter(){}
|
*/
|
||||||
|
class JSON_API StyledStreamWriter {
|
||||||
|
public:
|
||||||
|
StyledStreamWriter(std::string indentation = "\t");
|
||||||
|
~StyledStreamWriter() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
* \param out Stream to write to. (Can be ostringstream, e.g.)
|
||||||
* \param root Value to serialize.
|
* \param root Value to serialize.
|
||||||
* \note There is no point in deriving from Writer, since write() should not return a value.
|
* \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(std::ostream &out, const Value &root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue( const Value &value );
|
void writeValue(const Value &value);
|
||||||
void writeArrayValue( const Value &value );
|
void writeArrayValue(const Value &value);
|
||||||
bool isMultineArray( const Value &value );
|
bool isMultineArray(const Value &value);
|
||||||
void pushValue( const std::string &value );
|
void pushValue(const std::string &value);
|
||||||
void writeIndent();
|
void writeIndent();
|
||||||
void writeWithIndent( const std::string &value );
|
void writeWithIndent(const std::string &value);
|
||||||
void indent();
|
void indent();
|
||||||
void unindent();
|
void unindent();
|
||||||
void writeCommentBeforeValue( const Value &root );
|
void writeCommentBeforeValue(const Value &root);
|
||||||
void writeCommentAfterValueOnSameLine( const Value &root );
|
void writeCommentAfterValueOnSameLine(const Value &root);
|
||||||
bool hasCommentForValue( const Value &value );
|
bool hasCommentForValue(const Value &value);
|
||||||
static std::string normalizeEOL( const std::string &text );
|
static std::string normalizeEOL(const std::string &text);
|
||||||
|
|
||||||
typedef std::vector<std::string> ChildValues;
|
typedef std::vector<std::string> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
std::ostream* document_;
|
std::ostream *document_;
|
||||||
std::string indentString_;
|
std::string indentString_;
|
||||||
int rightMargin_;
|
int rightMargin_;
|
||||||
std::string indentation_;
|
std::string indentation_;
|
||||||
bool addChildValues_;
|
bool addChildValues_;
|
||||||
};
|
};
|
||||||
|
|
||||||
# if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
std::string JSON_API valueToString( Int value );
|
std::string JSON_API valueToString(Int value);
|
||||||
std::string JSON_API valueToString( UInt value );
|
std::string JSON_API valueToString(UInt value);
|
||||||
# endif // if defined(JSON_HAS_INT64)
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
std::string JSON_API valueToString( LargestInt value );
|
std::string JSON_API valueToString(LargestInt value);
|
||||||
std::string JSON_API valueToString( LargestUInt value );
|
std::string JSON_API valueToString(LargestUInt value);
|
||||||
std::string JSON_API valueToString( double value );
|
std::string JSON_API valueToString(double value);
|
||||||
std::string JSON_API valueToString( bool value );
|
std::string JSON_API valueToString(bool value);
|
||||||
std::string JSON_API valueToQuotedString( const char *value );
|
std::string JSON_API valueToQuotedString(const char *value);
|
||||||
|
|
||||||
/// \brief Output using the StyledStreamWriter.
|
/// \brief Output using the StyledStreamWriter.
|
||||||
/// \see Json::operator>>()
|
/// \see Json::operator>>()
|
||||||
JSON_API std::ostream& operator<<( std::ostream&, const Value &root );
|
JSON_API std::ostream &operator<<(std::ostream &, const Value &root);
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
# pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
|
||||||
#endif // JSON_WRITER_H_INCLUDED
|
#endif // JSON_WRITER_H_INCLUDED
|
||||||
|
@ -6,296 +6,266 @@
|
|||||||
/* This executable is used for testing parser/writer using real JSON files.
|
/* This executable is used for testing parser/writer using real JSON files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <algorithm> // sort
|
#include <algorithm> // sort
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1310
|
#if defined(_MSC_VER) && _MSC_VER >= 1310
|
||||||
# pragma warning( disable: 4996 ) // disable fopen deprecation warning
|
#pragma warning(disable : 4996) // disable fopen deprecation warning
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string
|
static std::string normalizeFloatingPointStr(double value) {
|
||||||
normalizeFloatingPointStr( double value )
|
char buffer[32];
|
||||||
{
|
|
||||||
char buffer[32];
|
|
||||||
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
||||||
sprintf_s( buffer, sizeof(buffer), "%.16g", value );
|
sprintf_s(buffer, sizeof(buffer), "%.16g", value);
|
||||||
#else
|
#else
|
||||||
snprintf( buffer, sizeof(buffer), "%.16g", value );
|
snprintf(buffer, sizeof(buffer), "%.16g", value);
|
||||||
#endif
|
#endif
|
||||||
buffer[sizeof(buffer)-1] = 0;
|
buffer[sizeof(buffer) - 1] = 0;
|
||||||
std::string s( buffer );
|
std::string s(buffer);
|
||||||
std::string::size_type index = s.find_last_of( "eE" );
|
std::string::size_type index = s.find_last_of("eE");
|
||||||
if ( index != std::string::npos )
|
if (index != std::string::npos) {
|
||||||
|
std::string::size_type hasSign =
|
||||||
|
(s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
|
||||||
|
std::string::size_type exponentStartIndex = index + 1 + hasSign;
|
||||||
|
std::string normalized = s.substr(0, exponentStartIndex);
|
||||||
|
std::string::size_type indexDigit =
|
||||||
|
s.find_first_not_of('0', exponentStartIndex);
|
||||||
|
std::string exponent = "0";
|
||||||
|
if (indexDigit !=
|
||||||
|
std::string::npos) // There is an exponent different from 0
|
||||||
{
|
{
|
||||||
std::string::size_type hasSign = (s[index+1] == '+' || s[index+1] == '-') ? 1 : 0;
|
exponent = s.substr(indexDigit);
|
||||||
std::string::size_type exponentStartIndex = index + 1 + hasSign;
|
|
||||||
std::string normalized = s.substr( 0, exponentStartIndex );
|
|
||||||
std::string::size_type indexDigit = s.find_first_not_of( '0', exponentStartIndex );
|
|
||||||
std::string exponent = "0";
|
|
||||||
if ( indexDigit != std::string::npos ) // There is an exponent different from 0
|
|
||||||
{
|
|
||||||
exponent = s.substr( indexDigit );
|
|
||||||
}
|
|
||||||
return normalized + exponent;
|
|
||||||
}
|
}
|
||||||
return s;
|
return normalized + exponent;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string readInputTestFile(const char *path) {
|
||||||
static std::string
|
FILE *file = fopen(path, "rb");
|
||||||
readInputTestFile( const char *path )
|
if (!file)
|
||||||
{
|
return std::string("");
|
||||||
FILE *file = fopen( path, "rb" );
|
fseek(file, 0, SEEK_END);
|
||||||
if ( !file )
|
long size = ftell(file);
|
||||||
return std::string("");
|
fseek(file, 0, SEEK_SET);
|
||||||
fseek( file, 0, SEEK_END );
|
std::string text;
|
||||||
long size = ftell( file );
|
char *buffer = new char[size + 1];
|
||||||
fseek( file, 0, SEEK_SET );
|
buffer[size] = 0;
|
||||||
std::string text;
|
if (fread(buffer, 1, size, file) == (unsigned long)size)
|
||||||
char *buffer = new char[size+1];
|
text = buffer;
|
||||||
buffer[size] = 0;
|
fclose(file);
|
||||||
if ( fread( buffer, 1, size, file ) == (unsigned long)size )
|
delete[] buffer;
|
||||||
text = buffer;
|
return text;
|
||||||
fclose( file );
|
|
||||||
delete[] buffer;
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
printValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )
|
printValueTree(FILE *fout, Json::Value &value, const std::string &path = ".") {
|
||||||
{
|
switch (value.type()) {
|
||||||
switch ( value.type() )
|
case Json::nullValue:
|
||||||
{
|
fprintf(fout, "%s=null\n", path.c_str());
|
||||||
case Json::nullValue:
|
break;
|
||||||
fprintf( fout, "%s=null\n", path.c_str() );
|
case Json::intValue:
|
||||||
break;
|
fprintf(fout,
|
||||||
case Json::intValue:
|
"%s=%s\n",
|
||||||
fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestInt() ).c_str() );
|
path.c_str(),
|
||||||
break;
|
Json::valueToString(value.asLargestInt()).c_str());
|
||||||
case Json::uintValue:
|
break;
|
||||||
fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestUInt() ).c_str() );
|
case Json::uintValue:
|
||||||
break;
|
fprintf(fout,
|
||||||
case Json::realValue:
|
"%s=%s\n",
|
||||||
fprintf( fout, "%s=%s\n", path.c_str(), normalizeFloatingPointStr(value.asDouble()).c_str() );
|
path.c_str(),
|
||||||
break;
|
Json::valueToString(value.asLargestUInt()).c_str());
|
||||||
case Json::stringValue:
|
break;
|
||||||
fprintf( fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str() );
|
case Json::realValue:
|
||||||
break;
|
fprintf(fout,
|
||||||
case Json::booleanValue:
|
"%s=%s\n",
|
||||||
fprintf( fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false" );
|
path.c_str(),
|
||||||
break;
|
normalizeFloatingPointStr(value.asDouble()).c_str());
|
||||||
case Json::arrayValue:
|
break;
|
||||||
{
|
case Json::stringValue:
|
||||||
fprintf( fout, "%s=[]\n", path.c_str() );
|
fprintf(fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str());
|
||||||
int size = value.size();
|
break;
|
||||||
for ( int index =0; index < size; ++index )
|
case Json::booleanValue:
|
||||||
{
|
fprintf(fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false");
|
||||||
static char buffer[16];
|
break;
|
||||||
|
case Json::arrayValue: {
|
||||||
|
fprintf(fout, "%s=[]\n", path.c_str());
|
||||||
|
int size = value.size();
|
||||||
|
for (int index = 0; index < size; ++index) {
|
||||||
|
static char buffer[16];
|
||||||
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
||||||
sprintf_s( buffer, sizeof(buffer), "[%d]", index );
|
sprintf_s(buffer, sizeof(buffer), "[%d]", index);
|
||||||
#else
|
#else
|
||||||
snprintf( buffer, sizeof(buffer), "[%d]", index );
|
snprintf(buffer, sizeof(buffer), "[%d]", index);
|
||||||
#endif
|
#endif
|
||||||
printValueTree( fout, value[index], path + buffer );
|
printValueTree(fout, value[index], path + buffer);
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
break;
|
case Json::objectValue: {
|
||||||
case Json::objectValue:
|
fprintf(fout, "%s={}\n", path.c_str());
|
||||||
{
|
Json::Value::Members members(value.getMemberNames());
|
||||||
fprintf( fout, "%s={}\n", path.c_str() );
|
std::sort(members.begin(), members.end());
|
||||||
Json::Value::Members members( value.getMemberNames() );
|
std::string suffix = *(path.end() - 1) == '.' ? "" : ".";
|
||||||
std::sort( members.begin(), members.end() );
|
for (Json::Value::Members::iterator it = members.begin();
|
||||||
std::string suffix = *(path.end()-1) == '.' ? "" : ".";
|
it != members.end();
|
||||||
for ( Json::Value::Members::iterator it = members.begin();
|
++it) {
|
||||||
it != members.end();
|
const std::string &name = *it;
|
||||||
++it )
|
printValueTree(fout, value[name], path + suffix + name);
|
||||||
{
|
}
|
||||||
const std::string &name = *it;
|
} break;
|
||||||
printValueTree( fout, value[name], path + suffix + name );
|
default:
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parseAndSaveValueTree(const std::string &input,
|
||||||
|
const std::string &actual,
|
||||||
|
const std::string &kind,
|
||||||
|
Json::Value &root,
|
||||||
|
const Json::Features &features,
|
||||||
|
bool parseOnly) {
|
||||||
|
Json::Reader reader(features);
|
||||||
|
bool parsingSuccessful = reader.parse(input, root);
|
||||||
|
if (!parsingSuccessful) {
|
||||||
|
printf("Failed to parse %s file: \n%s\n",
|
||||||
|
kind.c_str(),
|
||||||
|
reader.getFormattedErrorMessages().c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
if (!parseOnly) {
|
||||||
parseAndSaveValueTree( const std::string &input,
|
FILE *factual = fopen(actual.c_str(), "wt");
|
||||||
const std::string &actual,
|
if (!factual) {
|
||||||
const std::string &kind,
|
printf("Failed to create %s actual file.\n", kind.c_str());
|
||||||
Json::Value &root,
|
|
||||||
const Json::Features &features,
|
|
||||||
bool parseOnly )
|
|
||||||
{
|
|
||||||
Json::Reader reader( features );
|
|
||||||
bool parsingSuccessful = reader.parse( input, root );
|
|
||||||
if ( !parsingSuccessful )
|
|
||||||
{
|
|
||||||
printf( "Failed to parse %s file: \n%s\n",
|
|
||||||
kind.c_str(),
|
|
||||||
reader.getFormattedErrorMessages().c_str() );
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !parseOnly )
|
|
||||||
{
|
|
||||||
FILE *factual = fopen( actual.c_str(), "wt" );
|
|
||||||
if ( !factual )
|
|
||||||
{
|
|
||||||
printf( "Failed to create %s actual file.\n", kind.c_str() );
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
printValueTree( factual, root );
|
|
||||||
fclose( factual );
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
rewriteValueTree( const std::string &rewritePath,
|
|
||||||
const Json::Value &root,
|
|
||||||
std::string &rewrite )
|
|
||||||
{
|
|
||||||
//Json::FastWriter writer;
|
|
||||||
//writer.enableYAMLCompatibility();
|
|
||||||
Json::StyledWriter writer;
|
|
||||||
rewrite = writer.write( root );
|
|
||||||
FILE *fout = fopen( rewritePath.c_str(), "wt" );
|
|
||||||
if ( !fout )
|
|
||||||
{
|
|
||||||
printf( "Failed to create rewrite file: %s\n", rewritePath.c_str() );
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
fprintf( fout, "%s\n", rewrite.c_str() );
|
printValueTree(factual, root);
|
||||||
fclose( fout );
|
fclose(factual);
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rewriteValueTree(const std::string &rewritePath,
|
||||||
static std::string
|
const Json::Value &root,
|
||||||
removeSuffix( const std::string &path,
|
std::string &rewrite) {
|
||||||
const std::string &extension )
|
// Json::FastWriter writer;
|
||||||
{
|
// writer.enableYAMLCompatibility();
|
||||||
if ( extension.length() >= path.length() )
|
Json::StyledWriter writer;
|
||||||
return std::string("");
|
rewrite = writer.write(root);
|
||||||
std::string suffix = path.substr( path.length() - extension.length() );
|
FILE *fout = fopen(rewritePath.c_str(), "wt");
|
||||||
if ( suffix != extension )
|
if (!fout) {
|
||||||
return std::string("");
|
printf("Failed to create rewrite file: %s\n", rewritePath.c_str());
|
||||||
return path.substr( 0, path.length() - extension.length() );
|
return 2;
|
||||||
|
}
|
||||||
|
fprintf(fout, "%s\n", rewrite.c_str());
|
||||||
|
fclose(fout);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string removeSuffix(const std::string &path,
|
||||||
|
const std::string &extension) {
|
||||||
|
if (extension.length() >= path.length())
|
||||||
|
return std::string("");
|
||||||
|
std::string suffix = path.substr(path.length() - extension.length());
|
||||||
|
if (suffix != extension)
|
||||||
|
return std::string("");
|
||||||
|
return path.substr(0, path.length() - extension.length());
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void printConfig() {
|
||||||
printConfig()
|
// Print the configuration used to compile JsonCpp
|
||||||
{
|
|
||||||
// Print the configuration used to compile JsonCpp
|
|
||||||
#if defined(JSON_NO_INT64)
|
#if defined(JSON_NO_INT64)
|
||||||
printf( "JSON_NO_INT64=1\n" );
|
printf("JSON_NO_INT64=1\n");
|
||||||
#else
|
#else
|
||||||
printf( "JSON_NO_INT64=0\n" );
|
printf("JSON_NO_INT64=0\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int printUsage(const char *argv[]) {
|
||||||
static int
|
printf("Usage: %s [--strict] input-json-file", argv[0]);
|
||||||
printUsage( const char *argv[] )
|
return 3;
|
||||||
{
|
|
||||||
printf( "Usage: %s [--strict] input-json-file", argv[0] );
|
|
||||||
return 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parseCommandLine(int argc,
|
||||||
|
const char *argv[],
|
||||||
|
Json::Features &features,
|
||||||
|
std::string &path,
|
||||||
|
bool &parseOnly) {
|
||||||
|
parseOnly = false;
|
||||||
|
if (argc < 2) {
|
||||||
|
return printUsage(argv);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int index = 1;
|
||||||
parseCommandLine( int argc, const char *argv[],
|
if (std::string(argv[1]) == "--json-checker") {
|
||||||
Json::Features &features, std::string &path,
|
features = Json::Features::strictMode();
|
||||||
bool &parseOnly )
|
parseOnly = true;
|
||||||
{
|
++index;
|
||||||
parseOnly = false;
|
}
|
||||||
if ( argc < 2 )
|
|
||||||
{
|
|
||||||
return printUsage( argv );
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = 1;
|
if (std::string(argv[1]) == "--json-config") {
|
||||||
if ( std::string(argv[1]) == "--json-checker" )
|
printConfig();
|
||||||
{
|
return 3;
|
||||||
features = Json::Features::strictMode();
|
}
|
||||||
parseOnly = true;
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( std::string(argv[1]) == "--json-config" )
|
if (index == argc || index + 1 < argc) {
|
||||||
{
|
return printUsage(argv);
|
||||||
printConfig();
|
}
|
||||||
|
|
||||||
|
path = argv[index];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char *argv[]) {
|
||||||
|
std::string path;
|
||||||
|
Json::Features features;
|
||||||
|
bool parseOnly;
|
||||||
|
int exitCode = parseCommandLine(argc, argv, features, path, parseOnly);
|
||||||
|
if (exitCode != 0) {
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::string input = readInputTestFile(path.c_str());
|
||||||
|
if (input.empty()) {
|
||||||
|
printf("Failed to read input or empty input: %s\n", path.c_str());
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( index == argc || index + 1 < argc )
|
std::string basePath = removeSuffix(argv[1], ".json");
|
||||||
{
|
if (!parseOnly && basePath.empty()) {
|
||||||
return printUsage( argv );
|
printf("Bad input path. Path does not end with '.expected':\n%s\n",
|
||||||
}
|
path.c_str());
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
path = argv[index];
|
std::string actualPath = basePath + ".actual";
|
||||||
return 0;
|
std::string rewritePath = basePath + ".rewrite";
|
||||||
}
|
std::string rewriteActualPath = basePath + ".actual-rewrite";
|
||||||
|
|
||||||
|
Json::Value root;
|
||||||
int main( int argc, const char *argv[] )
|
exitCode = parseAndSaveValueTree(
|
||||||
{
|
input, actualPath, "input", root, features, parseOnly);
|
||||||
std::string path;
|
if (exitCode == 0 && !parseOnly) {
|
||||||
Json::Features features;
|
std::string rewrite;
|
||||||
bool parseOnly;
|
exitCode = rewriteValueTree(rewritePath, root, rewrite);
|
||||||
int exitCode = parseCommandLine( argc, argv, features, path, parseOnly );
|
if (exitCode == 0) {
|
||||||
if ( exitCode != 0 )
|
Json::Value rewriteRoot;
|
||||||
{
|
exitCode = parseAndSaveValueTree(rewrite,
|
||||||
return exitCode;
|
rewriteActualPath,
|
||||||
}
|
"rewrite",
|
||||||
|
rewriteRoot,
|
||||||
try
|
features,
|
||||||
{
|
parseOnly);
|
||||||
std::string input = readInputTestFile( path.c_str() );
|
|
||||||
if ( input.empty() )
|
|
||||||
{
|
|
||||||
printf( "Failed to read input or empty input: %s\n", path.c_str() );
|
|
||||||
return 3;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e) {
|
||||||
|
printf("Unhandled exception:\n%s\n", e.what());
|
||||||
|
exitCode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
std::string basePath = removeSuffix( argv[1], ".json" );
|
return exitCode;
|
||||||
if ( !parseOnly && basePath.empty() )
|
|
||||||
{
|
|
||||||
printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string actualPath = basePath + ".actual";
|
|
||||||
std::string rewritePath = basePath + ".rewrite";
|
|
||||||
std::string rewriteActualPath = basePath + ".actual-rewrite";
|
|
||||||
|
|
||||||
Json::Value root;
|
|
||||||
exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
|
|
||||||
if ( exitCode == 0 && !parseOnly )
|
|
||||||
{
|
|
||||||
std::string rewrite;
|
|
||||||
exitCode = rewriteValueTree( rewritePath, root, rewrite );
|
|
||||||
if ( exitCode == 0 )
|
|
||||||
{
|
|
||||||
Json::Value rewriteRoot;
|
|
||||||
exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath,
|
|
||||||
"rewrite", rewriteRoot, features, parseOnly );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ( const std::exception &e )
|
|
||||||
{
|
|
||||||
printf( "Unhandled exception:\n%s\n", e.what() );
|
|
||||||
exitCode = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return exitCode;
|
|
||||||
}
|
}
|
||||||
// vim: et ts=4 sts=4 sw=4 tw=0
|
// vim: et ts=4 sts=4 sw=4 tw=0
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||||
# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
#define JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||||
|
|
||||||
# include <stdlib.h>
|
#include <stdlib.h>
|
||||||
# include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
@ -18,111 +18,108 @@ namespace Json {
|
|||||||
* This memory allocator allocates memory for a batch of object (specified by
|
* This memory allocator allocates memory for a batch of object (specified by
|
||||||
* the page size, the number of object in each page).
|
* the page size, the number of object in each page).
|
||||||
*
|
*
|
||||||
* It does not allow the destruction of a single object. All the allocated objects
|
* It does not allow the destruction of a single object. All the allocated
|
||||||
* can be destroyed at once. The memory can be either released or reused for future
|
*objects
|
||||||
|
* can be destroyed at once. The memory can be either released or reused for
|
||||||
|
*future
|
||||||
* allocation.
|
* allocation.
|
||||||
*
|
*
|
||||||
* The in-place new operator must be used to construct the object using the pointer
|
* The in-place new operator must be used to construct the object using the
|
||||||
|
*pointer
|
||||||
* returned by allocate.
|
* returned by allocate.
|
||||||
*/
|
*/
|
||||||
template<typename AllocatedType
|
template <typename AllocatedType, const unsigned int objectPerAllocation>
|
||||||
,const unsigned int objectPerAllocation>
|
class BatchAllocator {
|
||||||
class BatchAllocator
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
BatchAllocator( unsigned int objectsPerPage = 255 )
|
BatchAllocator(unsigned int objectsPerPage = 255)
|
||||||
: freeHead_( 0 )
|
: freeHead_(0), objectsPerPage_(objectsPerPage) {
|
||||||
, objectsPerPage_( objectsPerPage )
|
// printf( "Size: %d => %s\n", sizeof(AllocatedType),
|
||||||
{
|
// typeid(AllocatedType).name() );
|
||||||
// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
|
assert(sizeof(AllocatedType) * objectPerAllocation >=
|
||||||
assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
|
sizeof(AllocatedType *)); // We must be able to store a slist in the
|
||||||
assert( objectsPerPage >= 16 );
|
// object free space.
|
||||||
batches_ = allocateBatch( 0 ); // allocated a dummy page
|
assert(objectsPerPage >= 16);
|
||||||
currentBatch_ = batches_;
|
batches_ = allocateBatch(0); // allocated a dummy page
|
||||||
}
|
currentBatch_ = batches_;
|
||||||
|
}
|
||||||
|
|
||||||
~BatchAllocator()
|
~BatchAllocator() {
|
||||||
{
|
for (BatchInfo *batch = batches_; batch;) {
|
||||||
for ( BatchInfo *batch = batches_; batch; )
|
BatchInfo *nextBatch = batch->next_;
|
||||||
|
free(batch);
|
||||||
|
batch = nextBatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// allocate space for an array of objectPerAllocation object.
|
||||||
|
/// @warning it is the responsability of the caller to call objects
|
||||||
|
/// constructors.
|
||||||
|
AllocatedType *allocate() {
|
||||||
|
if (freeHead_) // returns node from free list.
|
||||||
|
{
|
||||||
|
AllocatedType *object = freeHead_;
|
||||||
|
freeHead_ = *(AllocatedType **)object;
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
if (currentBatch_->used_ == currentBatch_->end_) {
|
||||||
|
currentBatch_ = currentBatch_->next_;
|
||||||
|
while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_)
|
||||||
|
currentBatch_ = currentBatch_->next_;
|
||||||
|
|
||||||
|
if (!currentBatch_) // no free batch found, allocate a new one
|
||||||
{
|
{
|
||||||
BatchInfo *nextBatch = batch->next_;
|
currentBatch_ = allocateBatch(objectsPerPage_);
|
||||||
free( batch );
|
currentBatch_->next_ = batches_; // insert at the head of the list
|
||||||
batch = nextBatch;
|
batches_ = currentBatch_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AllocatedType *allocated = currentBatch_->used_;
|
||||||
|
currentBatch_->used_ += objectPerAllocation;
|
||||||
|
return allocated;
|
||||||
|
}
|
||||||
|
|
||||||
/// allocate space for an array of objectPerAllocation object.
|
/// Release the object.
|
||||||
/// @warning it is the responsability of the caller to call objects constructors.
|
/// @warning it is the responsability of the caller to actually destruct the
|
||||||
AllocatedType *allocate()
|
/// object.
|
||||||
{
|
void release(AllocatedType *object) {
|
||||||
if ( freeHead_ ) // returns node from free list.
|
assert(object != 0);
|
||||||
{
|
*(AllocatedType **)object = freeHead_;
|
||||||
AllocatedType *object = freeHead_;
|
freeHead_ = object;
|
||||||
freeHead_ = *(AllocatedType **)object;
|
}
|
||||||
return object;
|
|
||||||
}
|
|
||||||
if ( currentBatch_->used_ == currentBatch_->end_ )
|
|
||||||
{
|
|
||||||
currentBatch_ = currentBatch_->next_;
|
|
||||||
while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
|
|
||||||
currentBatch_ = currentBatch_->next_;
|
|
||||||
|
|
||||||
if ( !currentBatch_ ) // no free batch found, allocate a new one
|
|
||||||
{
|
|
||||||
currentBatch_ = allocateBatch( objectsPerPage_ );
|
|
||||||
currentBatch_->next_ = batches_; // insert at the head of the list
|
|
||||||
batches_ = currentBatch_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AllocatedType *allocated = currentBatch_->used_;
|
|
||||||
currentBatch_->used_ += objectPerAllocation;
|
|
||||||
return allocated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Release the object.
|
|
||||||
/// @warning it is the responsability of the caller to actually destruct the object.
|
|
||||||
void release( AllocatedType *object )
|
|
||||||
{
|
|
||||||
assert( object != 0 );
|
|
||||||
*(AllocatedType **)object = freeHead_;
|
|
||||||
freeHead_ = object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct BatchInfo
|
struct BatchInfo {
|
||||||
{
|
BatchInfo *next_;
|
||||||
BatchInfo *next_;
|
AllocatedType *used_;
|
||||||
AllocatedType *used_;
|
AllocatedType *end_;
|
||||||
AllocatedType *end_;
|
AllocatedType buffer_[objectPerAllocation];
|
||||||
AllocatedType buffer_[objectPerAllocation];
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// disabled copy constructor and assignement operator.
|
// disabled copy constructor and assignement operator.
|
||||||
BatchAllocator( const BatchAllocator & );
|
BatchAllocator(const BatchAllocator &);
|
||||||
void operator =( const BatchAllocator &);
|
void operator=(const BatchAllocator &);
|
||||||
|
|
||||||
static BatchInfo *allocateBatch( unsigned int objectsPerPage )
|
static BatchInfo *allocateBatch(unsigned int objectsPerPage) {
|
||||||
{
|
const unsigned int mallocSize =
|
||||||
const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
|
sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation +
|
||||||
+ sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
|
sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
|
||||||
BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
|
BatchInfo *batch = static_cast<BatchInfo *>(malloc(mallocSize));
|
||||||
batch->next_ = 0;
|
batch->next_ = 0;
|
||||||
batch->used_ = batch->buffer_;
|
batch->used_ = batch->buffer_;
|
||||||
batch->end_ = batch->buffer_ + objectsPerPage;
|
batch->end_ = batch->buffer_ + objectsPerPage;
|
||||||
return batch;
|
return batch;
|
||||||
}
|
}
|
||||||
|
|
||||||
BatchInfo *batches_;
|
BatchInfo *batches_;
|
||||||
BatchInfo *currentBatch_;
|
BatchInfo *currentBatch_;
|
||||||
/// Head of a single linked list within the allocated space of freeed object
|
/// Head of a single linked list within the allocated space of freeed object
|
||||||
AllocatedType *freeHead_;
|
AllocatedType *freeHead_;
|
||||||
unsigned int objectsPerPage_;
|
unsigned int objectsPerPage_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
|
#endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
|
||||||
|
|
||||||
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
||||||
// vim: et ts=3 sts=3 sw=3 tw=0
|
// vim: et ts=3 sts=3 sw=3 tw=0
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
# define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
|
||||||
/* This header provides common string manipulation support, such as UTF-8,
|
/* This header provides common string manipulation support, such as UTF-8,
|
||||||
* portable conversion from/to string...
|
* portable conversion from/to string...
|
||||||
@ -15,77 +15,57 @@
|
|||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
/// Converts a unicode code-point to UTF-8.
|
/// Converts a unicode code-point to UTF-8.
|
||||||
static inline std::string
|
static inline std::string codePointToUTF8(unsigned int cp) {
|
||||||
codePointToUTF8(unsigned int cp)
|
std::string result;
|
||||||
{
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
|
||||||
|
|
||||||
if (cp <= 0x7f)
|
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
||||||
{
|
|
||||||
result.resize(1);
|
|
||||||
result[0] = static_cast<char>(cp);
|
|
||||||
}
|
|
||||||
else if (cp <= 0x7FF)
|
|
||||||
{
|
|
||||||
result.resize(2);
|
|
||||||
result[1] = static_cast<char>(0x80 | (0x3f & cp));
|
|
||||||
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
|
|
||||||
}
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
else if (cp <= 0x10FFFF)
|
|
||||||
{
|
|
||||||
result.resize(4);
|
|
||||||
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
|
||||||
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
|
||||||
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
|
|
||||||
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
if (cp <= 0x7f) {
|
||||||
|
result.resize(1);
|
||||||
|
result[0] = static_cast<char>(cp);
|
||||||
|
} else if (cp <= 0x7FF) {
|
||||||
|
result.resize(2);
|
||||||
|
result[1] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
|
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
|
||||||
|
} 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)));
|
||||||
|
} else if (cp <= 0x10FFFF) {
|
||||||
|
result.resize(4);
|
||||||
|
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
|
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||||
|
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
|
||||||
|
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Returns true if ch is a control character (in range [0,32[).
|
/// Returns true if ch is a control character (in range [0,32[).
|
||||||
static inline bool
|
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
|
||||||
isControlCharacter(char ch)
|
|
||||||
{
|
|
||||||
return ch > 0 && ch <= 0x1F;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
enum {
|
||||||
enum {
|
/// Constant that specify the size of the buffer that must be passed to
|
||||||
/// Constant that specify the size of the buffer that must be passed to uintToString.
|
/// uintToString.
|
||||||
uintToStringBufferSize = 3*sizeof(LargestUInt)+1
|
uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
|
||||||
};
|
};
|
||||||
|
|
||||||
// Defines a char buffer for use with uintToString().
|
// Defines a char buffer for use with uintToString().
|
||||||
typedef char UIntToStringBuffer[uintToStringBufferSize];
|
typedef char UIntToStringBuffer[uintToStringBufferSize];
|
||||||
|
|
||||||
|
|
||||||
/** Converts an unsigned integer to string.
|
/** Converts an unsigned integer to string.
|
||||||
* @param value Unsigned interger to convert to string
|
* @param value Unsigned interger to convert to string
|
||||||
* @param current Input/Output string buffer.
|
* @param current Input/Output string buffer.
|
||||||
* Must have at least uintToStringBufferSize chars free.
|
* Must have at least uintToStringBufferSize chars free.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void uintToString(LargestUInt value, char *¤t) {
|
||||||
uintToString( LargestUInt value,
|
*--current = 0;
|
||||||
char *¤t )
|
do {
|
||||||
{
|
*--current = char(value % 10) + '0';
|
||||||
*--current = 0;
|
value /= 10;
|
||||||
do
|
} while (value != 0);
|
||||||
{
|
|
||||||
*--current = char(value % 10) + '0';
|
|
||||||
value /= 10;
|
|
||||||
}
|
|
||||||
while ( value != 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Json {
|
} // namespace Json {
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -10,569 +10,435 @@
|
|||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
// Used to install a report hook that prevent dialog on assertion and error.
|
// Used to install a report hook that prevent dialog on assertion and error.
|
||||||
# include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Used to prevent dialog on memory fault.
|
// Used to prevent dialog on memory fault.
|
||||||
// Limits headers included by Windows.h
|
// Limits headers included by Windows.h
|
||||||
# define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
# define NOSERVICE
|
#define NOSERVICE
|
||||||
# define NOMCX
|
#define NOMCX
|
||||||
# define NOIME
|
#define NOIME
|
||||||
# define NOSOUND
|
#define NOSOUND
|
||||||
# define NOCOMM
|
#define NOCOMM
|
||||||
# define NORPC
|
#define NORPC
|
||||||
# define NOGDI
|
#define NOGDI
|
||||||
# define NOUSER
|
#define NOUSER
|
||||||
# define NODRIVERS
|
#define NODRIVERS
|
||||||
# define NOLOGERROR
|
#define NOLOGERROR
|
||||||
# define NOPROFILER
|
#define NOPROFILER
|
||||||
# define NOMEMMGR
|
#define NOMEMMGR
|
||||||
# define NOLFILEIO
|
#define NOLFILEIO
|
||||||
# define NOOPENFILE
|
#define NOOPENFILE
|
||||||
# define NORESOURCE
|
#define NORESOURCE
|
||||||
# define NOATOM
|
#define NOATOM
|
||||||
# define NOLANGUAGE
|
#define NOLANGUAGE
|
||||||
# define NOLSTRING
|
#define NOLSTRING
|
||||||
# define NODBCS
|
#define NODBCS
|
||||||
# define NOKEYBOARDINFO
|
#define NOKEYBOARDINFO
|
||||||
# define NOGDICAPMASKS
|
#define NOGDICAPMASKS
|
||||||
# define NOCOLOR
|
#define NOCOLOR
|
||||||
# define NOGDIOBJ
|
#define NOGDIOBJ
|
||||||
# define NODRAWTEXT
|
#define NODRAWTEXT
|
||||||
# define NOTEXTMETRIC
|
#define NOTEXTMETRIC
|
||||||
# define NOSCALABLEFONT
|
#define NOSCALABLEFONT
|
||||||
# define NOBITMAP
|
#define NOBITMAP
|
||||||
# define NORASTEROPS
|
#define NORASTEROPS
|
||||||
# define NOMETAFILE
|
#define NOMETAFILE
|
||||||
# define NOSYSMETRICS
|
#define NOSYSMETRICS
|
||||||
# define NOSYSTEMPARAMSINFO
|
#define NOSYSTEMPARAMSINFO
|
||||||
# define NOMSG
|
#define NOMSG
|
||||||
# define NOWINSTYLES
|
#define NOWINSTYLES
|
||||||
# define NOWINOFFSETS
|
#define NOWINOFFSETS
|
||||||
# define NOSHOWWINDOW
|
#define NOSHOWWINDOW
|
||||||
# define NODEFERWINDOWPOS
|
#define NODEFERWINDOWPOS
|
||||||
# define NOVIRTUALKEYCODES
|
#define NOVIRTUALKEYCODES
|
||||||
# define NOKEYSTATES
|
#define NOKEYSTATES
|
||||||
# define NOWH
|
#define NOWH
|
||||||
# define NOMENUS
|
#define NOMENUS
|
||||||
# define NOSCROLL
|
#define NOSCROLL
|
||||||
# define NOCLIPBOARD
|
#define NOCLIPBOARD
|
||||||
# define NOICONS
|
#define NOICONS
|
||||||
# define NOMB
|
#define NOMB
|
||||||
# define NOSYSCOMMANDS
|
#define NOSYSCOMMANDS
|
||||||
# define NOMDI
|
#define NOMDI
|
||||||
# define NOCTLMGR
|
#define NOCTLMGR
|
||||||
# define NOWINMESSAGES
|
#define NOWINMESSAGES
|
||||||
# include <windows.h>
|
#include <windows.h>
|
||||||
#endif // if defined(_WIN32)
|
#endif // if defined(_WIN32)
|
||||||
|
|
||||||
namespace JsonTest {
|
namespace JsonTest {
|
||||||
|
|
||||||
|
|
||||||
// class TestResult
|
// class TestResult
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TestResult::TestResult()
|
TestResult::TestResult()
|
||||||
: predicateId_( 1 )
|
: predicateId_(1), lastUsedPredicateId_(0), messageTarget_(0) {
|
||||||
, lastUsedPredicateId_( 0 )
|
// The root predicate has id 0
|
||||||
, messageTarget_( 0 )
|
rootPredicateNode_.id_ = 0;
|
||||||
{
|
rootPredicateNode_.next_ = 0;
|
||||||
// The root predicate has id 0
|
predicateStackTail_ = &rootPredicateNode_;
|
||||||
rootPredicateNode_.id_ = 0;
|
|
||||||
rootPredicateNode_.next_ = 0;
|
|
||||||
predicateStackTail_ = &rootPredicateNode_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestResult::setTestName(const std::string &name) { name_ = name; }
|
||||||
void
|
|
||||||
TestResult::setTestName( const std::string &name )
|
|
||||||
{
|
|
||||||
name_ = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult &
|
TestResult &
|
||||||
TestResult::addFailure( const char *file, unsigned int line,
|
TestResult::addFailure(const char *file, unsigned int line, const char *expr) {
|
||||||
const char *expr )
|
/// Walks the PredicateContext stack adding them to failures_ if not already
|
||||||
{
|
/// added.
|
||||||
/// Walks the PredicateContext stack adding them to failures_ if not already added.
|
unsigned int nestingLevel = 0;
|
||||||
unsigned int nestingLevel = 0;
|
PredicateContext *lastNode = rootPredicateNode_.next_;
|
||||||
PredicateContext *lastNode = rootPredicateNode_.next_;
|
for (; lastNode != 0; lastNode = lastNode->next_) {
|
||||||
for ( ; lastNode != 0; lastNode = lastNode->next_ )
|
if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
|
||||||
{
|
{
|
||||||
if ( lastNode->id_ > lastUsedPredicateId_ ) // new PredicateContext
|
lastUsedPredicateId_ = lastNode->id_;
|
||||||
{
|
addFailureInfo(
|
||||||
lastUsedPredicateId_ = lastNode->id_;
|
lastNode->file_, lastNode->line_, lastNode->expr_, nestingLevel);
|
||||||
addFailureInfo( lastNode->file_, lastNode->line_, lastNode->expr_,
|
// Link the PredicateContext to the failure for message target when
|
||||||
nestingLevel );
|
// popping the PredicateContext.
|
||||||
// Link the PredicateContext to the failure for message target when
|
lastNode->failure_ = &(failures_.back());
|
||||||
// popping the PredicateContext.
|
}
|
||||||
lastNode->failure_ = &( failures_.back() );
|
++nestingLevel;
|
||||||
}
|
}
|
||||||
++nestingLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds the failed assertion
|
// Adds the failed assertion
|
||||||
addFailureInfo( file, line, expr, nestingLevel );
|
addFailureInfo(file, line, expr, nestingLevel);
|
||||||
messageTarget_ = &( failures_.back() );
|
messageTarget_ = &(failures_.back());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestResult::addFailureInfo(const char *file,
|
||||||
void
|
unsigned int line,
|
||||||
TestResult::addFailureInfo( const char *file, unsigned int line,
|
const char *expr,
|
||||||
const char *expr, unsigned int nestingLevel )
|
unsigned int nestingLevel) {
|
||||||
{
|
Failure failure;
|
||||||
Failure failure;
|
failure.file_ = file;
|
||||||
failure.file_ = file;
|
failure.line_ = line;
|
||||||
failure.line_ = line;
|
if (expr) {
|
||||||
if ( expr )
|
failure.expr_ = expr;
|
||||||
{
|
}
|
||||||
failure.expr_ = expr;
|
failure.nestingLevel_ = nestingLevel;
|
||||||
}
|
failures_.push_back(failure);
|
||||||
failure.nestingLevel_ = nestingLevel;
|
|
||||||
failures_.push_back( failure );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestResult &TestResult::popPredicateContext() {
|
||||||
TestResult &
|
PredicateContext *lastNode = &rootPredicateNode_;
|
||||||
TestResult::popPredicateContext()
|
while (lastNode->next_ != 0 && lastNode->next_->next_ != 0) {
|
||||||
{
|
lastNode = lastNode->next_;
|
||||||
PredicateContext *lastNode = &rootPredicateNode_;
|
}
|
||||||
while ( lastNode->next_ != 0 && lastNode->next_->next_ != 0 )
|
// Set message target to popped failure
|
||||||
{
|
PredicateContext *tail = lastNode->next_;
|
||||||
lastNode = lastNode->next_;
|
if (tail != 0 && tail->failure_ != 0) {
|
||||||
}
|
messageTarget_ = tail->failure_;
|
||||||
// Set message target to popped failure
|
}
|
||||||
PredicateContext *tail = lastNode->next_;
|
// Remove tail from list
|
||||||
if ( tail != 0 && tail->failure_ != 0 )
|
predicateStackTail_ = lastNode;
|
||||||
{
|
lastNode->next_ = 0;
|
||||||
messageTarget_ = tail->failure_;
|
return *this;
|
||||||
}
|
|
||||||
// Remove tail from list
|
|
||||||
predicateStackTail_ = lastNode;
|
|
||||||
lastNode->next_ = 0;
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TestResult::failed() const { return !failures_.empty(); }
|
||||||
|
|
||||||
bool
|
unsigned int TestResult::getAssertionNestingLevel() const {
|
||||||
TestResult::failed() const
|
unsigned int level = 0;
|
||||||
{
|
const PredicateContext *lastNode = &rootPredicateNode_;
|
||||||
return !failures_.empty();
|
while (lastNode->next_ != 0) {
|
||||||
|
lastNode = lastNode->next_;
|
||||||
|
++level;
|
||||||
|
}
|
||||||
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestResult::printFailure(bool printTestName) const {
|
||||||
|
if (failures_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int
|
if (printTestName) {
|
||||||
TestResult::getAssertionNestingLevel() const
|
printf("* Detail of %s test failure:\n", name_.c_str());
|
||||||
{
|
}
|
||||||
unsigned int level = 0;
|
|
||||||
const PredicateContext *lastNode = &rootPredicateNode_;
|
// Print in reverse to display the callstack in the right order
|
||||||
while ( lastNode->next_ != 0 )
|
Failures::const_iterator itEnd = failures_.end();
|
||||||
{
|
for (Failures::const_iterator it = failures_.begin(); it != itEnd; ++it) {
|
||||||
lastNode = lastNode->next_;
|
const Failure &failure = *it;
|
||||||
++level;
|
std::string indent(failure.nestingLevel_ * 2, ' ');
|
||||||
}
|
if (failure.file_) {
|
||||||
return level;
|
printf("%s%s(%d): ", indent.c_str(), failure.file_, failure.line_);
|
||||||
|
}
|
||||||
|
if (!failure.expr_.empty()) {
|
||||||
|
printf("%s\n", failure.expr_.c_str());
|
||||||
|
} else if (failure.file_) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
if (!failure.message_.empty()) {
|
||||||
|
std::string reindented = indentText(failure.message_, indent + " ");
|
||||||
|
printf("%s\n", reindented.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string TestResult::indentText(const std::string &text,
|
||||||
void
|
const std::string &indent) {
|
||||||
TestResult::printFailure( bool printTestName ) const
|
std::string reindented;
|
||||||
{
|
std::string::size_type lastIndex = 0;
|
||||||
if ( failures_.empty() )
|
while (lastIndex < text.size()) {
|
||||||
{
|
std::string::size_type nextIndex = text.find('\n', lastIndex);
|
||||||
return;
|
if (nextIndex == std::string::npos) {
|
||||||
}
|
nextIndex = text.size() - 1;
|
||||||
|
}
|
||||||
if ( printTestName )
|
reindented += indent;
|
||||||
{
|
reindented += text.substr(lastIndex, nextIndex - lastIndex + 1);
|
||||||
printf( "* Detail of %s test failure:\n", name_.c_str() );
|
lastIndex = nextIndex + 1;
|
||||||
}
|
}
|
||||||
|
return reindented;
|
||||||
// Print in reverse to display the callstack in the right order
|
|
||||||
Failures::const_iterator itEnd = failures_.end();
|
|
||||||
for ( Failures::const_iterator it = failures_.begin(); it != itEnd; ++it )
|
|
||||||
{
|
|
||||||
const Failure &failure = *it;
|
|
||||||
std::string indent( failure.nestingLevel_ * 2, ' ' );
|
|
||||||
if ( failure.file_ )
|
|
||||||
{
|
|
||||||
printf( "%s%s(%d): ", indent.c_str(), failure.file_, failure.line_ );
|
|
||||||
}
|
|
||||||
if ( !failure.expr_.empty() )
|
|
||||||
{
|
|
||||||
printf( "%s\n", failure.expr_.c_str() );
|
|
||||||
}
|
|
||||||
else if ( failure.file_ )
|
|
||||||
{
|
|
||||||
printf( "\n" );
|
|
||||||
}
|
|
||||||
if ( !failure.message_.empty() )
|
|
||||||
{
|
|
||||||
std::string reindented = indentText( failure.message_, indent + " " );
|
|
||||||
printf( "%s\n", reindented.c_str() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestResult &TestResult::addToLastFailure(const std::string &message) {
|
||||||
std::string
|
if (messageTarget_ != 0) {
|
||||||
TestResult::indentText( const std::string &text,
|
messageTarget_->message_ += message;
|
||||||
const std::string &indent )
|
}
|
||||||
{
|
return *this;
|
||||||
std::string reindented;
|
|
||||||
std::string::size_type lastIndex = 0;
|
|
||||||
while ( lastIndex < text.size() )
|
|
||||||
{
|
|
||||||
std::string::size_type nextIndex = text.find( '\n', lastIndex );
|
|
||||||
if ( nextIndex == std::string::npos )
|
|
||||||
{
|
|
||||||
nextIndex = text.size() - 1;
|
|
||||||
}
|
|
||||||
reindented += indent;
|
|
||||||
reindented += text.substr( lastIndex, nextIndex - lastIndex + 1 );
|
|
||||||
lastIndex = nextIndex + 1;
|
|
||||||
}
|
|
||||||
return reindented;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestResult &TestResult::operator<<(Json::Int64 value) {
|
||||||
TestResult &
|
return addToLastFailure(Json::valueToString(value));
|
||||||
TestResult::addToLastFailure( const std::string &message )
|
|
||||||
{
|
|
||||||
if ( messageTarget_ != 0 )
|
|
||||||
{
|
|
||||||
messageTarget_->message_ += message;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResult &
|
TestResult &TestResult::operator<<(Json::UInt64 value) {
|
||||||
TestResult::operator << ( Json::Int64 value ) {
|
return addToLastFailure(Json::valueToString(value));
|
||||||
return addToLastFailure( Json::valueToString(value) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestResult &TestResult::operator<<(bool value) {
|
||||||
TestResult &
|
return addToLastFailure(value ? "true" : "false");
|
||||||
TestResult::operator << ( Json::UInt64 value ) {
|
|
||||||
return addToLastFailure( Json::valueToString(value) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TestResult &
|
|
||||||
TestResult::operator << ( bool value ) {
|
|
||||||
return addToLastFailure(value ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// class TestCase
|
// class TestCase
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TestCase::TestCase()
|
TestCase::TestCase() : result_(0) {}
|
||||||
: result_( 0 )
|
|
||||||
{
|
TestCase::~TestCase() {}
|
||||||
|
|
||||||
|
void TestCase::run(TestResult &result) {
|
||||||
|
result_ = &result;
|
||||||
|
runTestCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TestCase::~TestCase()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TestCase::run( TestResult &result )
|
|
||||||
{
|
|
||||||
result_ = &result;
|
|
||||||
runTestCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// class Runner
|
// class Runner
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Runner::Runner()
|
Runner::Runner() {}
|
||||||
{
|
|
||||||
|
Runner &Runner::add(TestCaseFactory factory) {
|
||||||
|
tests_.push_back(factory);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int Runner::testCount() const {
|
||||||
Runner &
|
return static_cast<unsigned int>(tests_.size());
|
||||||
Runner::add( TestCaseFactory factory )
|
|
||||||
{
|
|
||||||
tests_.push_back( factory );
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Runner::testNameAt(unsigned int index) const {
|
||||||
unsigned int
|
TestCase *test = tests_[index]();
|
||||||
Runner::testCount() const
|
std::string name = test->testName();
|
||||||
{
|
delete test;
|
||||||
return static_cast<unsigned int>( tests_.size() );
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Runner::runTestAt(unsigned int index, TestResult &result) const {
|
||||||
std::string
|
TestCase *test = tests_[index]();
|
||||||
Runner::testNameAt( unsigned int index ) const
|
result.setTestName(test->testName());
|
||||||
{
|
printf("Testing %s: ", test->testName());
|
||||||
TestCase *test = tests_[index]();
|
fflush(stdout);
|
||||||
std::string name = test->testName();
|
|
||||||
delete test;
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Runner::runTestAt( unsigned int index, TestResult &result ) const
|
|
||||||
{
|
|
||||||
TestCase *test = tests_[index]();
|
|
||||||
result.setTestName( test->testName() );
|
|
||||||
printf( "Testing %s: ", test->testName() );
|
|
||||||
fflush( stdout );
|
|
||||||
#if JSON_USE_EXCEPTION
|
#if JSON_USE_EXCEPTION
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
#endif // if JSON_USE_EXCEPTION
|
#endif // if JSON_USE_EXCEPTION
|
||||||
test->run( result );
|
test->run(result);
|
||||||
#if JSON_USE_EXCEPTION
|
#if JSON_USE_EXCEPTION
|
||||||
}
|
}
|
||||||
catch ( const std::exception &e )
|
catch (const std::exception &e) {
|
||||||
{
|
result.addFailure(__FILE__, __LINE__, "Unexpected exception caught:")
|
||||||
result.addFailure( __FILE__, __LINE__,
|
<< e.what();
|
||||||
"Unexpected exception caught:" ) << e.what();
|
}
|
||||||
}
|
|
||||||
#endif // if JSON_USE_EXCEPTION
|
#endif // if JSON_USE_EXCEPTION
|
||||||
delete test;
|
delete test;
|
||||||
const char *status = result.failed() ? "FAILED"
|
const char *status = result.failed() ? "FAILED" : "OK";
|
||||||
: "OK";
|
printf("%s\n", status);
|
||||||
printf( "%s\n", status );
|
fflush(stdout);
|
||||||
fflush( stdout );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Runner::runAllTest(bool printSummary) const {
|
||||||
|
unsigned int count = testCount();
|
||||||
|
std::deque<TestResult> failures;
|
||||||
|
for (unsigned int index = 0; index < count; ++index) {
|
||||||
|
TestResult result;
|
||||||
|
runTestAt(index, result);
|
||||||
|
if (result.failed()) {
|
||||||
|
failures.push_back(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
if (failures.empty()) {
|
||||||
Runner::runAllTest( bool printSummary ) const
|
if (printSummary) {
|
||||||
{
|
printf("All %d tests passed\n", count);
|
||||||
unsigned int count = testCount();
|
}
|
||||||
std::deque<TestResult> failures;
|
return true;
|
||||||
for ( unsigned int index = 0; index < count; ++index )
|
} else {
|
||||||
{
|
for (unsigned int index = 0; index < failures.size(); ++index) {
|
||||||
TestResult result;
|
TestResult &result = failures[index];
|
||||||
runTestAt( index, result );
|
result.printFailure(count > 1);
|
||||||
if ( result.failed() )
|
}
|
||||||
{
|
|
||||||
failures.push_back( result );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( failures.empty() )
|
if (printSummary) {
|
||||||
{
|
unsigned int failedCount = static_cast<unsigned int>(failures.size());
|
||||||
if ( printSummary )
|
unsigned int passedCount = count - failedCount;
|
||||||
{
|
printf("%d/%d tests passed (%d failure(s))\n",
|
||||||
printf( "All %d tests passed\n", count );
|
passedCount,
|
||||||
}
|
count,
|
||||||
|
failedCount);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Runner::testIndex(const std::string &testName,
|
||||||
|
unsigned int &indexOut) const {
|
||||||
|
unsigned int count = testCount();
|
||||||
|
for (unsigned int index = 0; index < count; ++index) {
|
||||||
|
if (testNameAt(index) == testName) {
|
||||||
|
indexOut = index;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
return false;
|
||||||
for ( unsigned int index = 0; index < failures.size(); ++index )
|
|
||||||
{
|
|
||||||
TestResult &result = failures[index];
|
|
||||||
result.printFailure( count > 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( printSummary )
|
|
||||||
{
|
|
||||||
unsigned int failedCount = static_cast<unsigned int>( failures.size() );
|
|
||||||
unsigned int passedCount = count - failedCount;
|
|
||||||
printf( "%d/%d tests passed (%d failure(s))\n", passedCount, count, failedCount );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Runner::listTests() const {
|
||||||
bool
|
unsigned int count = testCount();
|
||||||
Runner::testIndex( const std::string &testName,
|
for (unsigned int index = 0; index < count; ++index) {
|
||||||
unsigned int &indexOut ) const
|
printf("%s\n", testNameAt(index).c_str());
|
||||||
{
|
}
|
||||||
unsigned int count = testCount();
|
|
||||||
for ( unsigned int index = 0; index < count; ++index )
|
|
||||||
{
|
|
||||||
if ( testNameAt(index) == testName )
|
|
||||||
{
|
|
||||||
indexOut = index;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Runner::runCommandLine(int argc, const char *argv[]) const {
|
||||||
void
|
typedef std::deque<std::string> TestNames;
|
||||||
Runner::listTests() const
|
Runner subrunner;
|
||||||
{
|
for (int index = 1; index < argc; ++index) {
|
||||||
unsigned int count = testCount();
|
std::string opt = argv[index];
|
||||||
for ( unsigned int index = 0; index < count; ++index )
|
if (opt == "--list-tests") {
|
||||||
{
|
listTests();
|
||||||
printf( "%s\n", testNameAt( index ).c_str() );
|
return 0;
|
||||||
}
|
} else if (opt == "--test-auto") {
|
||||||
|
preventDialogOnCrash();
|
||||||
|
} else if (opt == "--test") {
|
||||||
|
++index;
|
||||||
|
if (index < argc) {
|
||||||
|
unsigned int testNameIndex;
|
||||||
|
if (testIndex(argv[index], testNameIndex)) {
|
||||||
|
subrunner.add(tests_[testNameIndex]);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Test '%s' does not exist!\n", argv[index]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printUsage(argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printUsage(argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool succeeded;
|
||||||
|
if (subrunner.testCount() > 0) {
|
||||||
|
succeeded = subrunner.runAllTest(subrunner.testCount() > 1);
|
||||||
|
} else {
|
||||||
|
succeeded = runAllTest(true);
|
||||||
|
}
|
||||||
|
return succeeded ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||||
int
|
|
||||||
Runner::runCommandLine( int argc, const char *argv[] ) const
|
|
||||||
{
|
|
||||||
typedef std::deque<std::string> TestNames;
|
|
||||||
Runner subrunner;
|
|
||||||
for ( int index = 1; index < argc; ++index )
|
|
||||||
{
|
|
||||||
std::string opt = argv[index];
|
|
||||||
if ( opt == "--list-tests" )
|
|
||||||
{
|
|
||||||
listTests();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if ( opt == "--test-auto" )
|
|
||||||
{
|
|
||||||
preventDialogOnCrash();
|
|
||||||
}
|
|
||||||
else if ( opt == "--test" )
|
|
||||||
{
|
|
||||||
++index;
|
|
||||||
if ( index < argc )
|
|
||||||
{
|
|
||||||
unsigned int testNameIndex;
|
|
||||||
if ( testIndex( argv[index], testNameIndex ) )
|
|
||||||
{
|
|
||||||
subrunner.add( tests_[testNameIndex] );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Test '%s' does not exist!\n", argv[index] );
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printUsage( argv[0] );
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printUsage( argv[0] );
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool succeeded;
|
|
||||||
if ( subrunner.testCount() > 0 )
|
|
||||||
{
|
|
||||||
succeeded = subrunner.runAllTest( subrunner.testCount() > 1 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
succeeded = runAllTest( true );
|
|
||||||
}
|
|
||||||
return succeeded ? 0
|
|
||||||
: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
|
||||||
// Hook MSVCRT assertions to prevent dialog from appearing
|
// Hook MSVCRT assertions to prevent dialog from appearing
|
||||||
static int
|
static int
|
||||||
msvcrtSilentReportHook( int reportType, char *message, int * /*returnValue*/ )
|
msvcrtSilentReportHook(int reportType, char *message, int * /*returnValue*/) {
|
||||||
{
|
// The default CRT handling of error and assertion is to display
|
||||||
// The default CRT handling of error and assertion is to display
|
// an error dialog to the user.
|
||||||
// an error dialog to the user.
|
// Instead, when an error or an assertion occurs, we force the
|
||||||
// Instead, when an error or an assertion occurs, we force the
|
// application to terminate using abort() after display
|
||||||
// application to terminate using abort() after display
|
// the message on stderr.
|
||||||
// the message on stderr.
|
if (reportType == _CRT_ERROR || reportType == _CRT_ASSERT) {
|
||||||
if ( reportType == _CRT_ERROR ||
|
// calling abort() cause the ReportHook to be called
|
||||||
reportType == _CRT_ASSERT )
|
// The following is used to detect this case and let's the
|
||||||
{
|
// error handler fallback on its default behaviour (
|
||||||
// calling abort() cause the ReportHook to be called
|
// display a warning message)
|
||||||
// The following is used to detect this case and let's the
|
static volatile bool isAborting = false;
|
||||||
// error handler fallback on its default behaviour (
|
if (isAborting) {
|
||||||
// display a warning message)
|
return TRUE;
|
||||||
static volatile bool isAborting = false;
|
}
|
||||||
if ( isAborting )
|
isAborting = true;
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
isAborting = true;
|
|
||||||
|
|
||||||
fprintf( stderr, "CRT Error/Assert:\n%s\n", message );
|
fprintf(stderr, "CRT Error/Assert:\n%s\n", message);
|
||||||
fflush( stderr );
|
fflush(stderr);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
// Let's other reportType (_CRT_WARNING) be handled as they would by default
|
// Let's other reportType (_CRT_WARNING) be handled as they would by default
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
|
|
||||||
|
void Runner::preventDialogOnCrash() {
|
||||||
void
|
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||||
Runner::preventDialogOnCrash()
|
// Install a hook to prevent MSVCRT error and assertion from
|
||||||
{
|
// popping a dialog
|
||||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
// This function a NO-OP in release configuration
|
||||||
// Install a hook to prevent MSVCRT error and assertion from
|
// (which cause warning since msvcrtSilentReportHook is not referenced)
|
||||||
// popping a dialog
|
_CrtSetReportHook(&msvcrtSilentReportHook);
|
||||||
// This function a NO-OP in release configuration
|
|
||||||
// (which cause warning since msvcrtSilentReportHook is not referenced)
|
|
||||||
_CrtSetReportHook( &msvcrtSilentReportHook );
|
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
|
|
||||||
// @todo investiguate this handler (for buffer overflow)
|
// @todo investiguate this handler (for buffer overflow)
|
||||||
// _set_security_error_handler
|
// _set_security_error_handler
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Prevents the system from popping a dialog for debugging if the
|
// Prevents the system from popping a dialog for debugging if the
|
||||||
// application fails due to invalid memory access.
|
// application fails due to invalid memory access.
|
||||||
SetErrorMode( SEM_FAILCRITICALERRORS
|
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
|
||||||
| SEM_NOGPFAULTERRORBOX
|
SEM_NOOPENFILEERRORBOX);
|
||||||
| SEM_NOOPENFILEERRORBOX );
|
|
||||||
#endif // if defined(_WIN32)
|
#endif // if defined(_WIN32)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void Runner::printUsage(const char *appName) {
|
||||||
Runner::printUsage( const char *appName )
|
printf("Usage: %s [options]\n"
|
||||||
{
|
"\n"
|
||||||
printf(
|
"If --test is not specified, then all the test cases be run.\n"
|
||||||
"Usage: %s [options]\n"
|
"\n"
|
||||||
"\n"
|
"Valid options:\n"
|
||||||
"If --test is not specified, then all the test cases be run.\n"
|
"--list-tests: print the name of all test cases on the standard\n"
|
||||||
"\n"
|
" output and exit.\n"
|
||||||
"Valid options:\n"
|
"--test TESTNAME: executes the test case with the specified name.\n"
|
||||||
"--list-tests: print the name of all test cases on the standard\n"
|
" May be repeated.\n"
|
||||||
" output and exit.\n"
|
"--test-auto: prevent dialog prompting for debugging on crash.\n",
|
||||||
"--test TESTNAME: executes the test case with the specified name.\n"
|
appName);
|
||||||
" May be repeated.\n"
|
|
||||||
"--test-auto: prevent dialog prompting for debugging on crash.\n"
|
|
||||||
, appName );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Assertion functions
|
// Assertion functions
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TestResult &
|
TestResult &checkStringEqual(TestResult &result,
|
||||||
checkStringEqual( TestResult &result,
|
const std::string &expected,
|
||||||
const std::string &expected, const std::string &actual,
|
const std::string &actual,
|
||||||
const char *file, unsigned int line, const char *expr )
|
const char *file,
|
||||||
{
|
unsigned int line,
|
||||||
if ( expected != actual )
|
const char *expr) {
|
||||||
{
|
if (expected != actual) {
|
||||||
result.addFailure( file, line, expr );
|
result.addFailure(file, line, expr);
|
||||||
result << "Expected: '" << expected << "'\n";
|
result << "Expected: '" << expected << "'\n";
|
||||||
result << "Actual : '" << actual << "'";
|
result << "Actual : '" << actual << "'";
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace JsonTest
|
} // namespace JsonTest
|
||||||
// vim: et ts=4 sts=4 sw=4 tw=0
|
// vim: et ts=4 sts=4 sw=4 tw=0
|
||||||
|
@ -4,15 +4,15 @@
|
|||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSONTEST_H_INCLUDED
|
#ifndef JSONTEST_H_INCLUDED
|
||||||
# define JSONTEST_H_INCLUDED
|
#define JSONTEST_H_INCLUDED
|
||||||
|
|
||||||
# include <json/config.h>
|
#include <json/config.h>
|
||||||
# include <json/value.h>
|
#include <json/value.h>
|
||||||
# include <json/writer.h>
|
#include <json/writer.h>
|
||||||
# include <stdio.h>
|
#include <stdio.h>
|
||||||
# include <deque>
|
#include <deque>
|
||||||
# include <sstream>
|
#include <sstream>
|
||||||
# include <string>
|
#include <string>
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
@ -20,8 +20,6 @@
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Unit testing framework.
|
/** \brief Unit testing framework.
|
||||||
* \warning: all assertions are non-aborting, test case execution will continue
|
* \warning: all assertions are non-aborting, test case execution will continue
|
||||||
* even if an assertion namespace.
|
* even if an assertion namespace.
|
||||||
@ -30,244 +28,239 @@
|
|||||||
*/
|
*/
|
||||||
namespace JsonTest {
|
namespace JsonTest {
|
||||||
|
|
||||||
|
class Failure {
|
||||||
|
public:
|
||||||
|
const char *file_;
|
||||||
|
unsigned int line_;
|
||||||
|
std::string expr_;
|
||||||
|
std::string message_;
|
||||||
|
unsigned int nestingLevel_;
|
||||||
|
};
|
||||||
|
|
||||||
class Failure
|
/// Context used to create the assertion callstack on failure.
|
||||||
{
|
/// Must be a POD to allow inline initialisation without stepping
|
||||||
public:
|
/// into the debugger.
|
||||||
const char *file_;
|
struct PredicateContext {
|
||||||
unsigned int line_;
|
typedef unsigned int Id;
|
||||||
std::string expr_;
|
Id id_;
|
||||||
std::string message_;
|
const char *file_;
|
||||||
unsigned int nestingLevel_;
|
unsigned int line_;
|
||||||
};
|
const char *expr_;
|
||||||
|
PredicateContext *next_;
|
||||||
|
/// Related Failure, set when the PredicateContext is converted
|
||||||
|
/// into a Failure.
|
||||||
|
Failure *failure_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestResult {
|
||||||
|
public:
|
||||||
|
TestResult();
|
||||||
|
|
||||||
/// Context used to create the assertion callstack on failure.
|
/// \internal Implementation detail for assertion macros
|
||||||
/// Must be a POD to allow inline initialisation without stepping
|
/// Not encapsulated to prevent step into when debugging failed assertions
|
||||||
/// into the debugger.
|
/// Incremented by one on assertion predicate entry, decreased by one
|
||||||
struct PredicateContext
|
/// by addPredicateContext().
|
||||||
{
|
PredicateContext::Id predicateId_;
|
||||||
typedef unsigned int Id;
|
|
||||||
Id id_;
|
|
||||||
const char *file_;
|
|
||||||
unsigned int line_;
|
|
||||||
const char *expr_;
|
|
||||||
PredicateContext *next_;
|
|
||||||
/// Related Failure, set when the PredicateContext is converted
|
|
||||||
/// into a Failure.
|
|
||||||
Failure *failure_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TestResult
|
/// \internal Implementation detail for predicate macros
|
||||||
{
|
PredicateContext *predicateStackTail_;
|
||||||
public:
|
|
||||||
TestResult();
|
|
||||||
|
|
||||||
/// \internal Implementation detail for assertion macros
|
void setTestName(const std::string &name);
|
||||||
/// Not encapsulated to prevent step into when debugging failed assertions
|
|
||||||
/// Incremented by one on assertion predicate entry, decreased by one
|
|
||||||
/// by addPredicateContext().
|
|
||||||
PredicateContext::Id predicateId_;
|
|
||||||
|
|
||||||
/// \internal Implementation detail for predicate macros
|
/// Adds an assertion failure.
|
||||||
PredicateContext *predicateStackTail_;
|
TestResult &
|
||||||
|
addFailure(const char *file, unsigned int line, const char *expr = 0);
|
||||||
|
|
||||||
void setTestName( const std::string &name );
|
/// Removes the last PredicateContext added to the predicate stack
|
||||||
|
/// chained list.
|
||||||
|
/// Next messages will be targed at the PredicateContext that was removed.
|
||||||
|
TestResult &popPredicateContext();
|
||||||
|
|
||||||
/// Adds an assertion failure.
|
bool failed() const;
|
||||||
TestResult &addFailure( const char *file, unsigned int line,
|
|
||||||
const char *expr = 0 );
|
|
||||||
|
|
||||||
/// Removes the last PredicateContext added to the predicate stack
|
void printFailure(bool printTestName) const;
|
||||||
/// chained list.
|
|
||||||
/// Next messages will be targed at the PredicateContext that was removed.
|
|
||||||
TestResult &popPredicateContext();
|
|
||||||
|
|
||||||
bool failed() const;
|
// Generic operator that will work with anything ostream can deal with.
|
||||||
|
template <typename T> TestResult &operator<<(const T &value) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss.precision(16);
|
||||||
|
oss.setf(std::ios_base::floatfield);
|
||||||
|
oss << value;
|
||||||
|
return addToLastFailure(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
void printFailure( bool printTestName ) const;
|
// Specialized versions.
|
||||||
|
TestResult &operator<<(bool value);
|
||||||
|
// std:ostream does not support 64bits integers on all STL implementation
|
||||||
|
TestResult &operator<<(Json::Int64 value);
|
||||||
|
TestResult &operator<<(Json::UInt64 value);
|
||||||
|
|
||||||
// Generic operator that will work with anything ostream can deal with.
|
private:
|
||||||
template <typename T>
|
TestResult &addToLastFailure(const std::string &message);
|
||||||
TestResult &operator << ( const T& value ) {
|
unsigned int getAssertionNestingLevel() const;
|
||||||
std::ostringstream oss;
|
/// Adds a failure or a predicate context
|
||||||
oss.precision( 16 );
|
void addFailureInfo(const char *file,
|
||||||
oss.setf( std::ios_base::floatfield );
|
unsigned int line,
|
||||||
oss << value;
|
const char *expr,
|
||||||
return addToLastFailure(oss.str());
|
unsigned int nestingLevel);
|
||||||
}
|
static std::string indentText(const std::string &text,
|
||||||
|
const std::string &indent);
|
||||||
|
|
||||||
// Specialized versions.
|
typedef std::deque<Failure> Failures;
|
||||||
TestResult &operator << ( bool value );
|
Failures failures_;
|
||||||
// std:ostream does not support 64bits integers on all STL implementation
|
std::string name_;
|
||||||
TestResult &operator << ( Json::Int64 value );
|
PredicateContext rootPredicateNode_;
|
||||||
TestResult &operator << ( Json::UInt64 value );
|
PredicateContext::Id lastUsedPredicateId_;
|
||||||
|
/// Failure which is the target of the messages added using operator <<
|
||||||
|
Failure *messageTarget_;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
class TestCase {
|
||||||
TestResult &addToLastFailure( const std::string &message );
|
public:
|
||||||
unsigned int getAssertionNestingLevel() const;
|
TestCase();
|
||||||
/// Adds a failure or a predicate context
|
|
||||||
void addFailureInfo( const char *file, unsigned int line,
|
|
||||||
const char *expr, unsigned int nestingLevel );
|
|
||||||
static std::string indentText( const std::string &text,
|
|
||||||
const std::string &indent );
|
|
||||||
|
|
||||||
typedef std::deque<Failure> Failures;
|
virtual ~TestCase();
|
||||||
Failures failures_;
|
|
||||||
std::string name_;
|
|
||||||
PredicateContext rootPredicateNode_;
|
|
||||||
PredicateContext::Id lastUsedPredicateId_;
|
|
||||||
/// Failure which is the target of the messages added using operator <<
|
|
||||||
Failure *messageTarget_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
void run(TestResult &result);
|
||||||
|
|
||||||
class TestCase
|
virtual const char *testName() const = 0;
|
||||||
{
|
|
||||||
public:
|
|
||||||
TestCase();
|
|
||||||
|
|
||||||
virtual ~TestCase();
|
protected:
|
||||||
|
TestResult *result_;
|
||||||
|
|
||||||
void run( TestResult &result );
|
private:
|
||||||
|
virtual void runTestCase() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
virtual const char *testName() const = 0;
|
/// Function pointer type for TestCase factory
|
||||||
|
typedef TestCase *(*TestCaseFactory)();
|
||||||
|
|
||||||
protected:
|
class Runner {
|
||||||
TestResult *result_;
|
public:
|
||||||
|
Runner();
|
||||||
|
|
||||||
private:
|
/// Adds a test to the suite
|
||||||
virtual void runTestCase() = 0;
|
Runner &add(TestCaseFactory factory);
|
||||||
};
|
|
||||||
|
|
||||||
/// Function pointer type for TestCase factory
|
/// Runs test as specified on the command-line
|
||||||
typedef TestCase *(*TestCaseFactory)();
|
/// If no command-line arguments are provided, run all tests.
|
||||||
|
/// If --list-tests is provided, then print the list of all test cases
|
||||||
|
/// If --test <testname> is provided, then run test testname.
|
||||||
|
int runCommandLine(int argc, const char *argv[]) const;
|
||||||
|
|
||||||
class Runner
|
/// Runs all the test cases
|
||||||
{
|
bool runAllTest(bool printSummary) const;
|
||||||
public:
|
|
||||||
Runner();
|
|
||||||
|
|
||||||
/// Adds a test to the suite
|
/// Returns the number of test case in the suite
|
||||||
Runner &add( TestCaseFactory factory );
|
unsigned int testCount() const;
|
||||||
|
|
||||||
/// Runs test as specified on the command-line
|
/// Returns the name of the test case at the specified index
|
||||||
/// If no command-line arguments are provided, run all tests.
|
std::string testNameAt(unsigned int index) const;
|
||||||
/// If --list-tests is provided, then print the list of all test cases
|
|
||||||
/// If --test <testname> is provided, then run test testname.
|
|
||||||
int runCommandLine( int argc, const char *argv[] ) const;
|
|
||||||
|
|
||||||
/// Runs all the test cases
|
/// Runs the test case at the specified index using the specified TestResult
|
||||||
bool runAllTest( bool printSummary ) const;
|
void runTestAt(unsigned int index, TestResult &result) const;
|
||||||
|
|
||||||
/// Returns the number of test case in the suite
|
static void printUsage(const char *appName);
|
||||||
unsigned int testCount() const;
|
|
||||||
|
|
||||||
/// Returns the name of the test case at the specified index
|
private: // prevents copy construction and assignment
|
||||||
std::string testNameAt( unsigned int index ) const;
|
Runner(const Runner &other);
|
||||||
|
Runner &operator=(const Runner &other);
|
||||||
|
|
||||||
/// Runs the test case at the specified index using the specified TestResult
|
private:
|
||||||
void runTestAt( unsigned int index, TestResult &result ) const;
|
void listTests() const;
|
||||||
|
bool testIndex(const std::string &testName, unsigned int &index) const;
|
||||||
|
static void preventDialogOnCrash();
|
||||||
|
|
||||||
static void printUsage( const char *appName );
|
private:
|
||||||
|
typedef std::deque<TestCaseFactory> Factories;
|
||||||
|
Factories tests_;
|
||||||
|
};
|
||||||
|
|
||||||
private: // prevents copy construction and assignment
|
template <typename T, typename U>
|
||||||
Runner( const Runner &other );
|
TestResult &checkEqual(TestResult &result,
|
||||||
Runner &operator =( const Runner &other );
|
const T &expected,
|
||||||
|
const U &actual,
|
||||||
|
const char *file,
|
||||||
|
unsigned int line,
|
||||||
|
const char *expr) {
|
||||||
|
if (static_cast<U>(expected) != actual) {
|
||||||
|
result.addFailure(file, line, expr);
|
||||||
|
result << "Expected: " << static_cast<U>(expected) << "\n";
|
||||||
|
result << "Actual : " << actual;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
TestResult &checkStringEqual(TestResult &result,
|
||||||
void listTests() const;
|
const std::string &expected,
|
||||||
bool testIndex( const std::string &testName, unsigned int &index ) const;
|
const std::string &actual,
|
||||||
static void preventDialogOnCrash();
|
const char *file,
|
||||||
|
unsigned int line,
|
||||||
private:
|
const char *expr);
|
||||||
typedef std::deque<TestCaseFactory> Factories;
|
|
||||||
Factories tests_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
TestResult &
|
|
||||||
checkEqual( TestResult &result, const T &expected, const U &actual,
|
|
||||||
const char *file, unsigned int line, const char *expr )
|
|
||||||
{
|
|
||||||
if ( static_cast< U >( expected ) != actual )
|
|
||||||
{
|
|
||||||
result.addFailure( file, line, expr );
|
|
||||||
result << "Expected: " << static_cast< U >( expected ) << "\n";
|
|
||||||
result << "Actual : " << actual;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TestResult &
|
|
||||||
checkStringEqual( TestResult &result,
|
|
||||||
const std::string &expected, const std::string &actual,
|
|
||||||
const char *file, unsigned int line, const char *expr );
|
|
||||||
|
|
||||||
} // namespace JsonTest
|
} // namespace JsonTest
|
||||||
|
|
||||||
|
|
||||||
/// \brief Asserts that the given expression is true.
|
/// \brief Asserts that the given expression is true.
|
||||||
/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y;
|
/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y;
|
||||||
/// JSONTEST_ASSERT( x == y );
|
/// JSONTEST_ASSERT( x == y );
|
||||||
#define JSONTEST_ASSERT( expr ) \
|
#define JSONTEST_ASSERT(expr) \
|
||||||
if ( expr ) \
|
if (expr) { \
|
||||||
{ \
|
} else \
|
||||||
} \
|
result_->addFailure(__FILE__, __LINE__, #expr)
|
||||||
else \
|
|
||||||
result_->addFailure( __FILE__, __LINE__, #expr )
|
|
||||||
|
|
||||||
/// \brief Asserts that the given predicate is true.
|
/// \brief Asserts that the given predicate is true.
|
||||||
/// The predicate may do other assertions and be a member function of the fixture.
|
/// The predicate may do other assertions and be a member function of the
|
||||||
#define JSONTEST_ASSERT_PRED( expr ) \
|
/// fixture.
|
||||||
{ \
|
#define JSONTEST_ASSERT_PRED(expr) \
|
||||||
JsonTest::PredicateContext _minitest_Context = { \
|
{ \
|
||||||
result_->predicateId_, __FILE__, __LINE__, #expr }; \
|
JsonTest::PredicateContext _minitest_Context = { \
|
||||||
result_->predicateStackTail_->next_ = &_minitest_Context; \
|
result_->predicateId_, __FILE__, __LINE__, #expr \
|
||||||
result_->predicateId_ += 1; \
|
}; \
|
||||||
result_->predicateStackTail_ = &_minitest_Context; \
|
result_->predicateStackTail_->next_ = &_minitest_Context; \
|
||||||
(expr); \
|
result_->predicateId_ += 1; \
|
||||||
result_->popPredicateContext(); \
|
result_->predicateStackTail_ = &_minitest_Context; \
|
||||||
}
|
(expr); \
|
||||||
|
result_->popPredicateContext(); \
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Asserts that two values are equals.
|
/// \brief Asserts that two values are equals.
|
||||||
#define JSONTEST_ASSERT_EQUAL( expected, actual ) \
|
#define JSONTEST_ASSERT_EQUAL(expected, actual) \
|
||||||
JsonTest::checkEqual( *result_, expected, actual, \
|
JsonTest::checkEqual(*result_, \
|
||||||
__FILE__, __LINE__, \
|
expected, \
|
||||||
#expected " == " #actual )
|
actual, \
|
||||||
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
#expected " == " #actual)
|
||||||
|
|
||||||
/// \brief Asserts that two values are equals.
|
/// \brief Asserts that two values are equals.
|
||||||
#define JSONTEST_ASSERT_STRING_EQUAL( expected, actual ) \
|
#define JSONTEST_ASSERT_STRING_EQUAL(expected, actual) \
|
||||||
JsonTest::checkStringEqual( *result_, \
|
JsonTest::checkStringEqual(*result_, \
|
||||||
std::string(expected), std::string(actual), \
|
std::string(expected), \
|
||||||
__FILE__, __LINE__, \
|
std::string(actual), \
|
||||||
#expected " == " #actual )
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
#expected " == " #actual)
|
||||||
|
|
||||||
/// \brief Begin a fixture test case.
|
/// \brief Begin a fixture test case.
|
||||||
#define JSONTEST_FIXTURE( FixtureType, name ) \
|
#define JSONTEST_FIXTURE(FixtureType, name) \
|
||||||
class Test##FixtureType##name : public FixtureType \
|
class Test##FixtureType##name : public FixtureType { \
|
||||||
{ \
|
public: \
|
||||||
public: \
|
static JsonTest::TestCase *factory() { \
|
||||||
static JsonTest::TestCase *factory() \
|
return new Test##FixtureType##name(); \
|
||||||
{ \
|
} \
|
||||||
return new Test##FixtureType##name(); \
|
\
|
||||||
} \
|
public: /* overidden from TestCase */ \
|
||||||
public: /* overidden from TestCase */ \
|
virtual const char *testName() const { return #FixtureType "/" #name; } \
|
||||||
virtual const char *testName() const \
|
virtual void runTestCase(); \
|
||||||
{ \
|
}; \
|
||||||
return #FixtureType "/" #name; \
|
\
|
||||||
} \
|
void Test##FixtureType##name::runTestCase()
|
||||||
virtual void runTestCase(); \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
void Test##FixtureType##name::runTestCase()
|
|
||||||
|
|
||||||
#define JSONTEST_FIXTURE_FACTORY( FixtureType, name ) \
|
#define JSONTEST_FIXTURE_FACTORY(FixtureType, name) \
|
||||||
&Test##FixtureType##name::factory
|
&Test##FixtureType##name::factory
|
||||||
|
|
||||||
#define JSONTEST_REGISTER_FIXTURE( runner, FixtureType, name ) \
|
#define JSONTEST_REGISTER_FIXTURE(runner, FixtureType, name) \
|
||||||
(runner).add( JSONTEST_FIXTURE_FACTORY( FixtureType, name ) )
|
(runner).add(JSONTEST_FIXTURE_FACTORY(FixtureType, name))
|
||||||
|
|
||||||
#endif // ifndef JSONTEST_H_INCLUDED
|
#endif // ifndef JSONTEST_H_INCLUDED
|
||||||
// vim: et ts=4 sts=4 sw=4 tw=0
|
// vim: et ts=4 sts=4 sw=4 tw=0
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user