Ran clang-format over all .h and .cpp files.

clang-format -i $(find . -name '*.h' -or -name '*.cpp')
This commit is contained in:
Aaron Jacobs 2014-07-01 08:48:54 +10:00
parent 1b137a3802
commit 9fa4e849a1
19 changed files with 6109 additions and 7206 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 &current,
Location end,
unsigned int &unicode );
bool decodeUnicodeEscapeSequence( Token &token,
Location &current,
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 &currentValue();
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 &current,
Location end,
unsigned int &unicode);
bool decodeUnicodeEscapeSequence(Token &token,
Location &current,
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 &currentValue();
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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 *&current) {
uintToString( LargestUInt value, *--current = 0;
char *&current ) 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

View File

@ -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

View File

@ -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