From 8b22fd299e2110534ee67a24bd82587c87610f12 Mon Sep 17 00:00:00 2001 From: chetan Date: Sun, 23 Aug 2015 13:11:11 -0700 Subject: [PATCH 1/2] Extensive modifications to build for Android with ndk-build. CMake items and tests removed. --- jni/Android.mk | 11 + jni/Application.mk | 4 + jni/include/json/assertions.h | 54 + jni/include/json/autolink.h | 25 + jni/include/json/config.h | 109 ++ jni/include/json/features.h | 57 + jni/include/json/forwards.h | 37 + jni/include/json/json.h | 15 + jni/include/json/reader.h | 401 +++++ jni/include/json/value.h | 841 ++++++++++ jni/include/json/version.h | 13 + jni/include/json/writer.h | 327 ++++ jni/src/lib_json/json_reader.cpp | 1979 +++++++++++++++++++++++ jni/src/lib_json/json_tool.h | 87 + jni/src/lib_json/json_value.cpp | 1528 +++++++++++++++++ jni/src/lib_json/json_valueiterator.inl | 162 ++ jni/src/lib_json/json_writer.cpp | 1182 ++++++++++++++ jni/src/lib_json/version.h | 13 + 18 files changed, 6845 insertions(+) create mode 100644 jni/Android.mk create mode 100644 jni/Application.mk create mode 100644 jni/include/json/assertions.h create mode 100644 jni/include/json/autolink.h create mode 100644 jni/include/json/config.h create mode 100644 jni/include/json/features.h create mode 100644 jni/include/json/forwards.h create mode 100644 jni/include/json/json.h create mode 100644 jni/include/json/reader.h create mode 100644 jni/include/json/value.h create mode 100644 jni/include/json/version.h create mode 100644 jni/include/json/writer.h create mode 100644 jni/src/lib_json/json_reader.cpp create mode 100644 jni/src/lib_json/json_tool.h create mode 100644 jni/src/lib_json/json_value.cpp create mode 100644 jni/src/lib_json/json_valueiterator.inl create mode 100644 jni/src/lib_json/json_writer.cpp create mode 100644 jni/src/lib_json/version.h diff --git a/jni/Android.mk b/jni/Android.mk new file mode 100644 index 000000000..d3828f45d --- /dev/null +++ b/jni/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + + +include $(CLEAR_VARS) +LOCAL_MODULE := libjson +LOCAL_SRC_FILES := $(wildcard src/lib_json/*.cpp) +LOCAL_C_INCLUDES := include +include $(BUILD_SHARED_LIBRARY) + + + diff --git a/jni/Application.mk b/jni/Application.mk new file mode 100644 index 000000000..bba6a7962 --- /dev/null +++ b/jni/Application.mk @@ -0,0 +1,4 @@ +APP_STL := gnustl_shared +APP_ABI := armeabi-v7a +APP_CFLAGS := -std=c++11 -fexceptions +NDK_TOOLCHAIN_VERSION := 4.8 diff --git a/jni/include/json/assertions.h b/jni/include/json/assertions.h new file mode 100644 index 000000000..fbec7ae00 --- /dev/null +++ b/jni/include/json/assertions.h @@ -0,0 +1,54 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED +#define CPPTL_JSON_ASSERTIONS_H_INCLUDED + +#include +#include + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +/** It should not be possible for a maliciously designed file to + * cause an abort() or seg-fault, so these macros are used only + * for pre-condition violations and internal logic errors. + */ +#if JSON_USE_EXCEPTION + +// @todo <= add detail about condition in exception +# define JSON_ASSERT(condition) \ + {if (!(condition)) {Json::throwLogicError( "assert json failed" );}} + +# define JSON_FAIL_MESSAGE(message) \ + { \ + std::ostringstream oss; oss << message; \ + Json::throwLogicError(oss.str()); \ + abort(); \ + } + +#else // JSON_USE_EXCEPTION + +# define JSON_ASSERT(condition) assert(condition) + +// The call to assert() will show the failure message in debug builds. In +// release builds we abort, for a core-dump or debugger. +# define JSON_FAIL_MESSAGE(message) \ + { \ + std::ostringstream oss; oss << message; \ + assert(false && oss.str().c_str()); \ + abort(); \ + } + + +#endif + +#define JSON_ASSERT_MESSAGE(condition, message) \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } + +#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED diff --git a/jni/include/json/autolink.h b/jni/include/json/autolink.h new file mode 100644 index 000000000..6fcc8afac --- /dev/null +++ b/jni/include/json/autolink.h @@ -0,0 +1,25 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_AUTOLINK_H_INCLUDED +#define JSON_AUTOLINK_H_INCLUDED + +#include "config.h" + +#ifdef JSON_IN_CPPTL +#include +#endif + +#if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \ + !defined(JSON_IN_CPPTL) +#define CPPTL_AUTOLINK_NAME "json" +#undef CPPTL_AUTOLINK_DLL +#ifdef JSON_DLL +#define CPPTL_AUTOLINK_DLL +#endif +#include "autolink.h" +#endif + +#endif // JSON_AUTOLINK_H_INCLUDED diff --git a/jni/include/json/config.h b/jni/include/json/config.h new file mode 100644 index 000000000..0dcd8ae60 --- /dev/null +++ b/jni/include/json/config.h @@ -0,0 +1,109 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_CONFIG_H_INCLUDED +#define JSON_CONFIG_H_INCLUDED + +/// If defined, indicates that json library is embedded in CppTL library. +//# define JSON_IN_CPPTL 1 + +/// If defined, indicates that json may leverage CppTL library +//# define JSON_USE_CPPTL 1 +/// If defined, indicates that cpptl vector based map should be used instead of +/// std::map +/// as Value container. +//# define JSON_USE_CPPTL_SMALLMAP 1 + +// If non-zero, the library uses exceptions to report bad input instead of C +// assertion macros. The default is to use exceptions. +#ifndef JSON_USE_EXCEPTION +#define JSON_USE_EXCEPTION 1 +#endif + +/// If defined, indicates that the source file is amalgated +/// to prevent private header inclusion. +/// Remarks: it is automatically defined in the generated amalgated header. +// #define JSON_IS_AMALGAMATION + +#ifdef JSON_IN_CPPTL +#include +#ifndef JSON_USE_CPPTL +#define JSON_USE_CPPTL 1 +#endif +#endif + +#ifdef JSON_IN_CPPTL +#define JSON_API CPPTL_API +#elif defined(JSON_DLL_BUILD) +#if defined(_MSC_VER) +#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. +// #define JSON_NO_INT64 1 + +#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +// Microsoft Visual Studio 6 only support conversion from __int64 to double +// (no conversion from unsigned __int64). +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 +// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' +// characters in the debug information) +// All projects I've ever seen with VS6 were using this globally (not bothering +// with pragma push/pop). +#pragma warning(disable : 4786) +#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 + +#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +/// Indicates that the following function is deprecated. +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#elif defined(__clang__) && defined(__has_feature) +#if __has_feature(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) +#endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) +#elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif + +#if !defined(JSONCPP_DEPRECATED) +#define JSONCPP_DEPRECATED(message) +#endif // if !defined(JSONCPP_DEPRECATED) + +namespace Json { +typedef int Int; +typedef unsigned int UInt; +#if defined(JSON_NO_INT64) +typedef int LargestInt; +typedef unsigned int LargestUInt; +#undef JSON_HAS_INT64 +#else // if defined(JSON_NO_INT64) +// For Microsoft Visual use specific types as long long is not supported +#if defined(_MSC_VER) // Microsoft Visual Studio +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else // if defined(_MSC_VER) // Other platforms, use long long +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif // if defined(_MSC_VER) +typedef Int64 LargestInt; +typedef UInt64 LargestUInt; +#define JSON_HAS_INT64 +#endif // if defined(JSON_NO_INT64) +} // end namespace Json + +#endif // JSON_CONFIG_H_INCLUDED diff --git a/jni/include/json/features.h b/jni/include/json/features.h new file mode 100644 index 000000000..1bb7bb614 --- /dev/null +++ b/jni/include/json/features.h @@ -0,0 +1,57 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_FEATURES_H_INCLUDED +#define CPPTL_JSON_FEATURES_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +/** \brief Configuration passed to reader and writer. + * This configuration object can be used to force the Reader or Writer + * to behave in a standard conforming way. + */ +class JSON_API Features { +public: + /** \brief A configuration that allows all features and assumes all strings + * are UTF-8. + * - C & C++ comments are allowed + * - Root object can be any JSON value + * - Assumes Value strings are encoded in UTF-8 + */ + static Features all(); + + /** \brief A configuration that is strictly compatible with the JSON + * specification. + * - Comments are forbidden. + * - Root object must be either an array or an object value. + * - Assumes Value strings are encoded in UTF-8 + */ + static Features strictMode(); + + /** \brief Initialize the configuration like JsonConfig::allFeatures; + */ + Features(); + + /// \c true if comments are allowed. Default: \c true. + bool allowComments_; + + /// \c true if root must be either an array or an object value. Default: \c + /// false. + bool strictRoot_; + + /// \c true if dropped null placeholders are allowed. Default: \c false. + bool allowDroppedNullPlaceholders_; + + /// \c true if numeric object key are allowed. Default: \c false. + bool allowNumericKeys_; +}; + +} // namespace Json + +#endif // CPPTL_JSON_FEATURES_H_INCLUDED diff --git a/jni/include/json/forwards.h b/jni/include/json/forwards.h new file mode 100644 index 000000000..ccfe09abf --- /dev/null +++ b/jni/include/json/forwards.h @@ -0,0 +1,37 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_FORWARDS_H_INCLUDED +#define JSON_FORWARDS_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "config.h" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +// writer.h +class FastWriter; +class StyledWriter; + +// reader.h +class Reader; + +// features.h +class Features; + +// value.h +typedef unsigned int ArrayIndex; +class StaticString; +class Path; +class PathArgument; +class Value; +class ValueIteratorBase; +class ValueIterator; +class ValueConstIterator; + +} // namespace Json + +#endif // JSON_FORWARDS_H_INCLUDED diff --git a/jni/include/json/json.h b/jni/include/json/json.h new file mode 100644 index 000000000..8f10ac2bf --- /dev/null +++ b/jni/include/json/json.h @@ -0,0 +1,15 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_JSON_H_INCLUDED +#define JSON_JSON_H_INCLUDED + +#include "autolink.h" +#include "value.h" +#include "reader.h" +#include "writer.h" +#include "features.h" + +#endif // JSON_JSON_H_INCLUDED diff --git a/jni/include/json/reader.h b/jni/include/json/reader.h new file mode 100644 index 000000000..c8ff747e4 --- /dev/null +++ b/jni/include/json/reader.h @@ -0,0 +1,401 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_READER_H_INCLUDED +#define CPPTL_JSON_READER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "features.h" +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +namespace Json { + +/** \brief Unserialize a JSON document into a + *Value. + * + * \deprecated Use CharReader and CharReaderBuilder. + */ +class JSON_API Reader { +public: + typedef char Char; + typedef const Char* Location; + + /** \brief An error tagged with where in the JSON text it was encountered. + * + * The offsets give the [start, limit) range of bytes within the text. Note + * that this is bytes, not codepoints. + * + */ + struct StructuredError { + 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 JSON + * 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 JSON + 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 getStructuredErrors() const; + + /** \brief Add a semantic error message. + * \param value JSON Value location associated with the error + * \param message The error message. + * \return \c true if the error was successfully added, \c false if the + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, const std::string& message); + + /** \brief Add a semantic error message with extra context. + * \param value JSON Value location associated with the error + * \param message The error message. + * \param extra Additional JSON Value location to contextualize the error + * \return \c true if the error was successfully added, \c false if either + * Value offset exceeds the document size. + */ + bool pushError(const Value& value, const std::string& message, const Value& extra); + + /** \brief Return whether there are any errors. + * \return \c true if there are no errors to report \c false if + * errors have occurred. + */ + bool good() const; + +private: + enum TokenType { + 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 Errors; + + 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 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_; +}; // Reader + +/** Interface for reading JSON from a char array. + */ +class JSON_API CharReader { +public: + virtual ~CharReader() {} + /** \brief Read a Value from a JSON + document. + * The document must be a UTF-8 encoded string containing the document to read. + * + * \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 errs [out] Formatted error messages (if not NULL) + * a user friendly string that lists errors in the parsed + * document. + * \return \c true if the document was successfully parsed, \c false if an + error occurred. + */ + virtual bool parse( + char const* beginDoc, char const* endDoc, + Value* root, std::string* errs) = 0; + + class Factory { + public: + virtual ~Factory() {} + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual CharReader* newCharReader() const = 0; + }; // Factory +}; // CharReader + +/** \brief Build a CharReader implementation. + +Usage: +\code + using namespace Json; + CharReaderBuilder builder; + builder["collectComments"] = false; + Value value; + std::string errs; + bool ok = parseFromStream(builder, std::cin, &value, &errs); +\endcode +*/ +class JSON_API CharReaderBuilder : public CharReader::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + These are case-sensitive. + Available settings (case-sensitive): + - `"collectComments": false or true` + - true to collect comment and allow writing them + back during serialization, false to discard comments. + This parameter is ignored if allowComments is false. + - `"allowComments": false or true` + - true if comments are allowed. + - `"strictRoot": false or true` + - true if root must be either an array or an object value + - `"allowDroppedNullPlaceholders": false or true` + - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) + - `"allowNumericKeys": false or true` + - true if numeric object keys are allowed. + - `"allowSingleQuotes": false or true` + - true if '' are allowed for strings (both keys and values) + - `"stackLimit": integer` + - Exceeding stackLimit (recursive depth of `readValue()`) will + cause an exception. + - This is a security issue (seg-faults caused by deeply nested JSON), + so the default is low. + - `"failIfExtra": false or true` + - If true, `parse()` returns false when extra non-whitespace trails + the JSON value in the input string. + - `"rejectDupKeys": false or true` + - If true, `parse()` returns false when a key is duplicated within an object. + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + CharReaderBuilder(); + virtual ~CharReaderBuilder(); + + virtual CharReader* newCharReader() const; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + + /** A simple way to update a specific setting. + */ + Value& operator[](std::string key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults + */ + static void setDefaults(Json::Value* settings); + /** Same as old Features::strictMode(). + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode + */ + static void strictMode(Json::Value* settings); +}; + +/** Consume entire stream and use its begin/end. + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream( + CharReader::Factory const&, + std::istream&, + Value* root, std::string* errs); + +/** \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 + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_READER_H_INCLUDED diff --git a/jni/include/json/value.h b/jni/include/json/value.h new file mode 100644 index 000000000..8e996ae23 --- /dev/null +++ b/jni/include/json/value.h @@ -0,0 +1,841 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef CPPTL_JSON_H_INCLUDED +#define CPPTL_JSON_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "forwards.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +#ifndef JSON_USE_CPPTL_SMALLMAP +#include +#else +#include +#endif +#ifdef JSON_USE_CPPTL +#include +#endif + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +/** \brief JSON (JavaScript Object Notation). + */ +namespace Json { + +/** Base class for all exceptions we throw. + * + * We use nothing but these internally. Of course, STL can throw others. + */ +class JSON_API Exception : public std::exception { +public: + Exception(std::string const& msg); + virtual ~Exception() throw(); + virtual char const* what() const throw(); +protected: + std::string const msg_; +}; + +/** Exceptions which the user cannot easily avoid. + * + * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input + * + * \remark derived from Json::Exception + */ +class JSON_API RuntimeError : public Exception { +public: + RuntimeError(std::string const& msg); +}; + +/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. + * + * These are precondition-violations (user bugs) and internal errors (our bugs). + * + * \remark derived from Json::Exception + */ +class JSON_API LogicError : public Exception { +public: + LogicError(std::string const& msg); +}; + +/// used internally +void throwRuntimeError(std::string const& msg); +/// used internally +void throwLogicError(std::string const& msg); + +/** \brief Type of the value held by a Value object. + */ +enum ValueType { + nullValue = 0, ///< 'null' value + intValue, ///< signed integer value + uintValue, ///< unsigned integer value + realValue, ///< double value + stringValue, ///< UTF-8 string value + booleanValue, ///< bool value + arrayValue, ///< array value (ordered list) + objectValue ///< object value (collection of name/value pairs). +}; + +enum CommentPlacement { + commentBefore = 0, ///< a comment placed on the line before a value + commentAfterOnSameLine, ///< a comment just after a value on the same line + commentAfter, ///< a comment on the line after a value (only make sense for + /// root value) + numberOfCommentPlacement +}; + +//# ifdef JSON_USE_CPPTL +// typedef CppTL::AnyEnumerator EnumMemberNames; +// typedef CppTL::AnyEnumerator EnumValues; +//# endif + +/** \brief Lightweight wrapper to tag static string. + * + * Value constructor and objectValue member assignement takes advantage of the + * StaticString and avoid the cost of string duplication when storing the + * string or the member name. + * + * Example of usage: + * \code + * Json::Value aValue( StaticString("some text") ); + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ +class JSON_API StaticString { +public: + explicit StaticString(const char* czstring) : c_str_(czstring) {} + + operator const char*() const { return c_str_; } + + const char* c_str() const { return c_str_; } + +private: + const char* c_str_; +}; + +/** \brief Represents a JSON value. + * + * This class is a discriminated union wrapper that can represents a: + * - signed integer [range: Value::minInt - Value::maxInt] + * - unsigned integer (range: 0 - Value::maxUInt) + * - double + * - UTF-8 string + * - boolean + * - 'null' + * - an ordered list of Value + * - collection of name/value pairs (javascript object) + * + * The type of the held value is represented by a #ValueType and + * can be obtained using type(). + * + * Values of an #objectValue or #arrayValue can be accessed using operator[]() + * methods. + * Non-const methods will automatically create the a #nullValue element + * if it does not exist. + * The sequence of an #arrayValue will be automatically resized and initialized + * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. + * + * The get() methods can be used to obtain default value in the case the + * required element does not exist. + * + * It is possible to iterate over the list of a #objectValue values using + * the getMemberNames() method. + * + * \note #Value string-length fit in size_t, but keys must be < 2^30. + * (The reason is an implementation detail.) A #CharReader will raise an + * exception if a bound is exceeded to avoid security holes in your app, + * but the Value API does *not* check bounds. That is the responsibility + * of the caller. + */ +class JSON_API Value { + friend class ValueIteratorBase; +public: + typedef std::vector Members; + typedef ValueIterator iterator; + typedef ValueConstIterator const_iterator; + typedef Json::UInt UInt; + typedef Json::Int Int; +#if defined(JSON_HAS_INT64) + typedef Json::UInt64 UInt64; + typedef Json::Int64 Int64; +#endif // defined(JSON_HAS_INT64) + typedef Json::LargestInt LargestInt; + typedef Json::LargestUInt LargestUInt; + typedef Json::ArrayIndex ArrayIndex; + + static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value(). + static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null + /// Minimum signed integer value that can be stored in a Json::Value. + static const LargestInt minLargestInt; + /// Maximum signed integer value that can be stored in a Json::Value. + static const LargestInt maxLargestInt; + /// Maximum unsigned integer value that can be stored in a Json::Value. + static const LargestUInt maxLargestUInt; + + /// Minimum signed int value that can be stored in a Json::Value. + static const Int minInt; + /// Maximum signed int value that can be stored in a Json::Value. + static const Int maxInt; + /// Maximum unsigned int value that can be stored in a Json::Value. + static const UInt maxUInt; + +#if defined(JSON_HAS_INT64) + /// Minimum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 minInt64; + /// Maximum signed 64 bits int value that can be stored in a Json::Value. + static const Int64 maxInt64; + /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. + static const UInt64 maxUInt64; +#endif // defined(JSON_HAS_INT64) + +private: +#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + class CZString { + public: + enum DuplicationPolicy { + noDuplication = 0, + duplicate, + duplicateOnCopy + }; + CZString(ArrayIndex index); + CZString(char const* str, unsigned length, DuplicationPolicy allocate); + CZString(CZString const& other); + ~CZString(); + CZString& operator=(CZString other); + bool operator<(CZString const& other) const; + bool operator==(CZString const& other) const; + ArrayIndex index() const; + //const char* c_str() const; ///< \deprecated + char const* data() const; + unsigned length() const; + bool isStaticString() const; + + private: + void swap(CZString& other); + + struct StringStorage { + unsigned policy_: 2; + unsigned length_: 30; // 1GB max + }; + + char const* cstr_; // actually, a prefixed string, unless policy is noDup + union { + ArrayIndex index_; + StringStorage storage_; + }; + }; + +public: +#ifndef JSON_USE_CPPTL_SMALLMAP + typedef std::map ObjectValues; +#else + typedef CppTL::SmallMap ObjectValues; +#endif // ifndef JSON_USE_CPPTL_SMALLMAP +#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION + +public: + /** \brief Create a default Value of the given type. + + This is a very useful constructor. + To create an empty array, pass arrayValue. + To create an empty object, pass objectValue. + Another Value can then be set to this one by assignment. +This is useful since clear() and resize() will not alter types. + + Examples: +\code +Json::Value null_value; // null +Json::Value arr_value(Json::arrayValue); // [] +Json::Value obj_value(Json::objectValue); // {} +\endcode + */ + Value(ValueType type = nullValue); + Value(Int value); + Value(UInt value); +#if defined(JSON_HAS_INT64) + Value(Int64 value); + Value(UInt64 value); +#endif // if defined(JSON_HAS_INT64) + Value(double value); + Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) + Value(const char* begin, const char* end); ///< Copy all, incl zeroes. + /** \brief Constructs a value from a static string. + + * Like other value string constructor but do not duplicate the string for + * internal storage. The given string must remain alive after the call to this + * constructor. + * \note This works only for null-terminated strings. (We cannot change the + * size of this class, so we have nowhere to store the length, + * which might be computed later for various operations.) + * + * Example of usage: + * \code + * static StaticString foo("some text"); + * Json::Value aValue(foo); + * \endcode + */ + Value(const StaticString& value); + Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too. +#ifdef JSON_USE_CPPTL + Value(const CppTL::ConstString& value); +#endif + Value(bool value); + /// Deep copy. + Value(const Value& other); + ~Value(); + + /// Deep copy, then swap(other). + /// \note Over-write existing comments. To preserve comments, use #swapPayload(). + Value& operator=(Value other); + /// Swap everything. + void swap(Value& other); + /// Swap values but leave comments and source offsets in place. + void swapPayload(Value& other); + + ValueType type() const; + + /// Compare payload only, not comments etc. + bool operator<(const Value& other) const; + bool operator<=(const Value& other) const; + bool operator>=(const Value& other) const; + bool operator>(const Value& other) const; + bool operator==(const Value& other) const; + bool operator!=(const Value& other) const; + int compare(const Value& other) const; + + const char* asCString() const; ///< Embedded zeroes could cause you trouble! + std::string asString() const; ///< Embedded zeroes are possible. + /** Get raw char* of string-value. + * \return false if !string. (Seg-fault if str or end are NULL.) + */ + bool getString( + char const** begin, char const** end) const; +#ifdef JSON_USE_CPPTL + CppTL::ConstString asConstString() const; +#endif + Int asInt() const; + UInt asUInt() const; +#if defined(JSON_HAS_INT64) + Int64 asInt64() const; + UInt64 asUInt64() const; +#endif // if defined(JSON_HAS_INT64) + LargestInt asLargestInt() const; + LargestUInt asLargestUInt() const; + float asFloat() const; + double asDouble() const; + bool asBool() const; + + bool isNull() const; + bool isBool() const; + bool isInt() const; + bool isInt64() const; + bool isUInt() const; + bool isUInt64() const; + bool isIntegral() const; + bool isDouble() const; + bool isNumeric() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + bool isConvertibleTo(ValueType other) const; + + /// Number of values in array or object + ArrayIndex size() const; + + /// \brief Return true if empty array, empty object, or null; + /// otherwise, false. + bool empty() const; + + /// Return isNull() + bool operator!() const; + + /// Remove all object members and array elements. + /// \pre type() is arrayValue, objectValue, or nullValue + /// \post type() is unchanged + void clear(); + + /// Resize the array to size elements. + /// New elements are initialized to null. + /// May only be called on nullValue or arrayValue. + /// \pre type() is arrayValue or nullValue + /// \post type() is arrayValue + void resize(ArrayIndex size); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](ArrayIndex index); + + /// Access an array element (zero based index ). + /// If the array contains less than index element, then null value are + /// inserted + /// in the array so that its size is index+1. + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + Value& operator[](int index); + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](ArrayIndex index) const; + + /// Access an array element (zero based index ) + /// (You may need to say 'value[0u]' to get your compiler to distinguish + /// this from the operator[] which takes a string.) + const Value& operator[](int index) const; + + /// If the array contains at least index+1 elements, returns the element + /// value, + /// otherwise returns defaultValue. + Value get(ArrayIndex index, const Value& defaultValue) const; + /// Return true if index < size(). + bool isValidIndex(ArrayIndex index) const; + /// \brief Append value to array at the end. + /// + /// Equivalent to jsonvalue[jsonvalue.size()] = value; + Value& append(const Value& value); + + /// Access an object value by name, create a null member if it does not exist. + /// \note Because of our implementation, keys are limited to 2^30 -1 chars. + /// Exceeding that will cause an exception. + Value& operator[](const char* key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const char* key) const; + /// Access an object value by name, create a null member if it does not exist. + /// \param key may contain embedded nulls. + Value& operator[](const std::string& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + /// \param key may contain embedded nulls. + const Value& operator[](const std::string& key) const; + /** \brief Access an object value by name, create a null member if it does not + exist. + + * If the object has no entry for that name, then the member name used to store + * the new entry is not duplicated. + * Example of use: + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode + */ + Value& operator[](const StaticString& key); +#ifdef JSON_USE_CPPTL + /// Access an object value by name, create a null member if it does not exist. + Value& operator[](const CppTL::ConstString& key); + /// Access an object value by name, returns null if there is no member with + /// that name. + const Value& operator[](const CppTL::ConstString& key) const; +#endif + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const char* key, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \note key may contain embedded nulls. + Value get(const char* begin, const char* end, const Value& defaultValue) const; + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + /// \param key may contain embedded nulls. + Value get(const std::string& key, const Value& defaultValue) const; +#ifdef JSON_USE_CPPTL + /// Return the member named key if it exist, defaultValue otherwise. + /// \note deep copy + Value get(const CppTL::ConstString& key, const Value& defaultValue) const; +#endif + /// Most general and efficient version of isMember()const, get()const, + /// and operator[]const + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + Value const* find(char const* begin, char const* end) const; + /// Most general and efficient version of object-mutators. + /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 + /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. + Value const* demand(char const* begin, char const* end); + /// \brief Remove and return the named member. + /// + /// Do nothing if it did not exist. + /// \return the removed Value, or null. + /// \pre type() is objectValue or nullValue + /// \post type() is unchanged + /// \deprecated + Value removeMember(const char* key); + /// Same as removeMember(const char*) + /// \param key may contain embedded nulls. + /// \deprecated + Value removeMember(const std::string& key); + /// Same as removeMember(const char* begin, const char* end, Value* removed), + /// but 'key' is null-terminated. + bool removeMember(const char* key, Value* removed); + /** \brief Remove the named map member. + + Update 'removed' iff removed. + \param key may contain embedded nulls. + \return true iff removed (no exceptions) + */ + bool removeMember(std::string const& key, Value* removed); + /// Same as removeMember(std::string const& key, Value* removed) + bool removeMember(const char* begin, const char* end, Value* removed); + /** \brief Remove the indexed array element. + + O(n) expensive operations. + Update 'removed' iff removed. + \return true iff removed (no exceptions) + */ + bool removeIndex(ArrayIndex i, Value* removed); + + /// Return true if the object has a member named key. + /// \note 'key' must be null-terminated. + bool isMember(const char* key) const; + /// Return true if the object has a member named key. + /// \param key may contain embedded nulls. + bool isMember(const std::string& key) const; + /// Same as isMember(std::string const& key)const + bool isMember(const char* begin, const char* end) const; +#ifdef JSON_USE_CPPTL + /// Return true if the object has a member named key. + bool isMember(const CppTL::ConstString& key) const; +#endif + + /// \brief Return a list of the member names. + /// + /// If null, return an empty list. + /// \pre type() is objectValue or nullValue + /// \post if type() was nullValue, it remains nullValue + Members getMemberNames() const; + + //# ifdef JSON_USE_CPPTL + // EnumMemberNames enumMemberNames() const; + // EnumValues enumValues() const; + //# endif + + /// \deprecated Always pass len. + JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.") + void setComment(const char* comment, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const char* comment, size_t len, CommentPlacement placement); + /// Comments must be //... or /* ... */ + void setComment(const std::string& comment, CommentPlacement placement); + bool hasComment(CommentPlacement placement) const; + /// Include delimiters and embedded newlines. + std::string getComment(CommentPlacement placement) const; + + std::string toStyledString() const; + + const_iterator begin() const; + const_iterator end() const; + + iterator begin(); + iterator end(); + + // Accessors for the [start, limit) range of bytes within the JSON text from + // which this value was parsed, if any. + void setOffsetStart(size_t start); + void setOffsetLimit(size_t limit); + size_t getOffsetStart() const; + size_t getOffsetLimit() const; + +private: + void initBasic(ValueType type, bool allocated = false); + + Value& resolveReference(const char* key); + Value& resolveReference(const char* key, const char* end); + + struct CommentInfo { + CommentInfo(); + ~CommentInfo(); + + void setComment(const char* text, size_t len); + + char* comment_; + }; + + // struct MemberNamesTransform + //{ + // typedef const char *result_type; + // const char *operator()( const CZString &name ) const + // { + // return name.c_str(); + // } + //}; + + union ValueHolder { + LargestInt int_; + LargestUInt uint_; + double real_; + bool bool_; + char* string_; // actually ptr to unsigned, followed by str, unless !allocated_ + ObjectValues* map_; + } value_; + ValueType type_ : 8; + unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. + // If not allocated_, string_ must be null-terminated. + CommentInfo* comments_; + + // [start, limit) byte offsets in the source JSON text from which this Value + // was extracted. + size_t start_; + size_t limit_; +}; + +/** \brief Experimental and untested: represents an element of the "path" to + * access a node. + */ +class JSON_API PathArgument { +public: + friend class Path; + + PathArgument(); + PathArgument(ArrayIndex index); + PathArgument(const char* key); + PathArgument(const std::string& key); + +private: + enum Kind { + kindNone = 0, + kindIndex, + kindKey + }; + std::string key_; + ArrayIndex index_; + Kind kind_; +}; + +/** \brief Experimental and untested: represents a "path" to access a node. + * + * Syntax: + * - "." => root node + * - ".[n]" => elements at index 'n' of root node (an array value) + * - ".name" => member named 'name' of root node (an object value) + * - ".name1.name2.name3" + * - ".[0][1][2].name1[3]" + * - ".%" => member name is provided as parameter + * - ".[%]" => index is provied as parameter + */ +class JSON_API Path { +public: + Path(const std::string& path, + const PathArgument& a1 = PathArgument(), + const PathArgument& a2 = PathArgument(), + const PathArgument& a3 = PathArgument(), + const PathArgument& a4 = PathArgument(), + const PathArgument& a5 = PathArgument()); + + const Value& resolve(const Value& root) const; + Value resolve(const Value& root, const Value& defaultValue) const; + /// Creates the "path" to access the specified node and returns a reference on + /// the node. + Value& make(Value& root) const; + +private: + typedef std::vector InArgs; + typedef std::vector Args; + + void makePath(const std::string& path, const InArgs& in); + void addPathInArg(const std::string& path, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind); + void invalidPath(const std::string& path, int location); + + Args args_; +}; + +/** \brief base class for Value iterators. + * + */ +class JSON_API ValueIteratorBase { +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef unsigned int size_t; + typedef int difference_type; + typedef ValueIteratorBase SelfType; + + bool operator==(const SelfType& other) const { return isEqual(other); } + + bool operator!=(const SelfType& other) const { return !isEqual(other); } + + difference_type operator-(const SelfType& other) const { + return other.computeDistance(*this); + } + + /// Return either the index or the member name of the referenced value as a + /// Value. + Value key() const; + + /// Return the index of the referenced Value, or -1 if it is not an arrayValue. + UInt index() const; + + /// Return the member name of the referenced Value, or "" if it is not an + /// objectValue. + /// \note Avoid `c_str()` on result, as embedded zeroes are possible. + std::string name() const; + + /// Return the member name of the referenced Value. "" if it is not an + /// objectValue. + /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls. + JSONCPP_DEPRECATED("Use `key = name();` instead.") + char const* memberName() const; + /// Return the member name of the referenced Value, or NULL if it is not an + /// objectValue. + /// \note Better version than memberName(). Allows embedded nulls. + char const* memberName(char const** end) const; + +protected: + Value& deref() const; + + void increment(); + + void decrement(); + + difference_type computeDistance(const SelfType& other) const; + + bool isEqual(const SelfType& other) const; + + void copy(const SelfType& other); + +private: + Value::ObjectValues::iterator current_; + // Indicates that iterator is for a null value. + bool isNull_; + +public: + // For some reason, BORLAND needs these at the end, rather + // than earlier. No idea why. + ValueIteratorBase(); + explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); +}; + +/** \brief const iterator for object and array value. + * + */ +class JSON_API ValueConstIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef const Value value_type; + //typedef unsigned int size_t; + //typedef int difference_type; + typedef const Value& reference; + typedef const Value* pointer; + typedef ValueConstIterator SelfType; + + ValueConstIterator(); + +private: +/*! \internal Use by Value to create an iterator. + */ + explicit ValueConstIterator(const Value::ObjectValues::iterator& current); +public: + SelfType& operator=(const ValueIteratorBase& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +/** \brief Iterator for object and array value. + */ +class JSON_API ValueIterator : public ValueIteratorBase { + friend class Value; + +public: + typedef Value value_type; + typedef unsigned int size_t; + typedef int difference_type; + typedef Value& reference; + typedef Value* pointer; + typedef ValueIterator SelfType; + + ValueIterator(); + ValueIterator(const ValueConstIterator& other); + ValueIterator(const ValueIterator& other); + +private: +/*! \internal Use by Value to create an iterator. + */ + explicit ValueIterator(const Value::ObjectValues::iterator& current); +public: + SelfType& operator=(const SelfType& other); + + SelfType operator++(int) { + SelfType temp(*this); + ++*this; + return temp; + } + + SelfType operator--(int) { + SelfType temp(*this); + --*this; + return temp; + } + + SelfType& operator--() { + decrement(); + return *this; + } + + SelfType& operator++() { + increment(); + return *this; + } + + reference operator*() const { return deref(); } + + pointer operator->() const { return &deref(); } +}; + +} // namespace Json + + +namespace std { +/// Specialize std::swap() for Json::Value. +template<> +inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } +} + + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // CPPTL_JSON_H_INCLUDED diff --git a/jni/include/json/version.h b/jni/include/json/version.h new file mode 100644 index 000000000..9df36d7cd --- /dev/null +++ b/jni/include/json/version.h @@ -0,0 +1,13 @@ +// DO NOT EDIT. This file (and "version") is generated by CMake. +// Run CMake configure step to update it. +#ifndef JSON_VERSION_H_INCLUDED +# define JSON_VERSION_H_INCLUDED + +# define JSONCPP_VERSION_STRING "1.6.5" +# define JSONCPP_VERSION_MAJOR 1 +# define JSONCPP_VERSION_MINOR 6 +# define JSONCPP_VERSION_PATCH 5 +# define JSONCPP_VERSION_QUALIFIER +# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) + +#endif // JSON_VERSION_H_INCLUDED diff --git a/jni/include/json/writer.h b/jni/include/json/writer.h new file mode 100644 index 000000000..f5f0a389e --- /dev/null +++ b/jni/include/json/writer.h @@ -0,0 +1,327 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSON_WRITER_H_INCLUDED +#define JSON_WRITER_H_INCLUDED + +#if !defined(JSON_IS_AMALGAMATION) +#include "value.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include + +// Disable warning C4251: : needs to have dll-interface to +// be used by... +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(push) +#pragma warning(disable : 4251) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +namespace Json { + +class Value; + +/** + +Usage: +\code + using namespace Json; + void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { + std::unique_ptr const writer( + factory.newStreamWriter()); + writer->write(value, &std::cout); + std::cout << std::endl; // add lf and flush + } +\endcode +*/ +class JSON_API StreamWriter { +protected: + std::ostream* sout_; // not owned; will not delete +public: + StreamWriter(); + virtual ~StreamWriter(); + /** Write Value into document as configured in sub-class. + Do not take ownership of sout, but maintain a reference during function. + \pre sout != NULL + \return zero on success (For now, we always return zero, so check the stream instead.) + \throw std::exception possibly, depending on configuration + */ + virtual int write(Value const& root, std::ostream* sout) = 0; + + /** \brief A simple abstract factory. + */ + class JSON_API Factory { + public: + virtual ~Factory(); + /** \brief Allocate a CharReader via operator new(). + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual StreamWriter* newStreamWriter() const = 0; + }; // Factory +}; // StreamWriter + +/** \brief Write into stringstream, then return string, for convenience. + * A StreamWriter will be created from the factory, used, and then deleted. + */ +std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root); + + +/** \brief Build a StreamWriter implementation. + +Usage: +\code + using namespace Json; + Value value = ...; + StreamWriterBuilder builder; + builder["commentStyle"] = "None"; + builder["indentation"] = " "; // or whatever you like + std::unique_ptr writer( + builder.newStreamWriter()); + writer->write(value, &std::cout); + std::cout << std::endl; // add lf and flush +\endcode +*/ +class JSON_API StreamWriterBuilder : public StreamWriter::Factory { +public: + // Note: We use a Json::Value so that we can add data-members to this class + // without a major version bump. + /** Configuration of this builder. + Available settings (case-sensitive): + - "commentStyle": "None" or "All" + - "indentation": "" + - "enableYAMLCompatibility": false or true + - slightly change the whitespace around colons + - "dropNullPlaceholders": false or true + - Drop the "null" string from the writer's output for nullValues. + Strictly speaking, this is not valid JSON. But when the output is being + fed to a browser's Javascript, it makes for smaller output and the + browser can handle the output just fine. + + You can examine 'settings_` yourself + to see the defaults. You can also write and read them just like any + JSON Value. + \sa setDefaults() + */ + Json::Value settings_; + + StreamWriterBuilder(); + virtual ~StreamWriterBuilder(); + + /** + * \throw std::exception if something goes wrong (e.g. invalid settings) + */ + virtual StreamWriter* newStreamWriter() const; + + /** \return true if 'settings' are legal and consistent; + * otherwise, indicate bad settings via 'invalid'. + */ + bool validate(Json::Value* invalid) const; + /** A simple way to update a specific setting. + */ + Value& operator[](std::string key); + + /** Called by ctor, but you can use this to reset settings_. + * \pre 'settings' != NULL (but Json::null is fine) + * \remark Defaults: + * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults + */ + static void setDefaults(Json::Value* settings); +}; + +/** \brief Abstract class for writers. + * \deprecated Use StreamWriter. (And really, this is an implementation detail.) + */ +class JSON_API Writer { +public: + virtual ~Writer(); + + virtual std::string write(const Value& root) = 0; +}; + +/** \brief Outputs a Value in JSON 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. + * \sa Reader, Value + * \deprecated Use StreamWriterBuilder. + */ +class JSON_API FastWriter : public Writer { + +public: + FastWriter(); + virtual ~FastWriter() {} + + void enableYAMLCompatibility(); + + /** \brief Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's Javascript, it makes for smaller output and the + * browser can handle the output just fine. + */ + void dropNullPlaceholders(); + + void omitEndingLineFeed(); + +public: // overridden from Writer + virtual std::string write(const Value& root); + +private: + void writeValue(const Value& value); + + std::string document_; + bool yamlCompatiblityEnabled_; + bool dropNullPlaceholders_; + bool omitEndingLineFeed_; +}; + +/** \brief Writes a Value in JSON format in a + *human friendly way. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + *line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + *types, + * and all the values fit on one lines, then print the array on a single + *line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + *#CommentPlacement. + * + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +class JSON_API StyledWriter : public Writer { +public: + StyledWriter(); + virtual ~StyledWriter() {} + +public: // overridden from Writer + /** \brief Serialize a Value in JSON format. + * \param root Value to serialize. + * \return String containing the JSON document that represents the root value. + */ + virtual std::string write(const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultineArray(const Value& value); + void pushValue(const std::string& value); + void writeIndent(); + void writeWithIndent(const std::string& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + bool hasCommentForValue(const Value& value); + static std::string normalizeEOL(const std::string& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::string document_; + std::string indentString_; + int rightMargin_; + int indentSize_; + bool addChildValues_; +}; + +/** \brief Writes a Value in JSON format in a + human friendly way, + to a stream rather than to a string. + * + * The rules for line break and indent are as follow: + * - Object value: + * - if empty then print {} without indent and line break + * - if not empty the print '{', line break & indent, print one value per + line + * and then unindent and line break and print '}'. + * - Array value: + * - if empty then print [] without indent and line break + * - if the array contains no object value, empty array or some other value + types, + * and all the values fit on one lines, then print the array on a single + line. + * - otherwise, it the values do not fit on one line, or the array contains + * object or non empty array, then print one value per line. + * + * If the Value have comments then they are outputed according to their + #CommentPlacement. + * + * \param indentation Each level will be indented by this amount extra. + * \sa Reader, Value, Value::setComment() + * \deprecated Use StreamWriterBuilder. + */ +class JSON_API StyledStreamWriter { +public: + StyledStreamWriter(std::string indentation = "\t"); + ~StyledStreamWriter() {} + +public: + /** \brief Serialize a Value in JSON format. + * \param out Stream to write to. (Can be ostringstream, e.g.) + * \param root Value to serialize. + * \note There is no point in deriving from Writer, since write() should not + * return a value. + */ + void write(std::ostream& out, const Value& root); + +private: + void writeValue(const Value& value); + void writeArrayValue(const Value& value); + bool isMultineArray(const Value& value); + void pushValue(const std::string& value); + void writeIndent(); + void writeWithIndent(const std::string& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(const Value& root); + void writeCommentAfterValueOnSameLine(const Value& root); + bool hasCommentForValue(const Value& value); + static std::string normalizeEOL(const std::string& text); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::ostream* document_; + std::string indentString_; + int rightMargin_; + std::string indentation_; + bool addChildValues_ : 1; + bool indented_ : 1; +}; + +#if defined(JSON_HAS_INT64) +std::string JSON_API valueToString(Int value); +std::string JSON_API valueToString(UInt value); +#endif // if defined(JSON_HAS_INT64) +std::string JSON_API valueToString(LargestInt value); +std::string JSON_API valueToString(LargestUInt value); +std::string JSON_API valueToString(double value); +std::string JSON_API valueToString(bool value); +std::string JSON_API valueToQuotedString(const char* value); + +/// \brief Output using the StyledStreamWriter. +/// \see Json::operator>>() +JSON_API std::ostream& operator<<(std::ostream&, const Value& root); + +} // namespace Json + +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#pragma warning(pop) +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) + +#endif // JSON_WRITER_H_INCLUDED diff --git a/jni/src/lib_json/json_reader.cpp b/jni/src/lib_json/json_reader.cpp new file mode 100644 index 000000000..8d092737e --- /dev/null +++ b/jni/src/lib_json/json_reader.cpp @@ -0,0 +1,1979 @@ +// Copyright 2007-2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below +#define snprintf _snprintf +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +static int const stackLimit_g = 1000; +static int stackDepth_g = 0; // see readValue() + +namespace Json { + +#if __cplusplus >= 201103L +typedef std::unique_ptr CharReaderPtr; +#else +typedef std::auto_ptr CharReaderPtr; +#endif + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() + : allowComments_(true), strictRoot_(false), + allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} + +Features Features::all() { return Features(); } + +Features Features::strictMode() { + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + features.allowDroppedNullPlaceholders_ = false; + features.allowNumericKeys_ = false; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + +static bool containsNewLine(Reader::Location begin, Reader::Location end) { + for (; begin < end; ++begin) + if (*begin == '\n' || *begin == '\r') + return true; + return false; +} + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(Features::all()), + collectComments_() {} + +Reader::Reader(const Features& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool +Reader::parse(const std::string& document, Value& root, bool collectComments) { + document_ = document; + const char* begin = document_.c_str(); + const char* end = begin + document_.length(); + return parse(begin, end, root, collectComments); +} + +bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { + // std::istream_iterator begin(sin); + // std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since std::string is reference-counted, this at least does not + // create an extra copy. + std::string doc; + std::getline(sin, doc, (char)EOF); + return parse(doc, root, collectComments); +} + +bool Reader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_ = ""; + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + stackDepth_g = 0; // Yes, this is bad coding, but options are limited. + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool Reader::readValue() { + // This is a non-reentrant way to support a stackLimit. Terrible! + // But this deprecated class has a security problem: Bad input can + // cause a seg-fault. This seems like a fair, binary-compatible way + // to prevent the problem. + if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); + ++stackDepth_g; + + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_ = ""; + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenFalse: + { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenNull: + { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // Else, fall through... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + --stackDepth_g; + return successful; +} + +void Reader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool Reader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void Reader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool Reader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool Reader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +static std::string normalizeEOL(Reader::Location begin, Reader::Location end) { + std::string normalized; + normalized.reserve(end - begin); + Reader::Location current = begin; + while (current != end) { + char c = *current++; + if (c == '\r') { + if (current != end && *current == '\n') + // convert dos EOL + ++current; + // convert Mac EOL + normalized += '\n'; + } else { + normalized += c; + } + } + return normalized; +} + +void +Reader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); + const std::string& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool Reader::readCStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool Reader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +void Reader::readNumber() { + const char *p = current_; + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : 0; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } +} + +bool Reader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + +bool Reader::readObject(Token& tokenStart) { + Token tokenName; + std::string name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name = ""; + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover( + "Missing ':' after object member name", colon, tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover( + "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover( + "Missing '}' or object member name", tokenName, tokenObjectEnd); +} + +bool Reader::readArray(Token& tokenStart) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + skipSpaces(); + if (*current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token token; + // Accept Comment after last item in the array. + ok = readToken(token); + while (token.type_ == tokenComment && ok) { + ok = readToken(token); + } + bool badTokenType = + (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover( + "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + } + if (token.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool Reader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(c - '0'); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative && value == maxIntegerValue) + decoded = Value::minLargestInt; + else if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool Reader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + std::string buffer(token.start_, token.end_); + std::istringstream is(buffer); + if (!(is >> value)) + return addError("'" + std::string(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool Reader::decodeString(Token& token) { + std::string decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool Reader::decodeString(Token& token, std::string& decoded) { + decoded.reserve(token.end_ - token.start_ - 2); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool Reader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, + current); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++) == 'u') { + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, + current); + } + return true; +} + +bool Reader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", + token, + current); + unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, + current); + } + return true; +} + +bool +Reader::addError(const std::string& message, Token& token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool Reader::recoverFromError(TokenType skipUntilToken) { + int errorCount = int(errors_.size()); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool Reader::addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& Reader::currentValue() { return *(nodes_.top()); } + +Reader::Char Reader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void Reader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +std::string Reader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) +#if defined(WINCE) + _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#else + sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#endif +#else + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#endif + return buffer; +} + +// Deprecated. Preserved for backward compatibility +std::string Reader::getFormatedErrorMessages() const { + return getFormattedErrorMessages(); +} + +std::string Reader::getFormattedErrorMessages() const { + std::string formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector Reader::getStructuredErrors() const { + std::vector allErrors; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + Reader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +bool Reader::pushError(const Value& value, const std::string& message) { + size_t length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = 0; + errors_.push_back(info); + return true; +} + +bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) { + size_t length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length + || extra.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); + return true; +} + +bool Reader::good() const { + return !errors_.size(); +} + +// exact copy of Features +class OurFeatures { +public: + static OurFeatures all(); + OurFeatures(); + bool allowComments_; + bool strictRoot_; + bool allowDroppedNullPlaceholders_; + bool allowNumericKeys_; + bool allowSingleQuotes_; + bool failIfExtra_; + bool rejectDupKeys_; + int stackLimit_; +}; // OurFeatures + +// exact copy of Implementation of class Features +// //////////////////////////////// + +OurFeatures::OurFeatures() + : allowComments_(true), strictRoot_(false) + , allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) + , allowSingleQuotes_(false) + , failIfExtra_(false) +{ +} + +OurFeatures OurFeatures::all() { return OurFeatures(); } + +// Implementation of class Reader +// //////////////////////////////// + +// exact copy of Reader, renamed to OurReader +class OurReader { +public: + typedef char Char; + typedef const Char* Location; + struct StructuredError { + size_t offset_start; + size_t offset_limit; + std::string message; + }; + + OurReader(OurFeatures const& features); + bool parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments = true); + std::string getFormattedErrorMessages() const; + std::vector getStructuredErrors() const; + bool pushError(const Value& value, const std::string& message); + bool pushError(const Value& value, const std::string& message, const Value& extra); + bool good() const; + +private: + OurReader(OurReader const&); // no impl + void operator=(OurReader const&); // no impl + + 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 Errors; + + bool readToken(Token& token); + void skipSpaces(); + bool match(Location pattern, int patternLength); + bool readComment(); + bool readCStyleComment(); + bool readCppStyleComment(); + bool readString(); + bool readStringSingleQuote(); + 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 Nodes; + Nodes nodes_; + Errors errors_; + std::string document_; + Location begin_; + Location end_; + Location current_; + Location lastValueEnd_; + Value* lastValue_; + std::string commentsBefore_; + int stackDepth_; + + OurFeatures const features_; + bool collectComments_; +}; // OurReader + +// complete copy of Read impl, for OurReader + +OurReader::OurReader(OurFeatures const& features) + : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), + lastValue_(), commentsBefore_(), features_(features), collectComments_() { +} + +bool OurReader::parse(const char* beginDoc, + const char* endDoc, + Value& root, + bool collectComments) { + if (!features_.allowComments_) { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_ = ""; + errors_.clear(); + while (!nodes_.empty()) + nodes_.pop(); + nodes_.push(&root); + + stackDepth_ = 0; + bool successful = readValue(); + Token token; + skipCommentTokens(token); + if (features_.failIfExtra_) { + if (token.type_ != tokenError && token.type_ != tokenEndOfStream) { + addError("Extra non-whitespace after JSON value.", token); + return false; + } + } + if (collectComments_ && !commentsBefore_.empty()) + root.setComment(commentsBefore_, commentAfter); + if (features_.strictRoot_) { + if (!root.isArray() && !root.isObject()) { + // Set error location to start of doc, ideally should be first token found + // in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( + "A valid JSON document must be either an array or an object value.", + token); + return false; + } + } + return successful; +} + +bool OurReader::readValue() { + if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); + ++stackDepth_; + Token token; + skipCommentTokens(token); + bool successful = true; + + if (collectComments_ && !commentsBefore_.empty()) { + currentValue().setComment(commentsBefore_, commentBefore); + commentsBefore_ = ""; + } + + switch (token.type_) { + case tokenObjectBegin: + successful = readObject(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenArrayBegin: + successful = readArray(token); + currentValue().setOffsetLimit(current_ - begin_); + break; + case tokenNumber: + successful = decodeNumber(token); + break; + case tokenString: + successful = decodeString(token); + break; + case tokenTrue: + { + Value v(true); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenFalse: + { + Value v(false); + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenNull: + { + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + } + break; + case tokenArraySeparator: + case tokenObjectEnd: + case tokenArrayEnd: + if (features_.allowDroppedNullPlaceholders_) { + // "Un-read" the current token and mark the current value as a null + // token. + current_--; + Value v; + currentValue().swapPayload(v); + currentValue().setOffsetStart(current_ - begin_ - 1); + currentValue().setOffsetLimit(current_ - begin_); + break; + } // else, fall through ... + default: + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return addError("Syntax error: value, object or array expected.", token); + } + + if (collectComments_) { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + --stackDepth_; + return successful; +} + +void OurReader::skipCommentTokens(Token& token) { + if (features_.allowComments_) { + do { + readToken(token); + } while (token.type_ == tokenComment); + } else { + readToken(token); + } +} + +bool OurReader::readToken(Token& token) { + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch (c) { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '\'': + if (features_.allowSingleQuotes_) { + token.type_ = tokenString; + ok = readStringSingleQuote(); + break; + } // else continue + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match("rue", 3); + break; + case 'f': + token.type_ = tokenFalse; + ok = match("alse", 4); + break; + case 'n': + token.type_ = tokenNull; + ok = match("ull", 3); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if (!ok) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + +void OurReader::skipSpaces() { + while (current_ != end_) { + Char c = *current_; + if (c == ' ' || c == '\t' || c == '\r' || c == '\n') + ++current_; + else + break; + } +} + +bool OurReader::match(Location pattern, int patternLength) { + if (end_ - current_ < patternLength) + return false; + int index = patternLength; + while (index--) + if (current_[index] != pattern[index]) + return false; + current_ += patternLength; + return true; +} + +bool OurReader::readComment() { + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if (c == '*') + successful = readCStyleComment(); + else if (c == '/') + successful = readCppStyleComment(); + if (!successful) + return false; + + if (collectComments_) { + CommentPlacement placement = commentBefore; + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (c != '*' || !containsNewLine(commentBegin, current_)) + placement = commentAfterOnSameLine; + } + + addComment(commentBegin, current_, placement); + } + return true; +} + +void +OurReader::addComment(Location begin, Location end, CommentPlacement placement) { + assert(collectComments_); + const std::string& normalized = normalizeEOL(begin, end); + if (placement == commentAfterOnSameLine) { + assert(lastValue_ != 0); + lastValue_->setComment(normalized, placement); + } else { + commentsBefore_ += normalized; + } +} + +bool OurReader::readCStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '*' && *current_ == '/') + break; + } + return getNextChar() == '/'; +} + +bool OurReader::readCppStyleComment() { + while (current_ != end_) { + Char c = getNextChar(); + if (c == '\n') + break; + if (c == '\r') { + // Consume DOS EOL. It will be normalized in addComment. + if (current_ != end_ && *current_ == '\n') + getNextChar(); + // Break on Moc OS 9 EOL. + break; + } + } + return true; +} + +void OurReader::readNumber() { + const char *p = current_; + char c = '0'; // stopgap for already consumed character + // integral part + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + // fractional part + if (c == '.') { + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } + // exponential part + if (c == 'e' || c == 'E') { + c = (current_ = p) < end_ ? *p++ : 0; + if (c == '+' || c == '-') + c = (current_ = p) < end_ ? *p++ : 0; + while (c >= '0' && c <= '9') + c = (current_ = p) < end_ ? *p++ : 0; + } +} +bool OurReader::readString() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '"') + break; + } + return c == '"'; +} + + +bool OurReader::readStringSingleQuote() { + Char c = 0; + while (current_ != end_) { + c = getNextChar(); + if (c == '\\') + getNextChar(); + else if (c == '\'') + break; + } + return c == '\''; +} + +bool OurReader::readObject(Token& tokenStart) { + Token tokenName; + std::string name; + Value init(objectValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + while (readToken(tokenName)) { + bool initialTokenOk = true; + while (tokenName.type_ == tokenComment && initialTokenOk) + initialTokenOk = readToken(tokenName); + if (!initialTokenOk) + break; + if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + return true; + name = ""; + if (tokenName.type_ == tokenString) { + if (!decodeString(tokenName, name)) + return recoverFromError(tokenObjectEnd); + } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { + Value numberName; + if (!decodeNumber(tokenName, numberName)) + return recoverFromError(tokenObjectEnd); + name = numberName.asString(); + } else { + break; + } + + Token colon; + if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { + return addErrorAndRecover( + "Missing ':' after object member name", colon, tokenObjectEnd); + } + if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { + std::string msg = "Duplicate key: '" + name + "'"; + return addErrorAndRecover( + msg, tokenName, tokenObjectEnd); + } + Value& value = currentValue()[name]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenObjectEnd); + + Token comma; + if (!readToken(comma) || + (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment)) { + return addErrorAndRecover( + "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + } + bool finalizeTokenOk = true; + while (comma.type_ == tokenComment && finalizeTokenOk) + finalizeTokenOk = readToken(comma); + if (comma.type_ == tokenObjectEnd) + return true; + } + return addErrorAndRecover( + "Missing '}' or object member name", tokenName, tokenObjectEnd); +} + +bool OurReader::readArray(Token& tokenStart) { + Value init(arrayValue); + currentValue().swapPayload(init); + currentValue().setOffsetStart(tokenStart.start_ - begin_); + skipSpaces(); + if (*current_ == ']') // empty array + { + Token endArray; + readToken(endArray); + return true; + } + int index = 0; + for (;;) { + Value& value = currentValue()[index++]; + nodes_.push(&value); + bool ok = readValue(); + nodes_.pop(); + if (!ok) // error already set + return recoverFromError(tokenArrayEnd); + + Token token; + // Accept Comment after last item in the array. + ok = readToken(token); + while (token.type_ == tokenComment && ok) { + ok = readToken(token); + } + bool badTokenType = + (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + if (!ok || badTokenType) { + return addErrorAndRecover( + "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + } + if (token.type_ == tokenArrayEnd) + break; + } + return true; +} + +bool OurReader::decodeNumber(Token& token) { + Value decoded; + if (!decodeNumber(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeNumber(Token& token, Value& decoded) { + // Attempts to parse the number as an integer. If the number is + // larger than the maximum supported value of an integer then + // we decode the number as a double. + Location current = token.start_; + bool isNegative = *current == '-'; + if (isNegative) + ++current; + // TODO: Help the compiler do the div and mod at compile time or get rid of them. + Value::LargestUInt maxIntegerValue = + isNegative ? Value::LargestUInt(-Value::minLargestInt) + : Value::maxLargestUInt; + Value::LargestUInt threshold = maxIntegerValue / 10; + Value::LargestUInt value = 0; + while (current < token.end_) { + Char c = *current++; + if (c < '0' || c > '9') + return decodeDouble(token, decoded); + Value::UInt digit(c - '0'); + if (value >= threshold) { + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || current != token.end_ || + digit > maxIntegerValue % 10) { + return decodeDouble(token, decoded); + } + } + value = value * 10 + digit; + } + if (isNegative) + decoded = -Value::LargestInt(value); + else if (value <= Value::LargestUInt(Value::maxInt)) + decoded = Value::LargestInt(value); + else + decoded = value; + return true; +} + +bool OurReader::decodeDouble(Token& token) { + Value decoded; + if (!decodeDouble(token, decoded)) + return false; + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeDouble(Token& token, Value& decoded) { + double value = 0; + const int bufferSize = 32; + int count; + int length = int(token.end_ - token.start_); + + // Sanity check to avoid buffer overflow exploits. + if (length < 0) { + return addError("Unable to parse token length", token); + } + + // Avoid using a string constant for the format control string given to + // sscanf, as this can cause hard to debug crashes on OS X. See here for more + // info: + // + // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html + char format[] = "%lf"; + + if (length <= bufferSize) { + Char buffer[bufferSize + 1]; + memcpy(buffer, token.start_, length); + buffer[length] = 0; + count = sscanf(buffer, format, &value); + } else { + std::string buffer(token.start_, token.end_); + count = sscanf(buffer.c_str(), format, &value); + } + + if (count != 1) + return addError("'" + std::string(token.start_, token.end_) + + "' is not a number.", + token); + decoded = value; + return true; +} + +bool OurReader::decodeString(Token& token) { + std::string decoded_string; + if (!decodeString(token, decoded_string)) + return false; + Value decoded(decoded_string); + currentValue().swapPayload(decoded); + currentValue().setOffsetStart(token.start_ - begin_); + currentValue().setOffsetLimit(token.end_ - begin_); + return true; +} + +bool OurReader::decodeString(Token& token, std::string& decoded) { + decoded.reserve(token.end_ - token.start_ - 2); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while (current != end) { + Char c = *current++; + if (c == '"') + break; + else if (c == '\\') { + if (current == end) + return addError("Empty escape sequence in string", token, current); + Char escape = *current++; + switch (escape) { + case '"': + decoded += '"'; + break; + case '/': + decoded += '/'; + break; + case '\\': + decoded += '\\'; + break; + case 'b': + decoded += '\b'; + break; + case 'f': + decoded += '\f'; + break; + case 'n': + decoded += '\n'; + break; + case 'r': + decoded += '\r'; + break; + case 't': + decoded += '\t'; + break; + case 'u': { + unsigned int unicode; + if (!decodeUnicodeCodePoint(token, current, end, unicode)) + return false; + decoded += codePointToUTF8(unicode); + } break; + default: + return addError("Bad escape sequence in string", token, current); + } + } else { + decoded += c; + } + } + return true; +} + +bool OurReader::decodeUnicodeCodePoint(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + + if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) { + // surrogate pairs + if (end - current < 6) + return addError( + "additional six characters expected to parse unicode surrogate pair.", + token, + current); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++) == 'u') { + if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } else + return false; + } else + return addError("expecting another \\u token to begin the second half of " + "a unicode surrogate pair", + token, + current); + } + return true; +} + +bool OurReader::decodeUnicodeEscapeSequence(Token& token, + Location& current, + Location end, + unsigned int& unicode) { + if (end - current < 4) + return addError( + "Bad unicode escape sequence in string: four digits expected.", + token, + current); + unicode = 0; + for (int index = 0; index < 4; ++index) { + Char c = *current++; + unicode *= 16; + if (c >= '0' && c <= '9') + unicode += c - '0'; + else if (c >= 'a' && c <= 'f') + unicode += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + unicode += c - 'A' + 10; + else + return addError( + "Bad unicode escape sequence in string: hexadecimal digit expected.", + token, + current); + } + return true; +} + +bool +OurReader::addError(const std::string& message, Token& token, Location extra) { + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back(info); + return false; +} + +bool OurReader::recoverFromError(TokenType skipUntilToken) { + int errorCount = int(errors_.size()); + Token skip; + for (;;) { + if (!readToken(skip)) + errors_.resize(errorCount); // discard errors caused by recovery + if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) + break; + } + errors_.resize(errorCount); + return false; +} + +bool OurReader::addErrorAndRecover(const std::string& message, + Token& token, + TokenType skipUntilToken) { + addError(message, token); + return recoverFromError(skipUntilToken); +} + +Value& OurReader::currentValue() { return *(nodes_.top()); } + +OurReader::Char OurReader::getNextChar() { + if (current_ == end_) + return 0; + return *current_++; +} + +void OurReader::getLocationLineAndColumn(Location location, + int& line, + int& column) const { + Location current = begin_; + Location lastLineStart = current; + line = 0; + while (current < location && current != end_) { + Char c = *current++; + if (c == '\r') { + if (*current == '\n') + ++current; + lastLineStart = current; + ++line; + } else if (c == '\n') { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + +std::string OurReader::getLocationLineAndColumn(Location location) const { + int line, column; + getLocationLineAndColumn(location, line, column); + char buffer[18 + 16 + 16 + 1]; +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) +#if defined(WINCE) + _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#else + sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#endif +#else + snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); +#endif + return buffer; +} + +std::string OurReader::getFormattedErrorMessages() const { + std::string formattedMessage; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + formattedMessage += + "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if (error.extra_) + formattedMessage += + "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; + } + return formattedMessage; +} + +std::vector OurReader::getStructuredErrors() const { + std::vector allErrors; + for (Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError) { + const ErrorInfo& error = *itError; + OurReader::StructuredError structured; + structured.offset_start = error.token_.start_ - begin_; + structured.offset_limit = error.token_.end_ - begin_; + structured.message = error.message_; + allErrors.push_back(structured); + } + return allErrors; +} + +bool OurReader::pushError(const Value& value, const std::string& message) { + size_t length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = end_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = 0; + errors_.push_back(info); + return true; +} + +bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) { + size_t length = end_ - begin_; + if(value.getOffsetStart() > length + || value.getOffsetLimit() > length + || extra.getOffsetLimit() > length) + return false; + Token token; + token.type_ = tokenError; + token.start_ = begin_ + value.getOffsetStart(); + token.end_ = begin_ + value.getOffsetLimit(); + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = begin_ + extra.getOffsetStart(); + errors_.push_back(info); + return true; +} + +bool OurReader::good() const { + return !errors_.size(); +} + + +class OurCharReader : public CharReader { + bool const collectComments_; + OurReader reader_; +public: + OurCharReader( + bool collectComments, + OurFeatures const& features) + : collectComments_(collectComments) + , reader_(features) + {} + virtual bool parse( + char const* beginDoc, char const* endDoc, + Value* root, std::string* errs) { + bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); + if (errs) { + *errs = reader_.getFormattedErrorMessages(); + } + return ok; + } +}; + +CharReaderBuilder::CharReaderBuilder() +{ + setDefaults(&settings_); +} +CharReaderBuilder::~CharReaderBuilder() +{} +CharReader* CharReaderBuilder::newCharReader() const +{ + bool collectComments = settings_["collectComments"].asBool(); + OurFeatures features = OurFeatures::all(); + features.allowComments_ = settings_["allowComments"].asBool(); + features.strictRoot_ = settings_["strictRoot"].asBool(); + features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); + features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); + features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); + features.stackLimit_ = settings_["stackLimit"].asInt(); + features.failIfExtra_ = settings_["failIfExtra"].asBool(); + features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); + return new OurCharReader(collectComments, features); +} +static void getValidReaderKeys(std::set* valid_keys) +{ + valid_keys->clear(); + valid_keys->insert("collectComments"); + valid_keys->insert("allowComments"); + valid_keys->insert("strictRoot"); + valid_keys->insert("allowDroppedNullPlaceholders"); + valid_keys->insert("allowNumericKeys"); + valid_keys->insert("allowSingleQuotes"); + valid_keys->insert("stackLimit"); + valid_keys->insert("failIfExtra"); + valid_keys->insert("rejectDupKeys"); +} +bool CharReaderBuilder::validate(Json::Value* invalid) const +{ + Json::Value my_invalid; + if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL + Json::Value& inv = *invalid; + std::set valid_keys; + getValidReaderKeys(&valid_keys); + Value::Members keys = settings_.getMemberNames(); + size_t n = keys.size(); + for (size_t i = 0; i < n; ++i) { + std::string const& key = keys[i]; + if (valid_keys.find(key) == valid_keys.end()) { + inv[key] = settings_[key]; + } + } + return 0u == inv.size(); +} +Value& CharReaderBuilder::operator[](std::string key) +{ + return settings_[key]; +} +// static +void CharReaderBuilder::strictMode(Json::Value* settings) +{ +//! [CharReaderBuilderStrictMode] + (*settings)["allowComments"] = false; + (*settings)["strictRoot"] = true; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["failIfExtra"] = true; + (*settings)["rejectDupKeys"] = true; +//! [CharReaderBuilderStrictMode] +} +// static +void CharReaderBuilder::setDefaults(Json::Value* settings) +{ +//! [CharReaderBuilderDefaults] + (*settings)["collectComments"] = true; + (*settings)["allowComments"] = true; + (*settings)["strictRoot"] = false; + (*settings)["allowDroppedNullPlaceholders"] = false; + (*settings)["allowNumericKeys"] = false; + (*settings)["allowSingleQuotes"] = false; + (*settings)["stackLimit"] = 1000; + (*settings)["failIfExtra"] = false; + (*settings)["rejectDupKeys"] = false; +//! [CharReaderBuilderDefaults] +} + +////////////////////////////////// +// global functions + +bool parseFromStream( + CharReader::Factory const& fact, std::istream& sin, + Value* root, std::string* errs) +{ + std::ostringstream ssin; + ssin << sin.rdbuf(); + std::string doc = ssin.str(); + char const* begin = doc.data(); + char const* end = begin + doc.size(); + // Note that we do not actually need a null-terminator. + CharReaderPtr const reader(fact.newCharReader()); + return reader->parse(begin, end, root, errs); +} + +std::istream& operator>>(std::istream& sin, Value& root) { + CharReaderBuilder b; + std::string errs; + bool ok = parseFromStream(b, sin, &root, &errs); + if (!ok) { + fprintf(stderr, + "Error from reader: %s", + errs.c_str()); + + throwRuntimeError("reader error"); + } + return sin; +} + +} // namespace Json diff --git a/jni/src/lib_json/json_tool.h b/jni/src/lib_json/json_tool.h new file mode 100644 index 000000000..e65e51b41 --- /dev/null +++ b/jni/src/lib_json/json_tool.h @@ -0,0 +1,87 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED + +/* This header provides common string manipulation support, such as UTF-8, + * portable conversion from/to string... + * + * It is an internal header that must not be exposed. + */ + +namespace Json { + +/// Converts a unicode code-point to UTF-8. +static inline std::string codePointToUTF8(unsigned int cp) { + std::string result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) { + result.resize(1); + result[0] = static_cast(cp); + } else if (cp <= 0x7FF) { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } else if (cp <= 0xFFFF) { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); + } else if (cp <= 0x10FFFF) { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + + return result; +} + +/// Returns true if ch is a control character (in range [1,31]). +static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } + +enum { + /// Constant that specify the size of the buffer that must be passed to + /// uintToString. + uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 +}; + +// Defines a char buffer for use with uintToString(). +typedef char UIntToStringBuffer[uintToStringBufferSize]; + +/** Converts an unsigned integer to string. + * @param value Unsigned interger to convert to string + * @param current Input/Output string buffer. + * Must have at least uintToStringBufferSize chars free. + */ +static inline void uintToString(LargestUInt value, char*& current) { + *--current = 0; + do { + *--current = static_cast(value % 10U + static_cast('0')); + value /= 10; + } while (value != 0); +} + +/** Change ',' to '.' everywhere in buffer. + * + * We had a sophisticated way, but it did not work in WinCE. + * @see https://github.com/open-source-parsers/jsoncpp/pull/9 + */ +static inline void fixNumericLocale(char* begin, char* end) { + while (begin < end) { + if (*begin == ',') { + *begin = '.'; + } + ++begin; + } +} + +} // namespace Json { + +#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED diff --git a/jni/src/lib_json/json_value.cpp b/jni/src/lib_json/json_value.cpp new file mode 100644 index 000000000..9a16491d0 --- /dev/null +++ b/jni/src/lib_json/json_value.cpp @@ -0,0 +1,1528 @@ +// Copyright 2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#ifdef JSON_USE_CPPTL +#include +#endif +#include // size_t +#include // min() + +#define JSON_ASSERT_UNREACHABLE assert(false) + +namespace Json { + +// This is a walkaround to avoid the static initialization of Value::null. +// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of +// 8 (instead of 4) as a bit of future-proofing. +#if defined(__ARMEL__) +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) +#else +#define ALIGNAS(byte_alignment) +#endif +static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; +const unsigned char& kNullRef = kNull[0]; +const Value& Value::null = reinterpret_cast(kNullRef); +const Value& Value::nullRef = null; + +const Int Value::minInt = Int(~(UInt(-1) / 2)); +const Int Value::maxInt = Int(UInt(-1) / 2); +const UInt Value::maxUInt = UInt(-1); +#if defined(JSON_HAS_INT64) +const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); +const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); +const UInt64 Value::maxUInt64 = UInt64(-1); +// The constant is hard-coded because some compiler have trouble +// converting Value::maxUInt64 to a double correctly (AIX/xlC). +// Assumes that UInt64 is a 64 bits integer. +static const double maxUInt64AsDouble = 18446744073709551615.0; +#endif // defined(JSON_HAS_INT64) +const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); +const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); +const LargestUInt Value::maxLargestUInt = LargestUInt(-1); + +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +template +static inline bool InRange(double d, T min, U max) { + return d >= min && d <= max; +} +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double integerToDouble(Json::UInt64 value) { + return static_cast(Int64(value / 2)) * 2.0 + Int64(value & 1); +} + +template static inline double integerToDouble(T value) { + return static_cast(value); +} + +template +static inline bool InRange(double d, T min, U max) { + return d >= integerToDouble(min) && d <= integerToDouble(max); +} +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + +/** Duplicates the specified string value. + * @param value Pointer to the string to duplicate. Must be zero-terminated if + * length is "unknown". + * @param length Length of the value. if equals to unknown, then it will be + * computed using strlen(value). + * @return Pointer on the duplicate instance of string. + */ +static inline char* duplicateStringValue(const char* value, + size_t length) { + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + if (length >= (size_t)Value::maxInt) + length = Value::maxInt - 1; + + char* newString = static_cast(malloc(length + 1)); + if (newString == NULL) { + throwRuntimeError( + "in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); + } + memcpy(newString, value, length); + newString[length] = 0; + return newString; +} + +/* Record the length as a prefix. + */ +static inline char* duplicateAndPrefixStringValue( + const char* value, + unsigned int length) +{ + // Avoid an integer overflow in the call to malloc below by limiting length + // to a sane value. + JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U, + "in Json::Value::duplicateAndPrefixStringValue(): " + "length too big for prefixing"); + unsigned actualLength = length + static_cast(sizeof(unsigned)) + 1U; + char* newString = static_cast(malloc(actualLength)); + if (newString == 0) { + throwRuntimeError( + "in Json::Value::duplicateAndPrefixStringValue(): " + "Failed to allocate string value buffer"); + } + *reinterpret_cast(newString) = length; + memcpy(newString + sizeof(unsigned), value, length); + newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later + return newString; +} +inline static void decodePrefixedString( + bool isPrefixed, char const* prefixed, + unsigned* length, char const** value) +{ + if (!isPrefixed) { + *length = static_cast(strlen(prefixed)); + *value = prefixed; + } else { + *length = *reinterpret_cast(prefixed); + *value = prefixed + sizeof(unsigned); + } +} +/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue(). + */ +static inline void releaseStringValue(char* value) { free(value); } + +} // namespace Json + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ValueInternals... +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +#if !defined(JSON_IS_AMALGAMATION) + +#include "json_valueiterator.inl" +#endif // if !defined(JSON_IS_AMALGAMATION) + +namespace Json { + +Exception::Exception(std::string const& msg) + : msg_(msg) +{} +Exception::~Exception() throw() +{} +char const* Exception::what() const throw() +{ + return msg_.c_str(); +} +RuntimeError::RuntimeError(std::string const& msg) + : Exception(msg) +{} +LogicError::LogicError(std::string const& msg) + : Exception(msg) +{} +void throwRuntimeError(std::string const& msg) +{ + throw RuntimeError(msg); +} +void throwLogicError(std::string const& msg) +{ + throw LogicError(msg); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CommentInfo +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +Value::CommentInfo::CommentInfo() : comment_(0) {} + +Value::CommentInfo::~CommentInfo() { + if (comment_) + releaseStringValue(comment_); +} + +void Value::CommentInfo::setComment(const char* text, size_t len) { + if (comment_) { + releaseStringValue(comment_); + comment_ = 0; + } + JSON_ASSERT(text != 0); + JSON_ASSERT_MESSAGE( + text[0] == '\0' || text[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + // It seems that /**/ style comments are acceptable as well. + comment_ = duplicateStringValue(text, len); +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::CZString +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +// Notes: policy_ indicates if the string was allocated when +// a string is stored. + +Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {} + +Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate) + : cstr_(str) +{ + // allocate != duplicate + storage_.policy_ = allocate & 0x3; + storage_.length_ = ulength & 0x3FFFFFFF; +} + +Value::CZString::CZString(const CZString& other) + : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0 + ? duplicateStringValue(other.cstr_, other.storage_.length_) + : other.cstr_) +{ + storage_.policy_ = (other.cstr_ + ? (static_cast(other.storage_.policy_) == noDuplication + ? noDuplication : duplicate) + : static_cast(other.storage_.policy_)); + storage_.length_ = other.storage_.length_; +} + +Value::CZString::~CZString() { + if (cstr_ && storage_.policy_ == duplicate) + releaseStringValue(const_cast(cstr_)); +} + +void Value::CZString::swap(CZString& other) { + std::swap(cstr_, other.cstr_); + std::swap(index_, other.index_); +} + +Value::CZString& Value::CZString::operator=(CZString other) { + swap(other); + return *this; +} + +bool Value::CZString::operator<(const CZString& other) const { + if (!cstr_) return index_ < other.index_; + //return strcmp(cstr_, other.cstr_) < 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + unsigned min_len = std::min(this_len, other_len); + int comp = memcmp(this->cstr_, other.cstr_, min_len); + if (comp < 0) return true; + if (comp > 0) return false; + return (this_len < other_len); +} + +bool Value::CZString::operator==(const CZString& other) const { + if (!cstr_) return index_ == other.index_; + //return strcmp(cstr_, other.cstr_) == 0; + // Assume both are strings. + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; + if (this_len != other_len) return false; + int comp = memcmp(this->cstr_, other.cstr_, this_len); + return comp == 0; +} + +ArrayIndex Value::CZString::index() const { return index_; } + +//const char* Value::CZString::c_str() const { return cstr_; } +const char* Value::CZString::data() const { return cstr_; } +unsigned Value::CZString::length() const { return storage_.length_; } +bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Value::Value +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/*! \internal Default constructor initialization must be equivalent to: + * memset( this, 0, sizeof(Value) ) + * This optimization is used in ValueInternalMap fast allocator. + */ +Value::Value(ValueType vtype) { + initBasic(vtype); + switch (vtype) { + case nullValue: + break; + case intValue: + case uintValue: + value_.int_ = 0; + break; + case realValue: + value_.real_ = 0.0; + break; + case stringValue: + value_.string_ = 0; + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(); + break; + case booleanValue: + value_.bool_ = false; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +Value::Value(Int value) { + initBasic(intValue); + value_.int_ = value; +} + +Value::Value(UInt value) { + initBasic(uintValue); + value_.uint_ = value; +} +#if defined(JSON_HAS_INT64) +Value::Value(Int64 value) { + initBasic(intValue); + value_.int_ = value; +} +Value::Value(UInt64 value) { + initBasic(uintValue); + value_.uint_ = value; +} +#endif // defined(JSON_HAS_INT64) + +Value::Value(double value) { + initBasic(realValue); + value_.real_ = value; +} + +Value::Value(const char* value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue(value, static_cast(strlen(value))); +} + +Value::Value(const char* beginValue, const char* endValue) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(beginValue, static_cast(endValue - beginValue)); +} + +Value::Value(const std::string& value) { + initBasic(stringValue, true); + value_.string_ = + duplicateAndPrefixStringValue(value.data(), static_cast(value.length())); +} + +Value::Value(const StaticString& value) { + initBasic(stringValue); + value_.string_ = const_cast(value.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value::Value(const CppTL::ConstString& value) { + initBasic(stringValue, true); + value_.string_ = duplicateAndPrefixStringValue(value, static_cast(value.length())); +} +#endif + +Value::Value(bool value) { + initBasic(booleanValue); + value_.bool_ = value; +} + +Value::Value(Value const& other) + : type_(other.type_), allocated_(false) + , + comments_(0), start_(other.start_), limit_(other.limit_) +{ + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.allocated_) { + unsigned len; + char const* str; + decodePrefixedString(other.allocated_, other.value_.string_, + &len, &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + allocated_ = true; + } else { + value_.string_ = other.value_.string_; + allocated_ = false; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } + if (other.comments_) { + comments_ = new CommentInfo[numberOfCommentPlacement]; + for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { + const CommentInfo& otherComment = other.comments_[comment]; + if (otherComment.comment_) + comments_[comment].setComment( + otherComment.comment_, strlen(otherComment.comment_)); + } + } +} + +Value::~Value() { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (allocated_) + releaseStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } + + if (comments_) + delete[] comments_; +} + +Value& Value::operator=(Value other) { + swap(other); + return *this; +} + +void Value::swapPayload(Value& other) { + ValueType temp = type_; + type_ = other.type_; + other.type_ = temp; + std::swap(value_, other.value_); + int temp2 = allocated_; + allocated_ = other.allocated_; + other.allocated_ = temp2 & 0x1; +} + +void Value::swap(Value& other) { + swapPayload(other); + std::swap(comments_, other.comments_); + std::swap(start_, other.start_); + std::swap(limit_, other.limit_); +} + +ValueType Value::type() const { return type_; } + +int Value::compare(const Value& other) const { + if (*this < other) + return -1; + if (*this > other) + return 1; + return 0; +} + +bool Value::operator<(const Value& other) const { + int typeDelta = type_ - other.type_; + if (typeDelta) + return typeDelta < 0 ? true : false; + switch (type_) { + case nullValue: + return false; + case intValue: + return value_.int_ < other.value_.int_; + case uintValue: + return value_.uint_ < other.value_.uint_; + case realValue: + return value_.real_ < other.value_.real_; + case booleanValue: + return value_.bool_ < other.value_.bool_; + case stringValue: + { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + if (other.value_.string_) return true; + else return false; + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); + unsigned min_len = std::min(this_len, other_len); + int comp = memcmp(this_str, other_str, min_len); + if (comp < 0) return true; + if (comp > 0) return false; + return (this_len < other_len); + } + case arrayValue: + case objectValue: { + int delta = int(value_.map_->size() - other.value_.map_->size()); + if (delta) + return delta < 0; + return (*value_.map_) < (*other.value_.map_); + } + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator<=(const Value& other) const { return !(other < *this); } + +bool Value::operator>=(const Value& other) const { return !(*this < other); } + +bool Value::operator>(const Value& other) const { return other < *this; } + +bool Value::operator==(const Value& other) const { + // if ( type_ != other.type_ ) + // GCC 2.95.3 says: + // attempt to take address of bit-field structure member `Json::Value::type_' + // Beats me, but a temp solves the problem. + int temp = other.type_; + if (type_ != temp) + return false; + switch (type_) { + case nullValue: + return true; + case intValue: + return value_.int_ == other.value_.int_; + case uintValue: + return value_.uint_ == other.value_.uint_; + case realValue: + return value_.real_ == other.value_.real_; + case booleanValue: + return value_.bool_ == other.value_.bool_; + case stringValue: + { + if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + return (value_.string_ == other.value_.string_); + } + unsigned this_len; + unsigned other_len; + char const* this_str; + char const* other_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); + if (this_len != other_len) return false; + int comp = memcmp(this_str, other_str, this_len); + return comp == 0; + } + case arrayValue: + case objectValue: + return value_.map_->size() == other.value_.map_->size() && + (*value_.map_) == (*other.value_.map_); + default: + JSON_ASSERT_UNREACHABLE; + } + return false; // unreachable +} + +bool Value::operator!=(const Value& other) const { return !(*this == other); } + +const char* Value::asCString() const { + JSON_ASSERT_MESSAGE(type_ == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) return 0; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + return this_str; +} + +bool Value::getString(char const** str, char const** cend) const { + if (type_ != stringValue) return false; + if (value_.string_ == 0) return false; + unsigned length; + decodePrefixedString(this->allocated_, this->value_.string_, &length, str); + *cend = *str + length; + return true; +} + +std::string Value::asString() const { + switch (type_) { + case nullValue: + return ""; + case stringValue: + { + if (value_.string_ == 0) return ""; + unsigned this_len; + char const* this_str; + decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + return std::string(this_str, this_len); + } + case booleanValue: + return value_.bool_ ? "true" : "false"; + case intValue: + return valueToString(value_.int_); + case uintValue: + return valueToString(value_.uint_); + case realValue: + return valueToString(value_.real_); + default: + JSON_FAIL_MESSAGE("Type is not convertible to string"); + } +} + +#ifdef JSON_USE_CPPTL +CppTL::ConstString Value::asConstString() const { + unsigned len; + char const* str; + decodePrefixedString(allocated_, value_.string_, + &len, &str); + return CppTL::ConstString(str, len); +} +#endif + +Value::Int Value::asInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); + return Int(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); + return Int(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), + "double out of Int range"); + return Int(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int."); +} + +Value::UInt Value::asUInt() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); + return UInt(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); + return UInt(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), + "double out of UInt range"); + return UInt(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt."); +} + +#if defined(JSON_HAS_INT64) + +Value::Int64 Value::asInt64() const { + switch (type_) { + case intValue: + return Int64(value_.int_); + case uintValue: + JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); + return Int64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), + "double out of Int64 range"); + return Int64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to Int64."); +} + +Value::UInt64 Value::asUInt64() const { + switch (type_) { + case intValue: + JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); + return UInt64(value_.int_); + case uintValue: + return UInt64(value_.uint_); + case realValue: + JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), + "double out of UInt64 range"); + return UInt64(value_.real_); + case nullValue: + return 0; + case booleanValue: + return value_.bool_ ? 1 : 0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); +} +#endif // if defined(JSON_HAS_INT64) + +LargestInt Value::asLargestInt() const { +#if defined(JSON_NO_INT64) + return asInt(); +#else + return asInt64(); +#endif +} + +LargestUInt Value::asLargestUInt() const { +#if defined(JSON_NO_INT64) + return asUInt(); +#else + return asUInt64(); +#endif +} + +double Value::asDouble() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return value_.real_; + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0 : 0.0; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to double."); +} + +float Value::asFloat() const { + switch (type_) { + case intValue: + return static_cast(value_.int_); + case uintValue: +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return static_cast(value_.uint_); +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + return integerToDouble(value_.uint_); +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + case realValue: + return static_cast(value_.real_); + case nullValue: + return 0.0; + case booleanValue: + return value_.bool_ ? 1.0f : 0.0f; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to float."); +} + +bool Value::asBool() const { + switch (type_) { + case booleanValue: + return value_.bool_; + case nullValue: + return false; + case intValue: + return value_.int_ ? true : false; + case uintValue: + return value_.uint_ ? true : false; + case realValue: + // This is kind of strange. Not recommended. + return (value_.real_ != 0.0) ? true : false; + default: + break; + } + JSON_FAIL_MESSAGE("Value is not convertible to bool."); +} + +bool Value::isConvertibleTo(ValueType other) const { + switch (other) { + case nullValue: + return (isNumeric() && asDouble() == 0.0) || + (type_ == booleanValue && value_.bool_ == false) || + (type_ == stringValue && asString() == "") || + (type_ == arrayValue && value_.map_->size() == 0) || + (type_ == objectValue && value_.map_->size() == 0) || + type_ == nullValue; + case intValue: + return isInt() || + (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || + type_ == booleanValue || type_ == nullValue; + case uintValue: + return isUInt() || + (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || + type_ == booleanValue || type_ == nullValue; + case realValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case booleanValue: + return isNumeric() || type_ == booleanValue || type_ == nullValue; + case stringValue: + return isNumeric() || type_ == booleanValue || type_ == stringValue || + type_ == nullValue; + case arrayValue: + return type_ == arrayValue || type_ == nullValue; + case objectValue: + return type_ == objectValue || type_ == nullValue; + } + JSON_ASSERT_UNREACHABLE; + return false; +} + +/// Number of values in array or object +ArrayIndex Value::size() const { + switch (type_) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + case stringValue: + return 0; + case arrayValue: // size of the array is highest index + 1 + if (!value_.map_->empty()) { + ObjectValues::const_iterator itLast = value_.map_->end(); + --itLast; + return (*itLast).first.index() + 1; + } + return 0; + case objectValue: + return ArrayIndex(value_.map_->size()); + } + JSON_ASSERT_UNREACHABLE; + return 0; // unreachable; +} + +bool Value::empty() const { + if (isNull() || isArray() || isObject()) + return size() == 0u; + else + return false; +} + +bool Value::operator!() const { return isNull(); } + +void Value::clear() { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || + type_ == objectValue, + "in Json::Value::clear(): requires complex value"); + start_ = 0; + limit_ = 0; + switch (type_) { + case arrayValue: + case objectValue: + value_.map_->clear(); + break; + default: + break; + } +} + +void Value::resize(ArrayIndex newSize) { + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, + "in Json::Value::resize(): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); + ArrayIndex oldSize = size(); + if (newSize == 0) + clear(); + else if (newSize > oldSize) + (*this)[newSize - 1]; + else { + for (ArrayIndex index = newSize; index < oldSize; ++index) { + value_.map_->erase(index); + } + assert(size() == newSize); + } +} + +Value& Value::operator[](ArrayIndex index) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex): requires arrayValue"); + if (type_ == nullValue) + *this = Value(arrayValue); + CZString key(index); + ObjectValues::iterator it = value_.map_->lower_bound(key); + if (it != value_.map_->end() && (*it).first == key) + return (*it).second; + + ObjectValues::value_type defaultValue(key, nullRef); + it = value_.map_->insert(it, defaultValue); + return (*it).second; +} + +Value& Value::operator[](int index) { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index): index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +const Value& Value::operator[](ArrayIndex index) const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == arrayValue, + "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); + if (type_ == nullValue) + return nullRef; + CZString key(index); + ObjectValues::const_iterator it = value_.map_->find(key); + if (it == value_.map_->end()) + return nullRef; + return (*it).second; +} + +const Value& Value::operator[](int index) const { + JSON_ASSERT_MESSAGE( + index >= 0, + "in Json::Value::operator[](int index) const: index cannot be negative"); + return (*this)[ArrayIndex(index)]; +} + +void Value::initBasic(ValueType vtype, bool allocated) { + type_ = vtype; + allocated_ = allocated; + comments_ = 0; + start_ = 0; + limit_ = 0; +} + +// Access an object value by name, create a null member if it does not exist. +// @pre Type of '*this' is object or null. +// @param key is null-terminated. +Value& Value::resolveReference(const char* key) { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); + CZString actualKey( + key, static_cast(strlen(key)), CZString::noDuplication); // NOTE! + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullRef); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +// @param key is not null-terminated. +Value& Value::resolveReference(char const* key, char const* cend) +{ + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::resolveReference(key, end): requires objectValue"); + if (type_ == nullValue) + *this = Value(objectValue); + CZString actualKey( + key, static_cast(cend-key), CZString::duplicateOnCopy); + ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + if (it != value_.map_->end() && (*it).first == actualKey) + return (*it).second; + + ObjectValues::value_type defaultValue(actualKey, nullRef); + it = value_.map_->insert(it, defaultValue); + Value& value = (*it).second; + return value; +} + +Value Value::get(ArrayIndex index, const Value& defaultValue) const { + const Value* value = &((*this)[index]); + return value == &nullRef ? defaultValue : *value; +} + +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } + +Value const* Value::find(char const* key, char const* cend) const +{ + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::find(key, end, found): requires objectValue or nullValue"); + if (type_ == nullValue) return NULL; + CZString actualKey(key, static_cast(cend-key), CZString::noDuplication); + ObjectValues::const_iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) return NULL; + return &(*it).second; +} +const Value& Value::operator[](const char* key) const +{ + Value const* found = find(key, key + strlen(key)); + if (!found) return nullRef; + return *found; +} +Value const& Value::operator[](std::string const& key) const +{ + Value const* found = find(key.data(), key.data() + key.length()); + if (!found) return nullRef; + return *found; +} + +Value& Value::operator[](const char* key) { + return resolveReference(key, key + strlen(key)); +} + +Value& Value::operator[](const std::string& key) { + return resolveReference(key.data(), key.data() + key.length()); +} + +Value& Value::operator[](const StaticString& key) { + return resolveReference(key.c_str()); +} + +#ifdef JSON_USE_CPPTL +Value& Value::operator[](const CppTL::ConstString& key) { + return resolveReference(key.c_str(), key.end_c_str()); +} +Value const& Value::operator[](CppTL::ConstString const& key) const +{ + Value const* found = find(key.c_str(), key.end_c_str()); + if (!found) return nullRef; + return *found; +} +#endif + +Value& Value::append(const Value& value) { return (*this)[size()] = value; } + +Value Value::get(char const* key, char const* cend, Value const& defaultValue) const +{ + Value const* found = find(key, cend); + return !found ? defaultValue : *found; +} +Value Value::get(char const* key, Value const& defaultValue) const +{ + return get(key, key + strlen(key), defaultValue); +} +Value Value::get(std::string const& key, Value const& defaultValue) const +{ + return get(key.data(), key.data() + key.length(), defaultValue); +} + + +bool Value::removeMember(const char* key, const char* cend, Value* removed) +{ + if (type_ != objectValue) { + return false; + } + CZString actualKey(key, static_cast(cend-key), CZString::noDuplication); + ObjectValues::iterator it = value_.map_->find(actualKey); + if (it == value_.map_->end()) + return false; + *removed = it->second; + value_.map_->erase(it); + return true; +} +bool Value::removeMember(const char* key, Value* removed) +{ + return removeMember(key, key + strlen(key), removed); +} +bool Value::removeMember(std::string const& key, Value* removed) +{ + return removeMember(key.data(), key.data() + key.length(), removed); +} +Value Value::removeMember(const char* key) +{ + JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, + "in Json::Value::removeMember(): requires objectValue"); + if (type_ == nullValue) + return nullRef; + + Value removed; // null + removeMember(key, key + strlen(key), &removed); + return removed; // still null if removeMember() did nothing +} +Value Value::removeMember(const std::string& key) +{ + return removeMember(key.c_str()); +} + +bool Value::removeIndex(ArrayIndex index, Value* removed) { + if (type_ != arrayValue) { + return false; + } + CZString key(index); + ObjectValues::iterator it = value_.map_->find(key); + if (it == value_.map_->end()) { + return false; + } + *removed = it->second; + ArrayIndex oldSize = size(); + // shift left all items left, into the place of the "removed" + for (ArrayIndex i = index; i < (oldSize - 1); ++i){ + CZString keey(i); + (*value_.map_)[keey] = (*this)[i + 1]; + } + // erase the last one ("leftover") + CZString keyLast(oldSize - 1); + ObjectValues::iterator itLast = value_.map_->find(keyLast); + value_.map_->erase(itLast); + return true; +} + +#ifdef JSON_USE_CPPTL +Value Value::get(const CppTL::ConstString& key, + const Value& defaultValue) const { + return get(key.c_str(), key.end_c_str(), defaultValue); +} +#endif + +bool Value::isMember(char const* key, char const* cend) const +{ + Value const* value = find(key, cend); + return NULL != value; +} +bool Value::isMember(char const* key) const +{ + return isMember(key, key + strlen(key)); +} +bool Value::isMember(std::string const& key) const +{ + return isMember(key.data(), key.data() + key.length()); +} + +#ifdef JSON_USE_CPPTL +bool Value::isMember(const CppTL::ConstString& key) const { + return isMember(key.c_str(), key.end_c_str()); +} +#endif + +Value::Members Value::getMemberNames() const { + JSON_ASSERT_MESSAGE( + type_ == nullValue || type_ == objectValue, + "in Json::Value::getMemberNames(), value must be objectValue"); + if (type_ == nullValue) + return Value::Members(); + Members members; + members.reserve(value_.map_->size()); + ObjectValues::const_iterator it = value_.map_->begin(); + ObjectValues::const_iterator itEnd = value_.map_->end(); + for (; it != itEnd; ++it) { + members.push_back(std::string((*it).first.data(), + (*it).first.length())); + } + return members; +} +// +//# ifdef JSON_USE_CPPTL +// EnumMemberNames +// Value::enumMemberNames() const +//{ +// if ( type_ == objectValue ) +// { +// return CppTL::Enum::any( CppTL::Enum::transform( +// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), +// MemberNamesTransform() ) ); +// } +// return EnumMemberNames(); +//} +// +// +// EnumValues +// Value::enumValues() const +//{ +// if ( type_ == objectValue || type_ == arrayValue ) +// return CppTL::Enum::anyValues( *(value_.map_), +// CppTL::Type() ); +// return EnumValues(); +//} +// +//# endif + +static bool IsIntegral(double d) { + double integral_part; + return modf(d, &integral_part) == 0.0; +} + +bool Value::isNull() const { return type_ == nullValue; } + +bool Value::isBool() const { return type_ == booleanValue; } + +bool Value::isInt() const { + switch (type_) { + case intValue: + return value_.int_ >= minInt && value_.int_ <= maxInt; + case uintValue: + return value_.uint_ <= UInt(maxInt); + case realValue: + return value_.real_ >= minInt && value_.real_ <= maxInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isUInt() const { + switch (type_) { + case intValue: + return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); + case uintValue: + return value_.uint_ <= maxUInt; + case realValue: + return value_.real_ >= 0 && value_.real_ <= maxUInt && + IsIntegral(value_.real_); + default: + break; + } + return false; +} + +bool Value::isInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return true; + case uintValue: + return value_.uint_ <= UInt64(maxInt64); + case realValue: + // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a + // double, so double(maxInt64) will be rounded up to 2^63. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < double(maxInt64) && IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isUInt64() const { +#if defined(JSON_HAS_INT64) + switch (type_) { + case intValue: + return value_.int_ >= 0; + case uintValue: + return true; + case realValue: + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && + IsIntegral(value_.real_); + default: + break; + } +#endif // JSON_HAS_INT64 + return false; +} + +bool Value::isIntegral() const { +#if defined(JSON_HAS_INT64) + return isInt64() || isUInt64(); +#else + return isInt() || isUInt(); +#endif +} + +bool Value::isDouble() const { return type_ == realValue || isIntegral(); } + +bool Value::isNumeric() const { return isIntegral() || isDouble(); } + +bool Value::isString() const { return type_ == stringValue; } + +bool Value::isArray() const { return type_ == arrayValue; } + +bool Value::isObject() const { return type_ == objectValue; } + +void Value::setComment(const char* comment, size_t len, CommentPlacement placement) { + if (!comments_) + comments_ = new CommentInfo[numberOfCommentPlacement]; + if ((len > 0) && (comment[len-1] == '\n')) { + // Always discard trailing newline, to aid indentation. + len -= 1; + } + comments_[placement].setComment(comment, len); +} + +void Value::setComment(const char* comment, CommentPlacement placement) { + setComment(comment, strlen(comment), placement); +} + +void Value::setComment(const std::string& comment, CommentPlacement placement) { + setComment(comment.c_str(), comment.length(), placement); +} + +bool Value::hasComment(CommentPlacement placement) const { + return comments_ != 0 && comments_[placement].comment_ != 0; +} + +std::string Value::getComment(CommentPlacement placement) const { + if (hasComment(placement)) + return comments_[placement].comment_; + return ""; +} + +void Value::setOffsetStart(size_t start) { start_ = start; } + +void Value::setOffsetLimit(size_t limit) { limit_ = limit; } + +size_t Value::getOffsetStart() const { return start_; } + +size_t Value::getOffsetLimit() const { return limit_; } + +std::string Value::toStyledString() const { + StyledWriter writer; + return writer.write(*this); +} + +Value::const_iterator Value::begin() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->begin()); + break; + default: + break; + } + return const_iterator(); +} + +Value::const_iterator Value::end() const { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return const_iterator(value_.map_->end()); + break; + default: + break; + } + return const_iterator(); +} + +Value::iterator Value::begin() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->begin()); + break; + default: + break; + } + return iterator(); +} + +Value::iterator Value::end() { + switch (type_) { + case arrayValue: + case objectValue: + if (value_.map_) + return iterator(value_.map_->end()); + break; + default: + break; + } + return iterator(); +} + +// class PathArgument +// ////////////////////////////////////////////////////////////////// + +PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} + +PathArgument::PathArgument(ArrayIndex index) + : key_(), index_(index), kind_(kindIndex) {} + +PathArgument::PathArgument(const char* key) + : key_(key), index_(), kind_(kindKey) {} + +PathArgument::PathArgument(const std::string& key) + : key_(key.c_str()), index_(), kind_(kindKey) {} + +// class Path +// ////////////////////////////////////////////////////////////////// + +Path::Path(const std::string& path, + const PathArgument& a1, + const PathArgument& a2, + const PathArgument& a3, + const PathArgument& a4, + const PathArgument& a5) { + InArgs in; + in.push_back(&a1); + in.push_back(&a2); + in.push_back(&a3); + in.push_back(&a4); + in.push_back(&a5); + makePath(path, in); +} + +void Path::makePath(const std::string& path, const InArgs& in) { + const char* current = path.c_str(); + const char* end = current + path.length(); + InArgs::const_iterator itInArg = in.begin(); + while (current != end) { + if (*current == '[') { + ++current; + if (*current == '%') + addPathInArg(path, in, itInArg, PathArgument::kindIndex); + else { + ArrayIndex index = 0; + for (; current != end && *current >= '0' && *current <= '9'; ++current) + index = index * 10 + ArrayIndex(*current - '0'); + args_.push_back(index); + } + if (current == end || *current++ != ']') + invalidPath(path, int(current - path.c_str())); + } else if (*current == '%') { + addPathInArg(path, in, itInArg, PathArgument::kindKey); + ++current; + } else if (*current == '.') { + ++current; + } else { + const char* beginName = current; + while (current != end && !strchr("[.", *current)) + ++current; + args_.push_back(std::string(beginName, current)); + } + } +} + +void Path::addPathInArg(const std::string& /*path*/, + const InArgs& in, + InArgs::const_iterator& itInArg, + PathArgument::Kind kind) { + if (itInArg == in.end()) { + // Error: missing argument %d + } else if ((*itInArg)->kind_ != kind) { + // Error: bad argument type + } else { + args_.push_back(**itInArg); + } +} + +void Path::invalidPath(const std::string& /*path*/, int /*location*/) { + // Error: invalid path. +} + +const Value& Path::resolve(const Value& root) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) { + // Error: unable to resolve path (array value expected at position... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: unable to resolve path (object value expected at position...) + } + node = &((*node)[arg.key_]); + if (node == &Value::nullRef) { + // Error: unable to resolve path (object has no member named '' at + // position...) + } + } + } + return *node; +} + +Value Path::resolve(const Value& root, const Value& defaultValue) const { + const Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray() || !node->isValidIndex(arg.index_)) + return defaultValue; + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) + return defaultValue; + node = &((*node)[arg.key_]); + if (node == &Value::nullRef) + return defaultValue; + } + } + return *node; +} + +Value& Path::make(Value& root) const { + Value* node = &root; + for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { + const PathArgument& arg = *it; + if (arg.kind_ == PathArgument::kindIndex) { + if (!node->isArray()) { + // Error: node is not an array at position ... + } + node = &((*node)[arg.index_]); + } else if (arg.kind_ == PathArgument::kindKey) { + if (!node->isObject()) { + // Error: node is not an object at position... + } + node = &((*node)[arg.key_]); + } + } + return *node; +} + +} // namespace Json diff --git a/jni/src/lib_json/json_valueiterator.inl b/jni/src/lib_json/json_valueiterator.inl new file mode 100644 index 000000000..b3bbc354f --- /dev/null +++ b/jni/src/lib_json/json_valueiterator.inl @@ -0,0 +1,162 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +// included by json_value.cpp + +namespace Json { + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIteratorBase +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIteratorBase::ValueIteratorBase() + : current_(), isNull_(true) { +} + +ValueIteratorBase::ValueIteratorBase( + const Value::ObjectValues::iterator& current) + : current_(current), isNull_(false) {} + +Value& ValueIteratorBase::deref() const { + return current_->second; +} + +void ValueIteratorBase::increment() { + ++current_; +} + +void ValueIteratorBase::decrement() { + --current_; +} + +ValueIteratorBase::difference_type +ValueIteratorBase::computeDistance(const SelfType& other) const { +#ifdef JSON_USE_CPPTL_SMALLMAP + return other.current_ - current_; +#else + // Iterator for null value are initialized using the default + // constructor, which initialize current_ to the default + // std::map::iterator. As begin() and end() are two instance + // of the default std::map::iterator, they can not be compared. + // To allow this, we handle this comparison specifically. + if (isNull_ && other.isNull_) { + return 0; + } + + // Usage of std::distance is not portable (does not compile with Sun Studio 12 + // RogueWave STL, + // which is the one used by default). + // Using a portable hand-made version for non random iterator instead: + // return difference_type( std::distance( current_, other.current_ ) ); + difference_type myDistance = 0; + for (Value::ObjectValues::iterator it = current_; it != other.current_; + ++it) { + ++myDistance; + } + return myDistance; +#endif +} + +bool ValueIteratorBase::isEqual(const SelfType& other) const { + if (isNull_) { + return other.isNull_; + } + return current_ == other.current_; +} + +void ValueIteratorBase::copy(const SelfType& other) { + current_ = other.current_; + isNull_ = other.isNull_; +} + +Value ValueIteratorBase::key() const { + const Value::CZString czstring = (*current_).first; + if (czstring.data()) { + if (czstring.isStaticString()) + return Value(StaticString(czstring.data())); + return Value(czstring.data(), czstring.data() + czstring.length()); + } + return Value(czstring.index()); +} + +UInt ValueIteratorBase::index() const { + const Value::CZString czstring = (*current_).first; + if (!czstring.data()) + return czstring.index(); + return Value::UInt(-1); +} + +std::string ValueIteratorBase::name() const { + char const* keey; + char const* end; + keey = memberName(&end); + if (!keey) return std::string(); + return std::string(keey, end); +} + +char const* ValueIteratorBase::memberName() const { + const char* cname = (*current_).first.data(); + return cname ? cname : ""; +} + +char const* ValueIteratorBase::memberName(char const** end) const { + const char* cname = (*current_).first.data(); + if (!cname) { + *end = NULL; + return NULL; + } + *end = cname + (*current_).first.length(); + return cname; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueConstIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueConstIterator::ValueConstIterator() {} + +ValueConstIterator::ValueConstIterator( + const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueConstIterator& ValueConstIterator:: +operator=(const ValueIteratorBase& other) { + copy(other); + return *this; +} + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class ValueIterator +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ValueIterator::ValueIterator() {} + +ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) + : ValueIteratorBase(current) {} + +ValueIterator::ValueIterator(const ValueConstIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator::ValueIterator(const ValueIterator& other) + : ValueIteratorBase(other) {} + +ValueIterator& ValueIterator::operator=(const SelfType& other) { + copy(other); + return *this; +} + +} // namespace Json diff --git a/jni/src/lib_json/json_writer.cpp b/jni/src/lib_json/json_writer.cpp new file mode 100644 index 000000000..89cd65131 --- /dev/null +++ b/jni/src/lib_json/json_writer.cpp @@ -0,0 +1,1182 @@ +// Copyright 2011 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#if !defined(JSON_IS_AMALGAMATION) +#include +#include "json_tool.h" +#endif // if !defined(JSON_IS_AMALGAMATION) +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 +#include +#define isfinite _finite +#elif defined(__sun) && defined(__SVR4) //Solaris +#include +#define isfinite finite +#else +#include +#define isfinite std::isfinite +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below +#define snprintf _snprintf +#elif defined(__ANDROID__) +#define snprintf snprintf +#elif __cplusplus >= 201103L +#define snprintf std::snprintf +#endif + +#if defined(__BORLANDC__) +#include +#define isfinite _finite +#define snprintf _snprintf +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +// Disable warning about strdup being deprecated. +#pragma warning(disable : 4996) +#endif + +namespace Json { + +#if __cplusplus >= 201103L +typedef std::unique_ptr StreamWriterPtr; +#else +typedef std::auto_ptr StreamWriterPtr; +#endif + +static bool containsControlCharacter(const char* str) { + while (*str) { + if (isControlCharacter(*(str++))) + return true; + } + return false; +} + +static bool containsControlCharacter0(const char* str, unsigned len) { + char const* end = str + len; + while (end != str) { + if (isControlCharacter(*str) || 0==*str) + return true; + ++str; + } + return false; +} + +std::string valueToString(LargestInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + if (value == Value::minLargestInt) { + uintToString(LargestUInt(Value::maxLargestInt) + 1, current); + *--current = '-'; + } else if (value < 0) { + uintToString(LargestUInt(-value), current); + *--current = '-'; + } else { + uintToString(LargestUInt(value), current); + } + assert(current >= buffer); + return current; +} + +std::string valueToString(LargestUInt value) { + UIntToStringBuffer buffer; + char* current = buffer + sizeof(buffer); + uintToString(value, current); + assert(current >= buffer); + return current; +} + +#if defined(JSON_HAS_INT64) + +std::string valueToString(Int value) { + return valueToString(LargestInt(value)); +} + +std::string valueToString(UInt value) { + return valueToString(LargestUInt(value)); +} + +#endif // # if defined(JSON_HAS_INT64) + +std::string valueToString(double value) { + // Allocate a buffer that is more than large enough to store the 16 digits of + // precision requested below. + char buffer[32]; + int len = -1; + +// Print into the buffer. We need not request the alternative representation +// that always has a decimal point because JSON doesn't distingish the +// concepts of reals and integers. +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with + // visual studio 2005 to + // avoid warning. +#if defined(WINCE) + len = _snprintf(buffer, sizeof(buffer), "%.17g", value); +#else + len = sprintf_s(buffer, sizeof(buffer), "%.17g", value); +#endif +#else + if (isfinite(value)) { + len = snprintf(buffer, sizeof(buffer), "%.17g", value); + } else { + // IEEE standard states that NaN values will not compare to themselves + if (value != value) { + len = snprintf(buffer, sizeof(buffer), "null"); + } else if (value < 0) { + len = snprintf(buffer, sizeof(buffer), "-1e+9999"); + } else { + len = snprintf(buffer, sizeof(buffer), "1e+9999"); + } + // For those, we do not need to call fixNumLoc, but it is fast. + } +#endif + assert(len >= 0); + fixNumericLocale(buffer, buffer + len); + return buffer; +} + +std::string valueToString(bool value) { return value ? "true" : "false"; } + +std::string valueToQuotedString(const char* value) { + if (value == NULL) + return ""; + // Not sure how to handle unicode... + if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && + !containsControlCharacter(value)) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + std::string::size_type maxsize = + strlen(value) * 2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + for (const char* c = value; *c != 0; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something. + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; + } + } + result += "\""; + return result; +} + +// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp +static char const* strnpbrk(char const* s, char const* accept, size_t n) { + assert((s || !n) && accept); + + char const* const end = s + n; + for (char const* cur = s; cur < end; ++cur) { + int const c = *cur; + for (char const* a = accept; *a; ++a) { + if (*a == c) { + return cur; + } + } + } + return NULL; +} +static std::string valueToQuotedStringN(const char* value, unsigned length) { + if (value == NULL) + return ""; + // Not sure how to handle unicode... + if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && + !containsControlCharacter0(value, length)) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + std::string::size_type maxsize = + length * 2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + char const* end = value + length; + for (const char* c = value; c != end; ++c) { + switch (*c) { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + // case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something.) + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } else { + result += *c; + } + break; + } + } + result += "\""; + return result; +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() {} + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), + omitEndingLineFeed_(false) {} + +void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } + +void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } + +void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } + +std::string FastWriter::write(const Value& root) { + document_ = ""; + writeValue(root); + if (!omitEndingLineFeed_) + document_ += "\n"; + return document_; +} + +void FastWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + if (!dropNullPlaceholders_) + document_ += "null"; + break; + case intValue: + document_ += valueToString(value.asLargestInt()); + break; + case uintValue: + document_ += valueToString(value.asLargestUInt()); + break; + case realValue: + document_ += valueToString(value.asDouble()); + break; + case stringValue: + { + // Is NULL possible for value.string_? + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) document_ += valueToQuotedStringN(str, static_cast(end-str)); + break; + } + case booleanValue: + document_ += valueToString(value.asBool()); + break; + case arrayValue: { + document_ += '['; + int size = value.size(); + for (int index = 0; index < size; ++index) { + if (index > 0) + document_ += ','; + writeValue(value[index]); + } + document_ += ']'; + } break; + case objectValue: { + Value::Members members(value.getMemberNames()); + document_ += '{'; + for (Value::Members::iterator it = members.begin(); it != members.end(); + ++it) { + const std::string& name = *it; + if (it != members.begin()) + document_ += ','; + document_ += valueToQuotedStringN(name.data(), static_cast(name.length())); + document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + writeValue(value[name]); + } + document_ += '}'; + } break; + } +} + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() + : rightMargin_(74), indentSize_(3), addChildValues_() {} + +std::string StyledWriter::write(const Value& root) { + document_ = ""; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue(root); + writeValue(root); + writeCommentAfterValueOnSameLine(root); + document_ += "\n"; + return document_; +} + +void StyledWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + { + // Is NULL possible for value.string_? + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const std::string& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + document_ += " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + writeIndent(); + writeValue(childValue); + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + document_ += ','; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + document_ += "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + +bool StyledWriter::isMultineArray(const Value& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledWriter::pushValue(const std::string& value) { + if (addChildValues_) + childValues_.push_back(value); + else + document_ += value; +} + +void StyledWriter::writeIndent() { + if (!document_.empty()) { + char last = document_[document_.length() - 1]; + if (last == ' ') // already indented + return; + if (last != '\n') // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + +void StyledWriter::writeWithIndent(const std::string& value) { + writeIndent(); + document_ += value; +} + +void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } + +void StyledWriter::unindent() { + assert(int(indentString_.size()) >= indentSize_); + indentString_.resize(indentString_.size() - indentSize_); +} + +void StyledWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + document_ += "\n"; + writeIndent(); + const std::string& comment = root.getComment(commentBefore); + std::string::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + document_ += *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) + writeIndent(); + ++iter; + } + + // Comments are stripped of trailing newlines, so add one here + document_ += "\n"; +} + +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + document_ += " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + document_ += "\n"; + document_ += root.getComment(commentAfter); + document_ += "\n"; + } +} + +bool StyledWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter(std::string indentation) + : document_(NULL), rightMargin_(74), indentation_(indentation), + addChildValues_() {} + +void StyledStreamWriter::write(std::ostream& out, const Value& root) { + document_ = &out; + addChildValues_ = false; + indentString_ = ""; + indented_ = true; + writeCommentBeforeValue(root); + if (!indented_) writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + +void StyledStreamWriter::writeValue(const Value& value) { + switch (value.type()) { + case nullValue: + pushValue("null"); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + { + // Is NULL possible for value.string_? + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + const std::string& name = *it; + const Value& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedString(name.c_str())); + *document_ << " : "; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void StyledStreamWriter::writeArrayValue(const Value& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isArrayMultiLine = isMultineArray(value); + if (isArrayMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + const Value& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *document_ << "[ "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + +bool StyledStreamWriter::isMultineArray(const Value& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + const Value& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void StyledStreamWriter::pushValue(const std::string& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *document_ << value; +} + +void StyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + *document_ << '\n' << indentString_; +} + +void StyledStreamWriter::writeWithIndent(const std::string& value) { + if (!indented_) writeIndent(); + *document_ << value; + indented_ = false; +} + +void StyledStreamWriter::indent() { indentString_ += indentation_; } + +void StyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) writeIndent(); + const std::string& comment = root.getComment(commentBefore); + std::string::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *document_ << *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would include newline + *document_ << indentString_; + ++iter; + } + indented_ = false; +} + +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { + if (root.hasComment(commentAfterOnSameLine)) + *document_ << ' ' << root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *document_ << root.getComment(commentAfter); + } + indented_ = false; +} + +bool StyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +////////////////////////// +// BuiltStyledStreamWriter + +/// Scoped enums are not available until C++11. +struct CommentStyle { + /// Decide whether to write comments. + enum Enum { + None, ///< Drop all comments. + Most, ///< Recover odd behavior of previous versions (not implemented yet). + All ///< Keep all comments. + }; +}; + +struct BuiltStyledStreamWriter : public StreamWriter +{ + BuiltStyledStreamWriter( + std::string const& indentation, + CommentStyle::Enum cs, + std::string const& colonSymbol, + std::string const& nullSymbol, + std::string const& endingLineFeedSymbol); + virtual int write(Value const& root, std::ostream* sout); +private: + void writeValue(Value const& value); + void writeArrayValue(Value const& value); + bool isMultineArray(Value const& value); + void pushValue(std::string const& value); + void writeIndent(); + void writeWithIndent(std::string const& value); + void indent(); + void unindent(); + void writeCommentBeforeValue(Value const& root); + void writeCommentAfterValueOnSameLine(Value const& root); + static bool hasCommentForValue(const Value& value); + + typedef std::vector ChildValues; + + ChildValues childValues_; + std::string indentString_; + int rightMargin_; + std::string indentation_; + CommentStyle::Enum cs_; + std::string colonSymbol_; + std::string nullSymbol_; + std::string endingLineFeedSymbol_; + bool addChildValues_ : 1; + bool indented_ : 1; +}; +BuiltStyledStreamWriter::BuiltStyledStreamWriter( + std::string const& indentation, + CommentStyle::Enum cs, + std::string const& colonSymbol, + std::string const& nullSymbol, + std::string const& endingLineFeedSymbol) + : rightMargin_(74) + , indentation_(indentation) + , cs_(cs) + , colonSymbol_(colonSymbol) + , nullSymbol_(nullSymbol) + , endingLineFeedSymbol_(endingLineFeedSymbol) + , addChildValues_(false) + , indented_(false) +{ +} +int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout) +{ + sout_ = sout; + addChildValues_ = false; + indented_ = true; + indentString_ = ""; + writeCommentBeforeValue(root); + if (!indented_) writeIndent(); + indented_ = true; + writeValue(root); + writeCommentAfterValueOnSameLine(root); + *sout_ << endingLineFeedSymbol_; + sout_ = NULL; + return 0; +} +void BuiltStyledStreamWriter::writeValue(Value const& value) { + switch (value.type()) { + case nullValue: + pushValue(nullSymbol_); + break; + case intValue: + pushValue(valueToString(value.asLargestInt())); + break; + case uintValue: + pushValue(valueToString(value.asLargestUInt())); + break; + case realValue: + pushValue(valueToString(value.asDouble())); + break; + case stringValue: + { + // Is NULL is possible for value.string_? + char const* str; + char const* end; + bool ok = value.getString(&str, &end); + if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); + else pushValue(""); + break; + } + case booleanValue: + pushValue(valueToString(value.asBool())); + break; + case arrayValue: + writeArrayValue(value); + break; + case objectValue: { + Value::Members members(value.getMemberNames()); + if (members.empty()) + pushValue("{}"); + else { + writeWithIndent("{"); + indent(); + Value::Members::iterator it = members.begin(); + for (;;) { + std::string const& name = *it; + Value const& childValue = value[name]; + writeCommentBeforeValue(childValue); + writeWithIndent(valueToQuotedStringN(name.data(), static_cast(name.length()))); + *sout_ << colonSymbol_; + writeValue(childValue); + if (++it == members.end()) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("}"); + } + } break; + } +} + +void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { + unsigned size = value.size(); + if (size == 0) + pushValue("[]"); + else { + bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); + if (isMultiLine) { + writeWithIndent("["); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index = 0; + for (;;) { + Value const& childValue = value[index]; + writeCommentBeforeValue(childValue); + if (hasChildValue) + writeWithIndent(childValues_[index]); + else { + if (!indented_) writeIndent(); + indented_ = true; + writeValue(childValue); + indented_ = false; + } + if (++index == size) { + writeCommentAfterValueOnSameLine(childValue); + break; + } + *sout_ << ","; + writeCommentAfterValueOnSameLine(childValue); + } + unindent(); + writeWithIndent("]"); + } else // output on a single line + { + assert(childValues_.size() == size); + *sout_ << "["; + if (!indentation_.empty()) *sout_ << " "; + for (unsigned index = 0; index < size; ++index) { + if (index > 0) + *sout_ << ", "; + *sout_ << childValues_[index]; + } + if (!indentation_.empty()) *sout_ << " "; + *sout_ << "]"; + } + } +} + +bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { + int size = value.size(); + bool isMultiLine = size * 3 >= rightMargin_; + childValues_.clear(); + for (int index = 0; index < size && !isMultiLine; ++index) { + Value const& childValue = value[index]; + isMultiLine = + isMultiLine || ((childValue.isArray() || childValue.isObject()) && + childValue.size() > 0); + } + if (!isMultiLine) // check if line length > max line length + { + childValues_.reserve(size); + addChildValues_ = true; + int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' + for (int index = 0; index < size; ++index) { + if (hasCommentForValue(value[index])) { + isMultiLine = true; + } + writeValue(value[index]); + lineLength += int(childValues_[index].length()); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + +void BuiltStyledStreamWriter::pushValue(std::string const& value) { + if (addChildValues_) + childValues_.push_back(value); + else + *sout_ << value; +} + +void BuiltStyledStreamWriter::writeIndent() { + // blep intended this to look at the so-far-written string + // to determine whether we are already indented, but + // with a stream we cannot do that. So we rely on some saved state. + // The caller checks indented_. + + if (!indentation_.empty()) { + // In this case, drop newlines too. + *sout_ << '\n' << indentString_; + } +} + +void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) { + if (!indented_) writeIndent(); + *sout_ << value; + indented_ = false; +} + +void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } + +void BuiltStyledStreamWriter::unindent() { + assert(indentString_.size() >= indentation_.size()); + indentString_.resize(indentString_.size() - indentation_.size()); +} + +void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { + if (cs_ == CommentStyle::None) return; + if (!root.hasComment(commentBefore)) + return; + + if (!indented_) writeIndent(); + const std::string& comment = root.getComment(commentBefore); + std::string::const_iterator iter = comment.begin(); + while (iter != comment.end()) { + *sout_ << *iter; + if (*iter == '\n' && + (iter != comment.end() && *(iter + 1) == '/')) + // writeIndent(); // would write extra newline + *sout_ << indentString_; + ++iter; + } + indented_ = false; +} + +void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) { + if (cs_ == CommentStyle::None) return; + if (root.hasComment(commentAfterOnSameLine)) + *sout_ << " " + root.getComment(commentAfterOnSameLine); + + if (root.hasComment(commentAfter)) { + writeIndent(); + *sout_ << root.getComment(commentAfter); + } +} + +// static +bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { + return value.hasComment(commentBefore) || + value.hasComment(commentAfterOnSameLine) || + value.hasComment(commentAfter); +} + +/////////////// +// StreamWriter + +StreamWriter::StreamWriter() + : sout_(NULL) +{ +} +StreamWriter::~StreamWriter() +{ +} +StreamWriter::Factory::~Factory() +{} +StreamWriterBuilder::StreamWriterBuilder() +{ + setDefaults(&settings_); +} +StreamWriterBuilder::~StreamWriterBuilder() +{} +StreamWriter* StreamWriterBuilder::newStreamWriter() const +{ + std::string indentation = settings_["indentation"].asString(); + std::string cs_str = settings_["commentStyle"].asString(); + bool eyc = settings_["enableYAMLCompatibility"].asBool(); + bool dnp = settings_["dropNullPlaceholders"].asBool(); + CommentStyle::Enum cs = CommentStyle::All; + if (cs_str == "All") { + cs = CommentStyle::All; + } else if (cs_str == "None") { + cs = CommentStyle::None; + } else { + throwRuntimeError("commentStyle must be 'All' or 'None'"); + } + std::string colonSymbol = " : "; + if (eyc) { + colonSymbol = ": "; + } else if (indentation.empty()) { + colonSymbol = ":"; + } + std::string nullSymbol = "null"; + if (dnp) { + nullSymbol = ""; + } + std::string endingLineFeedSymbol = ""; + return new BuiltStyledStreamWriter( + indentation, cs, + colonSymbol, nullSymbol, endingLineFeedSymbol); +} +static void getValidWriterKeys(std::set* valid_keys) +{ + valid_keys->clear(); + valid_keys->insert("indentation"); + valid_keys->insert("commentStyle"); + valid_keys->insert("enableYAMLCompatibility"); + valid_keys->insert("dropNullPlaceholders"); +} +bool StreamWriterBuilder::validate(Json::Value* invalid) const +{ + Json::Value my_invalid; + if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL + Json::Value& inv = *invalid; + std::set valid_keys; + getValidWriterKeys(&valid_keys); + Value::Members keys = settings_.getMemberNames(); + size_t n = keys.size(); + for (size_t i = 0; i < n; ++i) { + std::string const& key = keys[i]; + if (valid_keys.find(key) == valid_keys.end()) { + inv[key] = settings_[key]; + } + } + return 0u == inv.size(); +} +Value& StreamWriterBuilder::operator[](std::string key) +{ + return settings_[key]; +} +// static +void StreamWriterBuilder::setDefaults(Json::Value* settings) +{ + //! [StreamWriterBuilderDefaults] + (*settings)["commentStyle"] = "All"; + (*settings)["indentation"] = "\t"; + (*settings)["enableYAMLCompatibility"] = false; + (*settings)["dropNullPlaceholders"] = false; + //! [StreamWriterBuilderDefaults] +} + +std::string writeString(StreamWriter::Factory const& builder, Value const& root) { + std::ostringstream sout; + StreamWriterPtr const writer(builder.newStreamWriter()); + writer->write(root, &sout); + return sout.str(); +} + +std::ostream& operator<<(std::ostream& sout, Value const& root) { + StreamWriterBuilder builder; + StreamWriterPtr const writer(builder.newStreamWriter()); + writer->write(root, &sout); + return sout; +} + +} // namespace Json diff --git a/jni/src/lib_json/version.h b/jni/src/lib_json/version.h new file mode 100644 index 000000000..9df36d7cd --- /dev/null +++ b/jni/src/lib_json/version.h @@ -0,0 +1,13 @@ +// DO NOT EDIT. This file (and "version") is generated by CMake. +// Run CMake configure step to update it. +#ifndef JSON_VERSION_H_INCLUDED +# define JSON_VERSION_H_INCLUDED + +# define JSONCPP_VERSION_STRING "1.6.5" +# define JSONCPP_VERSION_MAJOR 1 +# define JSONCPP_VERSION_MINOR 6 +# define JSONCPP_VERSION_PATCH 5 +# define JSONCPP_VERSION_QUALIFIER +# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) + +#endif // JSON_VERSION_H_INCLUDED From d0c8dd41c993723ade3d90bad052d340751f0d7e Mon Sep 17 00:00:00 2001 From: chetan Date: Sun, 23 Aug 2015 13:12:35 -0700 Subject: [PATCH 2/2] Getting rid of unused files. --- .gitignore | 38 +- CMakeLists.txt | 130 - SConstruct | 248 -- amalgamate.py | 154 -- appveyor.yml | 35 - dev.makefile | 35 - devtools/__init__.py | 6 - devtools/agent_vmw7.json | 33 - devtools/agent_vmxp.json | 26 - devtools/antglob.py | 205 -- devtools/batchbuild.py | 278 -- devtools/fixeol.py | 70 - devtools/licenseupdater.py | 94 - devtools/tarball.py | 52 - doxybuild.py | 189 -- include/CMakeLists.txt | 2 - include/json/assertions.h | 54 - include/json/autolink.h | 25 - include/json/config.h | 109 - include/json/features.h | 57 - include/json/forwards.h | 37 - include/json/json.h | 15 - include/json/reader.h | 401 --- include/json/value.h | 841 ------ include/json/version.h | 13 - include/json/writer.h | 327 --- makefiles/msvc2010/jsoncpp.sln | 42 - makefiles/msvc2010/jsontest.vcxproj | 96 - makefiles/msvc2010/jsontest.vcxproj.filters | 13 - makefiles/msvc2010/lib_json.vcxproj | 143 - makefiles/msvc2010/lib_json.vcxproj.filters | 33 - makefiles/msvc2010/test_lib_json.vcxproj | 109 - .../msvc2010/test_lib_json.vcxproj.filters | 24 - makefiles/vs71/jsoncpp.sln | 46 - makefiles/vs71/jsontest.vcproj | 119 - makefiles/vs71/lib_json.vcproj | 205 -- makefiles/vs71/test_lib_json.vcproj | 130 - makerelease.py | 390 --- pkg-config/jsoncpp.pc.in | 11 - scons-tools/globtool.py | 58 - scons-tools/srcdist.py | 183 -- scons-tools/substinfile.py | 85 - scons-tools/targz.py | 87 - src/CMakeLists.txt | 5 - src/jsontestrunner/CMakeLists.txt | 25 - src/jsontestrunner/main.cpp | 325 --- src/jsontestrunner/sconscript | 9 - src/lib_json/CMakeLists.txt | 80 - src/lib_json/json_reader.cpp | 1979 -------------- src/lib_json/json_tool.h | 87 - src/lib_json/json_value.cpp | 1528 ----------- src/lib_json/json_valueiterator.inl | 162 -- src/lib_json/json_writer.cpp | 1182 -------- src/lib_json/sconscript | 8 - src/lib_json/version.h.in | 13 - src/test_lib_json/CMakeLists.txt | 38 - src/test_lib_json/jsontest.cpp | 443 --- src/test_lib_json/jsontest.h | 280 -- src/test_lib_json/main.cpp | 2406 ----------------- src/test_lib_json/sconscript | 10 - test/cleantests.py | 16 - test/data/fail_test_array_01.json | 1 - test/data/test_array_01.expected | 1 - test/data/test_array_01.json | 1 - test/data/test_array_02.expected | 2 - test/data/test_array_02.json | 1 - test/data/test_array_03.expected | 6 - test/data/test_array_03.json | 1 - test/data/test_array_04.expected | 5 - test/data/test_array_04.json | 1 - test/data/test_array_05.expected | 100 - test/data/test_array_05.json | 1 - test/data/test_array_06.expected | 5 - test/data/test_array_06.json | 4 - test/data/test_array_07.expected | 2122 --------------- test/data/test_array_07.json | 2 - test/data/test_basic_01.expected | 1 - test/data/test_basic_01.json | 1 - test/data/test_basic_02.expected | 1 - test/data/test_basic_02.json | 1 - test/data/test_basic_03.expected | 3 - test/data/test_basic_03.json | 3 - test/data/test_basic_04.expected | 2 - test/data/test_basic_04.json | 2 - test/data/test_basic_05.expected | 2 - test/data/test_basic_05.json | 2 - test/data/test_basic_06.expected | 2 - test/data/test_basic_06.json | 2 - test/data/test_basic_07.expected | 2 - test/data/test_basic_07.json | 2 - test/data/test_basic_08.expected | 3 - test/data/test_basic_08.json | 3 - test/data/test_basic_09.expected | 4 - test/data/test_basic_09.json | 4 - test/data/test_comment_00.expected | 4 - test/data/test_comment_00.json | 5 - test/data/test_comment_01.expected | 10 - test/data/test_comment_01.json | 10 - test/data/test_comment_02.expected | 23 - test/data/test_comment_02.json | 26 - test/data/test_complex_01.expected | 20 - test/data/test_complex_01.json | 17 - test/data/test_integer_01.expected | 2 - test/data/test_integer_01.json | 2 - test/data/test_integer_02.expected | 2 - test/data/test_integer_02.json | 2 - test/data/test_integer_03.expected | 2 - test/data/test_integer_03.json | 2 - test/data/test_integer_04.expected | 3 - test/data/test_integer_04.json | 3 - test/data/test_integer_05.expected | 2 - test/data/test_integer_05.json | 2 - test/data/test_integer_06_64bits.expected | 1 - test/data/test_integer_06_64bits.json | 2 - test/data/test_integer_07_64bits.expected | 1 - test/data/test_integer_07_64bits.json | 2 - test/data/test_integer_08_64bits.expected | 1 - test/data/test_integer_08_64bits.json | 2 - test/data/test_large_01.expected | 2122 --------------- test/data/test_large_01.json | 2 - test/data/test_object_01.expected | 1 - test/data/test_object_01.json | 1 - test/data/test_object_02.expected | 2 - test/data/test_object_02.json | 1 - test/data/test_object_03.expected | 4 - test/data/test_object_03.json | 5 - test/data/test_object_04.expected | 2 - test/data/test_object_04.json | 3 - test/data/test_preserve_comment_01.expected | 11 - test/data/test_preserve_comment_01.json | 14 - test/data/test_real_01.expected | 3 - test/data/test_real_01.json | 3 - test/data/test_real_02.expected | 3 - test/data/test_real_02.json | 3 - test/data/test_real_03.expected | 3 - test/data/test_real_03.json | 3 - test/data/test_real_04.expected | 3 - test/data/test_real_04.json | 3 - test/data/test_real_05.expected | 4 - test/data/test_real_05.json | 3 - test/data/test_real_06.expected | 4 - test/data/test_real_06.json | 3 - test/data/test_real_07.expected | 4 - test/data/test_real_07.json | 3 - test/data/test_real_08.expected | 4 - test/data/test_real_08.json | 4 - test/data/test_real_09.expected | 4 - test/data/test_real_09.json | 4 - test/data/test_real_10.expected | 4 - test/data/test_real_10.json | 4 - test/data/test_real_11.expected | 4 - test/data/test_real_11.json | 4 - test/data/test_real_12.expected | 2 - test/data/test_real_12.json | 2 - test/data/test_string_01.expected | 1 - test/data/test_string_01.json | 1 - test/data/test_string_02.expected | 1 - test/data/test_string_02.json | 1 - test/data/test_string_03.expected | 1 - test/data/test_string_03.json | 1 - test/data/test_string_04.expected | 2 - test/data/test_string_04.json | 2 - test/data/test_string_05.expected | 2 - test/data/test_string_05.json | 2 - test/data/test_string_unicode_01.expected | 1 - test/data/test_string_unicode_01.json | 1 - test/data/test_string_unicode_02.expected | 1 - test/data/test_string_unicode_02.json | 1 - test/data/test_string_unicode_03.expected | 1 - test/data/test_string_unicode_03.json | 1 - test/data/test_string_unicode_04.expected | 1 - test/data/test_string_unicode_04.json | 1 - test/data/test_string_unicode_05.expected | 2 - test/data/test_string_unicode_05.json | 1 - test/generate_expected.py | 17 - test/jsonchecker/fail1.json | 1 - test/jsonchecker/fail10.json | 1 - test/jsonchecker/fail11.json | 1 - test/jsonchecker/fail12.json | 1 - test/jsonchecker/fail13.json | 1 - test/jsonchecker/fail14.json | 1 - test/jsonchecker/fail15.json | 1 - test/jsonchecker/fail16.json | 1 - test/jsonchecker/fail17.json | 1 - test/jsonchecker/fail18.json | 1 - test/jsonchecker/fail19.json | 1 - test/jsonchecker/fail2.json | 1 - test/jsonchecker/fail20.json | 1 - test/jsonchecker/fail21.json | 1 - test/jsonchecker/fail22.json | 1 - test/jsonchecker/fail23.json | 1 - test/jsonchecker/fail24.json | 1 - test/jsonchecker/fail25.json | 1 - test/jsonchecker/fail26.json | 1 - test/jsonchecker/fail27.json | 2 - test/jsonchecker/fail28.json | 2 - test/jsonchecker/fail29.json | 1 - test/jsonchecker/fail3.json | 1 - test/jsonchecker/fail30.json | 1 - test/jsonchecker/fail31.json | 1 - test/jsonchecker/fail32.json | 1 - test/jsonchecker/fail33.json | 1 - test/jsonchecker/fail4.json | 1 - test/jsonchecker/fail5.json | 1 - test/jsonchecker/fail6.json | 1 - test/jsonchecker/fail7.json | 1 - test/jsonchecker/fail8.json | 1 - test/jsonchecker/fail9.json | 1 - test/jsonchecker/pass1.json | 58 - test/jsonchecker/pass2.json | 1 - test/jsonchecker/pass3.json | 6 - test/jsonchecker/readme.txt | 3 - test/pyjsontestrunner.py | 71 - test/runjsontests.py | 174 -- test/rununittests.py | 84 - travis.sh | 29 - version | 1 - version.in | 1 - 218 files changed, 2 insertions(+), 19035 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 SConstruct delete mode 100644 amalgamate.py delete mode 100644 appveyor.yml delete mode 100644 dev.makefile delete mode 100644 devtools/__init__.py delete mode 100644 devtools/agent_vmw7.json delete mode 100644 devtools/agent_vmxp.json delete mode 100644 devtools/antglob.py delete mode 100644 devtools/batchbuild.py delete mode 100644 devtools/fixeol.py delete mode 100644 devtools/licenseupdater.py delete mode 100644 devtools/tarball.py delete mode 100644 doxybuild.py delete mode 100644 include/CMakeLists.txt delete mode 100644 include/json/assertions.h delete mode 100644 include/json/autolink.h delete mode 100644 include/json/config.h delete mode 100644 include/json/features.h delete mode 100644 include/json/forwards.h delete mode 100644 include/json/json.h delete mode 100644 include/json/reader.h delete mode 100644 include/json/value.h delete mode 100644 include/json/version.h delete mode 100644 include/json/writer.h delete mode 100644 makefiles/msvc2010/jsoncpp.sln delete mode 100644 makefiles/msvc2010/jsontest.vcxproj delete mode 100644 makefiles/msvc2010/jsontest.vcxproj.filters delete mode 100644 makefiles/msvc2010/lib_json.vcxproj delete mode 100644 makefiles/msvc2010/lib_json.vcxproj.filters delete mode 100644 makefiles/msvc2010/test_lib_json.vcxproj delete mode 100644 makefiles/msvc2010/test_lib_json.vcxproj.filters delete mode 100644 makefiles/vs71/jsoncpp.sln delete mode 100644 makefiles/vs71/jsontest.vcproj delete mode 100644 makefiles/vs71/lib_json.vcproj delete mode 100644 makefiles/vs71/test_lib_json.vcproj delete mode 100644 makerelease.py delete mode 100644 pkg-config/jsoncpp.pc.in delete mode 100644 scons-tools/globtool.py delete mode 100644 scons-tools/srcdist.py delete mode 100644 scons-tools/substinfile.py delete mode 100644 scons-tools/targz.py delete mode 100644 src/CMakeLists.txt delete mode 100644 src/jsontestrunner/CMakeLists.txt delete mode 100644 src/jsontestrunner/main.cpp delete mode 100644 src/jsontestrunner/sconscript delete mode 100644 src/lib_json/CMakeLists.txt delete mode 100644 src/lib_json/json_reader.cpp delete mode 100644 src/lib_json/json_tool.h delete mode 100644 src/lib_json/json_value.cpp delete mode 100644 src/lib_json/json_valueiterator.inl delete mode 100644 src/lib_json/json_writer.cpp delete mode 100644 src/lib_json/sconscript delete mode 100644 src/lib_json/version.h.in delete mode 100644 src/test_lib_json/CMakeLists.txt delete mode 100644 src/test_lib_json/jsontest.cpp delete mode 100644 src/test_lib_json/jsontest.h delete mode 100644 src/test_lib_json/main.cpp delete mode 100644 src/test_lib_json/sconscript delete mode 100644 test/cleantests.py delete mode 100644 test/data/fail_test_array_01.json delete mode 100644 test/data/test_array_01.expected delete mode 100644 test/data/test_array_01.json delete mode 100644 test/data/test_array_02.expected delete mode 100644 test/data/test_array_02.json delete mode 100644 test/data/test_array_03.expected delete mode 100644 test/data/test_array_03.json delete mode 100644 test/data/test_array_04.expected delete mode 100644 test/data/test_array_04.json delete mode 100644 test/data/test_array_05.expected delete mode 100644 test/data/test_array_05.json delete mode 100644 test/data/test_array_06.expected delete mode 100644 test/data/test_array_06.json delete mode 100644 test/data/test_array_07.expected delete mode 100644 test/data/test_array_07.json delete mode 100644 test/data/test_basic_01.expected delete mode 100644 test/data/test_basic_01.json delete mode 100644 test/data/test_basic_02.expected delete mode 100644 test/data/test_basic_02.json delete mode 100644 test/data/test_basic_03.expected delete mode 100644 test/data/test_basic_03.json delete mode 100644 test/data/test_basic_04.expected delete mode 100644 test/data/test_basic_04.json delete mode 100644 test/data/test_basic_05.expected delete mode 100644 test/data/test_basic_05.json delete mode 100644 test/data/test_basic_06.expected delete mode 100644 test/data/test_basic_06.json delete mode 100644 test/data/test_basic_07.expected delete mode 100644 test/data/test_basic_07.json delete mode 100644 test/data/test_basic_08.expected delete mode 100644 test/data/test_basic_08.json delete mode 100644 test/data/test_basic_09.expected delete mode 100644 test/data/test_basic_09.json delete mode 100644 test/data/test_comment_00.expected delete mode 100644 test/data/test_comment_00.json delete mode 100644 test/data/test_comment_01.expected delete mode 100644 test/data/test_comment_01.json delete mode 100644 test/data/test_comment_02.expected delete mode 100644 test/data/test_comment_02.json delete mode 100644 test/data/test_complex_01.expected delete mode 100644 test/data/test_complex_01.json delete mode 100644 test/data/test_integer_01.expected delete mode 100644 test/data/test_integer_01.json delete mode 100644 test/data/test_integer_02.expected delete mode 100644 test/data/test_integer_02.json delete mode 100644 test/data/test_integer_03.expected delete mode 100644 test/data/test_integer_03.json delete mode 100644 test/data/test_integer_04.expected delete mode 100644 test/data/test_integer_04.json delete mode 100644 test/data/test_integer_05.expected delete mode 100644 test/data/test_integer_05.json delete mode 100644 test/data/test_integer_06_64bits.expected delete mode 100644 test/data/test_integer_06_64bits.json delete mode 100644 test/data/test_integer_07_64bits.expected delete mode 100644 test/data/test_integer_07_64bits.json delete mode 100644 test/data/test_integer_08_64bits.expected delete mode 100644 test/data/test_integer_08_64bits.json delete mode 100644 test/data/test_large_01.expected delete mode 100644 test/data/test_large_01.json delete mode 100644 test/data/test_object_01.expected delete mode 100644 test/data/test_object_01.json delete mode 100644 test/data/test_object_02.expected delete mode 100644 test/data/test_object_02.json delete mode 100644 test/data/test_object_03.expected delete mode 100644 test/data/test_object_03.json delete mode 100644 test/data/test_object_04.expected delete mode 100644 test/data/test_object_04.json delete mode 100644 test/data/test_preserve_comment_01.expected delete mode 100644 test/data/test_preserve_comment_01.json delete mode 100644 test/data/test_real_01.expected delete mode 100644 test/data/test_real_01.json delete mode 100644 test/data/test_real_02.expected delete mode 100644 test/data/test_real_02.json delete mode 100644 test/data/test_real_03.expected delete mode 100644 test/data/test_real_03.json delete mode 100644 test/data/test_real_04.expected delete mode 100644 test/data/test_real_04.json delete mode 100644 test/data/test_real_05.expected delete mode 100644 test/data/test_real_05.json delete mode 100644 test/data/test_real_06.expected delete mode 100644 test/data/test_real_06.json delete mode 100644 test/data/test_real_07.expected delete mode 100644 test/data/test_real_07.json delete mode 100644 test/data/test_real_08.expected delete mode 100644 test/data/test_real_08.json delete mode 100644 test/data/test_real_09.expected delete mode 100644 test/data/test_real_09.json delete mode 100644 test/data/test_real_10.expected delete mode 100644 test/data/test_real_10.json delete mode 100644 test/data/test_real_11.expected delete mode 100644 test/data/test_real_11.json delete mode 100644 test/data/test_real_12.expected delete mode 100644 test/data/test_real_12.json delete mode 100644 test/data/test_string_01.expected delete mode 100644 test/data/test_string_01.json delete mode 100644 test/data/test_string_02.expected delete mode 100644 test/data/test_string_02.json delete mode 100644 test/data/test_string_03.expected delete mode 100644 test/data/test_string_03.json delete mode 100644 test/data/test_string_04.expected delete mode 100644 test/data/test_string_04.json delete mode 100644 test/data/test_string_05.expected delete mode 100644 test/data/test_string_05.json delete mode 100644 test/data/test_string_unicode_01.expected delete mode 100644 test/data/test_string_unicode_01.json delete mode 100644 test/data/test_string_unicode_02.expected delete mode 100644 test/data/test_string_unicode_02.json delete mode 100644 test/data/test_string_unicode_03.expected delete mode 100644 test/data/test_string_unicode_03.json delete mode 100644 test/data/test_string_unicode_04.expected delete mode 100644 test/data/test_string_unicode_04.json delete mode 100644 test/data/test_string_unicode_05.expected delete mode 100644 test/data/test_string_unicode_05.json delete mode 100644 test/generate_expected.py delete mode 100644 test/jsonchecker/fail1.json delete mode 100644 test/jsonchecker/fail10.json delete mode 100644 test/jsonchecker/fail11.json delete mode 100644 test/jsonchecker/fail12.json delete mode 100644 test/jsonchecker/fail13.json delete mode 100644 test/jsonchecker/fail14.json delete mode 100644 test/jsonchecker/fail15.json delete mode 100644 test/jsonchecker/fail16.json delete mode 100644 test/jsonchecker/fail17.json delete mode 100644 test/jsonchecker/fail18.json delete mode 100644 test/jsonchecker/fail19.json delete mode 100644 test/jsonchecker/fail2.json delete mode 100644 test/jsonchecker/fail20.json delete mode 100644 test/jsonchecker/fail21.json delete mode 100644 test/jsonchecker/fail22.json delete mode 100644 test/jsonchecker/fail23.json delete mode 100644 test/jsonchecker/fail24.json delete mode 100644 test/jsonchecker/fail25.json delete mode 100644 test/jsonchecker/fail26.json delete mode 100644 test/jsonchecker/fail27.json delete mode 100644 test/jsonchecker/fail28.json delete mode 100644 test/jsonchecker/fail29.json delete mode 100644 test/jsonchecker/fail3.json delete mode 100644 test/jsonchecker/fail30.json delete mode 100644 test/jsonchecker/fail31.json delete mode 100644 test/jsonchecker/fail32.json delete mode 100644 test/jsonchecker/fail33.json delete mode 100644 test/jsonchecker/fail4.json delete mode 100644 test/jsonchecker/fail5.json delete mode 100644 test/jsonchecker/fail6.json delete mode 100644 test/jsonchecker/fail7.json delete mode 100644 test/jsonchecker/fail8.json delete mode 100644 test/jsonchecker/fail9.json delete mode 100644 test/jsonchecker/pass1.json delete mode 100644 test/jsonchecker/pass2.json delete mode 100644 test/jsonchecker/pass3.json delete mode 100644 test/jsonchecker/readme.txt delete mode 100644 test/pyjsontestrunner.py delete mode 100644 test/runjsontests.py delete mode 100644 test/rununittests.py delete mode 100755 travis.sh delete mode 100644 version delete mode 100644 version.in diff --git a/.gitignore b/.gitignore index ef226a887..74c331c8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,36 +1,2 @@ -/build/ -*.pyc -*.swp -*.actual -*.actual-rewrite -*.process-output -*.rewrite -/bin/ -/buildscons/ -/libs/ -/doc/doxyfile -/dist/ -#/version -#/include/json/version.h - -# MSVC project files: -*.sln -*.vcxproj -*.filters -*.user -*.sdf -*.opensdf -*.suo - -# MSVC build files: -*.lib -*.obj -*.tlog/ -*.pdb - -# CMake-generated files: -CMakeFiles/ -CTestTestFile.cmake -cmake_install.cmake -pkg-config/jsoncpp.pc -jsoncpp_lib_static.dir/ +libs +obj diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 7d459fd60..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,130 +0,0 @@ -# vim: et ts=4 sts=4 sw=4 tw=0 - -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5) -PROJECT(jsoncpp) -ENABLE_TESTING() - -OPTION(JSONCPP_WITH_TESTS "Compile and (for jsoncpp_check) run JsonCpp test executables" ON) -OPTION(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON) -OPTION(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occurs" OFF) -OPTION(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON) -OPTION(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" OFF) -OPTION(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." OFF) -OPTION(BUILD_STATIC_LIBS "Build jsoncpp_lib static library." ON) - -# Ensures that CMAKE_BUILD_TYPE is visible in cmake-gui on Unix -IF(NOT WIN32) - IF(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE Release CACHE STRING - "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage." - FORCE) - ENDIF() -ENDIF() - -SET(DEBUG_LIBNAME_SUFFIX "" CACHE STRING "Optional suffix to append to the library name for a debug build") -SET(LIB_SUFFIX "" CACHE STRING "Optional arch-dependent suffix for the library installation directory") - -SET(RUNTIME_INSTALL_DIR bin - CACHE PATH "Install dir for executables and dlls") -SET(ARCHIVE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX} - CACHE PATH "Install dir for static libraries") -SET(LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX} - CACHE PATH "Install dir for shared libraries") -SET(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include - CACHE PATH "Install dir for headers") -SET(PACKAGE_INSTALL_DIR lib${LIB_SUFFIX}/cmake - CACHE PATH "Install dir for cmake package config files") -MARK_AS_ADVANCED( RUNTIME_INSTALL_DIR ARCHIVE_INSTALL_DIR INCLUDE_INSTALL_DIR PACKAGE_INSTALL_DIR ) - -# Set variable named ${VAR_NAME} to value ${VALUE} -FUNCTION(set_using_dynamic_name VAR_NAME VALUE) - SET( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE) -ENDFUNCTION() - -# Extract major, minor, patch from version text -# Parse a version string "X.Y.Z" and outputs -# version parts in ${OUPUT_PREFIX}_MAJOR, _MINOR, _PATCH. -# If parse succeeds then ${OUPUT_PREFIX}_FOUND is TRUE. -MACRO(jsoncpp_parse_version VERSION_TEXT OUPUT_PREFIX) - SET(VERSION_REGEX "[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9_]+)?") - IF( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} ) - STRING(REGEX MATCHALL "[0-9]+|-([A-Za-z0-9_]+)" VERSION_PARTS ${VERSION_TEXT}) - LIST(GET VERSION_PARTS 0 ${OUPUT_PREFIX}_MAJOR) - LIST(GET VERSION_PARTS 1 ${OUPUT_PREFIX}_MINOR) - LIST(GET VERSION_PARTS 2 ${OUPUT_PREFIX}_PATCH) - set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" TRUE ) - ELSE( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} ) - set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" FALSE ) - ENDIF() -ENDMACRO() - -# Read out version from "version" file -#FILE(STRINGS "version" JSONCPP_VERSION) -#SET( JSONCPP_VERSION_MAJOR X ) -#SET( JSONCPP_VERSION_MINOR Y ) -#SET( JSONCPP_VERSION_PATCH Z ) -SET( JSONCPP_VERSION 1.6.5 ) -jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION ) -#IF(NOT JSONCPP_VERSION_FOUND) -# MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z") -#ENDIF(NOT JSONCPP_VERSION_FOUND) - -MESSAGE(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}") -# File version.h is only regenerated on CMake configure step -CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/src/lib_json/version.h.in" - "${PROJECT_SOURCE_DIR}/include/json/version.h" - NEWLINE_STYLE UNIX ) -CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/version.in" - "${PROJECT_SOURCE_DIR}/version" - NEWLINE_STYLE UNIX ) - -macro(UseCompilationWarningAsError) - if ( MSVC ) - # Only enabled in debug because some old versions of VS STL generate - # warnings when compiled in release configuration. - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ") - endif() -endmacro() - -# Include our configuration header -INCLUDE_DIRECTORIES( ${jsoncpp_SOURCE_DIR}/include ) - -if ( MSVC ) - # Only enabled in debug because some old versions of VS STL generate - # unreachable code warning when compiled in release configuration. - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ") -endif() - -if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # using regular Clang or AppleClang - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wconversion -Wshadow -Wno-sign-conversion") -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # using GCC - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wconversion -Wshadow -Wextra -pedantic") - # not yet ready for -Wsign-conversion -endif() - -IF(JSONCPP_WITH_WARNING_AS_ERROR) - UseCompilationWarningAsError() -ENDIF() - -IF(JSONCPP_WITH_PKGCONFIG_SUPPORT) - CONFIGURE_FILE( - "pkg-config/jsoncpp.pc.in" - "pkg-config/jsoncpp.pc" - @ONLY) - INSTALL(FILES "${CMAKE_BINARY_DIR}/pkg-config/jsoncpp.pc" - DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig") -ENDIF() - -IF(JSONCPP_WITH_CMAKE_PACKAGE) - INSTALL(EXPORT jsoncpp - DESTINATION ${PACKAGE_INSTALL_DIR}/jsoncpp - FILE jsoncppConfig.cmake) -ENDIF() - -# Build the different applications -ADD_SUBDIRECTORY( src ) - -#install the includes -ADD_SUBDIRECTORY( include ) diff --git a/SConstruct b/SConstruct deleted file mode 100644 index f3a73f773..000000000 --- a/SConstruct +++ /dev/null @@ -1,248 +0,0 @@ -""" -Notes: -- shared library support is buggy: it assumes that a static and dynamic library can be build from the same object files. This is not true on many platforms. For this reason it is only enabled on linux-gcc at the current time. - -To add a platform: -- add its name in options allowed_values below -- add tool initialization for this platform. Search for "if platform == 'suncc'" as an example. -""" - -import os -import os.path -import sys - -JSONCPP_VERSION = open(File('#version').abspath,'rt').read().strip() -DIST_DIR = '#dist' - -options = Variables() -options.Add( EnumVariable('platform', - 'Platform (compiler/stl) used to build the project', - 'msvc71', - allowed_values='suncc vacpp mingw msvc6 msvc7 msvc71 msvc80 msvc90 linux-gcc'.split(), - ignorecase=2) ) - -try: - platform = ARGUMENTS['platform'] - if platform == 'linux-gcc': - CXX = 'g++' # not quite right, but env is not yet available. - import commands - version = commands.getoutput('%s -dumpversion' %CXX) - platform = 'linux-gcc-%s' %version - print "Using platform '%s'" %platform - LD_LIBRARY_PATH = os.environ.get('LD_LIBRARY_PATH', '') - LD_LIBRARY_PATH = "%s:libs/%s" %(LD_LIBRARY_PATH, platform) - os.environ['LD_LIBRARY_PATH'] = LD_LIBRARY_PATH - print "LD_LIBRARY_PATH =", LD_LIBRARY_PATH -except KeyError: - print 'You must specify a "platform"' - sys.exit(2) - -print "Building using PLATFORM =", platform - -rootbuild_dir = Dir('#buildscons') -build_dir = os.path.join( '#buildscons', platform ) -bin_dir = os.path.join( '#bin', platform ) -lib_dir = os.path.join( '#libs', platform ) -sconsign_dir_path = Dir(build_dir).abspath -sconsign_path = os.path.join( sconsign_dir_path, '.sconsign.dbm' ) - -# Ensure build directory exist (SConsignFile fail otherwise!) -if not os.path.exists( sconsign_dir_path ): - os.makedirs( sconsign_dir_path ) - -# Store all dependencies signature in a database -SConsignFile( sconsign_path ) - -def make_environ_vars(): - """Returns a dictionnary with environment variable to use when compiling.""" - # PATH is required to find the compiler - # TEMP is required for at least mingw - # LD_LIBRARY_PATH & co is required on some system for the compiler - vars = {} - for name in ('PATH', 'TEMP', 'TMP', 'LD_LIBRARY_PATH', 'LIBRARY_PATH'): - if name in os.environ: - vars[name] = os.environ[name] - return vars - - -env = Environment( ENV = make_environ_vars(), - toolpath = ['scons-tools'], - tools=[] ) #, tools=['default'] ) - -if platform == 'suncc': - env.Tool( 'sunc++' ) - env.Tool( 'sunlink' ) - env.Tool( 'sunar' ) - env.Append( CCFLAGS = ['-mt'] ) -elif platform == 'vacpp': - env.Tool( 'default' ) - env.Tool( 'aixcc' ) - env['CXX'] = 'xlC_r' #scons does not pick-up the correct one ! - # using xlC_r ensure multi-threading is enabled: - # http://publib.boulder.ibm.com/infocenter/pseries/index.jsp?topic=/com.ibm.vacpp7a.doc/compiler/ref/cuselect.htm - env.Append( CCFLAGS = '-qrtti=all', - LINKFLAGS='-bh:5' ) # -bh:5 remove duplicate symbol warning -elif platform == 'msvc6': - env['MSVS_VERSION']='6.0' - for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: - env.Tool( tool ) - env['CXXFLAGS']='-GR -GX /nologo /MT' -elif platform == 'msvc70': - env['MSVS_VERSION']='7.0' - for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: - env.Tool( tool ) - env['CXXFLAGS']='-GR -GX /nologo /MT' -elif platform == 'msvc71': - env['MSVS_VERSION']='7.1' - for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: - env.Tool( tool ) - env['CXXFLAGS']='-GR -GX /nologo /MT' -elif platform == 'msvc80': - env['MSVS_VERSION']='8.0' - for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: - env.Tool( tool ) - env['CXXFLAGS']='-GR -EHsc /nologo /MT' -elif platform == 'msvc90': - env['MSVS_VERSION']='9.0' - # Scons 1.2 fails to detect the correct location of the platform SDK. - # So we propagate those from the environment. This requires that the - # user run vcvars32.bat before compiling. - if 'INCLUDE' in os.environ: - env['ENV']['INCLUDE'] = os.environ['INCLUDE'] - if 'LIB' in os.environ: - env['ENV']['LIB'] = os.environ['LIB'] - for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']: - env.Tool( tool ) - env['CXXFLAGS']='-GR -EHsc /nologo /MT' -elif platform == 'mingw': - env.Tool( 'mingw' ) - env.Append( CPPDEFINES=[ "WIN32", "NDEBUG", "_MT" ] ) -elif platform.startswith('linux-gcc'): - env.Tool( 'default' ) - env.Append( LIBS = ['pthread'], CCFLAGS = os.environ.get("CXXFLAGS", "-Wall"), LINKFLAGS=os.environ.get("LDFLAGS", "") ) - env['SHARED_LIB_ENABLED'] = True -else: - print "UNSUPPORTED PLATFORM." - env.Exit(1) - -env.Tool('targz') -env.Tool('srcdist') -env.Tool('globtool') - -env.Append( CPPPATH = ['#include'], - LIBPATH = lib_dir ) -short_platform = platform -if short_platform.startswith('msvc'): - short_platform = short_platform[2:] -# Notes: on Windows you need to rebuild the source for each variant -# Build script does not support that yet so we only build static libraries. -# This also fails on AIX because both dynamic and static library ends with -# extension .a. -env['SHARED_LIB_ENABLED'] = env.get('SHARED_LIB_ENABLED', False) -env['LIB_PLATFORM'] = short_platform -env['LIB_LINK_TYPE'] = 'lib' # static -env['LIB_CRUNTIME'] = 'mt' -env['LIB_NAME_SUFFIX'] = '${LIB_PLATFORM}_${LIB_LINK_TYPE}${LIB_CRUNTIME}' # must match autolink naming convention -env['JSONCPP_VERSION'] = JSONCPP_VERSION -env['BUILD_DIR'] = env.Dir(build_dir) -env['ROOTBUILD_DIR'] = env.Dir(rootbuild_dir) -env['DIST_DIR'] = DIST_DIR -if 'TarGz' in env['BUILDERS']: - class SrcDistAdder: - def __init__( self, env ): - self.env = env - def __call__( self, *args, **kw ): - apply( self.env.SrcDist, (self.env['SRCDIST_TARGET'],) + args, kw ) - env['SRCDIST_BUILDER'] = env.TarGz -else: # If tarfile module is missing - class SrcDistAdder: - def __init__( self, env ): - pass - def __call__( self, *args, **kw ): - pass -env['SRCDIST_ADD'] = SrcDistAdder( env ) -env['SRCDIST_TARGET'] = os.path.join( DIST_DIR, 'jsoncpp-src-%s.tar.gz' % env['JSONCPP_VERSION'] ) - -env_testing = env.Clone( ) -env_testing.Append( LIBS = ['json_${LIB_NAME_SUFFIX}'] ) - -def buildJSONExample( env, target_sources, target_name ): - env = env.Clone() - env.Append( CPPPATH = ['#'] ) - exe = env.Program( target=target_name, - source=target_sources ) - env['SRCDIST_ADD']( source=[target_sources] ) - global bin_dir - return env.Install( bin_dir, exe ) - -def buildJSONTests( env, target_sources, target_name ): - jsontests_node = buildJSONExample( env, target_sources, target_name ) - check_alias_target = env.Alias( 'check', jsontests_node, RunJSONTests( jsontests_node, jsontests_node ) ) - env.AlwaysBuild( check_alias_target ) - -def buildUnitTests( env, target_sources, target_name ): - jsontests_node = buildJSONExample( env, target_sources, target_name ) - check_alias_target = env.Alias( 'check', jsontests_node, - RunUnitTests( jsontests_node, jsontests_node ) ) - env.AlwaysBuild( check_alias_target ) - -def buildLibrary( env, target_sources, target_name ): - static_lib = env.StaticLibrary( target=target_name + '_${LIB_NAME_SUFFIX}', - source=target_sources ) - global lib_dir - env.Install( lib_dir, static_lib ) - if env['SHARED_LIB_ENABLED']: - shared_lib = env.SharedLibrary( target=target_name + '_${LIB_NAME_SUFFIX}', - source=target_sources ) - env.Install( lib_dir, shared_lib ) - env['SRCDIST_ADD']( source=[target_sources] ) - -Export( 'env env_testing buildJSONExample buildLibrary buildJSONTests buildUnitTests' ) - -def buildProjectInDirectory( target_directory ): - global build_dir - target_build_dir = os.path.join( build_dir, target_directory ) - target = os.path.join( target_directory, 'sconscript' ) - SConscript( target, build_dir=target_build_dir, duplicate=0 ) - env['SRCDIST_ADD']( source=[target] ) - - -def runJSONTests_action( target, source = None, env = None ): - # Add test scripts to python path - jsontest_path = Dir( '#test' ).abspath - sys.path.insert( 0, jsontest_path ) - data_path = os.path.join( jsontest_path, 'data' ) - import runjsontests - return runjsontests.runAllTests( os.path.abspath(source[0].path), data_path ) - -def runJSONTests_string( target, source = None, env = None ): - return 'RunJSONTests("%s")' % source[0] - -import SCons.Action -ActionFactory = SCons.Action.ActionFactory -RunJSONTests = ActionFactory(runJSONTests_action, runJSONTests_string ) - -def runUnitTests_action( target, source = None, env = None ): - # Add test scripts to python path - jsontest_path = Dir( '#test' ).abspath - sys.path.insert( 0, jsontest_path ) - import rununittests - return rununittests.runAllTests( os.path.abspath(source[0].path) ) - -def runUnitTests_string( target, source = None, env = None ): - return 'RunUnitTests("%s")' % source[0] - -RunUnitTests = ActionFactory(runUnitTests_action, runUnitTests_string ) - -env.Alias( 'check' ) - -srcdist_cmd = env['SRCDIST_ADD']( source = """ - AUTHORS README.md SConstruct - """.split() ) -env.Alias( 'src-dist', srcdist_cmd ) - -buildProjectInDirectory( 'src/jsontestrunner' ) -buildProjectInDirectory( 'src/lib_json' ) -buildProjectInDirectory( 'src/test_lib_json' ) -#print env.Dump() - diff --git a/amalgamate.py b/amalgamate.py deleted file mode 100644 index 1916bb0d5..000000000 --- a/amalgamate.py +++ /dev/null @@ -1,154 +0,0 @@ -"""Amalgate json-cpp library sources into a single source and header file. - -Works with python2.6+ and python3.4+. - -Example of invocation (must be invoked from json-cpp top directory): -python amalgate.py -""" -import os -import os.path -import sys - -class AmalgamationFile: - def __init__(self, top_dir): - self.top_dir = top_dir - self.blocks = [] - - def add_text(self, text): - if not text.endswith("\n"): - text += "\n" - self.blocks.append(text) - - def add_file(self, relative_input_path, wrap_in_comment=False): - def add_marker(prefix): - self.add_text("") - self.add_text("// " + "/"*70) - self.add_text("// %s of content of file: %s" % (prefix, relative_input_path.replace("\\","/"))) - self.add_text("// " + "/"*70) - self.add_text("") - add_marker("Beginning") - f = open(os.path.join(self.top_dir, relative_input_path), "rt") - content = f.read() - if wrap_in_comment: - content = "/*\n" + content + "\n*/" - self.add_text(content) - f.close() - add_marker("End") - self.add_text("\n\n\n\n") - - def get_value(self): - return "".join(self.blocks).replace("\r\n","\n") - - def write_to(self, output_path): - output_dir = os.path.dirname(output_path) - if output_dir and not os.path.isdir(output_dir): - os.makedirs(output_dir) - f = open(output_path, "wb") - f.write(str.encode(self.get_value(), 'UTF-8')) - f.close() - -def amalgamate_source(source_top_dir=None, - target_source_path=None, - header_include_path=None): - """Produces amalgated source. - Parameters: - source_top_dir: top-directory - target_source_path: output .cpp path - header_include_path: generated header path relative to target_source_path. - """ - print("Amalgating header...") - header = AmalgamationFile(source_top_dir) - header.add_text("/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).") - header.add_text('/// It is intended to be used with #include "%s"' % header_include_path) - header.add_file("LICENSE", wrap_in_comment=True) - header.add_text("#ifndef JSON_AMALGATED_H_INCLUDED") - header.add_text("# define JSON_AMALGATED_H_INCLUDED") - header.add_text("/// If defined, indicates that the source file is amalgated") - header.add_text("/// to prevent private header inclusion.") - header.add_text("#define JSON_IS_AMALGAMATION") - header.add_file("include/json/version.h") - header.add_file("include/json/config.h") - header.add_file("include/json/forwards.h") - header.add_file("include/json/features.h") - header.add_file("include/json/value.h") - header.add_file("include/json/reader.h") - header.add_file("include/json/writer.h") - header.add_file("include/json/assertions.h") - header.add_text("#endif //ifndef JSON_AMALGATED_H_INCLUDED") - - target_header_path = os.path.join(os.path.dirname(target_source_path), header_include_path) - print("Writing amalgated header to %r" % target_header_path) - header.write_to(target_header_path) - - base, ext = os.path.splitext(header_include_path) - forward_header_include_path = base + "-forwards" + ext - print("Amalgating forward header...") - header = AmalgamationFile(source_top_dir) - header.add_text("/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).") - header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path) - header.add_text("/// This header provides forward declaration for all JsonCpp types.") - header.add_file("LICENSE", wrap_in_comment=True) - header.add_text("#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED") - header.add_text("# define JSON_FORWARD_AMALGATED_H_INCLUDED") - header.add_text("/// If defined, indicates that the source file is amalgated") - header.add_text("/// to prevent private header inclusion.") - header.add_text("#define JSON_IS_AMALGAMATION") - header.add_file("include/json/config.h") - header.add_file("include/json/forwards.h") - header.add_text("#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED") - - target_forward_header_path = os.path.join(os.path.dirname(target_source_path), - forward_header_include_path) - print("Writing amalgated forward header to %r" % target_forward_header_path) - header.write_to(target_forward_header_path) - - print("Amalgating source...") - source = AmalgamationFile(source_top_dir) - source.add_text("/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).") - source.add_text('/// It is intended to be used with #include "%s"' % header_include_path) - source.add_file("LICENSE", wrap_in_comment=True) - source.add_text("") - source.add_text('#include "%s"' % header_include_path) - source.add_text(""" -#ifndef JSON_IS_AMALGAMATION -#error "Compile with -I PATH_TO_JSON_DIRECTORY" -#endif -""") - source.add_text("") - lib_json = "src/lib_json" - source.add_file(os.path.join(lib_json, "json_tool.h")) - source.add_file(os.path.join(lib_json, "json_reader.cpp")) - source.add_file(os.path.join(lib_json, "json_valueiterator.inl")) - source.add_file(os.path.join(lib_json, "json_value.cpp")) - source.add_file(os.path.join(lib_json, "json_writer.cpp")) - - print("Writing amalgated source to %r" % target_source_path) - source.write_to(target_source_path) - -def main(): - usage = """%prog [options] -Generate a single amalgated source and header file from the sources. -""" - from optparse import OptionParser - parser = OptionParser(usage=usage) - parser.allow_interspersed_args = False - parser.add_option("-s", "--source", dest="target_source_path", action="http://github.com/store", default="dist/jsoncpp.cpp", - help="""Output .cpp source path. [Default: %default]""") - parser.add_option("-i", "--include", dest="header_include_path", action="http://github.com/store", default="json/json.h", - help="""Header include path. Used to include the header from the amalgated source file. [Default: %default]""") - parser.add_option("-t", "--top-dir", dest="top_dir", action="http://github.com/store", default=os.getcwd(), - help="""Source top-directory. [Default: %default]""") - parser.enable_interspersed_args() - options, args = parser.parse_args() - - msg = amalgamate_source(source_top_dir=options.top_dir, - target_source_path=options.target_source_path, - header_include_path=options.header_include_path) - if msg: - sys.stderr.write(msg + "\n") - sys.exit(1) - else: - print("Source succesfully amalagated") - -if __name__ == "__main__": - main() diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index f4966a34d..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,35 +0,0 @@ -# This is a comment. - -version: build.{build} - -os: Windows Server 2012 R2 - -clone_folder: c:\projects\jsoncpp - -platform: - - Win32 - - x64 - -configuration: - - Debug - - Release - -# scripts to run before build -before_build: - - echo "Running cmake..." - - cd c:\projects\jsoncpp - - cmake --version - - set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% - - if %PLATFORM% == Win32 cmake . - - if %PLATFORM% == x64 cmake -G "Visual Studio 12 2013 Win64" . - -build: - project: jsoncpp.sln # path to Visual Studio solution or project - -deploy: - provider: GitHub - auth_token: - secure: K2Tp1q8pIZ7rs0Ot24ZMWuwr12Ev6Tc6QkhMjGQxoQG3ng1pXtgPasiJ45IDXGdg - on: - branch: master - appveyor_repo_tag: true diff --git a/dev.makefile b/dev.makefile deleted file mode 100644 index d288b1665..000000000 --- a/dev.makefile +++ /dev/null @@ -1,35 +0,0 @@ -# This is only for jsoncpp developers/contributors. -# We use this to sign releases, generate documentation, etc. -VER?=$(shell cat version) - -default: - @echo "VER=${VER}" -sign: jsoncpp-${VER}.tar.gz - gpg --armor --detach-sign $< - gpg --verify $<.asc - # Then upload .asc to the release. -jsoncpp-%.tar.gz: - curl https://github.com/open-source-parsers/jsoncpp/archive/$*.tar.gz -o $@ -dox: - python doxybuild.py --doxygen=$$(which doxygen) --in doc/web_doxyfile.in - rsync -va --delete dist/doxygen/jsoncpp-api-html-${VER}/ ../jsoncpp-docs/doxygen/ - # Then 'git add -A' and 'git push' in jsoncpp-docs. -build: - mkdir -p build/debug - cd build/debug; cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_SHARED_LIBS=ON -G "Unix Makefiles" ../.. - make -C build/debug - -# Currently, this depends on include/json/version.h generated -# by cmake. -test-amalgamate: - python2.7 amalgamate.py - python3.4 amalgamate.py - cd dist; gcc -I. -c jsoncpp.cpp - -valgrind: - valgrind --error-exitcode=42 --leak-check=full ./build/debug/src/test_lib_json/jsoncpp_test - -clean: - \rm -rf *.gz *.asc dist/ - -.PHONY: build diff --git a/devtools/__init__.py b/devtools/__init__.py deleted file mode 100644 index d18a52168..000000000 --- a/devtools/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2010 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -# module diff --git a/devtools/agent_vmw7.json b/devtools/agent_vmw7.json deleted file mode 100644 index cd7b777fe..000000000 --- a/devtools/agent_vmw7.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "cmake_variants" : [ - {"name": "generator", - "generators": [ - {"generator": [ - "Visual Studio 7 .NET 2003", - "Visual Studio 9 2008", - "Visual Studio 9 2008 Win64", - "Visual Studio 10", - "Visual Studio 10 Win64", - "Visual Studio 11", - "Visual Studio 11 Win64" - ] - }, - {"generator": ["MinGW Makefiles"], - "env_prepend": [{"path": "c:/wut/prg/MinGW/bin"}] - } - ] - }, - {"name": "shared_dll", - "variables": [ - ["BUILD_SHARED_LIBS=true"], - ["BUILD_SHARED_LIBS=false"] - ] - }, - {"name": "build_type", - "build_types": [ - "debug", - "release" - ] - } - ] -} diff --git a/devtools/agent_vmxp.json b/devtools/agent_vmxp.json deleted file mode 100644 index f82a0773a..000000000 --- a/devtools/agent_vmxp.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "cmake_variants" : [ - {"name": "generator", - "generators": [ - {"generator": [ - "Visual Studio 6", - "Visual Studio 7", - "Visual Studio 8 2005" - ] - } - ] - }, - {"name": "shared_dll", - "variables": [ - ["BUILD_SHARED_LIBS=true"], - ["BUILD_SHARED_LIBS=false"] - ] - }, - {"name": "build_type", - "build_types": [ - "debug", - "release" - ] - } - ] -} diff --git a/devtools/antglob.py b/devtools/antglob.py deleted file mode 100644 index c272f6634..000000000 --- a/devtools/antglob.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Copyright 2009 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -from __future__ import print_function -from dircache import listdir -import re -import fnmatch -import os.path - - -# These fnmatch expressions are used by default to prune the directory tree -# while doing the recursive traversal in the glob_impl method of glob function. -prune_dirs = '.git .bzr .hg .svn _MTN _darcs CVS SCCS ' - -# These fnmatch expressions are used by default to exclude files and dirs -# while doing the recursive traversal in the glob_impl method of glob function. -##exclude_pats = prune_pats + '*~ #*# .#* %*% ._* .gitignore .cvsignore vssver.scc .DS_Store'.split() - -# These ant_glob expressions are used by default to exclude files and dirs and also prune the directory tree -# while doing the recursive traversal in the glob_impl method of glob function. -default_excludes = ''' -**/*~ -**/#*# -**/.#* -**/%*% -**/._* -**/CVS -**/CVS/** -**/.cvsignore -**/SCCS -**/SCCS/** -**/vssver.scc -**/.svn -**/.svn/** -**/.git -**/.git/** -**/.gitignore -**/.bzr -**/.bzr/** -**/.hg -**/.hg/** -**/_MTN -**/_MTN/** -**/_darcs -**/_darcs/** -**/.DS_Store ''' - -DIR = 1 -FILE = 2 -DIR_LINK = 4 -FILE_LINK = 8 -LINKS = DIR_LINK | FILE_LINK -ALL_NO_LINK = DIR | FILE -ALL = DIR | FILE | LINKS - -_ANT_RE = re.compile(r'(/\*\*/)|(\*\*/)|(/\*\*)|(\*)|(/)|([^\*/]*)') - -def ant_pattern_to_re(ant_pattern): - """Generates a regular expression from the ant pattern. - Matching convention: - **/a: match 'a', 'dir/a', 'dir1/dir2/a' - a/**/b: match 'a/b', 'a/c/b', 'a/d/c/b' - *.py: match 'script.py' but not 'a/script.py' - """ - rex = ['^'] - next_pos = 0 - sep_rex = r'(?:/|%s)' % re.escape(os.path.sep) -## print 'Converting', ant_pattern - for match in _ANT_RE.finditer(ant_pattern): -## print 'Matched', match.group() -## print match.start(0), next_pos - if match.start(0) != next_pos: - raise ValueError("Invalid ant pattern") - if match.group(1): # /**/ - rex.append(sep_rex + '(?:.*%s)?' % sep_rex) - elif match.group(2): # **/ - rex.append('(?:.*%s)?' % sep_rex) - elif match.group(3): # /** - rex.append(sep_rex + '.*') - elif match.group(4): # * - rex.append('[^/%s]*' % re.escape(os.path.sep)) - elif match.group(5): # / - rex.append(sep_rex) - else: # somepath - rex.append(re.escape(match.group(6))) - next_pos = match.end() - rex.append('$') - return re.compile(''.join(rex)) - -def _as_list(l): - if isinstance(l, basestring): - return l.split() - return l - -def glob(dir_path, - includes = '**/*', - excludes = default_excludes, - entry_type = FILE, - prune_dirs = prune_dirs, - max_depth = 25): - include_filter = [ant_pattern_to_re(p) for p in _as_list(includes)] - exclude_filter = [ant_pattern_to_re(p) for p in _as_list(excludes)] - prune_dirs = [p.replace('/',os.path.sep) for p in _as_list(prune_dirs)] - dir_path = dir_path.replace('/',os.path.sep) - entry_type_filter = entry_type - - def is_pruned_dir(dir_name): - for pattern in prune_dirs: - if fnmatch.fnmatch(dir_name, pattern): - return True - return False - - def apply_filter(full_path, filter_rexs): - """Return True if at least one of the filter regular expression match full_path.""" - for rex in filter_rexs: - if rex.match(full_path): - return True - return False - - def glob_impl(root_dir_path): - child_dirs = [root_dir_path] - while child_dirs: - dir_path = child_dirs.pop() - for entry in listdir(dir_path): - full_path = os.path.join(dir_path, entry) -## print 'Testing:', full_path, - is_dir = os.path.isdir(full_path) - if is_dir and not is_pruned_dir(entry): # explore child directory ? -## print '===> marked for recursion', - child_dirs.append(full_path) - included = apply_filter(full_path, include_filter) - rejected = apply_filter(full_path, exclude_filter) - if not included or rejected: # do not include entry ? -## print '=> not included or rejected' - continue - link = os.path.islink(full_path) - is_file = os.path.isfile(full_path) - if not is_file and not is_dir: -## print '=> unknown entry type' - continue - if link: - entry_type = is_file and FILE_LINK or DIR_LINK - else: - entry_type = is_file and FILE or DIR -## print '=> type: %d' % entry_type, - if (entry_type & entry_type_filter) != 0: -## print ' => KEEP' - yield os.path.join(dir_path, entry) -## else: -## print ' => TYPE REJECTED' - return list(glob_impl(dir_path)) - - -if __name__ == "__main__": - import unittest - - class AntPatternToRETest(unittest.TestCase): -## def test_conversion(self): -## self.assertEqual('^somepath$', ant_pattern_to_re('somepath').pattern) - - def test_matching(self): - test_cases = [ ('path', - ['path'], - ['somepath', 'pathsuffix', '/path', '/path']), - ('*.py', - ['source.py', 'source.ext.py', '.py'], - ['path/source.py', '/.py', 'dir.py/z', 'z.pyc', 'z.c']), - ('**/path', - ['path', '/path', '/a/path', 'c:/a/path', '/a/b/path', '//a/path', '/a/path/b/path'], - ['path/', 'a/path/b', 'dir.py/z', 'somepath', 'pathsuffix', 'a/somepath']), - ('path/**', - ['path/a', 'path/path/a', 'path//'], - ['path', 'somepath/a', 'a/path', 'a/path/a', 'pathsuffix/a']), - ('/**/path', - ['/path', '/a/path', '/a/b/path/path', '/path/path'], - ['path', 'path/', 'a/path', '/pathsuffix', '/somepath']), - ('a/b', - ['a/b'], - ['somea/b', 'a/bsuffix', 'a/b/c']), - ('**/*.py', - ['script.py', 'src/script.py', 'a/b/script.py', '/a/b/script.py'], - ['script.pyc', 'script.pyo', 'a.py/b']), - ('src/**/*.py', - ['src/a.py', 'src/dir/a.py'], - ['a/src/a.py', '/src/a.py']), - ] - for ant_pattern, accepted_matches, rejected_matches in list(test_cases): - def local_path(paths): - return [ p.replace('/',os.path.sep) for p in paths ] - test_cases.append((ant_pattern, local_path(accepted_matches), local_path(rejected_matches))) - for ant_pattern, accepted_matches, rejected_matches in test_cases: - rex = ant_pattern_to_re(ant_pattern) - print('ant_pattern:', ant_pattern, ' => ', rex.pattern) - for accepted_match in accepted_matches: - print('Accepted?:', accepted_match) - self.assertTrue(rex.match(accepted_match) is not None) - for rejected_match in rejected_matches: - print('Rejected?:', rejected_match) - self.assertTrue(rex.match(rejected_match) is None) - - unittest.main() diff --git a/devtools/batchbuild.py b/devtools/batchbuild.py deleted file mode 100644 index 0eb0690e8..000000000 --- a/devtools/batchbuild.py +++ /dev/null @@ -1,278 +0,0 @@ -from __future__ import print_function -import collections -import itertools -import json -import os -import os.path -import re -import shutil -import string -import subprocess -import sys -import cgi - -class BuildDesc: - def __init__(self, prepend_envs=None, variables=None, build_type=None, generator=None): - self.prepend_envs = prepend_envs or [] # [ { "var": "value" } ] - self.variables = variables or [] - self.build_type = build_type - self.generator = generator - - def merged_with(self, build_desc): - """Returns a new BuildDesc by merging field content. - Prefer build_desc fields to self fields for single valued field. - """ - return BuildDesc(self.prepend_envs + build_desc.prepend_envs, - self.variables + build_desc.variables, - build_desc.build_type or self.build_type, - build_desc.generator or self.generator) - - def env(self): - environ = os.environ.copy() - for values_by_name in self.prepend_envs: - for var, value in list(values_by_name.items()): - var = var.upper() - if type(value) is unicode: - value = value.encode(sys.getdefaultencoding()) - if var in environ: - environ[var] = value + os.pathsep + environ[var] - else: - environ[var] = value - return environ - - def cmake_args(self): - args = ["-D%s" % var for var in self.variables] - # skip build type for Visual Studio solution as it cause warning - if self.build_type and 'Visual' not in self.generator: - args.append("-DCMAKE_BUILD_TYPE=%s" % self.build_type) - if self.generator: - args.extend(['-G', self.generator]) - return args - - def __repr__(self): - return "BuildDesc(%s, build_type=%s)" % (" ".join(self.cmake_args()), self.build_type) - -class BuildData: - def __init__(self, desc, work_dir, source_dir): - self.desc = desc - self.work_dir = work_dir - self.source_dir = source_dir - self.cmake_log_path = os.path.join(work_dir, 'batchbuild_cmake.log') - self.build_log_path = os.path.join(work_dir, 'batchbuild_build.log') - self.cmake_succeeded = False - self.build_succeeded = False - - def execute_build(self): - print('Build %s' % self.desc) - self._make_new_work_dir() - self.cmake_succeeded = self._generate_makefiles() - if self.cmake_succeeded: - self.build_succeeded = self._build_using_makefiles() - return self.build_succeeded - - def _generate_makefiles(self): - print(' Generating makefiles: ', end=' ') - cmd = ['cmake'] + self.desc.cmake_args() + [os.path.abspath(self.source_dir)] - succeeded = self._execute_build_subprocess(cmd, self.desc.env(), self.cmake_log_path) - print('done' if succeeded else 'FAILED') - return succeeded - - def _build_using_makefiles(self): - print(' Building:', end=' ') - cmd = ['cmake', '--build', self.work_dir] - if self.desc.build_type: - cmd += ['--config', self.desc.build_type] - succeeded = self._execute_build_subprocess(cmd, self.desc.env(), self.build_log_path) - print('done' if succeeded else 'FAILED') - return succeeded - - def _execute_build_subprocess(self, cmd, env, log_path): - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.work_dir, - env=env) - stdout, _ = process.communicate() - succeeded = (process.returncode == 0) - with open(log_path, 'wb') as flog: - log = ' '.join(cmd) + '\n' + stdout + '\nExit code: %r\n' % process.returncode - flog.write(fix_eol(log)) - return succeeded - - def _make_new_work_dir(self): - if os.path.isdir(self.work_dir): - print(' Removing work directory', self.work_dir) - shutil.rmtree(self.work_dir, ignore_errors=True) - if not os.path.isdir(self.work_dir): - os.makedirs(self.work_dir) - -def fix_eol(stdout): - """Fixes wrong EOL produced by cmake --build on Windows (\r\r\n instead of \r\n). - """ - return re.sub('\r*\n', os.linesep, stdout) - -def load_build_variants_from_config(config_path): - with open(config_path, 'rb') as fconfig: - data = json.load(fconfig) - variants = data[ 'cmake_variants' ] - build_descs_by_axis = collections.defaultdict(list) - for axis in variants: - axis_name = axis["name"] - build_descs = [] - if "generators" in axis: - for generator_data in axis["generators"]: - for generator in generator_data["generator"]: - build_desc = BuildDesc(generator=generator, - prepend_envs=generator_data.get("env_prepend")) - build_descs.append(build_desc) - elif "variables" in axis: - for variables in axis["variables"]: - build_desc = BuildDesc(variables=variables) - build_descs.append(build_desc) - elif "build_types" in axis: - for build_type in axis["build_types"]: - build_desc = BuildDesc(build_type=build_type) - build_descs.append(build_desc) - build_descs_by_axis[axis_name].extend(build_descs) - return build_descs_by_axis - -def generate_build_variants(build_descs_by_axis): - """Returns a list of BuildDesc generated for the partial BuildDesc for each axis.""" - axis_names = list(build_descs_by_axis.keys()) - build_descs = [] - for axis_name, axis_build_descs in list(build_descs_by_axis.items()): - if len(build_descs): - # for each existing build_desc and each axis build desc, create a new build_desc - new_build_descs = [] - for prototype_build_desc, axis_build_desc in itertools.product(build_descs, axis_build_descs): - new_build_descs.append(prototype_build_desc.merged_with(axis_build_desc)) - build_descs = new_build_descs - else: - build_descs = axis_build_descs - return build_descs - -HTML_TEMPLATE = string.Template(''' - - $title - - - - - - - - $th_vars - - - - $th_build_types - - - -$tr_builds - -
Variables
Build type
-''') - -def generate_html_report(html_report_path, builds): - report_dir = os.path.dirname(html_report_path) - # Vertical axis: generator - # Horizontal: variables, then build_type - builds_by_generator = collections.defaultdict(list) - variables = set() - build_types_by_variable = collections.defaultdict(set) - build_by_pos_key = {} # { (generator, var_key, build_type): build } - for build in builds: - builds_by_generator[build.desc.generator].append(build) - var_key = tuple(sorted(build.desc.variables)) - variables.add(var_key) - build_types_by_variable[var_key].add(build.desc.build_type) - pos_key = (build.desc.generator, var_key, build.desc.build_type) - build_by_pos_key[pos_key] = build - variables = sorted(variables) - th_vars = [] - th_build_types = [] - for variable in variables: - build_types = sorted(build_types_by_variable[variable]) - nb_build_type = len(build_types_by_variable[variable]) - th_vars.append('%s' % (nb_build_type, cgi.escape(' '.join(variable)))) - for build_type in build_types: - th_build_types.append('%s' % cgi.escape(build_type)) - tr_builds = [] - for generator in sorted(builds_by_generator): - tds = [ '%s\n' % cgi.escape(generator) ] - for variable in variables: - build_types = sorted(build_types_by_variable[variable]) - for build_type in build_types: - pos_key = (generator, variable, build_type) - build = build_by_pos_key.get(pos_key) - if build: - cmake_status = 'ok' if build.cmake_succeeded else 'FAILED' - build_status = 'ok' if build.build_succeeded else 'FAILED' - cmake_log_url = os.path.relpath(build.cmake_log_path, report_dir) - build_log_url = os.path.relpath(build.build_log_path, report_dir) - td = 'CMake: %s' % ( build_status.lower(), cmake_log_url, cmake_status.lower(), cmake_status) - if build.cmake_succeeded: - td += '
Build: %s' % ( build_log_url, build_status.lower(), build_status) - td += '' - else: - td = '' - tds.append(td) - tr_builds.append('%s' % '\n'.join(tds)) - html = HTML_TEMPLATE.substitute( title='Batch build report', - th_vars=' '.join(th_vars), - th_build_types=' '.join(th_build_types), - tr_builds='\n'.join(tr_builds)) - with open(html_report_path, 'wt') as fhtml: - fhtml.write(html) - print('HTML report generated in:', html_report_path) - -def main(): - usage = r"""%prog WORK_DIR SOURCE_DIR CONFIG_JSON_PATH [CONFIG2_JSON_PATH...] -Build a given CMake based project located in SOURCE_DIR with multiple generators/options.dry_run -as described in CONFIG_JSON_PATH building in WORK_DIR. - -Example of call: -python devtools\batchbuild.py e:\buildbots\jsoncpp\build . devtools\agent_vmw7.json -""" - from optparse import OptionParser - parser = OptionParser(usage=usage) - parser.allow_interspersed_args = True -# parser.add_option('-v', '--verbose', dest="verbose", action='http://github.com/store_true', -# help="""Be verbose.""") - parser.enable_interspersed_args() - options, args = parser.parse_args() - if len(args) < 3: - parser.error("Missing one of WORK_DIR SOURCE_DIR CONFIG_JSON_PATH.") - work_dir = args[0] - source_dir = args[1].rstrip('/\\') - config_paths = args[2:] - for config_path in config_paths: - if not os.path.isfile(config_path): - parser.error("Can not read: %r" % config_path) - - # generate build variants - build_descs = [] - for config_path in config_paths: - build_descs_by_axis = load_build_variants_from_config(config_path) - build_descs.extend(generate_build_variants(build_descs_by_axis)) - print('Build variants (%d):' % len(build_descs)) - # assign build directory for each variant - if not os.path.isdir(work_dir): - os.makedirs(work_dir) - builds = [] - with open(os.path.join(work_dir, 'matrix-dir-map.txt'), 'wt') as fmatrixmap: - for index, build_desc in enumerate(build_descs): - build_desc_work_dir = os.path.join(work_dir, '%03d' % (index+1)) - builds.append(BuildData(build_desc, build_desc_work_dir, source_dir)) - fmatrixmap.write('%s: %s\n' % (build_desc_work_dir, build_desc)) - for build in builds: - build.execute_build() - html_report_path = os.path.join(work_dir, 'batchbuild-report.html') - generate_html_report(html_report_path, builds) - print('Done') - - -if __name__ == '__main__': - main() - diff --git a/devtools/fixeol.py b/devtools/fixeol.py deleted file mode 100644 index b55e14616..000000000 --- a/devtools/fixeol.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2010 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -from __future__ import print_function -import os.path -import sys - -def fix_source_eol(path, is_dry_run = True, verbose = True, eol = '\n'): - """Makes sure that all sources have the specified eol sequence (default: unix).""" - if not os.path.isfile(path): - raise ValueError('Path "%s" is not a file' % path) - try: - f = open(path, 'rb') - except IOError as msg: - print("%s: I/O Error: %s" % (file, str(msg)), file=sys.stderr) - return False - try: - raw_lines = f.readlines() - finally: - f.close() - fixed_lines = [line.rstrip('\r\n') + eol for line in raw_lines] - if raw_lines != fixed_lines: - print('%s =>' % path, end=' ') - if not is_dry_run: - f = open(path, "wb") - try: - f.writelines(fixed_lines) - finally: - f.close() - if verbose: - print(is_dry_run and ' NEED FIX' or ' FIXED') - return True -## -## -## -##def _do_fix(is_dry_run = True): -## from waftools import antglob -## python_sources = antglob.glob('.', -## includes = '**/*.py **/wscript **/wscript_build', -## excludes = antglob.default_excludes + './waf.py', -## prune_dirs = antglob.prune_dirs + 'waf-* ./build') -## for path in python_sources: -## _fix_python_source(path, is_dry_run) -## -## cpp_sources = antglob.glob('.', -## includes = '**/*.cpp **/*.h **/*.inl', -## prune_dirs = antglob.prune_dirs + 'waf-* ./build') -## for path in cpp_sources: -## _fix_source_eol(path, is_dry_run) -## -## -##def dry_fix(context): -## _do_fix(is_dry_run = True) -## -##def fix(context): -## _do_fix(is_dry_run = False) -## -##def shutdown(): -## pass -## -##def check(context): -## # Unit tests are run when "check" target is used -## ut = UnitTest.unit_test() -## ut.change_to_testfile_dir = True -## ut.want_to_see_test_output = True -## ut.want_to_see_test_error = True -## ut.run() -## ut.print_results() diff --git a/devtools/licenseupdater.py b/devtools/licenseupdater.py deleted file mode 100644 index 6f823618f..000000000 --- a/devtools/licenseupdater.py +++ /dev/null @@ -1,94 +0,0 @@ -"""Updates the license text in source file. -""" -from __future__ import print_function - -# An existing license is found if the file starts with the string below, -# and ends with the first blank line. -LICENSE_BEGIN = "// Copyright " - -BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -""".replace('\r\n','\n') - -def update_license(path, dry_run, show_diff): - """Update the license statement in the specified file. - Parameters: - path: path of the C++ source file to update. - dry_run: if True, just print the path of the file that would be updated, - but don't change it. - show_diff: if True, print the path of the file that would be modified, - as well as the change made to the file. - """ - with open(path, 'rt') as fin: - original_text = fin.read().replace('\r\n','\n') - newline = fin.newlines and fin.newlines[0] or '\n' - if not original_text.startswith(LICENSE_BEGIN): - # No existing license found => prepend it - new_text = BRIEF_LICENSE + original_text - else: - license_end_index = original_text.index('\n\n') # search first blank line - new_text = BRIEF_LICENSE + original_text[license_end_index+2:] - if original_text != new_text: - if not dry_run: - with open(path, 'wb') as fout: - fout.write(new_text.replace('\n', newline)) - print('Updated', path) - if show_diff: - import difflib - print('\n'.join(difflib.unified_diff(original_text.split('\n'), - new_text.split('\n')))) - return True - return False - -def update_license_in_source_directories(source_dirs, dry_run, show_diff): - """Updates license text in C++ source files found in directory source_dirs. - Parameters: - source_dirs: list of directory to scan for C++ sources. Directories are - scanned recursively. - dry_run: if True, just print the path of the file that would be updated, - but don't change it. - show_diff: if True, print the path of the file that would be modified, - as well as the change made to the file. - """ - from devtools import antglob - prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist' - for source_dir in source_dirs: - cpp_sources = antglob.glob(source_dir, - includes = '''**/*.h **/*.cpp **/*.inl''', - prune_dirs = prune_dirs) - for source in cpp_sources: - update_license(source, dry_run, show_diff) - -def main(): - usage = """%prog DIR [DIR2...] -Updates license text in sources of the project in source files found -in the directory specified on the command-line. - -Example of call: -python devtools\licenseupdater.py include src -n --diff -=> Show change that would be made to the sources. - -python devtools\licenseupdater.py include src -=> Update license statement on all sources in directories include/ and src/. -""" - from optparse import OptionParser - parser = OptionParser(usage=usage) - parser.allow_interspersed_args = False - parser.add_option('-n', '--dry-run', dest="dry_run", action='http://github.com/store_true', default=False, - help="""Only show what files are updated, do not update the files""") - parser.add_option('--diff', dest="show_diff", action='http://github.com/store_true', default=False, - help="""On update, show change made to the file.""") - parser.enable_interspersed_args() - options, args = parser.parse_args() - update_license_in_source_directories(args, options.dry_run, options.show_diff) - print('Done') - -if __name__ == '__main__': - import sys - import os.path - sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - main() - diff --git a/devtools/tarball.py b/devtools/tarball.py deleted file mode 100644 index 2e72717ab..000000000 --- a/devtools/tarball.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2010 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -from contextlib import closing -import os -import tarfile - -TARGZ_DEFAULT_COMPRESSION_LEVEL = 9 - -def make_tarball(tarball_path, sources, base_dir, prefix_dir=''): - """Parameters: - tarball_path: output path of the .tar.gz file - sources: list of sources to include in the tarball, relative to the current directory - base_dir: if a source file is in a sub-directory of base_dir, then base_dir is stripped - from path in the tarball. - prefix_dir: all files stored in the tarball be sub-directory of prefix_dir. Set to '' - to make them child of root. - """ - base_dir = os.path.normpath(os.path.abspath(base_dir)) - def archive_name(path): - """Makes path relative to base_dir.""" - path = os.path.normpath(os.path.abspath(path)) - common_path = os.path.commonprefix((base_dir, path)) - archive_name = path[len(common_path):] - if os.path.isabs(archive_name): - archive_name = archive_name[1:] - return os.path.join(prefix_dir, archive_name) - def visit(tar, dirname, names): - for name in names: - path = os.path.join(dirname, name) - if os.path.isfile(path): - path_in_tar = archive_name(path) - tar.add(path, path_in_tar) - compression = TARGZ_DEFAULT_COMPRESSION_LEVEL - with closing(tarfile.TarFile.open(tarball_path, 'w:gz', - compresslevel=compression)) as tar: - for source in sources: - source_path = source - if os.path.isdir(source): - for dirpath, dirnames, filenames in os.walk(source_path): - visit(tar, dirpath, filenames) - else: - path_in_tar = archive_name(source_path) - tar.add(source_path, path_in_tar) # filename, arcname - -def decompress(tarball_path, base_dir): - """Decompress the gzipped tarball into directory base_dir. - """ - with closing(tarfile.TarFile.open(tarball_path)) as tar: - tar.extractall(base_dir) diff --git a/doxybuild.py b/doxybuild.py deleted file mode 100644 index f18c9c069..000000000 --- a/doxybuild.py +++ /dev/null @@ -1,189 +0,0 @@ -"""Script to generate doxygen documentation. -""" -from __future__ import print_function -from __future__ import unicode_literals -from devtools import tarball -from contextlib import contextmanager -import subprocess -import traceback -import re -import os -import sys -import shutil - -@contextmanager -def cd(newdir): - """ - http://stackoverflow.com/questions/431684/how-do-i-cd-in-python - """ - prevdir = os.getcwd() - os.chdir(newdir) - try: - yield - finally: - os.chdir(prevdir) - -def find_program(*filenames): - """find a program in folders path_lst, and sets env[var] - @param filenames: a list of possible names of the program to search for - @return: the full path of the filename if found, or '' if filename could not be found -""" - paths = os.environ.get('PATH', '').split(os.pathsep) - suffixes = ('win32' in sys.platform) and '.exe .com .bat .cmd' or '' - for filename in filenames: - for name in [filename+ext for ext in suffixes.split(' ')]: - for directory in paths: - full_path = os.path.join(directory, name) - if os.path.isfile(full_path): - return full_path - return '' - -def do_subst_in_file(targetfile, sourcefile, dict): - """Replace all instances of the keys of dict with their values. - For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'}, - then all instances of %VERSION% in the file will be replaced with 1.2345 etc. - """ - with open(sourcefile, 'r') as f: - contents = f.read() - for (k,v) in list(dict.items()): - v = v.replace('\\','\\\\') - contents = re.sub(k, v, contents) - with open(targetfile, 'w') as f: - f.write(contents) - -def getstatusoutput(cmd): - """cmd is a list. - """ - try: - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - output, _ = process.communicate() - status = process.returncode - except: - status = -1 - output = traceback.format_exc() - return status, output - -def run_cmd(cmd, silent=False): - """Raise exception on failure. - """ - info = 'Running: %r in %r' %(' '.join(cmd), os.getcwd()) - print(info) - sys.stdout.flush() - if silent: - status, output = getstatusoutput(cmd) - else: - status, output = subprocess.call(cmd), '' - if status: - msg = 'Error while %s ...\n\terror=%d, output="""%s"""' %(info, status, output) - raise Exception(msg) - -def assert_is_exe(path): - if not path: - raise Exception('path is empty.') - if not os.path.isfile(path): - raise Exception('%r is not a file.' %path) - if not os.access(path, os.X_OK): - raise Exception('%r is not executable by this user.' %path) - -def run_doxygen(doxygen_path, config_file, working_dir, is_silent): - assert_is_exe(doxygen_path) - config_file = os.path.abspath(config_file) - with cd(working_dir): - cmd = [doxygen_path, config_file] - run_cmd(cmd, is_silent) - -def build_doc(options, make_release=False): - if make_release: - options.make_tarball = True - options.with_dot = True - options.with_html_help = True - options.with_uml_look = True - options.open = False - options.silent = True - - version = open('version', 'rt').read().strip() - output_dir = 'dist/doxygen' # relative to doc/doxyfile location. - if not os.path.isdir(output_dir): - os.makedirs(output_dir) - top_dir = os.path.abspath('.') - html_output_dirname = 'jsoncpp-api-html-' + version - tarball_path = os.path.join('dist', html_output_dirname + '.tar.gz') - warning_log_path = os.path.join(output_dir, '../jsoncpp-doxygen-warning.log') - html_output_path = os.path.join(output_dir, html_output_dirname) - def yesno(bool): - return bool and 'YES' or 'NO' - subst_keys = { - '%JSONCPP_VERSION%': version, - '%DOC_TOPDIR%': '', - '%TOPDIR%': top_dir, - '%HTML_OUTPUT%': os.path.join('..', output_dir, html_output_dirname), - '%HAVE_DOT%': yesno(options.with_dot), - '%DOT_PATH%': os.path.split(options.dot_path)[0], - '%HTML_HELP%': yesno(options.with_html_help), - '%UML_LOOK%': yesno(options.with_uml_look), - '%WARNING_LOG_PATH%': os.path.join('..', warning_log_path) - } - - if os.path.isdir(output_dir): - print('Deleting directory:', output_dir) - shutil.rmtree(output_dir) - if not os.path.isdir(output_dir): - os.makedirs(output_dir) - - do_subst_in_file('doc/doxyfile', options.doxyfile_input_path, subst_keys) - run_doxygen(options.doxygen_path, 'doc/doxyfile', 'doc', is_silent=options.silent) - if not options.silent: - print(open(warning_log_path, 'r').read()) - index_path = os.path.abspath(os.path.join('doc', subst_keys['%HTML_OUTPUT%'], 'index.html')) - print('Generated documentation can be found in:') - print(index_path) - if options.open: - import webbrowser - webbrowser.open('file://' + index_path) - if options.make_tarball: - print('Generating doc tarball to', tarball_path) - tarball_sources = [ - output_dir, - 'README.md', - 'LICENSE', - 'NEWS.txt', - 'version' - ] - tarball_basedir = os.path.join(output_dir, html_output_dirname) - tarball.make_tarball(tarball_path, tarball_sources, tarball_basedir, html_output_dirname) - return tarball_path, html_output_dirname - -def main(): - usage = """%prog - Generates doxygen documentation in build/doxygen. - Optionaly makes a tarball of the documentation to dist/. - - Must be started in the project top directory. - """ - from optparse import OptionParser - parser = OptionParser(usage=usage) - parser.allow_interspersed_args = False - parser.add_option('--with-dot', dest="with_dot", action='http://github.com/store_true', default=False, - help="""Enable usage of DOT to generate collaboration diagram""") - parser.add_option('--dot', dest="dot_path", action='http://github.com/store', default=find_program('dot'), - help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""") - parser.add_option('--doxygen', dest="doxygen_path", action='http://github.com/store', default=find_program('doxygen'), - help="""Path to Doxygen tool. [Default: %default]""") - parser.add_option('--in', dest="doxyfile_input_path", action='http://github.com/store', default='doc/doxyfile.in', - help="""Path to doxygen inputs. [Default: %default]""") - parser.add_option('--with-html-help', dest="with_html_help", action='http://github.com/store_true', default=False, - help="""Enable generation of Microsoft HTML HELP""") - parser.add_option('--no-uml-look', dest="with_uml_look", action='http://github.com/store_false', default=True, - help="""Generates DOT graph without UML look [Default: False]""") - parser.add_option('--open', dest="open", action='http://github.com/store_true', default=False, - help="""Open the HTML index in the web browser after generation""") - parser.add_option('--tarball', dest="make_tarball", action='http://github.com/store_true', default=False, - help="""Generates a tarball of the documentation in dist/ directory""") - parser.add_option('-s', '--silent', dest="silent", action='http://github.com/store_true', default=False, - help="""Hides doxygen output""") - parser.enable_interspersed_args() - options, args = parser.parse_args() - build_doc(options) - -if __name__ == '__main__': - main() diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt deleted file mode 100644 index 7dde10d6f..000000000 --- a/include/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -FILE(GLOB INCLUDE_FILES "json/*.h") -INSTALL(FILES ${INCLUDE_FILES} DESTINATION ${INCLUDE_INSTALL_DIR}/json) diff --git a/include/json/assertions.h b/include/json/assertions.h deleted file mode 100644 index fbec7ae00..000000000 --- a/include/json/assertions.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED -#define CPPTL_JSON_ASSERTIONS_H_INCLUDED - -#include -#include - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -/** It should not be possible for a maliciously designed file to - * cause an abort() or seg-fault, so these macros are used only - * for pre-condition violations and internal logic errors. - */ -#if JSON_USE_EXCEPTION - -// @todo <= add detail about condition in exception -# define JSON_ASSERT(condition) \ - {if (!(condition)) {Json::throwLogicError( "assert json failed" );}} - -# define JSON_FAIL_MESSAGE(message) \ - { \ - std::ostringstream oss; oss << message; \ - Json::throwLogicError(oss.str()); \ - abort(); \ - } - -#else // JSON_USE_EXCEPTION - -# define JSON_ASSERT(condition) assert(condition) - -// The call to assert() will show the failure message in debug builds. In -// release builds we abort, for a core-dump or debugger. -# define JSON_FAIL_MESSAGE(message) \ - { \ - std::ostringstream oss; oss << message; \ - assert(false && oss.str().c_str()); \ - abort(); \ - } - - -#endif - -#define JSON_ASSERT_MESSAGE(condition, message) \ - if (!(condition)) { \ - JSON_FAIL_MESSAGE(message); \ - } - -#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED diff --git a/include/json/autolink.h b/include/json/autolink.h deleted file mode 100644 index 6fcc8afac..000000000 --- a/include/json/autolink.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_AUTOLINK_H_INCLUDED -#define JSON_AUTOLINK_H_INCLUDED - -#include "config.h" - -#ifdef JSON_IN_CPPTL -#include -#endif - -#if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \ - !defined(JSON_IN_CPPTL) -#define CPPTL_AUTOLINK_NAME "json" -#undef CPPTL_AUTOLINK_DLL -#ifdef JSON_DLL -#define CPPTL_AUTOLINK_DLL -#endif -#include "autolink.h" -#endif - -#endif // JSON_AUTOLINK_H_INCLUDED diff --git a/include/json/config.h b/include/json/config.h deleted file mode 100644 index 0dcd8ae60..000000000 --- a/include/json/config.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -#define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 - -// If non-zero, the library uses exceptions to report bad input instead of C -// assertion macros. The default is to use exceptions. -#ifndef JSON_USE_EXCEPTION -#define JSON_USE_EXCEPTION 1 -#endif - -/// If defined, indicates that the source file is amalgated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. -// #define JSON_IS_AMALGAMATION - -#ifdef JSON_IN_CPPTL -#include -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) -#if defined(_MSC_VER) -#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. -// #define JSON_NO_INT64 1 - -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 -// Microsoft Visual Studio 6 only support conversion from __int64 to double -// (no conversion from unsigned __int64). -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' -// characters in the debug information) -// All projects I've ever seen with VS6 were using this globally (not bothering -// with pragma push/pop). -#pragma warning(disable : 4786) -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 - -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 -/// Indicates that the following function is deprecated. -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#elif defined(__clang__) && defined(__has_feature) -#if __has_feature(attribute_deprecated_with_message) -#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) -#endif -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) -#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) -#elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) -#endif - -#if !defined(JSONCPP_DEPRECATED) -#define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -namespace Json { -typedef int Int; -typedef unsigned int UInt; -#if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; -#undef JSON_HAS_INT64 -#else // if defined(JSON_NO_INT64) -// For Microsoft Visual use specific types as long long is not supported -#if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else // if defined(_MSC_VER) // Other platforms, use long long -typedef long long int Int64; -typedef unsigned long long int UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; -#define JSON_HAS_INT64 -#endif // if defined(JSON_NO_INT64) -} // end namespace Json - -#endif // JSON_CONFIG_H_INCLUDED diff --git a/include/json/features.h b/include/json/features.h deleted file mode 100644 index 1bb7bb614..000000000 --- a/include/json/features.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -#define CPPTL_JSON_FEATURES_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -/** \brief Configuration passed to reader and writer. - * This configuration object can be used to force the Reader or Writer - * to behave in a standard conforming way. - */ -class JSON_API Features { -public: - /** \brief A configuration that allows all features and assumes all strings - * are UTF-8. - * - C & C++ comments are allowed - * - Root object can be any JSON value - * - Assumes Value strings are encoded in UTF-8 - */ - static Features all(); - - /** \brief A configuration that is strictly compatible with the JSON - * specification. - * - Comments are forbidden. - * - Root object must be either an array or an object value. - * - Assumes Value strings are encoded in UTF-8 - */ - static Features strictMode(); - - /** \brief Initialize the configuration like JsonConfig::allFeatures; - */ - Features(); - - /// \c true if comments are allowed. Default: \c true. - bool allowComments_; - - /// \c true if root must be either an array or an object value. Default: \c - /// false. - bool strictRoot_; - - /// \c true if dropped null placeholders are allowed. Default: \c false. - bool allowDroppedNullPlaceholders_; - - /// \c true if numeric object key are allowed. Default: \c false. - bool allowNumericKeys_; -}; - -} // namespace Json - -#endif // CPPTL_JSON_FEATURES_H_INCLUDED diff --git a/include/json/forwards.h b/include/json/forwards.h deleted file mode 100644 index ccfe09abf..000000000 --- a/include/json/forwards.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -#define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// writer.h -class FastWriter; -class StyledWriter; - -// reader.h -class Reader; - -// features.h -class Features; - -// value.h -typedef unsigned int ArrayIndex; -class StaticString; -class Path; -class PathArgument; -class Value; -class ValueIteratorBase; -class ValueIterator; -class ValueConstIterator; - -} // namespace Json - -#endif // JSON_FORWARDS_H_INCLUDED diff --git a/include/json/json.h b/include/json/json.h deleted file mode 100644 index 8f10ac2bf..000000000 --- a/include/json/json.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_JSON_H_INCLUDED -#define JSON_JSON_H_INCLUDED - -#include "autolink.h" -#include "value.h" -#include "reader.h" -#include "writer.h" -#include "features.h" - -#endif // JSON_JSON_H_INCLUDED diff --git a/include/json/reader.h b/include/json/reader.h deleted file mode 100644 index c8ff747e4..000000000 --- a/include/json/reader.h +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_READER_H_INCLUDED -#define CPPTL_JSON_READER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "features.h" -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -namespace Json { - -/** \brief Unserialize a JSON document into a - *Value. - * - * \deprecated Use CharReader and CharReaderBuilder. - */ -class JSON_API Reader { -public: - typedef char Char; - typedef const Char* Location; - - /** \brief An error tagged with where in the JSON text it was encountered. - * - * The offsets give the [start, limit) range of bytes within the text. Note - * that this is bytes, not codepoints. - * - */ - struct StructuredError { - 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 JSON - * 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 JSON - 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 getStructuredErrors() const; - - /** \brief Add a semantic error message. - * \param value JSON Value location associated with the error - * \param message The error message. - * \return \c true if the error was successfully added, \c false if the - * Value offset exceeds the document size. - */ - bool pushError(const Value& value, const std::string& message); - - /** \brief Add a semantic error message with extra context. - * \param value JSON Value location associated with the error - * \param message The error message. - * \param extra Additional JSON Value location to contextualize the error - * \return \c true if the error was successfully added, \c false if either - * Value offset exceeds the document size. - */ - bool pushError(const Value& value, const std::string& message, const Value& extra); - - /** \brief Return whether there are any errors. - * \return \c true if there are no errors to report \c false if - * errors have occurred. - */ - bool good() const; - -private: - enum TokenType { - 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 Errors; - - 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 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_; -}; // Reader - -/** Interface for reading JSON from a char array. - */ -class JSON_API CharReader { -public: - virtual ~CharReader() {} - /** \brief Read a Value from a JSON - document. - * The document must be a UTF-8 encoded string containing the document to read. - * - * \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 errs [out] Formatted error messages (if not NULL) - * a user friendly string that lists errors in the parsed - * document. - * \return \c true if the document was successfully parsed, \c false if an - error occurred. - */ - virtual bool parse( - char const* beginDoc, char const* endDoc, - Value* root, std::string* errs) = 0; - - class Factory { - public: - virtual ~Factory() {} - /** \brief Allocate a CharReader via operator new(). - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - virtual CharReader* newCharReader() const = 0; - }; // Factory -}; // CharReader - -/** \brief Build a CharReader implementation. - -Usage: -\code - using namespace Json; - CharReaderBuilder builder; - builder["collectComments"] = false; - Value value; - std::string errs; - bool ok = parseFromStream(builder, std::cin, &value, &errs); -\endcode -*/ -class JSON_API CharReaderBuilder : public CharReader::Factory { -public: - // Note: We use a Json::Value so that we can add data-members to this class - // without a major version bump. - /** Configuration of this builder. - These are case-sensitive. - Available settings (case-sensitive): - - `"collectComments": false or true` - - true to collect comment and allow writing them - back during serialization, false to discard comments. - This parameter is ignored if allowComments is false. - - `"allowComments": false or true` - - true if comments are allowed. - - `"strictRoot": false or true` - - true if root must be either an array or an object value - - `"allowDroppedNullPlaceholders": false or true` - - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) - - `"allowNumericKeys": false or true` - - true if numeric object keys are allowed. - - `"allowSingleQuotes": false or true` - - true if '' are allowed for strings (both keys and values) - - `"stackLimit": integer` - - Exceeding stackLimit (recursive depth of `readValue()`) will - cause an exception. - - This is a security issue (seg-faults caused by deeply nested JSON), - so the default is low. - - `"failIfExtra": false or true` - - If true, `parse()` returns false when extra non-whitespace trails - the JSON value in the input string. - - `"rejectDupKeys": false or true` - - If true, `parse()` returns false when a key is duplicated within an object. - - You can examine 'settings_` yourself - to see the defaults. You can also write and read them just like any - JSON Value. - \sa setDefaults() - */ - Json::Value settings_; - - CharReaderBuilder(); - virtual ~CharReaderBuilder(); - - virtual CharReader* newCharReader() const; - - /** \return true if 'settings' are legal and consistent; - * otherwise, indicate bad settings via 'invalid'. - */ - bool validate(Json::Value* invalid) const; - - /** A simple way to update a specific setting. - */ - Value& operator[](std::string key); - - /** Called by ctor, but you can use this to reset settings_. - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults - */ - static void setDefaults(Json::Value* settings); - /** Same as old Features::strictMode(). - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode - */ - static void strictMode(Json::Value* settings); -}; - -/** Consume entire stream and use its begin/end. - * Someday we might have a real StreamReader, but for now this - * is convenient. - */ -bool JSON_API parseFromStream( - CharReader::Factory const&, - std::istream&, - Value* root, std::string* errs); - -/** \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 - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // CPPTL_JSON_READER_H_INCLUDED diff --git a/include/json/value.h b/include/json/value.h deleted file mode 100644 index 8e996ae23..000000000 --- a/include/json/value.h +++ /dev/null @@ -1,841 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef CPPTL_JSON_H_INCLUDED -#define CPPTL_JSON_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include - -#ifndef JSON_USE_CPPTL_SMALLMAP -#include -#else -#include -#endif -#ifdef JSON_USE_CPPTL -#include -#endif - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -/** \brief JSON (JavaScript Object Notation). - */ -namespace Json { - -/** Base class for all exceptions we throw. - * - * We use nothing but these internally. Of course, STL can throw others. - */ -class JSON_API Exception : public std::exception { -public: - Exception(std::string const& msg); - virtual ~Exception() throw(); - virtual char const* what() const throw(); -protected: - std::string const msg_; -}; - -/** Exceptions which the user cannot easily avoid. - * - * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input - * - * \remark derived from Json::Exception - */ -class JSON_API RuntimeError : public Exception { -public: - RuntimeError(std::string const& msg); -}; - -/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. - * - * These are precondition-violations (user bugs) and internal errors (our bugs). - * - * \remark derived from Json::Exception - */ -class JSON_API LogicError : public Exception { -public: - LogicError(std::string const& msg); -}; - -/// used internally -void throwRuntimeError(std::string const& msg); -/// used internally -void throwLogicError(std::string const& msg); - -/** \brief Type of the value held by a Value object. - */ -enum ValueType { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). -}; - -enum CommentPlacement { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for - /// root value) - numberOfCommentPlacement -}; - -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator EnumMemberNames; -// typedef CppTL::AnyEnumerator EnumValues; -//# endif - -/** \brief Lightweight wrapper to tag static string. - * - * Value constructor and objectValue member assignement takes advantage of the - * StaticString and avoid the cost of string duplication when storing the - * string or the member name. - * - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ -class JSON_API StaticString { -public: - explicit StaticString(const char* czstring) : c_str_(czstring) {} - - operator const char*() const { return c_str_; } - - const char* c_str() const { return c_str_; } - -private: - const char* c_str_; -}; - -/** \brief Represents a JSON value. - * - * This class is a discriminated union wrapper that can represents a: - * - signed integer [range: Value::minInt - Value::maxInt] - * - unsigned integer (range: 0 - Value::maxUInt) - * - double - * - UTF-8 string - * - boolean - * - 'null' - * - an ordered list of Value - * - collection of name/value pairs (javascript object) - * - * The type of the held value is represented by a #ValueType and - * can be obtained using type(). - * - * Values of an #objectValue or #arrayValue can be accessed using operator[]() - * methods. - * Non-const methods will automatically create the a #nullValue element - * if it does not exist. - * The sequence of an #arrayValue will be automatically resized and initialized - * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. - * - * The get() methods can be used to obtain default value in the case the - * required element does not exist. - * - * It is possible to iterate over the list of a #objectValue values using - * the getMemberNames() method. - * - * \note #Value string-length fit in size_t, but keys must be < 2^30. - * (The reason is an implementation detail.) A #CharReader will raise an - * exception if a bound is exceeded to avoid security holes in your app, - * but the Value API does *not* check bounds. That is the responsibility - * of the caller. - */ -class JSON_API Value { - friend class ValueIteratorBase; -public: - typedef std::vector Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; -#if defined(JSON_HAS_INT64) - typedef Json::UInt64 UInt64; - typedef Json::Int64 Int64; -#endif // defined(JSON_HAS_INT64) - typedef Json::LargestInt LargestInt; - typedef Json::LargestUInt LargestUInt; - typedef Json::ArrayIndex ArrayIndex; - - static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value(). - static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null - /// Minimum signed integer value that can be stored in a Json::Value. - static const LargestInt minLargestInt; - /// Maximum signed integer value that can be stored in a Json::Value. - static const LargestInt maxLargestInt; - /// Maximum unsigned integer value that can be stored in a Json::Value. - static const LargestUInt maxLargestUInt; - - /// Minimum signed int value that can be stored in a Json::Value. - static const Int minInt; - /// Maximum signed int value that can be stored in a Json::Value. - static const Int maxInt; - /// Maximum unsigned int value that can be stored in a Json::Value. - static const UInt maxUInt; - -#if defined(JSON_HAS_INT64) - /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 minInt64; - /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 maxInt64; - /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static const UInt64 maxUInt64; -#endif // defined(JSON_HAS_INT64) - -private: -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - class CZString { - public: - enum DuplicationPolicy { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; - CZString(ArrayIndex index); - CZString(char const* str, unsigned length, DuplicationPolicy allocate); - CZString(CZString const& other); - ~CZString(); - CZString& operator=(CZString other); - bool operator<(CZString const& other) const; - bool operator==(CZString const& other) const; - ArrayIndex index() const; - //const char* c_str() const; ///< \deprecated - char const* data() const; - unsigned length() const; - bool isStaticString() const; - - private: - void swap(CZString& other); - - struct StringStorage { - unsigned policy_: 2; - unsigned length_: 30; // 1GB max - }; - - char const* cstr_; // actually, a prefixed string, unless policy is noDup - union { - ArrayIndex index_; - StringStorage storage_; - }; - }; - -public: -#ifndef JSON_USE_CPPTL_SMALLMAP - typedef std::map ObjectValues; -#else - typedef CppTL::SmallMap ObjectValues; -#endif // ifndef JSON_USE_CPPTL_SMALLMAP -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. -This is useful since clear() and resize() will not alter types. - - Examples: -\code -Json::Value null_value; // null -Json::Value arr_value(Json::arrayValue); // [] -Json::Value obj_value(Json::objectValue); // {} -\endcode - */ - Value(ValueType type = nullValue); - Value(Int value); - Value(UInt value); -#if defined(JSON_HAS_INT64) - Value(Int64 value); - Value(UInt64 value); -#endif // if defined(JSON_HAS_INT64) - Value(double value); - Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) - Value(const char* begin, const char* end); ///< Copy all, incl zeroes. - /** \brief Constructs a value from a static string. - - * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. - * \note This works only for null-terminated strings. (We cannot change the - * size of this class, so we have nowhere to store the length, - * which might be computed later for various operations.) - * - * Example of usage: - * \code - * static StaticString foo("some text"); - * Json::Value aValue(foo); - * \endcode - */ - Value(const StaticString& value); - Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too. -#ifdef JSON_USE_CPPTL - Value(const CppTL::ConstString& value); -#endif - Value(bool value); - /// Deep copy. - Value(const Value& other); - ~Value(); - - /// Deep copy, then swap(other). - /// \note Over-write existing comments. To preserve comments, use #swapPayload(). - Value& operator=(Value other); - /// Swap everything. - void swap(Value& other); - /// Swap values but leave comments and source offsets in place. - void swapPayload(Value& other); - - ValueType type() const; - - /// Compare payload only, not comments etc. - bool operator<(const Value& other) const; - bool operator<=(const Value& other) const; - bool operator>=(const Value& other) const; - bool operator>(const Value& other) const; - bool operator==(const Value& other) const; - bool operator!=(const Value& other) const; - int compare(const Value& other) const; - - const char* asCString() const; ///< Embedded zeroes could cause you trouble! - std::string asString() const; ///< Embedded zeroes are possible. - /** Get raw char* of string-value. - * \return false if !string. (Seg-fault if str or end are NULL.) - */ - bool getString( - char const** begin, char const** end) const; -#ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -#endif - Int asInt() const; - UInt asUInt() const; -#if defined(JSON_HAS_INT64) - Int64 asInt64() const; - UInt64 asUInt64() const; -#endif // if defined(JSON_HAS_INT64) - LargestInt asLargestInt() const; - LargestUInt asLargestUInt() const; - float asFloat() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isInt64() const; - bool isUInt() const; - bool isUInt64() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - bool isConvertibleTo(ValueType other) const; - - /// Number of values in array or object - ArrayIndex size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return isNull() - bool operator!() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to size elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize(ArrayIndex size); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](ArrayIndex index); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](int index); - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](ArrayIndex index) const; - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](int index) const; - - /// If the array contains at least index+1 elements, returns the element - /// value, - /// otherwise returns defaultValue. - Value get(ArrayIndex index, const Value& defaultValue) const; - /// Return true if index < size(). - bool isValidIndex(ArrayIndex index) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value& append(const Value& value); - - /// Access an object value by name, create a null member if it does not exist. - /// \note Because of our implementation, keys are limited to 2^30 -1 chars. - /// Exceeding that will cause an exception. - Value& operator[](const char* key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const char* key) const; - /// Access an object value by name, create a null member if it does not exist. - /// \param key may contain embedded nulls. - Value& operator[](const std::string& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - /// \param key may contain embedded nulls. - const Value& operator[](const std::string& key) const; - /** \brief Access an object value by name, create a null member if it does not - exist. - - * If the object has no entry for that name, then the member name used to store - * the new entry is not duplicated. - * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - Value& operator[](const StaticString& key); -#ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const CppTL::ConstString& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const CppTL::ConstString& key) const; -#endif - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - Value get(const char* key, const Value& defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - /// \note key may contain embedded nulls. - Value get(const char* begin, const char* end, const Value& defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - /// \param key may contain embedded nulls. - Value get(const std::string& key, const Value& defaultValue) const; -#ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - Value get(const CppTL::ConstString& key, const Value& defaultValue) const; -#endif - /// Most general and efficient version of isMember()const, get()const, - /// and operator[]const - /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 - Value const* find(char const* begin, char const* end) const; - /// Most general and efficient version of object-mutators. - /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 - /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. - Value const* demand(char const* begin, char const* end); - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \return the removed Value, or null. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - /// \deprecated - Value removeMember(const char* key); - /// Same as removeMember(const char*) - /// \param key may contain embedded nulls. - /// \deprecated - Value removeMember(const std::string& key); - /// Same as removeMember(const char* begin, const char* end, Value* removed), - /// but 'key' is null-terminated. - bool removeMember(const char* key, Value* removed); - /** \brief Remove the named map member. - - Update 'removed' iff removed. - \param key may contain embedded nulls. - \return true iff removed (no exceptions) - */ - bool removeMember(std::string const& key, Value* removed); - /// Same as removeMember(std::string const& key, Value* removed) - bool removeMember(const char* begin, const char* end, Value* removed); - /** \brief Remove the indexed array element. - - O(n) expensive operations. - Update 'removed' iff removed. - \return true iff removed (no exceptions) - */ - bool removeIndex(ArrayIndex i, Value* removed); - - /// Return true if the object has a member named key. - /// \note 'key' must be null-terminated. - bool isMember(const char* key) const; - /// Return true if the object has a member named key. - /// \param key may contain embedded nulls. - bool isMember(const std::string& key) const; - /// Same as isMember(std::string const& key)const - bool isMember(const char* begin, const char* end) const; -#ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember(const CppTL::ConstString& key) const; -#endif - - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; - - //# ifdef JSON_USE_CPPTL - // EnumMemberNames enumMemberNames() const; - // EnumValues enumValues() const; - //# endif - - /// \deprecated Always pass len. - JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.") - void setComment(const char* comment, CommentPlacement placement); - /// Comments must be //... or /* ... */ - void setComment(const char* comment, size_t len, CommentPlacement placement); - /// Comments must be //... or /* ... */ - void setComment(const std::string& comment, CommentPlacement placement); - bool hasComment(CommentPlacement placement) const; - /// Include delimiters and embedded newlines. - std::string getComment(CommentPlacement placement) const; - - std::string toStyledString() const; - - const_iterator begin() const; - const_iterator end() const; - - iterator begin(); - iterator end(); - - // Accessors for the [start, limit) range of bytes within the JSON text from - // which this value was parsed, if any. - void setOffsetStart(size_t start); - void setOffsetLimit(size_t limit); - size_t getOffsetStart() const; - size_t getOffsetLimit() const; - -private: - void initBasic(ValueType type, bool allocated = false); - - Value& resolveReference(const char* key); - Value& resolveReference(const char* key, const char* end); - - struct CommentInfo { - CommentInfo(); - ~CommentInfo(); - - void setComment(const char* text, size_t len); - - char* comment_; - }; - - // struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder { - LargestInt int_; - LargestUInt uint_; - double real_; - bool bool_; - char* string_; // actually ptr to unsigned, followed by str, unless !allocated_ - ObjectValues* map_; - } value_; - ValueType type_ : 8; - unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. - // If not allocated_, string_ must be null-terminated. - CommentInfo* comments_; - - // [start, limit) byte offsets in the source JSON text from which this Value - // was extracted. - size_t start_; - size_t limit_; -}; - -/** \brief Experimental and untested: represents an element of the "path" to - * access a node. - */ -class JSON_API PathArgument { -public: - friend class Path; - - PathArgument(); - PathArgument(ArrayIndex index); - PathArgument(const char* key); - PathArgument(const std::string& key); - -private: - enum Kind { - kindNone = 0, - kindIndex, - kindKey - }; - std::string key_; - ArrayIndex index_; - Kind kind_; -}; - -/** \brief Experimental and untested: represents a "path" to access a node. - * - * Syntax: - * - "." => root node - * - ".[n]" => elements at index 'n' of root node (an array value) - * - ".name" => member named 'name' of root node (an object value) - * - ".name1.name2.name3" - * - ".[0][1][2].name1[3]" - * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter - */ -class JSON_API Path { -public: - Path(const std::string& path, - const PathArgument& a1 = PathArgument(), - const PathArgument& a2 = PathArgument(), - const PathArgument& a3 = PathArgument(), - const PathArgument& a4 = PathArgument(), - const PathArgument& a5 = PathArgument()); - - const Value& resolve(const Value& root) const; - Value resolve(const Value& root, const Value& defaultValue) const; - /// Creates the "path" to access the specified node and returns a reference on - /// the node. - Value& make(Value& root) const; - -private: - typedef std::vector InArgs; - typedef std::vector Args; - - void makePath(const std::string& path, const InArgs& in); - void addPathInArg(const std::string& path, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind); - void invalidPath(const std::string& path, int location); - - Args args_; -}; - -/** \brief base class for Value iterators. - * - */ -class JSON_API ValueIteratorBase { -public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; - - bool operator==(const SelfType& other) const { return isEqual(other); } - - bool operator!=(const SelfType& other) const { return !isEqual(other); } - - difference_type operator-(const SelfType& other) const { - return other.computeDistance(*this); - } - - /// Return either the index or the member name of the referenced value as a - /// Value. - Value key() const; - - /// Return the index of the referenced Value, or -1 if it is not an arrayValue. - UInt index() const; - - /// Return the member name of the referenced Value, or "" if it is not an - /// objectValue. - /// \note Avoid `c_str()` on result, as embedded zeroes are possible. - std::string name() const; - - /// Return the member name of the referenced Value. "" if it is not an - /// objectValue. - /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls. - JSONCPP_DEPRECATED("Use `key = name();` instead.") - char const* memberName() const; - /// Return the member name of the referenced Value, or NULL if it is not an - /// objectValue. - /// \note Better version than memberName(). Allows embedded nulls. - char const* memberName(char const** end) const; - -protected: - Value& deref() const; - - void increment(); - - void decrement(); - - difference_type computeDistance(const SelfType& other) const; - - bool isEqual(const SelfType& other) const; - - void copy(const SelfType& other); - -private: - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_; - -public: - // For some reason, BORLAND needs these at the end, rather - // than earlier. No idea why. - ValueIteratorBase(); - explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); -}; - -/** \brief const iterator for object and array value. - * - */ -class JSON_API ValueConstIterator : public ValueIteratorBase { - friend class Value; - -public: - typedef const Value value_type; - //typedef unsigned int size_t; - //typedef int difference_type; - typedef const Value& reference; - typedef const Value* pointer; - typedef ValueConstIterator SelfType; - - ValueConstIterator(); - -private: -/*! \internal Use by Value to create an iterator. - */ - explicit ValueConstIterator(const Value::ObjectValues::iterator& current); -public: - SelfType& operator=(const ValueIteratorBase& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -/** \brief Iterator for object and array value. - */ -class JSON_API ValueIterator : public ValueIteratorBase { - friend class Value; - -public: - typedef Value value_type; - typedef unsigned int size_t; - typedef int difference_type; - typedef Value& reference; - typedef Value* pointer; - typedef ValueIterator SelfType; - - ValueIterator(); - ValueIterator(const ValueConstIterator& other); - ValueIterator(const ValueIterator& other); - -private: -/*! \internal Use by Value to create an iterator. - */ - explicit ValueIterator(const Value::ObjectValues::iterator& current); -public: - SelfType& operator=(const SelfType& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -} // namespace Json - - -namespace std { -/// Specialize std::swap() for Json::Value. -template<> -inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } -} - - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // CPPTL_JSON_H_INCLUDED diff --git a/include/json/version.h b/include/json/version.h deleted file mode 100644 index 9df36d7cd..000000000 --- a/include/json/version.h +++ /dev/null @@ -1,13 +0,0 @@ -// DO NOT EDIT. This file (and "version") is generated by CMake. -// Run CMake configure step to update it. -#ifndef JSON_VERSION_H_INCLUDED -# define JSON_VERSION_H_INCLUDED - -# define JSONCPP_VERSION_STRING "1.6.5" -# define JSONCPP_VERSION_MAJOR 1 -# define JSONCPP_VERSION_MINOR 6 -# define JSONCPP_VERSION_PATCH 5 -# define JSONCPP_VERSION_QUALIFIER -# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) - -#endif // JSON_VERSION_H_INCLUDED diff --git a/include/json/writer.h b/include/json/writer.h deleted file mode 100644 index f5f0a389e..000000000 --- a/include/json/writer.h +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_WRITER_H_INCLUDED -#define JSON_WRITER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -namespace Json { - -class Value; - -/** - -Usage: -\code - using namespace Json; - void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { - std::unique_ptr const writer( - factory.newStreamWriter()); - writer->write(value, &std::cout); - std::cout << std::endl; // add lf and flush - } -\endcode -*/ -class JSON_API StreamWriter { -protected: - std::ostream* sout_; // not owned; will not delete -public: - StreamWriter(); - virtual ~StreamWriter(); - /** Write Value into document as configured in sub-class. - Do not take ownership of sout, but maintain a reference during function. - \pre sout != NULL - \return zero on success (For now, we always return zero, so check the stream instead.) - \throw std::exception possibly, depending on configuration - */ - virtual int write(Value const& root, std::ostream* sout) = 0; - - /** \brief A simple abstract factory. - */ - class JSON_API Factory { - public: - virtual ~Factory(); - /** \brief Allocate a CharReader via operator new(). - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - virtual StreamWriter* newStreamWriter() const = 0; - }; // Factory -}; // StreamWriter - -/** \brief Write into stringstream, then return string, for convenience. - * A StreamWriter will be created from the factory, used, and then deleted. - */ -std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root); - - -/** \brief Build a StreamWriter implementation. - -Usage: -\code - using namespace Json; - Value value = ...; - StreamWriterBuilder builder; - builder["commentStyle"] = "None"; - builder["indentation"] = " "; // or whatever you like - std::unique_ptr writer( - builder.newStreamWriter()); - writer->write(value, &std::cout); - std::cout << std::endl; // add lf and flush -\endcode -*/ -class JSON_API StreamWriterBuilder : public StreamWriter::Factory { -public: - // Note: We use a Json::Value so that we can add data-members to this class - // without a major version bump. - /** Configuration of this builder. - Available settings (case-sensitive): - - "commentStyle": "None" or "All" - - "indentation": "" - - "enableYAMLCompatibility": false or true - - slightly change the whitespace around colons - - "dropNullPlaceholders": false or true - - Drop the "null" string from the writer's output for nullValues. - Strictly speaking, this is not valid JSON. But when the output is being - fed to a browser's Javascript, it makes for smaller output and the - browser can handle the output just fine. - - You can examine 'settings_` yourself - to see the defaults. You can also write and read them just like any - JSON Value. - \sa setDefaults() - */ - Json::Value settings_; - - StreamWriterBuilder(); - virtual ~StreamWriterBuilder(); - - /** - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - virtual StreamWriter* newStreamWriter() const; - - /** \return true if 'settings' are legal and consistent; - * otherwise, indicate bad settings via 'invalid'. - */ - bool validate(Json::Value* invalid) const; - /** A simple way to update a specific setting. - */ - Value& operator[](std::string key); - - /** Called by ctor, but you can use this to reset settings_. - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults - */ - static void setDefaults(Json::Value* settings); -}; - -/** \brief Abstract class for writers. - * \deprecated Use StreamWriter. (And really, this is an implementation detail.) - */ -class JSON_API Writer { -public: - virtual ~Writer(); - - virtual std::string write(const Value& root) = 0; -}; - -/** \brief Outputs a Value in JSON 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. - * \sa Reader, Value - * \deprecated Use StreamWriterBuilder. - */ -class JSON_API FastWriter : public Writer { - -public: - FastWriter(); - virtual ~FastWriter() {} - - void enableYAMLCompatibility(); - - /** \brief Drop the "null" string from the writer's output for nullValues. - * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's Javascript, it makes for smaller output and the - * browser can handle the output just fine. - */ - void dropNullPlaceholders(); - - void omitEndingLineFeed(); - -public: // overridden from Writer - virtual std::string write(const Value& root); - -private: - void writeValue(const Value& value); - - std::string document_; - bool yamlCompatiblityEnabled_; - bool dropNullPlaceholders_; - bool omitEndingLineFeed_; -}; - -/** \brief Writes a Value in JSON format in a - *human friendly way. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - *line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - *types, - * and all the values fit on one lines, then print the array on a single - *line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their - *#CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - * \deprecated Use StreamWriterBuilder. - */ -class JSON_API StyledWriter : public Writer { -public: - StyledWriter(); - virtual ~StyledWriter() {} - -public: // overridden from Writer - /** \brief Serialize a Value in JSON format. - * \param root Value to serialize. - * \return String containing the JSON document that represents the root value. - */ - virtual std::string write(const Value& root); - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const std::string& value); - void writeIndent(); - void writeWithIndent(const std::string& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static std::string normalizeEOL(const std::string& text); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::string document_; - std::string indentString_; - int rightMargin_; - int indentSize_; - bool addChildValues_; -}; - -/** \brief Writes a Value in JSON format in a - human friendly way, - to a stream rather than to a string. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - types, - * and all the values fit on one lines, then print the array on a single - line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their - #CommentPlacement. - * - * \param indentation Each level will be indented by this amount extra. - * \sa Reader, Value, Value::setComment() - * \deprecated Use StreamWriterBuilder. - */ -class JSON_API StyledStreamWriter { -public: - StyledStreamWriter(std::string indentation = "\t"); - ~StyledStreamWriter() {} - -public: - /** \brief Serialize a Value in JSON format. - * \param out Stream to write to. (Can be ostringstream, e.g.) - * \param root Value to serialize. - * \note There is no point in deriving from Writer, since write() should not - * return a value. - */ - void write(std::ostream& out, const Value& root); - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const std::string& value); - void writeIndent(); - void writeWithIndent(const std::string& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static std::string normalizeEOL(const std::string& text); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::ostream* document_; - std::string indentString_; - int rightMargin_; - std::string indentation_; - bool addChildValues_ : 1; - bool indented_ : 1; -}; - -#if defined(JSON_HAS_INT64) -std::string JSON_API valueToString(Int value); -std::string JSON_API valueToString(UInt value); -#endif // if defined(JSON_HAS_INT64) -std::string JSON_API valueToString(LargestInt value); -std::string JSON_API valueToString(LargestUInt value); -std::string JSON_API valueToString(double value); -std::string JSON_API valueToString(bool value); -std::string JSON_API valueToQuotedString(const char* value); - -/// \brief Output using the StyledStreamWriter. -/// \see Json::operator>>() -JSON_API std::ostream& operator<<(std::ostream&, const Value& root); - -} // namespace Json - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // JSON_WRITER_H_INCLUDED diff --git a/makefiles/msvc2010/jsoncpp.sln b/makefiles/msvc2010/jsoncpp.sln deleted file mode 100644 index c4ecb9070..000000000 --- a/makefiles/msvc2010/jsoncpp.sln +++ /dev/null @@ -1,42 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_json", "lib_json.vcxproj", "{1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsontest", "jsontest.vcxproj", "{25AF2DD2-D396-4668-B188-488C33B8E620}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_lib_json", "test_lib_json.vcxproj", "{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Debug|Win32.ActiveCfg = Debug|Win32 - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Debug|Win32.Build.0 = Debug|Win32 - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Debug|x64.ActiveCfg = Debug|x64 - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Debug|x64.Build.0 = Debug|x64 - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Release|Win32.ActiveCfg = Release|Win32 - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Release|Win32.Build.0 = Release|Win32 - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Release|x64.ActiveCfg = Release|x64 - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89}.Release|x64.Build.0 = Release|x64 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug|Win32.ActiveCfg = Debug|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug|Win32.Build.0 = Debug|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug|x64.ActiveCfg = Debug|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Release|Win32.ActiveCfg = Release|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Release|Win32.Build.0 = Release|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Release|x64.ActiveCfg = Release|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug|Win32.ActiveCfg = Debug|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug|Win32.Build.0 = Debug|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug|x64.ActiveCfg = Debug|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release|Win32.ActiveCfg = Release|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release|Win32.Build.0 = Release|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release|x64.ActiveCfg = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/makefiles/msvc2010/jsontest.vcxproj b/makefiles/msvc2010/jsontest.vcxproj deleted file mode 100644 index 939d440dd..000000000 --- a/makefiles/msvc2010/jsontest.vcxproj +++ /dev/null @@ -1,96 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {25AF2DD2-D396-4668-B188-488C33B8E620} - Win32Proj - - - - Application - MultiByte - - - Application - MultiByte - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - ../../build/vs71/debug/jsontest\ - ../../build/vs71/debug/jsontest\ - true - ../../build/vs71/release/jsontest\ - ../../build/vs71/release/jsontest\ - false - - - - Disabled - ../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(OutDir)jsontest.exe - true - $(OutDir)jsontest.pdb - Console - MachineX86 - - - - - ../../include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(OutDir)jsontest.exe - true - Console - true - true - MachineX86 - - - - - - - - {1e6c2c1c-6453-4129-ae3f-0ee8e6599c89} - - - - - - \ No newline at end of file diff --git a/makefiles/msvc2010/jsontest.vcxproj.filters b/makefiles/msvc2010/jsontest.vcxproj.filters deleted file mode 100644 index 610b540ea..000000000 --- a/makefiles/msvc2010/jsontest.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - {903591b3-ade3-4ce4-b1f9-1e175e62b014} - - - - - Source Files - - - \ No newline at end of file diff --git a/makefiles/msvc2010/lib_json.vcxproj b/makefiles/msvc2010/lib_json.vcxproj deleted file mode 100644 index 3cfd0f936..000000000 --- a/makefiles/msvc2010/lib_json.vcxproj +++ /dev/null @@ -1,143 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - {1E6C2C1C-6453-4129-AE3F-0EE8E6599C89} - Win32Proj - jsoncpp - - - - StaticLibrary - true - Unicode - - - StaticLibrary - true - Unicode - - - StaticLibrary - false - true - Unicode - - - StaticLibrary - false - true - Unicode - - - - - - - - - - - - - - - - - - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ../../include - MultiThreadedDebug - - - Windows - true - - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ../../include - MultiThreadedDebug - - - Windows - true - - - - - Level3 - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ../../include - MultiThreaded - - - Windows - true - true - true - - - - - Level3 - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ../../include - MultiThreaded - - - Windows - true - true - true - - - - - - \ No newline at end of file diff --git a/makefiles/msvc2010/lib_json.vcxproj.filters b/makefiles/msvc2010/lib_json.vcxproj.filters deleted file mode 100644 index 63c740331..000000000 --- a/makefiles/msvc2010/lib_json.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {c110bc57-c46e-476c-97ea-84d8014f431c} - - - {ed718592-5acf-47b5-8f2b-b8224590da6a} - - - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/makefiles/msvc2010/test_lib_json.vcxproj b/makefiles/msvc2010/test_lib_json.vcxproj deleted file mode 100644 index 068af613e..000000000 --- a/makefiles/msvc2010/test_lib_json.vcxproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D} - test_lib_json - Win32Proj - - - - Application - MultiByte - - - Application - MultiByte - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - ../../build/vs71/debug/test_lib_json\ - ../../build/vs71/debug/test_lib_json\ - true - ../../build/vs71/release/test_lib_json\ - ../../build/vs71/release/test_lib_json\ - false - - - - Disabled - ../../include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(OutDir)test_lib_json.exe - true - $(OutDir)test_lib_json.pdb - Console - MachineX86 - - - Running all unit tests - $(TargetPath) - - - - - ../../include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(OutDir)test_lib_json.exe - true - Console - true - true - MachineX86 - - - Running all unit tests - $(TargetPath) - - - - - - - - - - - - {1e6c2c1c-6453-4129-ae3f-0ee8e6599c89} - - - - - - \ No newline at end of file diff --git a/makefiles/msvc2010/test_lib_json.vcxproj.filters b/makefiles/msvc2010/test_lib_json.vcxproj.filters deleted file mode 100644 index 8f0a17b99..000000000 --- a/makefiles/msvc2010/test_lib_json.vcxproj.filters +++ /dev/null @@ -1,24 +0,0 @@ - - - - - Source Filter - - - Source Filter - - - - - {bf40cbfc-8e98-40b4-b9f3-7e8d579cbae2} - - - {5fd39074-89e6-4939-aa3f-694fefd296b1} - - - - - Header Files - - - \ No newline at end of file diff --git a/makefiles/vs71/jsoncpp.sln b/makefiles/vs71/jsoncpp.sln deleted file mode 100644 index dd2f91b44..000000000 --- a/makefiles/vs71/jsoncpp.sln +++ /dev/null @@ -1,46 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_json", "lib_json.vcproj", "{B84F7231-16CE-41D8-8C08-7B523FF4225B}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsontest", "jsontest.vcproj", "{25AF2DD2-D396-4668-B188-488C33B8E620}" - ProjectSection(ProjectDependencies) = postProject - {B84F7231-16CE-41D8-8C08-7B523FF4225B} = {B84F7231-16CE-41D8-8C08-7B523FF4225B} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_lib_json", "test_lib_json.vcproj", "{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}" - ProjectSection(ProjectDependencies) = postProject - {B84F7231-16CE-41D8-8C08-7B523FF4225B} = {B84F7231-16CE-41D8-8C08-7B523FF4225B} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - dummy = dummy - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Debug.ActiveCfg = Debug|Win32 - {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Debug.Build.0 = Debug|Win32 - {B84F7231-16CE-41D8-8C08-7B523FF4225B}.dummy.ActiveCfg = dummy|Win32 - {B84F7231-16CE-41D8-8C08-7B523FF4225B}.dummy.Build.0 = dummy|Win32 - {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Release.ActiveCfg = Release|Win32 - {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Release.Build.0 = Release|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug.ActiveCfg = Debug|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug.Build.0 = Debug|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.dummy.ActiveCfg = Debug|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.dummy.Build.0 = Debug|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Release.ActiveCfg = Release|Win32 - {25AF2DD2-D396-4668-B188-488C33B8E620}.Release.Build.0 = Release|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug.ActiveCfg = Debug|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug.Build.0 = Debug|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.dummy.ActiveCfg = Debug|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.dummy.Build.0 = Debug|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release.ActiveCfg = Release|Win32 - {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/makefiles/vs71/jsontest.vcproj b/makefiles/vs71/jsontest.vcproj deleted file mode 100644 index 562c71f61..000000000 --- a/makefiles/vs71/jsontest.vcproj +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/makefiles/vs71/lib_json.vcproj b/makefiles/vs71/lib_json.vcproj deleted file mode 100644 index 24c5dd411..000000000 --- a/makefiles/vs71/lib_json.vcproj +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/makefiles/vs71/test_lib_json.vcproj b/makefiles/vs71/test_lib_json.vcproj deleted file mode 100644 index 9ebb986a6..000000000 --- a/makefiles/vs71/test_lib_json.vcproj +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/makerelease.py b/makerelease.py deleted file mode 100644 index ea3722de4..000000000 --- a/makerelease.py +++ /dev/null @@ -1,390 +0,0 @@ -# Copyright 2010 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -"""Tag the sandbox for release, make source and doc tarballs. - -Requires Python 2.6 - -Example of invocation (use to test the script): -python makerelease.py --platform=msvc6,msvc71,msvc80,msvc90,mingw -ublep 0.6.0 0.7.0-dev - -When testing this script: -python makerelease.py --force --retag --platform=msvc6,msvc71,msvc80,mingw -ublep test-0.6.0 test-0.6.1-dev - -Example of invocation when doing a release: -python makerelease.py 0.5.0 0.6.0-dev - -Note: This was for Subversion. Now that we are in GitHub, we do not -need to build versioned tarballs anymore, so makerelease.py is defunct. -""" - -from __future__ import print_function -import os.path -import subprocess -import sys -import doxybuild -import subprocess -import xml.etree.ElementTree as ElementTree -import shutil -import urllib2 -import tempfile -import os -import time -from devtools import antglob, fixeol, tarball -import amalgamate - -SVN_ROOT = 'https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/' -SVN_TAG_ROOT = SVN_ROOT + 'tags/jsoncpp' -SCONS_LOCAL_URL = 'http://sourceforge.net/projects/scons/files/scons-local/1.2.0/scons-local-1.2.0.tar.gz/download' -SOURCEFORGE_PROJECT = 'jsoncpp' - -def set_version(version): - with open('version','wb') as f: - f.write(version.strip()) - -def rmdir_if_exist(dir_path): - if os.path.isdir(dir_path): - shutil.rmtree(dir_path) - -class SVNError(Exception): - pass - -def svn_command(command, *args): - cmd = ['svn', '--non-interactive', command] + list(args) - print('Running:', ' '.join(cmd)) - process = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - stdout = process.communicate()[0] - if process.returncode: - error = SVNError('SVN command failed:\n' + stdout) - error.returncode = process.returncode - raise error - return stdout - -def check_no_pending_commit(): - """Checks that there is no pending commit in the sandbox.""" - stdout = svn_command('status', '--xml') - etree = ElementTree.fromstring(stdout) - msg = [] - for entry in etree.getiterator('entry'): - path = entry.get('path') - status = entry.find('wc-status').get('item') - if status != 'unversioned' and path != 'version': - msg.append('File "%s" has pending change (status="%s")' % (path, status)) - if msg: - msg.insert(0, 'Pending change to commit found in sandbox. Commit them first!') - return '\n'.join(msg) - -def svn_join_url(http://github.com/base_url,%20suffix): - if not base_url.endswith('/'): - base_url += '/' - if suffix.startswith('/'): - suffix = suffix[1:] - return base_url + suffix - -def svn_check_if_tag_exist(tag_url): - """Checks if a tag exist. - Returns: True if the tag exist, False otherwise. - """ - try: - list_stdout = svn_command('list', tag_url) - except SVNError as e: - if e.returncode != 1 or not str(e).find('tag_url'): - raise e - # otherwise ignore error, meaning tag does not exist - return False - return True - -def svn_commit(message): - """Commit the sandbox, providing the specified comment. - """ - svn_command('ci', '-m', message) - -def svn_tag_sandbox(tag_url, message): - """Makes a tag based on the sandbox revisions. - """ - svn_command('copy', '-m', message, '.', tag_url) - -def svn_remove_tag(tag_url, message): - """Removes an existing tag. - """ - svn_command('delete', '-m', message, tag_url) - -def svn_export(tag_url, export_dir): - """Exports the tag_url revision to export_dir. - Target directory, including its parent is created if it does not exist. - If the directory export_dir exist, it is deleted before export proceed. - """ - rmdir_if_exist(export_dir) - svn_command('export', tag_url, export_dir) - -def fix_sources_eol(dist_dir): - """Set file EOL for tarball distribution. - """ - print('Preparing exported source file EOL for distribution...') - prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist' - win_sources = antglob.glob(dist_dir, - includes = '**/*.sln **/*.vcproj', - prune_dirs = prune_dirs) - unix_sources = antglob.glob(dist_dir, - includes = '''**/*.h **/*.cpp **/*.inl **/*.txt **/*.dox **/*.py **/*.html **/*.in - sconscript *.json *.expected AUTHORS LICENSE''', - excludes = antglob.default_excludes + 'scons.py sconsign.py scons-*', - prune_dirs = prune_dirs) - for path in win_sources: - fixeol.fix_source_eol(path, is_dry_run = False, verbose = True, eol = '\r\n') - for path in unix_sources: - fixeol.fix_source_eol(path, is_dry_run = False, verbose = True, eol = '\n') - -def download(url, target_path): - """Download file represented by url to target_path. - """ - f = urllib2.urlopen(url) - try: - data = f.read() - finally: - f.close() - fout = open(target_path, 'wb') - try: - fout.write(data) - finally: - fout.close() - -def check_compile(distcheck_top_dir, platform): - cmd = [sys.executable, 'scons.py', 'platform=%s' % platform, 'check'] - print('Running:', ' '.join(cmd)) - log_path = os.path.join(distcheck_top_dir, 'build-%s.log' % platform) - flog = open(log_path, 'wb') - try: - process = subprocess.Popen(cmd, - stdout=flog, - stderr=subprocess.STDOUT, - cwd=distcheck_top_dir) - stdout = process.communicate()[0] - status = (process.returncode == 0) - finally: - flog.close() - return (status, log_path) - -def write_tempfile(content, **kwargs): - fd, path = tempfile.mkstemp(**kwargs) - f = os.fdopen(fd, 'wt') - try: - f.write(content) - finally: - f.close() - return path - -class SFTPError(Exception): - pass - -def run_sftp_batch(userhost, sftp, batch, retry=0): - path = write_tempfile(batch, suffix='.sftp', text=True) - # psftp -agent -C blep,jsoncpp@web.sourceforge.net -batch -b batch.sftp -bc - cmd = [sftp, '-agent', '-C', '-batch', '-b', path, '-bc', userhost] - error = None - for retry_index in range(0, max(1,retry)): - heading = retry_index == 0 and 'Running:' or 'Retrying:' - print(heading, ' '.join(cmd)) - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - stdout = process.communicate()[0] - if process.returncode != 0: - error = SFTPError('SFTP batch failed:\n' + stdout) - else: - break - if error: - raise error - return stdout - -def sourceforge_web_synchro(sourceforge_project, doc_dir, - user=None, sftp='sftp'): - """Notes: does not synchronize sub-directory of doc-dir. - """ - userhost = '%s,%s@web.sourceforge.net' % (user, sourceforge_project) - stdout = run_sftp_batch(userhost, sftp, """ -cd htdocs -dir -exit -""") - existing_paths = set() - collect = 0 - for line in stdout.split('\n'): - line = line.strip() - if not collect and line.endswith('> dir'): - collect = True - elif collect and line.endswith('> exit'): - break - elif collect == 1: - collect = 2 - elif collect == 2: - path = line.strip().split()[-1:] - if path and path[0] not in ('.', '..'): - existing_paths.add(path[0]) - upload_paths = set([os.path.basename(p) for p in antglob.glob(doc_dir)]) - paths_to_remove = existing_paths - upload_paths - if paths_to_remove: - print('Removing the following file from web:') - print('\n'.join(paths_to_remove)) - stdout = run_sftp_batch(userhost, sftp, """cd htdocs -rm %s -exit""" % ' '.join(paths_to_remove)) - print('Uploading %d files:' % len(upload_paths)) - batch_size = 10 - upload_paths = list(upload_paths) - start_time = time.time() - for index in range(0,len(upload_paths),batch_size): - paths = upload_paths[index:index+batch_size] - file_per_sec = (time.time() - start_time) / (index+1) - remaining_files = len(upload_paths) - index - remaining_sec = file_per_sec * remaining_files - print('%d/%d, ETA=%.1fs' % (index+1, len(upload_paths), remaining_sec)) - run_sftp_batch(userhost, sftp, """cd htdocs -lcd %s -mput %s -exit""" % (doc_dir, ' '.join(paths)), retry=3) - -def sourceforge_release_tarball(sourceforge_project, paths, user=None, sftp='sftp'): - userhost = '%s,%s@frs.sourceforge.net' % (user, sourceforge_project) - run_sftp_batch(userhost, sftp, """ -mput %s -exit -""" % (' '.join(paths),)) - - -def main(): - usage = """%prog release_version next_dev_version -Update 'version' file to release_version and commit. -Generates the document tarball. -Tags the sandbox revision with release_version. -Update 'version' file to next_dev_version and commit. - -Performs an svn export of tag release version, and build a source tarball. - -Must be started in the project top directory. - -Warning: --force should only be used when developping/testing the release script. -""" - from optparse import OptionParser - parser = OptionParser(usage=usage) - parser.allow_interspersed_args = False - parser.add_option('--dot', dest="dot_path", action='http://github.com/store', default=doxybuild.find_program('dot'), - help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""") - parser.add_option('--doxygen', dest="doxygen_path", action='http://github.com/store', default=doxybuild.find_program('doxygen'), - help="""Path to Doxygen tool. [Default: %default]""") - parser.add_option('--force', dest="ignore_pending_commit", action='http://github.com/store_true', default=False, - help="""Ignore pending commit. [Default: %default]""") - parser.add_option('--retag', dest="retag_release", action='http://github.com/store_true', default=False, - help="""Overwrite release existing tag if it exist. [Default: %default]""") - parser.add_option('-p', '--platforms', dest="platforms", action='http://github.com/store', default='', - help="""Comma separated list of platform passed to scons for build check.""") - parser.add_option('--no-test', dest="no_test", action='http://github.com/store_true', default=False, - help="""Skips build check.""") - parser.add_option('--no-web', dest="no_web", action='http://github.com/store_true', default=False, - help="""Do not update web site.""") - parser.add_option('-u', '--upload-user', dest="user", action='http://github.com/store', - help="""Sourceforge user for SFTP documentation upload.""") - parser.add_option('--sftp', dest='sftp', action='http://github.com/store', default=doxybuild.find_program('psftp', 'sftp'), - help="""Path of the SFTP compatible binary used to upload the documentation.""") - parser.enable_interspersed_args() - options, args = parser.parse_args() - - if len(args) != 2: - parser.error('release_version missing on command-line.') - release_version = args[0] - next_version = args[1] - - if not options.platforms and not options.no_test: - parser.error('You must specify either --platform or --no-test option.') - - if options.ignore_pending_commit: - msg = '' - else: - msg = check_no_pending_commit() - if not msg: - print('Setting version to', release_version) - set_version(release_version) - svn_commit('Release ' + release_version) - tag_url = svn_join_url(http://github.com/SVN_TAG_ROOT,%20release_version) - if svn_check_if_tag_exist(tag_url): - if options.retag_release: - svn_remove_tag(tag_url, 'Overwriting previous tag') - else: - print('Aborting, tag %s already exist. Use --retag to overwrite it!' % tag_url) - sys.exit(1) - svn_tag_sandbox(tag_url, 'Release ' + release_version) - - print('Generated doxygen document...') -## doc_dirname = r'jsoncpp-api-html-0.5.0' -## doc_tarball_path = r'e:\prg\vc\Lib\jsoncpp-trunk\dist\jsoncpp-api-html-0.5.0.tar.gz' - doc_tarball_path, doc_dirname = doxybuild.build_doc(options, make_release=True) - doc_distcheck_dir = 'dist/doccheck' - tarball.decompress(doc_tarball_path, doc_distcheck_dir) - doc_distcheck_top_dir = os.path.join(doc_distcheck_dir, doc_dirname) - - export_dir = 'dist/export' - svn_export(tag_url, export_dir) - fix_sources_eol(export_dir) - - source_dir = 'jsoncpp-src-' + release_version - source_tarball_path = 'dist/%s.tar.gz' % source_dir - print('Generating source tarball to', source_tarball_path) - tarball.make_tarball(source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir) - - amalgamation_tarball_path = 'dist/%s-amalgamation.tar.gz' % source_dir - print('Generating amalgamation source tarball to', amalgamation_tarball_path) - amalgamation_dir = 'dist/amalgamation' - amalgamate.amalgamate_source(export_dir, '%s/jsoncpp.cpp' % amalgamation_dir, 'json/json.h') - amalgamation_source_dir = 'jsoncpp-src-amalgamation' + release_version - tarball.make_tarball(amalgamation_tarball_path, [amalgamation_dir], - amalgamation_dir, prefix_dir=amalgamation_source_dir) - - # Decompress source tarball, download and install scons-local - distcheck_dir = 'dist/distcheck' - distcheck_top_dir = distcheck_dir + '/' + source_dir - print('Decompressing source tarball to', distcheck_dir) - rmdir_if_exist(distcheck_dir) - tarball.decompress(source_tarball_path, distcheck_dir) - scons_local_path = 'dist/scons-local.tar.gz' - print('Downloading scons-local to', scons_local_path) - download(SCONS_LOCAL_URL, scons_local_path) - print('Decompressing scons-local to', distcheck_top_dir) - tarball.decompress(scons_local_path, distcheck_top_dir) - - # Run compilation - print('Compiling decompressed tarball') - all_build_status = True - for platform in options.platforms.split(','): - print('Testing platform:', platform) - build_status, log_path = check_compile(distcheck_top_dir, platform) - print('see build log:', log_path) - print(build_status and '=> ok' or '=> FAILED') - all_build_status = all_build_status and build_status - if not build_status: - print('Testing failed on at least one platform, aborting...') - svn_remove_tag(tag_url, 'Removing tag due to failed testing') - sys.exit(1) - if options.user: - if not options.no_web: - print('Uploading documentation using user', options.user) - sourceforge_web_synchro(SOURCEFORGE_PROJECT, doc_distcheck_top_dir, user=options.user, sftp=options.sftp) - print('Completed documentation upload') - print('Uploading source and documentation tarballs for release using user', options.user) - sourceforge_release_tarball(SOURCEFORGE_PROJECT, - [source_tarball_path, doc_tarball_path], - user=options.user, sftp=options.sftp) - print('Source and doc release tarballs uploaded') - else: - print('No upload user specified. Web site and download tarbal were not uploaded.') - print('Tarball can be found at:', doc_tarball_path) - - # Set next version number and commit - set_version(next_version) - svn_commit('Released ' + release_version) - else: - sys.stderr.write(msg + '\n') - -if __name__ == '__main__': - main() diff --git a/pkg-config/jsoncpp.pc.in b/pkg-config/jsoncpp.pc.in deleted file mode 100644 index 3ca4a84d0..000000000 --- a/pkg-config/jsoncpp.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=${prefix} -libdir=@LIBRARY_INSTALL_DIR@ -includedir=@INCLUDE_INSTALL_DIR@ - -Name: jsoncpp -Description: A C++ library for interacting with JSON -Version: @JSONCPP_VERSION@ -URL: https://github.com/open-source-parsers/jsoncpp -Libs: -L${libdir} -ljsoncpp -Cflags: -I${includedir} diff --git a/scons-tools/globtool.py b/scons-tools/globtool.py deleted file mode 100644 index 890f1b7b1..000000000 --- a/scons-tools/globtool.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2009 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -import fnmatch -import os - -def generate(env): - def Glob(env, includes = None, excludes = None, dir = '.'): - """Adds Glob(includes = Split('*'), excludes = None, dir = '.') - helper function to environment. - - Glob both the file-system files. - - includes: list of file name pattern included in the return list when matched. - excludes: list of file name pattern exluced from the return list. - - Example: - sources = env.Glob(("*.cpp", '*.h'), "~*.cpp", "#src") - """ - def filterFilename(path): - abs_path = os.path.join(dir, path) - if not os.path.isfile(abs_path): - return 0 - fn = os.path.basename(path) - match = 0 - for include in includes: - if fnmatch.fnmatchcase(fn, include): - match = 1 - break - if match == 1 and not excludes is None: - for exclude in excludes: - if fnmatch.fnmatchcase(fn, exclude): - match = 0 - break - return match - if includes is None: - includes = ('*',) - elif type(includes) in (type(''), type(u'')): - includes = (includes,) - if type(excludes) in (type(''), type(u'')): - excludes = (excludes,) - dir = env.Dir(dir).abspath - paths = os.listdir(dir) - def makeAbsFileNode(path): - return env.File(os.path.join(dir, path)) - nodes = filter(filterFilename, paths) - return map(makeAbsFileNode, nodes) - - from SCons.Script import Environment - Environment.Glob = Glob - -def exists(env): - """ - Tool always exists. - """ - return True diff --git a/scons-tools/srcdist.py b/scons-tools/srcdist.py deleted file mode 100644 index fe1d74695..000000000 --- a/scons-tools/srcdist.py +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright 2007 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -import os -import os.path -from fnmatch import fnmatch -import targz - -##def DoxyfileParse(file_contents): -## """ -## Parse a Doxygen source file and return a dictionary of all the values. -## Values will be strings and lists of strings. -## """ -## data = {} -## -## import shlex -## lex = shlex.shlex(instream = file_contents, posix = True) -## lex.wordchars += "*+./-:" -## lex.whitespace = lex.whitespace.replace("\n", "") -## lex.escape = "" -## -## lineno = lex.lineno -## last_backslash_lineno = lineno -## token = lex.get_token() -## key = token # the first token should be a key -## last_token = "" -## key_token = False -## next_key = False -## new_data = True -## -## def append_data(data, key, new_data, token): -## if new_data or len(data[key]) == 0: -## data[key].append(token) -## else: -## data[key][-1] += token -## -## while token: -## if token in ['\n']: -## if last_token not in ['\\']: -## key_token = True -## elif token in ['\\']: -## pass -## elif key_token: -## key = token -## key_token = False -## else: -## if token == "+=": -## if not data.has_key(key): -## data[key] = list() -## elif token == "=": -## data[key] = list() -## else: -## append_data(data, key, new_data, token) -## new_data = True -## -## last_token = token -## token = lex.get_token() -## -## if last_token == '\\' and token != '\n': -## new_data = False -## append_data(data, key, new_data, '\\') -## -## # compress lists of len 1 into single strings -## for (k, v) in data.items(): -## if len(v) == 0: -## data.pop(k) -## -## # items in the following list will be kept as lists and not converted to strings -## if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]: -## continue -## -## if len(v) == 1: -## data[k] = v[0] -## -## return data -## -##def DoxySourceScan(node, env, path): -## """ -## Doxygen Doxyfile source scanner. This should scan the Doxygen file and add -## any files used to generate docs to the list of source files. -## """ -## default_file_patterns = [ -## '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx', -## '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++', -## '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm', -## '*.py', -## ] -## -## default_exclude_patterns = [ -## '*~', -## ] -## -## sources = [] -## -## data = DoxyfileParse(node.get_contents()) -## -## if data.get("RECURSIVE", "NO") == "YES": -## recursive = True -## else: -## recursive = False -## -## file_patterns = data.get("FILE_PATTERNS", default_file_patterns) -## exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns) -## -## for node in data.get("INPUT", []): -## if os.path.isfile(node): -## sources.add(node) -## elif os.path.isdir(node): -## if recursive: -## for root, dirs, files in os.walk(node): -## for f in files: -## filename = os.path.join(root, f) -## -## pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False) -## exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True) -## -## if pattern_check and not exclude_check: -## sources.append(filename) -## else: -## for pattern in file_patterns: -## sources.extend(glob.glob("/".join([node, pattern]))) -## sources = map(lambda path: env.File(path), sources) -## return sources -## -## -##def DoxySourceScanCheck(node, env): -## """Check if we should scan this file""" -## return os.path.isfile(node.path) - -def srcDistEmitter(source, target, env): -## """Doxygen Doxyfile emitter""" -## # possible output formats and their default values and output locations -## output_formats = { -## "HTML": ("YES", "html"), -## "LATEX": ("YES", "latex"), -## "RTF": ("NO", "rtf"), -## "MAN": ("YES", "man"), -## "XML": ("NO", "xml"), -## } -## -## data = DoxyfileParse(source[0].get_contents()) -## -## targets = [] -## out_dir = data.get("OUTPUT_DIRECTORY", ".") -## -## # add our output locations -## for (k, v) in output_formats.items(): -## if data.get("GENERATE_" + k, v[0]) == "YES": -## targets.append(env.Dir(os.path.join(out_dir, data.get(k + "_OUTPUT", v[1])))) -## -## # don't clobber targets -## for node in targets: -## env.Precious(node) -## -## # set up cleaning stuff -## for node in targets: -## env.Clean(node, node) -## -## return (targets, source) - return (target,source) - -def generate(env): - """ - Add builders and construction variables for the - SrcDist tool. - """ -## doxyfile_scanner = env.Scanner(## DoxySourceScan, -## "DoxySourceScan", -## scan_check = DoxySourceScanCheck, -##) - - if targz.exists(env): - srcdist_builder = targz.makeBuilder(srcDistEmitter) - - env['BUILDERS']['SrcDist'] = srcdist_builder - -def exists(env): - """ - Make sure srcdist exists. - """ - return targz.exists(env) diff --git a/scons-tools/substinfile.py b/scons-tools/substinfile.py deleted file mode 100644 index c620442d5..000000000 --- a/scons-tools/substinfile.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright 2010 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -import re -from SCons.Script import * # the usual scons stuff you get in a SConscript -import collections - -def generate(env): - """ - Add builders and construction variables for the - SubstInFile tool. - - Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT - from the source to the target. - The values of SUBST_DICT first have any construction variables expanded - (its keys are not expanded). - If a value of SUBST_DICT is a python callable function, it is called and - the result is expanded as the value. - If there's more than one source and more than one target, each target gets - substituted from the corresponding source. - """ - def do_subst_in_file(targetfile, sourcefile, dict): - """Replace all instances of the keys of dict with their values. - For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'}, - then all instances of %VERSION% in the file will be replaced with 1.2345 etc. - """ - try: - f = open(sourcefile, 'rb') - contents = f.read() - f.close() - except: - raise SCons.Errors.UserError("Can't read source file %s"%sourcefile) - for (k,v) in list(dict.items()): - contents = re.sub(k, v, contents) - try: - f = open(targetfile, 'wb') - f.write(contents) - f.close() - except: - raise SCons.Errors.UserError("Can't write target file %s"%targetfile) - return 0 # success - - def subst_in_file(target, source, env): - if 'SUBST_DICT' not in env: - raise SCons.Errors.UserError("SubstInFile requires SUBST_DICT to be set.") - d = dict(env['SUBST_DICT']) # copy it - for (k,v) in list(d.items()): - if isinstance(v, collections.Callable): - d[k] = env.subst(v()).replace('\\','\\\\') - elif SCons.Util.is_String(v): - d[k] = env.subst(v).replace('\\','\\\\') - else: - raise SCons.Errors.UserError("SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))) - for (t,s) in zip(target, source): - return do_subst_in_file(str(t), str(s), d) - - def subst_in_file_string(target, source, env): - """This is what gets printed on the console.""" - return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t)) - for (t,s) in zip(target, source)]) - - def subst_emitter(target, source, env): - """Add dependency from substituted SUBST_DICT to target. - Returns original target, source tuple unchanged. - """ - d = env['SUBST_DICT'].copy() # copy it - for (k,v) in list(d.items()): - if isinstance(v, collections.Callable): - d[k] = env.subst(v()) - elif SCons.Util.is_String(v): - d[k]=env.subst(v) - Depends(target, SCons.Node.Python.Value(d)) - return target, source - -## env.Append(TOOLS = 'substinfile') # this should be automaticaly done by Scons ?!? - subst_action = SCons.Action.Action(subst_in_file, subst_in_file_string) - env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter) - -def exists(env): - """ - Make sure tool exists. - """ - return True diff --git a/scons-tools/targz.py b/scons-tools/targz.py deleted file mode 100644 index 8e5ba8300..000000000 --- a/scons-tools/targz.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2007 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -"""tarball - -Tool-specific initialization for tarball. - -""" - -## Commands to tackle a command based implementation: -##to unpack on the fly... -##gunzip < FILE.tar.gz | tar xvf - -##to pack on the fly... -##tar cvf - FILE-LIST | gzip -c > FILE.tar.gz - -import os.path - -import SCons.Builder -import SCons.Node.FS -import SCons.Util - -try: - import gzip - import tarfile - internal_targz = 1 -except ImportError: - internal_targz = 0 - -TARGZ_DEFAULT_COMPRESSION_LEVEL = 9 - -if internal_targz: - def targz(target, source, env): - def archive_name(path): - path = os.path.normpath(os.path.abspath(path)) - common_path = os.path.commonprefix((base_dir, path)) - archive_name = path[len(common_path):] - return archive_name - - def visit(tar, dirname, names): - for name in names: - path = os.path.join(dirname, name) - if os.path.isfile(path): - tar.add(path, archive_name(path)) - compression = env.get('TARGZ_COMPRESSION_LEVEL',TARGZ_DEFAULT_COMPRESSION_LEVEL) - base_dir = os.path.normpath(env.get('TARGZ_BASEDIR', env.Dir('.')).abspath) - target_path = str(target[0]) - fileobj = gzip.GzipFile(target_path, 'wb', compression) - tar = tarfile.TarFile(os.path.splitext(target_path)[0], 'w', fileobj) - for source in source: - source_path = str(source) - if source.isdir(): - os.path.walk(source_path, visit, tar) - else: - tar.add(source_path, archive_name(source_path)) # filename, arcname - tar.close() - - targzAction = SCons.Action.Action(targz, varlist=['TARGZ_COMPRESSION_LEVEL','TARGZ_BASEDIR']) - - def makeBuilder(emitter = None): - return SCons.Builder.Builder(action = SCons.Action.Action('$TARGZ_COM', '$TARGZ_COMSTR'), - source_factory = SCons.Node.FS.Entry, - source_scanner = SCons.Defaults.DirScanner, - suffix = '$TARGZ_SUFFIX', - multi = 1) - TarGzBuilder = makeBuilder() - - def generate(env): - """Add Builders and construction variables for zip to an Environment. - The following environnement variables may be set: - TARGZ_COMPRESSION_LEVEL: integer, [0-9]. 0: no compression, 9: best compression (same as gzip compression level). - TARGZ_BASEDIR: base-directory used to determine archive name (this allow archive name to be relative - to something other than top-dir). - """ - env['BUILDERS']['TarGz'] = TarGzBuilder - env['TARGZ_COM'] = targzAction - env['TARGZ_COMPRESSION_LEVEL'] = TARGZ_DEFAULT_COMPRESSION_LEVEL # range 0-9 - env['TARGZ_SUFFIX'] = '.tar.gz' - env['TARGZ_BASEDIR'] = env.Dir('.') # Sources archive name are made relative to that directory. -else: - def generate(env): - pass - - -def exists(env): - return internal_targz diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index ca8ac15e2..000000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -ADD_SUBDIRECTORY(lib_json) -IF(JSONCPP_WITH_TESTS) - ADD_SUBDIRECTORY(jsontestrunner) - ADD_SUBDIRECTORY(test_lib_json) -ENDIF() diff --git a/src/jsontestrunner/CMakeLists.txt b/src/jsontestrunner/CMakeLists.txt deleted file mode 100644 index 20d01e626..000000000 --- a/src/jsontestrunner/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -FIND_PACKAGE(PythonInterp 2.6) - -ADD_EXECUTABLE(jsontestrunner_exe - main.cpp - ) - -IF(BUILD_SHARED_LIBS) - ADD_DEFINITIONS( -DJSON_DLL ) - TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib) -ELSE(BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib_static) -ENDIF() - -SET_TARGET_PROPERTIES(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe) - -IF(PYTHONINTERP_FOUND) - # Run end to end parser/writer tests - SET(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../test) - SET(RUNJSONTESTS_PATH ${TEST_DIR}/runjsontests.py) - ADD_CUSTOM_TARGET(jsoncpp_readerwriter_tests - "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $ "${TEST_DIR}/data" - DEPENDS jsontestrunner_exe jsoncpp_test - ) - ADD_CUSTOM_TARGET(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests) -ENDIF() diff --git a/src/jsontestrunner/main.cpp b/src/jsontestrunner/main.cpp deleted file mode 100644 index 1ec1fb6fb..000000000 --- a/src/jsontestrunner/main.cpp +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -/* This executable is used for testing parser/writer using real JSON files. - */ - -#include -#include // sort -#include -#include - -#if defined(_MSC_VER) && _MSC_VER >= 1310 -#pragma warning(disable : 4996) // disable fopen deprecation warning -#endif - -struct Options -{ - std::string path; - Json::Features features; - bool parseOnly; - typedef std::string (*writeFuncType)(Json::Value const&); - writeFuncType write; -}; - -static std::string normalizeFloatingPointStr(double value) { - char buffer[32]; -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) - sprintf_s(buffer, sizeof(buffer), "%.16g", value); -#else - snprintf(buffer, sizeof(buffer), "%.16g", value); -#endif - buffer[sizeof(buffer) - 1] = 0; - std::string s(buffer); - std::string::size_type index = s.find_last_of("eE"); - 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 - { - exponent = s.substr(indexDigit); - } - return normalized + exponent; - } - return s; -} - -static std::string readInputTestFile(const char* path) { - FILE* file = fopen(path, "rb"); - if (!file) - return std::string(""); - fseek(file, 0, SEEK_END); - long size = ftell(file); - fseek(file, 0, SEEK_SET); - std::string text; - char* buffer = new char[size + 1]; - buffer[size] = 0; - if (fread(buffer, 1, size, file) == (unsigned long)size) - text = buffer; - fclose(file); - delete[] buffer; - return text; -} - -static void -printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") { - if (value.hasComment(Json::commentBefore)) { - fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str()); - } - switch (value.type()) { - case Json::nullValue: - fprintf(fout, "%s=null\n", path.c_str()); - break; - case Json::intValue: - fprintf(fout, - "%s=%s\n", - path.c_str(), - Json::valueToString(value.asLargestInt()).c_str()); - break; - case Json::uintValue: - fprintf(fout, - "%s=%s\n", - path.c_str(), - Json::valueToString(value.asLargestUInt()).c_str()); - break; - case Json::realValue: - fprintf(fout, - "%s=%s\n", - path.c_str(), - normalizeFloatingPointStr(value.asDouble()).c_str()); - break; - case Json::stringValue: - fprintf(fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str()); - break; - case Json::booleanValue: - fprintf(fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false"); - 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__) - sprintf_s(buffer, sizeof(buffer), "[%d]", index); -#else - snprintf(buffer, sizeof(buffer), "[%d]", index); -#endif - printValueTree(fout, value[index], path + buffer); - } - } break; - case Json::objectValue: { - fprintf(fout, "%s={}\n", path.c_str()); - Json::Value::Members members(value.getMemberNames()); - std::sort(members.begin(), members.end()); - std::string suffix = *(path.end() - 1) == '.' ? "" : "."; - for (Json::Value::Members::iterator it = members.begin(); - it != members.end(); - ++it) { - const std::string& name = *it; - printValueTree(fout, value[name], path + suffix + name); - } - } break; - default: - break; - } - - if (value.hasComment(Json::commentAfter)) { - fprintf(fout, "%s\n", value.getComment(Json::commentAfter).c_str()); - } -} - -static int parseAndSaveValueTree(const std::string& input, - const std::string& actual, - const std::string& kind, - const Json::Features& features, - bool parseOnly, - Json::Value* root) -{ - 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 std::string useFastWriter(Json::Value const& root) { -// Json::FastWriter writer; -// writer.enableYAMLCompatibility(); -// return writer.write(root); -// } -static std::string useStyledWriter( - Json::Value const& root) -{ - Json::StyledWriter writer; - return writer.write(root); -} -static std::string useStyledStreamWriter( - Json::Value const& root) -{ - Json::StyledStreamWriter writer; - std::ostringstream sout; - writer.write(sout, root); - return sout.str(); -} -static std::string useBuiltStyledStreamWriter( - Json::Value const& root) -{ - Json::StreamWriterBuilder builder; - return Json::writeString(builder, root); -} -static int rewriteValueTree( - const std::string& rewritePath, - const Json::Value& root, - Options::writeFuncType write, - std::string* rewrite) -{ - *rewrite = write(root); - FILE* fout = fopen(rewritePath.c_str(), "wt"); - if (!fout) { - printf("Failed to create rewrite file: %s\n", rewritePath.c_str()); - 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 printConfig() { -// Print the configuration used to compile JsonCpp -#if defined(JSON_NO_INT64) - printf("JSON_NO_INT64=1\n"); -#else - printf("JSON_NO_INT64=0\n"); -#endif -} - -static int printUsage(const char* argv[]) { - printf("Usage: %s [--strict] input-json-file", argv[0]); - return 3; -} - -static int parseCommandLine( - int argc, const char* argv[], Options* opts) -{ - opts->parseOnly = false; - opts->write = &useStyledWriter; - if (argc < 2) { - return printUsage(argv); - } - int index = 1; - if (std::string(argv[index]) == "--json-checker") { - opts->features = Json::Features::strictMode(); - opts->parseOnly = true; - ++index; - } - if (std::string(argv[index]) == "--json-config") { - printConfig(); - return 3; - } - if (std::string(argv[index]) == "--json-writer") { - ++index; - std::string const writerName(argv[index++]); - if (writerName == "StyledWriter") { - opts->write = &useStyledWriter; - } else if (writerName == "StyledStreamWriter") { - opts->write = &useStyledStreamWriter; - } else if (writerName == "BuiltStyledStreamWriter") { - opts->write = &useBuiltStyledStreamWriter; - } else { - printf("Unknown '--json-writer %s'\n", writerName.c_str()); - return 4; - } - } - if (index == argc || index + 1 < argc) { - return printUsage(argv); - } - opts->path = argv[index]; - return 0; -} -static int runTest(Options const& opts) -{ - int exitCode = 0; - - std::string input = readInputTestFile(opts.path.c_str()); - if (input.empty()) { - printf("Failed to read input or empty input: %s\n", opts.path.c_str()); - return 3; - } - - std::string basePath = removeSuffix(opts.path, ".json"); - if (!opts.parseOnly && basePath.empty()) { - printf("Bad input path. Path does not end with '.expected':\n%s\n", - opts.path.c_str()); - return 3; - } - - std::string const actualPath = basePath + ".actual"; - std::string const rewritePath = basePath + ".rewrite"; - std::string const rewriteActualPath = basePath + ".actual-rewrite"; - - Json::Value root; - exitCode = parseAndSaveValueTree( - input, actualPath, "input", - opts.features, opts.parseOnly, &root); - if (exitCode || opts.parseOnly) { - return exitCode; - } - std::string rewrite; - exitCode = rewriteValueTree(rewritePath, root, opts.write, &rewrite); - if (exitCode) { - return exitCode; - } - Json::Value rewriteRoot; - exitCode = parseAndSaveValueTree( - rewrite, rewriteActualPath, "rewrite", - opts.features, opts.parseOnly, &rewriteRoot); - if (exitCode) { - return exitCode; - } - return 0; -} -int main(int argc, const char* argv[]) { - Options opts; - int exitCode = parseCommandLine(argc, argv, &opts); - if (exitCode != 0) { - printf("Failed to parse command-line."); - return exitCode; - } - try { - return runTest(opts); - } - catch (const std::exception& e) { - printf("Unhandled exception:\n%s\n", e.what()); - return 1; - } -} diff --git a/src/jsontestrunner/sconscript b/src/jsontestrunner/sconscript deleted file mode 100644 index 6e68e3153..000000000 --- a/src/jsontestrunner/sconscript +++ /dev/null @@ -1,9 +0,0 @@ -Import( 'env_testing buildJSONTests' ) - -buildJSONTests( env_testing, Split( """ - main.cpp - """ ), - 'jsontestrunner' ) - -# For 'check' to work, 'libs' must be built first. -env_testing.Depends('jsontestrunner', '#libs') diff --git a/src/lib_json/CMakeLists.txt b/src/lib_json/CMakeLists.txt deleted file mode 100644 index 99ddc7f8b..000000000 --- a/src/lib_json/CMakeLists.txt +++ /dev/null @@ -1,80 +0,0 @@ -if( CMAKE_COMPILER_IS_GNUCXX ) - #Get compiler version. - execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion - OUTPUT_VARIABLE GNUCXX_VERSION ) - - #-Werror=* was introduced -after- GCC 4.1.2 - if( GNUCXX_VERSION VERSION_GREATER 4.1.2 ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing") - endif() -endif( CMAKE_COMPILER_IS_GNUCXX ) - -SET( JSONCPP_INCLUDE_DIR ../../include ) - -SET( PUBLIC_HEADERS - ${JSONCPP_INCLUDE_DIR}/json/config.h - ${JSONCPP_INCLUDE_DIR}/json/forwards.h - ${JSONCPP_INCLUDE_DIR}/json/features.h - ${JSONCPP_INCLUDE_DIR}/json/value.h - ${JSONCPP_INCLUDE_DIR}/json/reader.h - ${JSONCPP_INCLUDE_DIR}/json/writer.h - ${JSONCPP_INCLUDE_DIR}/json/assertions.h - ${JSONCPP_INCLUDE_DIR}/json/version.h - ) - -SOURCE_GROUP( "Public API" FILES ${PUBLIC_HEADERS} ) - -SET(jsoncpp_sources - json_tool.h - json_reader.cpp - json_valueiterator.inl - json_value.cpp - json_writer.cpp - version.h.in) - -# Install instructions for this target -IF(JSONCPP_WITH_CMAKE_PACKAGE) - SET(INSTALL_EXPORT EXPORT jsoncpp) -ELSE(JSONCPP_WITH_CMAKE_PACKAGE) - SET(INSTALL_EXPORT) -ENDIF() - -IF(BUILD_SHARED_LIBS) - ADD_DEFINITIONS( -DJSON_DLL_BUILD ) - ADD_LIBRARY(jsoncpp_lib SHARED ${PUBLIC_HEADERS} ${jsoncpp_sources}) - SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR}) - SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp - DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} ) - - INSTALL( TARGETS jsoncpp_lib ${INSTALL_EXPORT} - RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} - LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} - ARCHIVE DESTINATION ${ARCHIVE_INSTALL_DIR}) - - IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11) - TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib PUBLIC - $ - $) - ENDIF() - -ENDIF() - -IF(BUILD_STATIC_LIBS) - ADD_LIBRARY(jsoncpp_lib_static STATIC ${PUBLIC_HEADERS} ${jsoncpp_sources}) - SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR}) - SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp - DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} ) - - INSTALL( TARGETS jsoncpp_lib_static ${INSTALL_EXPORT} - RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} - LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR} - ARCHIVE DESTINATION ${ARCHIVE_INSTALL_DIR}) - - IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11) - TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib_static PUBLIC - $ - $ - ) - ENDIF() - -ENDIF() diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp deleted file mode 100644 index 8d092737e..000000000 --- a/src/lib_json/json_reader.cpp +++ /dev/null @@ -1,1979 +0,0 @@ -// Copyright 2007-2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below -#define snprintf _snprintf -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -static int const stackLimit_g = 1000; -static int stackDepth_g = 0; // see readValue() - -namespace Json { - -#if __cplusplus >= 201103L -typedef std::unique_ptr CharReaderPtr; -#else -typedef std::auto_ptr CharReaderPtr; -#endif - -// Implementation of class Features -// //////////////////////////////// - -Features::Features() - : allowComments_(true), strictRoot_(false), - allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} - -Features Features::all() { return Features(); } - -Features Features::strictMode() { - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - features.allowDroppedNullPlaceholders_ = false; - features.allowNumericKeys_ = false; - return features; -} - -// Implementation of class Reader -// //////////////////////////////// - -static bool containsNewLine(Reader::Location begin, Reader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; -} - -// Class Reader -// ////////////////////////////////////////////////////////////////// - -Reader::Reader() - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(Features::all()), - collectComments_() {} - -Reader::Reader(const Features& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(features), collectComments_() { -} - -bool -Reader::parse(const std::string& document, Value& root, bool collectComments) { - document_ = document; - const char* begin = document_.c_str(); - const char* end = begin + document_.length(); - return parse(begin, end, root, collectComments); -} - -bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { - // std::istream_iterator begin(sin); - // std::istream_iterator end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since std::string is reference-counted, this at least does not - // create an extra copy. - std::string doc; - std::getline(sin, doc, (char)EOF); - return parse(doc, root, collectComments); -} - -bool Reader::parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; - commentsBefore_ = ""; - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - stackDepth_g = 0; // Yes, this is bad coding, but options are limited. - bool successful = readValue(); - Token token; - skipCommentTokens(token); - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found - // in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); - return false; - } - } - return successful; -} - -bool Reader::readValue() { - // This is a non-reentrant way to support a stackLimit. Terrible! - // But this deprecated class has a security problem: Bad input can - // cause a seg-fault. This seems like a fair, binary-compatible way - // to prevent the problem. - if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); - ++stackDepth_g; - - Token token; - skipCommentTokens(token); - bool successful = true; - - if (collectComments_ && !commentsBefore_.empty()) { - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_ = ""; - } - - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenArrayBegin: - successful = readArray(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: - { - Value v(true); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenFalse: - { - Value v(false); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNull: - { - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenArraySeparator: - case tokenObjectEnd: - case tokenArrayEnd: - if (features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - current_--; - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(current_ - begin_ - 1); - currentValue().setOffsetLimit(current_ - begin_); - break; - } // Else, fall through... - default: - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - --stackDepth_g; - return successful; -} - -void Reader::skipCommentTokens(Token& token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); - } -} - -bool Reader::readToken(Token& token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - -void Reader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; - } -} - -bool Reader::match(Location pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; -} - -bool Reader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') - successful = readCppStyleComment(); - if (!successful) - return false; - - if (collectComments_) { - CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; - } - - addComment(commentBegin, current_, placement); - } - return true; -} - -static std::string normalizeEOL(Reader::Location begin, Reader::Location end) { - std::string normalized; - normalized.reserve(end - begin); - Reader::Location current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') { - if (current != end && *current == '\n') - // convert dos EOL - ++current; - // convert Mac EOL - normalized += '\n'; - } else { - normalized += c; - } - } - return normalized; -} - -void -Reader::addComment(Location begin, Location end, CommentPlacement placement) { - assert(collectComments_); - const std::string& normalized = normalizeEOL(begin, end); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != 0); - lastValue_->setComment(normalized, placement); - } else { - commentsBefore_ += normalized; - } -} - -bool Reader::readCStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; - } - return getNextChar() == '/'; -} - -bool Reader::readCppStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '\n') - break; - if (c == '\r') { - // Consume DOS EOL. It will be normalized in addComment. - if (current_ != end_ && *current_ == '\n') - getNextChar(); - // Break on Moc OS 9 EOL. - break; - } - } - return true; -} - -void Reader::readNumber() { - const char *p = current_; - char c = '0'; // stopgap for already consumed character - // integral part - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : 0; - // fractional part - if (c == '.') { - c = (current_ = p) < end_ ? *p++ : 0; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : 0; - } - // exponential part - if (c == 'e' || c == 'E') { - c = (current_ = p) < end_ ? *p++ : 0; - if (c == '+' || c == '-') - c = (current_ = p) < end_ ? *p++ : 0; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : 0; - } -} - -bool Reader::readString() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; -} - -bool Reader::readObject(Token& tokenStart) { - Token tokenName; - std::string name; - Value init(objectValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object - return true; - name = ""; - if (tokenName.type_ == tokenString) { - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { - Value numberName; - if (!decodeNumber(tokenName, numberName)) - return recoverFromError(tokenObjectEnd); - name = numberName.asString(); - } else { - break; - } - - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); - } - Value& value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); - } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; - } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); -} - -bool Reader::readArray(Token& tokenStart) { - Value init(arrayValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - skipSpaces(); - if (*current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } - int index = 0; - for (;;) { - Value& value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - - Token token; - // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { - ok = readToken(token); - } - bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); - } - if (token.type_ == tokenArrayEnd) - break; - } - return true; -} - -bool Reader::decodeNumber(Token& token) { - Value decoded; - if (!decodeNumber(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeNumber(Token& token, Value& decoded) { - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) - ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of them. - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::LargestUInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return decodeDouble(token, decoded); - Value::UInt digit(c - '0'); - if (value >= threshold) { - // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and - // c) it's small enough to fit in that rounding delta, we're okay. - // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { - return decodeDouble(token, decoded); - } - } - value = value * 10 + digit; - } - if (isNegative && value == maxIntegerValue) - decoded = Value::minLargestInt; - else if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) - decoded = Value::LargestInt(value); - else - decoded = value; - return true; -} - -bool Reader::decodeDouble(Token& token) { - Value decoded; - if (!decodeDouble(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeDouble(Token& token, Value& decoded) { - double value = 0; - std::string buffer(token.start_, token.end_); - std::istringstream is(buffer); - if (!(is >> value)) - return addError("'" + std::string(token.start_, token.end_) + - "' is not a number.", - token); - decoded = value; - return true; -} - -bool Reader::decodeString(Token& token) { - std::string decoded_string; - if (!decodeString(token, decoded_string)) - return false; - Value decoded(decoded_string); - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeString(Token& token, std::string& decoded) { - decoded.reserve(token.end_ - token.start_ - 2); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - else if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); - } - } else { - decoded += c; - } - } - return true; -} - -bool Reader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError( - "additional six characters expected to parse unicode surrogate pair.", - token, - current); - unsigned int surrogatePair; - if (*(current++) == '\\' && *(current++) == 'u') { - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } else - return false; - } else - return addError("expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, - current); - } - return true; -} - -bool Reader::decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, - current); - unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, - current); - } - return true; -} - -bool -Reader::addError(const std::string& message, Token& token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; -} - -bool Reader::recoverFromError(TokenType skipUntilToken) { - int errorCount = int(errors_.size()); - Token skip; - for (;;) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; -} - -bool Reader::addErrorAndRecover(const std::string& message, - Token& token, - TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); -} - -Value& Reader::currentValue() { return *(nodes_.top()); } - -Reader::Char Reader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; -} - -void Reader::getLocationLineAndColumn(Location location, - int& line, - int& column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - -std::string Reader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) -#if defined(WINCE) - _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#else - sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#endif -#else - snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#endif - return buffer; -} - -// Deprecated. Preserved for backward compatibility -std::string Reader::getFormatedErrorMessages() const { - return getFormattedErrorMessages(); -} - -std::string Reader::getFormattedErrorMessages() const { - std::string formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += - "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; -} - -std::vector Reader::getStructuredErrors() const { - std::vector allErrors; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; - Reader::StructuredError structured; - structured.offset_start = error.token_.start_ - begin_; - structured.offset_limit = error.token_.end_ - begin_; - structured.message = error.message_; - allErrors.push_back(structured); - } - return allErrors; -} - -bool Reader::pushError(const Value& value, const std::string& message) { - size_t length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = end_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = 0; - errors_.push_back(info); - return true; -} - -bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) { - size_t length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length - || extra.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = begin_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = begin_ + extra.getOffsetStart(); - errors_.push_back(info); - return true; -} - -bool Reader::good() const { - return !errors_.size(); -} - -// exact copy of Features -class OurFeatures { -public: - static OurFeatures all(); - OurFeatures(); - bool allowComments_; - bool strictRoot_; - bool allowDroppedNullPlaceholders_; - bool allowNumericKeys_; - bool allowSingleQuotes_; - bool failIfExtra_; - bool rejectDupKeys_; - int stackLimit_; -}; // OurFeatures - -// exact copy of Implementation of class Features -// //////////////////////////////// - -OurFeatures::OurFeatures() - : allowComments_(true), strictRoot_(false) - , allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) - , allowSingleQuotes_(false) - , failIfExtra_(false) -{ -} - -OurFeatures OurFeatures::all() { return OurFeatures(); } - -// Implementation of class Reader -// //////////////////////////////// - -// exact copy of Reader, renamed to OurReader -class OurReader { -public: - typedef char Char; - typedef const Char* Location; - struct StructuredError { - size_t offset_start; - size_t offset_limit; - std::string message; - }; - - OurReader(OurFeatures const& features); - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments = true); - std::string getFormattedErrorMessages() const; - std::vector getStructuredErrors() const; - bool pushError(const Value& value, const std::string& message); - bool pushError(const Value& value, const std::string& message, const Value& extra); - bool good() const; - -private: - OurReader(OurReader const&); // no impl - void operator=(OurReader const&); // no impl - - 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 Errors; - - bool readToken(Token& token); - void skipSpaces(); - bool match(Location pattern, int patternLength); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - bool readStringSingleQuote(); - 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 Nodes; - Nodes nodes_; - Errors errors_; - std::string document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value* lastValue_; - std::string commentsBefore_; - int stackDepth_; - - OurFeatures const features_; - bool collectComments_; -}; // OurReader - -// complete copy of Read impl, for OurReader - -OurReader::OurReader(OurFeatures const& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(features), collectComments_() { -} - -bool OurReader::parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; - commentsBefore_ = ""; - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - stackDepth_ = 0; - bool successful = readValue(); - Token token; - skipCommentTokens(token); - if (features_.failIfExtra_) { - if (token.type_ != tokenError && token.type_ != tokenEndOfStream) { - addError("Extra non-whitespace after JSON value.", token); - return false; - } - } - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found - // in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); - return false; - } - } - return successful; -} - -bool OurReader::readValue() { - if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); - ++stackDepth_; - Token token; - skipCommentTokens(token); - bool successful = true; - - if (collectComments_ && !commentsBefore_.empty()) { - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_ = ""; - } - - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenArrayBegin: - successful = readArray(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: - { - Value v(true); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenFalse: - { - Value v(false); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNull: - { - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenArraySeparator: - case tokenObjectEnd: - case tokenArrayEnd: - if (features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - current_--; - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(current_ - begin_ - 1); - currentValue().setOffsetLimit(current_ - begin_); - break; - } // else, fall through ... - default: - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - --stackDepth_; - return successful; -} - -void OurReader::skipCommentTokens(Token& token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); - } -} - -bool OurReader::readToken(Token& token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '\'': - if (features_.allowSingleQuotes_) { - token.type_ = tokenString; - ok = readStringSingleQuote(); - break; - } // else continue - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - -void OurReader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; - } -} - -bool OurReader::match(Location pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; -} - -bool OurReader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') - successful = readCppStyleComment(); - if (!successful) - return false; - - if (collectComments_) { - CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; - } - - addComment(commentBegin, current_, placement); - } - return true; -} - -void -OurReader::addComment(Location begin, Location end, CommentPlacement placement) { - assert(collectComments_); - const std::string& normalized = normalizeEOL(begin, end); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != 0); - lastValue_->setComment(normalized, placement); - } else { - commentsBefore_ += normalized; - } -} - -bool OurReader::readCStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; - } - return getNextChar() == '/'; -} - -bool OurReader::readCppStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '\n') - break; - if (c == '\r') { - // Consume DOS EOL. It will be normalized in addComment. - if (current_ != end_ && *current_ == '\n') - getNextChar(); - // Break on Moc OS 9 EOL. - break; - } - } - return true; -} - -void OurReader::readNumber() { - const char *p = current_; - char c = '0'; // stopgap for already consumed character - // integral part - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : 0; - // fractional part - if (c == '.') { - c = (current_ = p) < end_ ? *p++ : 0; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : 0; - } - // exponential part - if (c == 'e' || c == 'E') { - c = (current_ = p) < end_ ? *p++ : 0; - if (c == '+' || c == '-') - c = (current_ = p) < end_ ? *p++ : 0; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : 0; - } -} -bool OurReader::readString() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; -} - - -bool OurReader::readStringSingleQuote() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '\'') - break; - } - return c == '\''; -} - -bool OurReader::readObject(Token& tokenStart) { - Token tokenName; - std::string name; - Value init(objectValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object - return true; - name = ""; - if (tokenName.type_ == tokenString) { - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { - Value numberName; - if (!decodeNumber(tokenName, numberName)) - return recoverFromError(tokenObjectEnd); - name = numberName.asString(); - } else { - break; - } - - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); - } - if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30"); - if (features_.rejectDupKeys_ && currentValue().isMember(name)) { - std::string msg = "Duplicate key: '" + name + "'"; - return addErrorAndRecover( - msg, tokenName, tokenObjectEnd); - } - Value& value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); - } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; - } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); -} - -bool OurReader::readArray(Token& tokenStart) { - Value init(arrayValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - skipSpaces(); - if (*current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } - int index = 0; - for (;;) { - Value& value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - - Token token; - // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { - ok = readToken(token); - } - bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); - } - if (token.type_ == tokenArrayEnd) - break; - } - return true; -} - -bool OurReader::decodeNumber(Token& token) { - Value decoded; - if (!decodeNumber(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeNumber(Token& token, Value& decoded) { - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) - ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of them. - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(-Value::minLargestInt) - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::LargestUInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return decodeDouble(token, decoded); - Value::UInt digit(c - '0'); - if (value >= threshold) { - // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and - // c) it's small enough to fit in that rounding delta, we're okay. - // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { - return decodeDouble(token, decoded); - } - } - value = value * 10 + digit; - } - if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) - decoded = Value::LargestInt(value); - else - decoded = value; - return true; -} - -bool OurReader::decodeDouble(Token& token) { - Value decoded; - if (!decodeDouble(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeDouble(Token& token, Value& decoded) { - double value = 0; - const int bufferSize = 32; - int count; - int length = int(token.end_ - token.start_); - - // Sanity check to avoid buffer overflow exploits. - if (length < 0) { - return addError("Unable to parse token length", token); - } - - // Avoid using a string constant for the format control string given to - // sscanf, as this can cause hard to debug crashes on OS X. See here for more - // info: - // - // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html - char format[] = "%lf"; - - if (length <= bufferSize) { - Char buffer[bufferSize + 1]; - memcpy(buffer, token.start_, length); - buffer[length] = 0; - count = sscanf(buffer, format, &value); - } else { - std::string buffer(token.start_, token.end_); - count = sscanf(buffer.c_str(), format, &value); - } - - if (count != 1) - return addError("'" + std::string(token.start_, token.end_) + - "' is not a number.", - token); - decoded = value; - return true; -} - -bool OurReader::decodeString(Token& token) { - std::string decoded_string; - if (!decodeString(token, decoded_string)) - return false; - Value decoded(decoded_string); - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeString(Token& token, std::string& decoded) { - decoded.reserve(token.end_ - token.start_ - 2); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - else if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); - } - } else { - decoded += c; - } - } - return true; -} - -bool OurReader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError( - "additional six characters expected to parse unicode surrogate pair.", - token, - current); - unsigned int surrogatePair; - if (*(current++) == '\\' && *(current++) == 'u') { - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } else - return false; - } else - return addError("expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, - current); - } - return true; -} - -bool OurReader::decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode) { - if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, - current); - unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, - current); - } - return true; -} - -bool -OurReader::addError(const std::string& message, Token& token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; -} - -bool OurReader::recoverFromError(TokenType skipUntilToken) { - int errorCount = int(errors_.size()); - Token skip; - for (;;) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; -} - -bool OurReader::addErrorAndRecover(const std::string& message, - Token& token, - TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); -} - -Value& OurReader::currentValue() { return *(nodes_.top()); } - -OurReader::Char OurReader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; -} - -void OurReader::getLocationLineAndColumn(Location location, - int& line, - int& column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - -std::string OurReader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) -#if defined(WINCE) - _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#else - sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#endif -#else - snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); -#endif - return buffer; -} - -std::string OurReader::getFormattedErrorMessages() const { - std::string formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += - "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; -} - -std::vector OurReader::getStructuredErrors() const { - std::vector allErrors; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; - OurReader::StructuredError structured; - structured.offset_start = error.token_.start_ - begin_; - structured.offset_limit = error.token_.end_ - begin_; - structured.message = error.message_; - allErrors.push_back(structured); - } - return allErrors; -} - -bool OurReader::pushError(const Value& value, const std::string& message) { - size_t length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = end_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = 0; - errors_.push_back(info); - return true; -} - -bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) { - size_t length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length - || extra.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = begin_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = begin_ + extra.getOffsetStart(); - errors_.push_back(info); - return true; -} - -bool OurReader::good() const { - return !errors_.size(); -} - - -class OurCharReader : public CharReader { - bool const collectComments_; - OurReader reader_; -public: - OurCharReader( - bool collectComments, - OurFeatures const& features) - : collectComments_(collectComments) - , reader_(features) - {} - virtual bool parse( - char const* beginDoc, char const* endDoc, - Value* root, std::string* errs) { - bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); - if (errs) { - *errs = reader_.getFormattedErrorMessages(); - } - return ok; - } -}; - -CharReaderBuilder::CharReaderBuilder() -{ - setDefaults(&settings_); -} -CharReaderBuilder::~CharReaderBuilder() -{} -CharReader* CharReaderBuilder::newCharReader() const -{ - bool collectComments = settings_["collectComments"].asBool(); - OurFeatures features = OurFeatures::all(); - features.allowComments_ = settings_["allowComments"].asBool(); - features.strictRoot_ = settings_["strictRoot"].asBool(); - features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); - features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); - features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); - features.stackLimit_ = settings_["stackLimit"].asInt(); - features.failIfExtra_ = settings_["failIfExtra"].asBool(); - features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); - return new OurCharReader(collectComments, features); -} -static void getValidReaderKeys(std::set* valid_keys) -{ - valid_keys->clear(); - valid_keys->insert("collectComments"); - valid_keys->insert("allowComments"); - valid_keys->insert("strictRoot"); - valid_keys->insert("allowDroppedNullPlaceholders"); - valid_keys->insert("allowNumericKeys"); - valid_keys->insert("allowSingleQuotes"); - valid_keys->insert("stackLimit"); - valid_keys->insert("failIfExtra"); - valid_keys->insert("rejectDupKeys"); -} -bool CharReaderBuilder::validate(Json::Value* invalid) const -{ - Json::Value my_invalid; - if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL - Json::Value& inv = *invalid; - std::set valid_keys; - getValidReaderKeys(&valid_keys); - Value::Members keys = settings_.getMemberNames(); - size_t n = keys.size(); - for (size_t i = 0; i < n; ++i) { - std::string const& key = keys[i]; - if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = settings_[key]; - } - } - return 0u == inv.size(); -} -Value& CharReaderBuilder::operator[](std::string key) -{ - return settings_[key]; -} -// static -void CharReaderBuilder::strictMode(Json::Value* settings) -{ -//! [CharReaderBuilderStrictMode] - (*settings)["allowComments"] = false; - (*settings)["strictRoot"] = true; - (*settings)["allowDroppedNullPlaceholders"] = false; - (*settings)["allowNumericKeys"] = false; - (*settings)["allowSingleQuotes"] = false; - (*settings)["failIfExtra"] = true; - (*settings)["rejectDupKeys"] = true; -//! [CharReaderBuilderStrictMode] -} -// static -void CharReaderBuilder::setDefaults(Json::Value* settings) -{ -//! [CharReaderBuilderDefaults] - (*settings)["collectComments"] = true; - (*settings)["allowComments"] = true; - (*settings)["strictRoot"] = false; - (*settings)["allowDroppedNullPlaceholders"] = false; - (*settings)["allowNumericKeys"] = false; - (*settings)["allowSingleQuotes"] = false; - (*settings)["stackLimit"] = 1000; - (*settings)["failIfExtra"] = false; - (*settings)["rejectDupKeys"] = false; -//! [CharReaderBuilderDefaults] -} - -////////////////////////////////// -// global functions - -bool parseFromStream( - CharReader::Factory const& fact, std::istream& sin, - Value* root, std::string* errs) -{ - std::ostringstream ssin; - ssin << sin.rdbuf(); - std::string doc = ssin.str(); - char const* begin = doc.data(); - char const* end = begin + doc.size(); - // Note that we do not actually need a null-terminator. - CharReaderPtr const reader(fact.newCharReader()); - return reader->parse(begin, end, root, errs); -} - -std::istream& operator>>(std::istream& sin, Value& root) { - CharReaderBuilder b; - std::string errs; - bool ok = parseFromStream(b, sin, &root, &errs); - if (!ok) { - fprintf(stderr, - "Error from reader: %s", - errs.c_str()); - - throwRuntimeError("reader error"); - } - return sin; -} - -} // namespace Json diff --git a/src/lib_json/json_tool.h b/src/lib_json/json_tool.h deleted file mode 100644 index e65e51b41..000000000 --- a/src/lib_json/json_tool.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED -#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -/* This header provides common string manipulation support, such as UTF-8, - * portable conversion from/to string... - * - * It is an internal header that must not be exposed. - */ - -namespace Json { - -/// Converts a unicode code-point to UTF-8. -static inline std::string codePointToUTF8(unsigned int cp) { - std::string result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) { - result.resize(1); - result[0] = static_cast(cp); - } else if (cp <= 0x7FF) { - result.resize(2); - result[1] = static_cast(0x80 | (0x3f & cp)); - result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); - } else if (cp <= 0xFFFF) { - result.resize(3); - result[2] = static_cast(0x80 | (0x3f & cp)); - result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); - } else if (cp <= 0x10FFFF) { - result.resize(4); - result[3] = static_cast(0x80 | (0x3f & cp)); - result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); - } - - return result; -} - -/// Returns true if ch is a control character (in range [1,31]). -static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } - -enum { - /// Constant that specify the size of the buffer that must be passed to - /// uintToString. - uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 -}; - -// Defines a char buffer for use with uintToString(). -typedef char UIntToStringBuffer[uintToStringBufferSize]; - -/** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string - * @param current Input/Output string buffer. - * Must have at least uintToStringBufferSize chars free. - */ -static inline void uintToString(LargestUInt value, char*& current) { - *--current = 0; - do { - *--current = static_cast(value % 10U + static_cast('0')); - value /= 10; - } while (value != 0); -} - -/** Change ',' to '.' everywhere in buffer. - * - * We had a sophisticated way, but it did not work in WinCE. - * @see https://github.com/open-source-parsers/jsoncpp/pull/9 - */ -static inline void fixNumericLocale(char* begin, char* end) { - while (begin < end) { - if (*begin == ',') { - *begin = '.'; - } - ++begin; - } -} - -} // namespace Json { - -#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp deleted file mode 100644 index 9a16491d0..000000000 --- a/src/lib_json/json_value.cpp +++ /dev/null @@ -1,1528 +0,0 @@ -// Copyright 2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#ifdef JSON_USE_CPPTL -#include -#endif -#include // size_t -#include // min() - -#define JSON_ASSERT_UNREACHABLE assert(false) - -namespace Json { - -// This is a walkaround to avoid the static initialization of Value::null. -// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of -// 8 (instead of 4) as a bit of future-proofing. -#if defined(__ARMEL__) -#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) -#else -#define ALIGNAS(byte_alignment) -#endif -static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; -const unsigned char& kNullRef = kNull[0]; -const Value& Value::null = reinterpret_cast(kNullRef); -const Value& Value::nullRef = null; - -const Int Value::minInt = Int(~(UInt(-1) / 2)); -const Int Value::maxInt = Int(UInt(-1) / 2); -const UInt Value::maxUInt = UInt(-1); -#if defined(JSON_HAS_INT64) -const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); -const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); -const UInt64 Value::maxUInt64 = UInt64(-1); -// The constant is hard-coded because some compiler have trouble -// converting Value::maxUInt64 to a double correctly (AIX/xlC). -// Assumes that UInt64 is a 64 bits integer. -static const double maxUInt64AsDouble = 18446744073709551615.0; -#endif // defined(JSON_HAS_INT64) -const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); -const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); -const LargestUInt Value::maxLargestUInt = LargestUInt(-1); - -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -template -static inline bool InRange(double d, T min, U max) { - return d >= min && d <= max; -} -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -static inline double integerToDouble(Json::UInt64 value) { - return static_cast(Int64(value / 2)) * 2.0 + Int64(value & 1); -} - -template static inline double integerToDouble(T value) { - return static_cast(value); -} - -template -static inline bool InRange(double d, T min, U max) { - return d >= integerToDouble(min) && d <= integerToDouble(max); -} -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - -/** Duplicates the specified string value. - * @param value Pointer to the string to duplicate. Must be zero-terminated if - * length is "unknown". - * @param length Length of the value. if equals to unknown, then it will be - * computed using strlen(value). - * @return Pointer on the duplicate instance of string. - */ -static inline char* duplicateStringValue(const char* value, - size_t length) { - // Avoid an integer overflow in the call to malloc below by limiting length - // to a sane value. - if (length >= (size_t)Value::maxInt) - length = Value::maxInt - 1; - - char* newString = static_cast(malloc(length + 1)); - if (newString == NULL) { - throwRuntimeError( - "in Json::Value::duplicateStringValue(): " - "Failed to allocate string value buffer"); - } - memcpy(newString, value, length); - newString[length] = 0; - return newString; -} - -/* Record the length as a prefix. - */ -static inline char* duplicateAndPrefixStringValue( - const char* value, - unsigned int length) -{ - // Avoid an integer overflow in the call to malloc below by limiting length - // to a sane value. - JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U, - "in Json::Value::duplicateAndPrefixStringValue(): " - "length too big for prefixing"); - unsigned actualLength = length + static_cast(sizeof(unsigned)) + 1U; - char* newString = static_cast(malloc(actualLength)); - if (newString == 0) { - throwRuntimeError( - "in Json::Value::duplicateAndPrefixStringValue(): " - "Failed to allocate string value buffer"); - } - *reinterpret_cast(newString) = length; - memcpy(newString + sizeof(unsigned), value, length); - newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later - return newString; -} -inline static void decodePrefixedString( - bool isPrefixed, char const* prefixed, - unsigned* length, char const** value) -{ - if (!isPrefixed) { - *length = static_cast(strlen(prefixed)); - *value = prefixed; - } else { - *length = *reinterpret_cast(prefixed); - *value = prefixed + sizeof(unsigned); - } -} -/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue(). - */ -static inline void releaseStringValue(char* value) { free(value); } - -} // namespace Json - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#if !defined(JSON_IS_AMALGAMATION) - -#include "json_valueiterator.inl" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -Exception::Exception(std::string const& msg) - : msg_(msg) -{} -Exception::~Exception() throw() -{} -char const* Exception::what() const throw() -{ - return msg_.c_str(); -} -RuntimeError::RuntimeError(std::string const& msg) - : Exception(msg) -{} -LogicError::LogicError(std::string const& msg) - : Exception(msg) -{} -void throwRuntimeError(std::string const& msg) -{ - throw RuntimeError(msg); -} -void throwLogicError(std::string const& msg) -{ - throw LogicError(msg); -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -Value::CommentInfo::CommentInfo() : comment_(0) {} - -Value::CommentInfo::~CommentInfo() { - if (comment_) - releaseStringValue(comment_); -} - -void Value::CommentInfo::setComment(const char* text, size_t len) { - if (comment_) { - releaseStringValue(comment_); - comment_ = 0; - } - JSON_ASSERT(text != 0); - JSON_ASSERT_MESSAGE( - text[0] == '\0' || text[0] == '/', - "in Json::Value::setComment(): Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = duplicateStringValue(text, len); -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CZString -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -// Notes: policy_ indicates if the string was allocated when -// a string is stored. - -Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {} - -Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate) - : cstr_(str) -{ - // allocate != duplicate - storage_.policy_ = allocate & 0x3; - storage_.length_ = ulength & 0x3FFFFFFF; -} - -Value::CZString::CZString(const CZString& other) - : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0 - ? duplicateStringValue(other.cstr_, other.storage_.length_) - : other.cstr_) -{ - storage_.policy_ = (other.cstr_ - ? (static_cast(other.storage_.policy_) == noDuplication - ? noDuplication : duplicate) - : static_cast(other.storage_.policy_)); - storage_.length_ = other.storage_.length_; -} - -Value::CZString::~CZString() { - if (cstr_ && storage_.policy_ == duplicate) - releaseStringValue(const_cast(cstr_)); -} - -void Value::CZString::swap(CZString& other) { - std::swap(cstr_, other.cstr_); - std::swap(index_, other.index_); -} - -Value::CZString& Value::CZString::operator=(CZString other) { - swap(other); - return *this; -} - -bool Value::CZString::operator<(const CZString& other) const { - if (!cstr_) return index_ < other.index_; - //return strcmp(cstr_, other.cstr_) < 0; - // Assume both are strings. - unsigned this_len = this->storage_.length_; - unsigned other_len = other.storage_.length_; - unsigned min_len = std::min(this_len, other_len); - int comp = memcmp(this->cstr_, other.cstr_, min_len); - if (comp < 0) return true; - if (comp > 0) return false; - return (this_len < other_len); -} - -bool Value::CZString::operator==(const CZString& other) const { - if (!cstr_) return index_ == other.index_; - //return strcmp(cstr_, other.cstr_) == 0; - // Assume both are strings. - unsigned this_len = this->storage_.length_; - unsigned other_len = other.storage_.length_; - if (this_len != other_len) return false; - int comp = memcmp(this->cstr_, other.cstr_, this_len); - return comp == 0; -} - -ArrayIndex Value::CZString::index() const { return index_; } - -//const char* Value::CZString::c_str() const { return cstr_; } -const char* Value::CZString::data() const { return cstr_; } -unsigned Value::CZString::length() const { return storage_.length_; } -bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::Value -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/*! \internal Default constructor initialization must be equivalent to: - * memset( this, 0, sizeof(Value) ) - * This optimization is used in ValueInternalMap fast allocator. - */ -Value::Value(ValueType vtype) { - initBasic(vtype); - switch (vtype) { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - value_.string_ = 0; - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -Value::Value(Int value) { - initBasic(intValue); - value_.int_ = value; -} - -Value::Value(UInt value) { - initBasic(uintValue); - value_.uint_ = value; -} -#if defined(JSON_HAS_INT64) -Value::Value(Int64 value) { - initBasic(intValue); - value_.int_ = value; -} -Value::Value(UInt64 value) { - initBasic(uintValue); - value_.uint_ = value; -} -#endif // defined(JSON_HAS_INT64) - -Value::Value(double value) { - initBasic(realValue); - value_.real_ = value; -} - -Value::Value(const char* value) { - initBasic(stringValue, true); - value_.string_ = duplicateAndPrefixStringValue(value, static_cast(strlen(value))); -} - -Value::Value(const char* beginValue, const char* endValue) { - initBasic(stringValue, true); - value_.string_ = - duplicateAndPrefixStringValue(beginValue, static_cast(endValue - beginValue)); -} - -Value::Value(const std::string& value) { - initBasic(stringValue, true); - value_.string_ = - duplicateAndPrefixStringValue(value.data(), static_cast(value.length())); -} - -Value::Value(const StaticString& value) { - initBasic(stringValue); - value_.string_ = const_cast(value.c_str()); -} - -#ifdef JSON_USE_CPPTL -Value::Value(const CppTL::ConstString& value) { - initBasic(stringValue, true); - value_.string_ = duplicateAndPrefixStringValue(value, static_cast(value.length())); -} -#endif - -Value::Value(bool value) { - initBasic(booleanValue); - value_.bool_ = value; -} - -Value::Value(Value const& other) - : type_(other.type_), allocated_(false) - , - comments_(0), start_(other.start_), limit_(other.limit_) -{ - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_ && other.allocated_) { - unsigned len; - char const* str; - decodePrefixedString(other.allocated_, other.value_.string_, - &len, &str); - value_.string_ = duplicateAndPrefixStringValue(str, len); - allocated_ = true; - } else { - value_.string_ = other.value_.string_; - allocated_ = false; - } - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; - default: - JSON_ASSERT_UNREACHABLE; - } - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo& otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment( - otherComment.comment_, strlen(otherComment.comment_)); - } - } -} - -Value::~Value() { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (allocated_) - releaseStringValue(value_.string_); - break; - case arrayValue: - case objectValue: - delete value_.map_; - break; - default: - JSON_ASSERT_UNREACHABLE; - } - - if (comments_) - delete[] comments_; -} - -Value& Value::operator=(Value other) { - swap(other); - return *this; -} - -void Value::swapPayload(Value& other) { - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; - std::swap(value_, other.value_); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2 & 0x1; -} - -void Value::swap(Value& other) { - swapPayload(other); - std::swap(comments_, other.comments_); - std::swap(start_, other.start_); - std::swap(limit_, other.limit_); -} - -ValueType Value::type() const { return type_; } - -int Value::compare(const Value& other) const { - if (*this < other) - return -1; - if (*this > other) - return 1; - return 0; -} - -bool Value::operator<(const Value& other) const { - int typeDelta = type_ - other.type_; - if (typeDelta) - return typeDelta < 0 ? true : false; - switch (type_) { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: - { - if ((value_.string_ == 0) || (other.value_.string_ == 0)) { - if (other.value_.string_) return true; - else return false; - } - unsigned this_len; - unsigned other_len; - char const* this_str; - char const* other_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); - unsigned min_len = std::min(this_len, other_len); - int comp = memcmp(this_str, other_str, min_len); - if (comp < 0) return true; - if (comp > 0) return false; - return (this_len < other_len); - } - case arrayValue: - case objectValue: { - int delta = int(value_.map_->size() - other.value_.map_->size()); - if (delta) - return delta < 0; - return (*value_.map_) < (*other.value_.map_); - } - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator<=(const Value& other) const { return !(other < *this); } - -bool Value::operator>=(const Value& other) const { return !(*this < other); } - -bool Value::operator>(const Value& other) const { return other < *this; } - -bool Value::operator==(const Value& other) const { - // if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if (type_ != temp) - return false; - switch (type_) { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: - { - if ((value_.string_ == 0) || (other.value_.string_ == 0)) { - return (value_.string_ == other.value_.string_); - } - unsigned this_len; - unsigned other_len; - char const* this_str; - char const* other_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); - if (this_len != other_len) return false; - int comp = memcmp(this_str, other_str, this_len); - return comp == 0; - } - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() && - (*value_.map_) == (*other.value_.map_); - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator!=(const Value& other) const { return !(*this == other); } - -const char* Value::asCString() const { - JSON_ASSERT_MESSAGE(type_ == stringValue, - "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == 0) return 0; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - return this_str; -} - -bool Value::getString(char const** str, char const** cend) const { - if (type_ != stringValue) return false; - if (value_.string_ == 0) return false; - unsigned length; - decodePrefixedString(this->allocated_, this->value_.string_, &length, str); - *cend = *str + length; - return true; -} - -std::string Value::asString() const { - switch (type_) { - case nullValue: - return ""; - case stringValue: - { - if (value_.string_ == 0) return ""; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - return std::string(this_str, this_len); - } - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - return valueToString(value_.int_); - case uintValue: - return valueToString(value_.uint_); - case realValue: - return valueToString(value_.real_); - default: - JSON_FAIL_MESSAGE("Type is not convertible to string"); - } -} - -#ifdef JSON_USE_CPPTL -CppTL::ConstString Value::asConstString() const { - unsigned len; - char const* str; - decodePrefixedString(allocated_, value_.string_, - &len, &str); - return CppTL::ConstString(str, len); -} -#endif - -Value::Int Value::asInt() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); - return Int(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); - return Int(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), - "double out of Int range"); - return Int(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int."); -} - -Value::UInt Value::asUInt() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); - return UInt(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); - return UInt(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), - "double out of UInt range"); - return UInt(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt."); -} - -#if defined(JSON_HAS_INT64) - -Value::Int64 Value::asInt64() const { - switch (type_) { - case intValue: - return Int64(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); - return Int64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), - "double out of Int64 range"); - return Int64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int64."); -} - -Value::UInt64 Value::asUInt64() const { - switch (type_) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); - return UInt64(value_.int_); - case uintValue: - return UInt64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), - "double out of UInt64 range"); - return UInt64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); -} -#endif // if defined(JSON_HAS_INT64) - -LargestInt Value::asLargestInt() const { -#if defined(JSON_NO_INT64) - return asInt(); -#else - return asInt64(); -#endif -} - -LargestUInt Value::asLargestUInt() const { -#if defined(JSON_NO_INT64) - return asUInt(); -#else - return asUInt64(); -#endif -} - -double Value::asDouble() const { - switch (type_) { - case intValue: - return static_cast(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return value_.real_; - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to double."); -} - -float Value::asFloat() const { - switch (type_) { - case intValue: - return static_cast(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return static_cast(value_.real_); - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0f : 0.0f; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to float."); -} - -bool Value::asBool() const { - switch (type_) { - case booleanValue: - return value_.bool_; - case nullValue: - return false; - case intValue: - return value_.int_ ? true : false; - case uintValue: - return value_.uint_ ? true : false; - case realValue: - // This is kind of strange. Not recommended. - return (value_.real_ != 0.0) ? true : false; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to bool."); -} - -bool Value::isConvertibleTo(ValueType other) const { - switch (other) { - case nullValue: - return (isNumeric() && asDouble() == 0.0) || - (type_ == booleanValue && value_.bool_ == false) || - (type_ == stringValue && asString() == "") || - (type_ == arrayValue && value_.map_->size() == 0) || - (type_ == objectValue && value_.map_->size() == 0) || - type_ == nullValue; - case intValue: - return isInt() || - (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || - type_ == booleanValue || type_ == nullValue; - case uintValue: - return isUInt() || - (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || - type_ == booleanValue || type_ == nullValue; - case realValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; - case booleanValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; - case stringValue: - return isNumeric() || type_ == booleanValue || type_ == stringValue || - type_ == nullValue; - case arrayValue: - return type_ == arrayValue || type_ == nullValue; - case objectValue: - return type_ == objectValue || type_ == nullValue; - } - JSON_ASSERT_UNREACHABLE; - return false; -} - -/// Number of values in array or object -ArrayIndex Value::size() const { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; - case arrayValue: // size of the array is highest index + 1 - if (!value_.map_->empty()) { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index() + 1; - } - return 0; - case objectValue: - return ArrayIndex(value_.map_->size()); - } - JSON_ASSERT_UNREACHABLE; - return 0; // unreachable; -} - -bool Value::empty() const { - if (isNull() || isArray() || isObject()) - return size() == 0u; - else - return false; -} - -bool Value::operator!() const { return isNull(); } - -void Value::clear() { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || - type_ == objectValue, - "in Json::Value::clear(): requires complex value"); - start_ = 0; - limit_ = 0; - switch (type_) { - case arrayValue: - case objectValue: - value_.map_->clear(); - break; - default: - break; - } -} - -void Value::resize(ArrayIndex newSize) { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, - "in Json::Value::resize(): requires arrayValue"); - if (type_ == nullValue) - *this = Value(arrayValue); - ArrayIndex oldSize = size(); - if (newSize == 0) - clear(); - else if (newSize > oldSize) - (*this)[newSize - 1]; - else { - for (ArrayIndex index = newSize; index < oldSize; ++index) { - value_.map_->erase(index); - } - assert(size() == newSize); - } -} - -Value& Value::operator[](ArrayIndex index) { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, - "in Json::Value::operator[](ArrayIndex): requires arrayValue"); - if (type_ == nullValue) - *this = Value(arrayValue); - CZString key(index); - ObjectValues::iterator it = value_.map_->lower_bound(key); - if (it != value_.map_->end() && (*it).first == key) - return (*it).second; - - ObjectValues::value_type defaultValue(key, nullRef); - it = value_.map_->insert(it, defaultValue); - return (*it).second; -} - -Value& Value::operator[](int index) { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index): index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -const Value& Value::operator[](ArrayIndex index) const { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, - "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); - if (type_ == nullValue) - return nullRef; - CZString key(index); - ObjectValues::const_iterator it = value_.map_->find(key); - if (it == value_.map_->end()) - return nullRef; - return (*it).second; -} - -const Value& Value::operator[](int index) const { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index) const: index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -void Value::initBasic(ValueType vtype, bool allocated) { - type_ = vtype; - allocated_ = allocated; - comments_ = 0; - start_ = 0; - limit_ = 0; -} - -// Access an object value by name, create a null member if it does not exist. -// @pre Type of '*this' is object or null. -// @param key is null-terminated. -Value& Value::resolveReference(const char* key) { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::resolveReference(): requires objectValue"); - if (type_ == nullValue) - *this = Value(objectValue); - CZString actualKey( - key, static_cast(strlen(key)), CZString::noDuplication); // NOTE! - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, nullRef); - it = value_.map_->insert(it, defaultValue); - Value& value = (*it).second; - return value; -} - -// @param key is not null-terminated. -Value& Value::resolveReference(char const* key, char const* cend) -{ - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::resolveReference(key, end): requires objectValue"); - if (type_ == nullValue) - *this = Value(objectValue); - CZString actualKey( - key, static_cast(cend-key), CZString::duplicateOnCopy); - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, nullRef); - it = value_.map_->insert(it, defaultValue); - Value& value = (*it).second; - return value; -} - -Value Value::get(ArrayIndex index, const Value& defaultValue) const { - const Value* value = &((*this)[index]); - return value == &nullRef ? defaultValue : *value; -} - -bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } - -Value const* Value::find(char const* key, char const* cend) const -{ - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::find(key, end, found): requires objectValue or nullValue"); - if (type_ == nullValue) return NULL; - CZString actualKey(key, static_cast(cend-key), CZString::noDuplication); - ObjectValues::const_iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) return NULL; - return &(*it).second; -} -const Value& Value::operator[](const char* key) const -{ - Value const* found = find(key, key + strlen(key)); - if (!found) return nullRef; - return *found; -} -Value const& Value::operator[](std::string const& key) const -{ - Value const* found = find(key.data(), key.data() + key.length()); - if (!found) return nullRef; - return *found; -} - -Value& Value::operator[](const char* key) { - return resolveReference(key, key + strlen(key)); -} - -Value& Value::operator[](const std::string& key) { - return resolveReference(key.data(), key.data() + key.length()); -} - -Value& Value::operator[](const StaticString& key) { - return resolveReference(key.c_str()); -} - -#ifdef JSON_USE_CPPTL -Value& Value::operator[](const CppTL::ConstString& key) { - return resolveReference(key.c_str(), key.end_c_str()); -} -Value const& Value::operator[](CppTL::ConstString const& key) const -{ - Value const* found = find(key.c_str(), key.end_c_str()); - if (!found) return nullRef; - return *found; -} -#endif - -Value& Value::append(const Value& value) { return (*this)[size()] = value; } - -Value Value::get(char const* key, char const* cend, Value const& defaultValue) const -{ - Value const* found = find(key, cend); - return !found ? defaultValue : *found; -} -Value Value::get(char const* key, Value const& defaultValue) const -{ - return get(key, key + strlen(key), defaultValue); -} -Value Value::get(std::string const& key, Value const& defaultValue) const -{ - return get(key.data(), key.data() + key.length(), defaultValue); -} - - -bool Value::removeMember(const char* key, const char* cend, Value* removed) -{ - if (type_ != objectValue) { - return false; - } - CZString actualKey(key, static_cast(cend-key), CZString::noDuplication); - ObjectValues::iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return false; - *removed = it->second; - value_.map_->erase(it); - return true; -} -bool Value::removeMember(const char* key, Value* removed) -{ - return removeMember(key, key + strlen(key), removed); -} -bool Value::removeMember(std::string const& key, Value* removed) -{ - return removeMember(key.data(), key.data() + key.length(), removed); -} -Value Value::removeMember(const char* key) -{ - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, - "in Json::Value::removeMember(): requires objectValue"); - if (type_ == nullValue) - return nullRef; - - Value removed; // null - removeMember(key, key + strlen(key), &removed); - return removed; // still null if removeMember() did nothing -} -Value Value::removeMember(const std::string& key) -{ - return removeMember(key.c_str()); -} - -bool Value::removeIndex(ArrayIndex index, Value* removed) { - if (type_ != arrayValue) { - return false; - } - CZString key(index); - ObjectValues::iterator it = value_.map_->find(key); - if (it == value_.map_->end()) { - return false; - } - *removed = it->second; - ArrayIndex oldSize = size(); - // shift left all items left, into the place of the "removed" - for (ArrayIndex i = index; i < (oldSize - 1); ++i){ - CZString keey(i); - (*value_.map_)[keey] = (*this)[i + 1]; - } - // erase the last one ("leftover") - CZString keyLast(oldSize - 1); - ObjectValues::iterator itLast = value_.map_->find(keyLast); - value_.map_->erase(itLast); - return true; -} - -#ifdef JSON_USE_CPPTL -Value Value::get(const CppTL::ConstString& key, - const Value& defaultValue) const { - return get(key.c_str(), key.end_c_str(), defaultValue); -} -#endif - -bool Value::isMember(char const* key, char const* cend) const -{ - Value const* value = find(key, cend); - return NULL != value; -} -bool Value::isMember(char const* key) const -{ - return isMember(key, key + strlen(key)); -} -bool Value::isMember(std::string const& key) const -{ - return isMember(key.data(), key.data() + key.length()); -} - -#ifdef JSON_USE_CPPTL -bool Value::isMember(const CppTL::ConstString& key) const { - return isMember(key.c_str(), key.end_c_str()); -} -#endif - -Value::Members Value::getMemberNames() const { - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::getMemberNames(), value must be objectValue"); - if (type_ == nullValue) - return Value::Members(); - Members members; - members.reserve(value_.map_->size()); - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for (; it != itEnd; ++it) { - members.push_back(std::string((*it).first.data(), - (*it).first.length())); - } - return members; -} -// -//# ifdef JSON_USE_CPPTL -// EnumMemberNames -// Value::enumMemberNames() const -//{ -// if ( type_ == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -// EnumValues -// Value::enumValues() const -//{ -// if ( type_ == objectValue || type_ == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type() ); -// return EnumValues(); -//} -// -//# endif - -static bool IsIntegral(double d) { - double integral_part; - return modf(d, &integral_part) == 0.0; -} - -bool Value::isNull() const { return type_ == nullValue; } - -bool Value::isBool() const { return type_ == booleanValue; } - -bool Value::isInt() const { - switch (type_) { - case intValue: - return value_.int_ >= minInt && value_.int_ <= maxInt; - case uintValue: - return value_.uint_ <= UInt(maxInt); - case realValue: - return value_.real_ >= minInt && value_.real_ <= maxInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isUInt() const { - switch (type_) { - case intValue: - return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); - case uintValue: - return value_.uint_ <= maxUInt; - case realValue: - return value_.real_ >= 0 && value_.real_ <= maxUInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isInt64() const { -#if defined(JSON_HAS_INT64) - switch (type_) { - case intValue: - return true; - case uintValue: - return value_.uint_ <= UInt64(maxInt64); - case realValue: - // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a - // double, so double(maxInt64) will be rounded up to 2^63. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && - value_.real_ < double(maxInt64) && IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isUInt64() const { -#if defined(JSON_HAS_INT64) - switch (type_) { - case intValue: - return value_.int_ >= 0; - case uintValue: - return true; - case realValue: - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && - IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isIntegral() const { -#if defined(JSON_HAS_INT64) - return isInt64() || isUInt64(); -#else - return isInt() || isUInt(); -#endif -} - -bool Value::isDouble() const { return type_ == realValue || isIntegral(); } - -bool Value::isNumeric() const { return isIntegral() || isDouble(); } - -bool Value::isString() const { return type_ == stringValue; } - -bool Value::isArray() const { return type_ == arrayValue; } - -bool Value::isObject() const { return type_ == objectValue; } - -void Value::setComment(const char* comment, size_t len, CommentPlacement placement) { - if (!comments_) - comments_ = new CommentInfo[numberOfCommentPlacement]; - if ((len > 0) && (comment[len-1] == '\n')) { - // Always discard trailing newline, to aid indentation. - len -= 1; - } - comments_[placement].setComment(comment, len); -} - -void Value::setComment(const char* comment, CommentPlacement placement) { - setComment(comment, strlen(comment), placement); -} - -void Value::setComment(const std::string& comment, CommentPlacement placement) { - setComment(comment.c_str(), comment.length(), placement); -} - -bool Value::hasComment(CommentPlacement placement) const { - return comments_ != 0 && comments_[placement].comment_ != 0; -} - -std::string Value::getComment(CommentPlacement placement) const { - if (hasComment(placement)) - return comments_[placement].comment_; - return ""; -} - -void Value::setOffsetStart(size_t start) { start_ = start; } - -void Value::setOffsetLimit(size_t limit) { limit_ = limit; } - -size_t Value::getOffsetStart() const { return start_; } - -size_t Value::getOffsetLimit() const { return limit_; } - -std::string Value::toStyledString() const { - StyledWriter writer; - return writer.write(*this); -} - -Value::const_iterator Value::begin() const { - switch (type_) { - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->begin()); - break; - default: - break; - } - return const_iterator(); -} - -Value::const_iterator Value::end() const { - switch (type_) { - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->end()); - break; - default: - break; - } - return const_iterator(); -} - -Value::iterator Value::begin() { - switch (type_) { - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->begin()); - break; - default: - break; - } - return iterator(); -} - -Value::iterator Value::end() { - switch (type_) { - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->end()); - break; - default: - break; - } - return iterator(); -} - -// class PathArgument -// ////////////////////////////////////////////////////////////////// - -PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} - -PathArgument::PathArgument(ArrayIndex index) - : key_(), index_(index), kind_(kindIndex) {} - -PathArgument::PathArgument(const char* key) - : key_(key), index_(), kind_(kindKey) {} - -PathArgument::PathArgument(const std::string& key) - : key_(key.c_str()), index_(), kind_(kindKey) {} - -// class Path -// ////////////////////////////////////////////////////////////////// - -Path::Path(const std::string& path, - const PathArgument& a1, - const PathArgument& a2, - const PathArgument& a3, - const PathArgument& a4, - const PathArgument& a5) { - InArgs in; - in.push_back(&a1); - in.push_back(&a2); - in.push_back(&a3); - in.push_back(&a4); - in.push_back(&a5); - makePath(path, in); -} - -void Path::makePath(const std::string& path, const InArgs& in) { - const char* current = path.c_str(); - const char* end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); - while (current != end) { - if (*current == '[') { - ++current; - if (*current == '%') - addPathInArg(path, in, itInArg, PathArgument::kindIndex); - else { - ArrayIndex index = 0; - for (; current != end && *current >= '0' && *current <= '9'; ++current) - index = index * 10 + ArrayIndex(*current - '0'); - args_.push_back(index); - } - if (current == end || *current++ != ']') - invalidPath(path, int(current - path.c_str())); - } else if (*current == '%') { - addPathInArg(path, in, itInArg, PathArgument::kindKey); - ++current; - } else if (*current == '.') { - ++current; - } else { - const char* beginName = current; - while (current != end && !strchr("[.", *current)) - ++current; - args_.push_back(std::string(beginName, current)); - } - } -} - -void Path::addPathInArg(const std::string& /*path*/, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind) { - if (itInArg == in.end()) { - // Error: missing argument %d - } else if ((*itInArg)->kind_ != kind) { - // Error: bad argument type - } else { - args_.push_back(**itInArg); - } -} - -void Path::invalidPath(const std::string& /*path*/, int /*location*/) { - // Error: invalid path. -} - -const Value& Path::resolve(const Value& root) const { - const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) { - // Error: unable to resolve path (array value expected at position... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: unable to resolve path (object value expected at position...) - } - node = &((*node)[arg.key_]); - if (node == &Value::nullRef) { - // Error: unable to resolve path (object has no member named '' at - // position...) - } - } - } - return *node; -} - -Value Path::resolve(const Value& root, const Value& defaultValue) const { - const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) - return defaultValue; - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) - return defaultValue; - node = &((*node)[arg.key_]); - if (node == &Value::nullRef) - return defaultValue; - } - } - return *node; -} - -Value& Path::make(Value& root) const { - Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray()) { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: node is not an object at position... - } - node = &((*node)[arg.key_]); - } - } - return *node; -} - -} // namespace Json diff --git a/src/lib_json/json_valueiterator.inl b/src/lib_json/json_valueiterator.inl deleted file mode 100644 index b3bbc354f..000000000 --- a/src/lib_json/json_valueiterator.inl +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -// included by json_value.cpp - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIteratorBase -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIteratorBase::ValueIteratorBase() - : current_(), isNull_(true) { -} - -ValueIteratorBase::ValueIteratorBase( - const Value::ObjectValues::iterator& current) - : current_(current), isNull_(false) {} - -Value& ValueIteratorBase::deref() const { - return current_->second; -} - -void ValueIteratorBase::increment() { - ++current_; -} - -void ValueIteratorBase::decrement() { - --current_; -} - -ValueIteratorBase::difference_type -ValueIteratorBase::computeDistance(const SelfType& other) const { -#ifdef JSON_USE_CPPTL_SMALLMAP - return other.current_ - current_; -#else - // Iterator for null value are initialized using the default - // constructor, which initialize current_ to the default - // std::map::iterator. As begin() and end() are two instance - // of the default std::map::iterator, they can not be compared. - // To allow this, we handle this comparison specifically. - if (isNull_ && other.isNull_) { - return 0; - } - - // Usage of std::distance is not portable (does not compile with Sun Studio 12 - // RogueWave STL, - // which is the one used by default). - // Using a portable hand-made version for non random iterator instead: - // return difference_type( std::distance( current_, other.current_ ) ); - difference_type myDistance = 0; - for (Value::ObjectValues::iterator it = current_; it != other.current_; - ++it) { - ++myDistance; - } - return myDistance; -#endif -} - -bool ValueIteratorBase::isEqual(const SelfType& other) const { - if (isNull_) { - return other.isNull_; - } - return current_ == other.current_; -} - -void ValueIteratorBase::copy(const SelfType& other) { - current_ = other.current_; - isNull_ = other.isNull_; -} - -Value ValueIteratorBase::key() const { - const Value::CZString czstring = (*current_).first; - if (czstring.data()) { - if (czstring.isStaticString()) - return Value(StaticString(czstring.data())); - return Value(czstring.data(), czstring.data() + czstring.length()); - } - return Value(czstring.index()); -} - -UInt ValueIteratorBase::index() const { - const Value::CZString czstring = (*current_).first; - if (!czstring.data()) - return czstring.index(); - return Value::UInt(-1); -} - -std::string ValueIteratorBase::name() const { - char const* keey; - char const* end; - keey = memberName(&end); - if (!keey) return std::string(); - return std::string(keey, end); -} - -char const* ValueIteratorBase::memberName() const { - const char* cname = (*current_).first.data(); - return cname ? cname : ""; -} - -char const* ValueIteratorBase::memberName(char const** end) const { - const char* cname = (*current_).first.data(); - if (!cname) { - *end = NULL; - return NULL; - } - *end = cname + (*current_).first.length(); - return cname; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueConstIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueConstIterator::ValueConstIterator() {} - -ValueConstIterator::ValueConstIterator( - const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} - -ValueConstIterator& ValueConstIterator:: -operator=(const ValueIteratorBase& other) { - copy(other); - return *this; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIterator::ValueIterator() {} - -ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} - -ValueIterator::ValueIterator(const ValueConstIterator& other) - : ValueIteratorBase(other) {} - -ValueIterator::ValueIterator(const ValueIterator& other) - : ValueIteratorBase(other) {} - -ValueIterator& ValueIterator::operator=(const SelfType& other) { - copy(other); - return *this; -} - -} // namespace Json diff --git a/src/lib_json/json_writer.cpp b/src/lib_json/json_writer.cpp deleted file mode 100644 index 89cd65131..000000000 --- a/src/lib_json/json_writer.cpp +++ /dev/null @@ -1,1182 +0,0 @@ -// Copyright 2011 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include "json_tool.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 -#include -#define isfinite _finite -#elif defined(__sun) && defined(__SVR4) //Solaris -#include -#define isfinite finite -#else -#include -#define isfinite std::isfinite -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below -#define snprintf _snprintf -#elif defined(__ANDROID__) -#define snprintf snprintf -#elif __cplusplus >= 201103L -#define snprintf std::snprintf -#endif - -#if defined(__BORLANDC__) -#include -#define isfinite _finite -#define snprintf _snprintf -#endif - -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -namespace Json { - -#if __cplusplus >= 201103L -typedef std::unique_ptr StreamWriterPtr; -#else -typedef std::auto_ptr StreamWriterPtr; -#endif - -static bool containsControlCharacter(const char* str) { - while (*str) { - if (isControlCharacter(*(str++))) - return true; - } - return false; -} - -static bool containsControlCharacter0(const char* str, unsigned len) { - char const* end = str + len; - while (end != str) { - if (isControlCharacter(*str) || 0==*str) - return true; - ++str; - } - return false; -} - -std::string valueToString(LargestInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - if (value == Value::minLargestInt) { - uintToString(LargestUInt(Value::maxLargestInt) + 1, current); - *--current = '-'; - } else if (value < 0) { - uintToString(LargestUInt(-value), current); - *--current = '-'; - } else { - uintToString(LargestUInt(value), current); - } - assert(current >= buffer); - return current; -} - -std::string valueToString(LargestUInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - uintToString(value, current); - assert(current >= buffer); - return current; -} - -#if defined(JSON_HAS_INT64) - -std::string valueToString(Int value) { - return valueToString(LargestInt(value)); -} - -std::string valueToString(UInt value) { - return valueToString(LargestUInt(value)); -} - -#endif // # if defined(JSON_HAS_INT64) - -std::string valueToString(double value) { - // Allocate a buffer that is more than large enough to store the 16 digits of - // precision requested below. - char buffer[32]; - int len = -1; - -// Print into the buffer. We need not request the alternative representation -// that always has a decimal point because JSON doesn't distingish the -// concepts of reals and integers. -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with - // visual studio 2005 to - // avoid warning. -#if defined(WINCE) - len = _snprintf(buffer, sizeof(buffer), "%.17g", value); -#else - len = sprintf_s(buffer, sizeof(buffer), "%.17g", value); -#endif -#else - if (isfinite(value)) { - len = snprintf(buffer, sizeof(buffer), "%.17g", value); - } else { - // IEEE standard states that NaN values will not compare to themselves - if (value != value) { - len = snprintf(buffer, sizeof(buffer), "null"); - } else if (value < 0) { - len = snprintf(buffer, sizeof(buffer), "-1e+9999"); - } else { - len = snprintf(buffer, sizeof(buffer), "1e+9999"); - } - // For those, we do not need to call fixNumLoc, but it is fast. - } -#endif - assert(len >= 0); - fixNumericLocale(buffer, buffer + len); - return buffer; -} - -std::string valueToString(bool value) { return value ? "true" : "false"; } - -std::string valueToQuotedString(const char* value) { - if (value == NULL) - return ""; - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && - !containsControlCharacter(value)) - return std::string("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to std::string is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - std::string::size_type maxsize = - strlen(value) * 2 + 3; // allescaped+quotes+NULL - std::string result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char* c = value; *c != 0; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); - result += oss.str(); - } else { - result += *c; - } - break; - } - } - result += "\""; - return result; -} - -// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp -static char const* strnpbrk(char const* s, char const* accept, size_t n) { - assert((s || !n) && accept); - - char const* const end = s + n; - for (char const* cur = s; cur < end; ++cur) { - int const c = *cur; - for (char const* a = accept; *a; ++a) { - if (*a == c) { - return cur; - } - } - } - return NULL; -} -static std::string valueToQuotedStringN(const char* value, unsigned length) { - if (value == NULL) - return ""; - // Not sure how to handle unicode... - if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && - !containsControlCharacter0(value, length)) - return std::string("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to std::string is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - std::string::size_type maxsize = - length * 2 + 3; // allescaped+quotes+NULL - std::string result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - char const* end = value + length; - for (const char* c = value; c != end; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something.) - // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); - result += oss.str(); - } else { - result += *c; - } - break; - } - } - result += "\""; - return result; -} - -// Class Writer -// ////////////////////////////////////////////////////////////////// -Writer::~Writer() {} - -// Class FastWriter -// ////////////////////////////////////////////////////////////////// - -FastWriter::FastWriter() - : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), - omitEndingLineFeed_(false) {} - -void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } - -void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } - -void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } - -std::string FastWriter::write(const Value& root) { - document_ = ""; - writeValue(root); - if (!omitEndingLineFeed_) - document_ += "\n"; - return document_; -} - -void FastWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - if (!dropNullPlaceholders_) - document_ += "null"; - break; - case intValue: - document_ += valueToString(value.asLargestInt()); - break; - case uintValue: - document_ += valueToString(value.asLargestUInt()); - break; - case realValue: - document_ += valueToString(value.asDouble()); - break; - case stringValue: - { - // Is NULL possible for value.string_? - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) document_ += valueToQuotedStringN(str, static_cast(end-str)); - break; - } - case booleanValue: - document_ += valueToString(value.asBool()); - break; - case arrayValue: { - document_ += '['; - int size = value.size(); - for (int index = 0; index < size; ++index) { - if (index > 0) - document_ += ','; - writeValue(value[index]); - } - document_ += ']'; - } break; - case objectValue: { - Value::Members members(value.getMemberNames()); - document_ += '{'; - for (Value::Members::iterator it = members.begin(); it != members.end(); - ++it) { - const std::string& name = *it; - if (it != members.begin()) - document_ += ','; - document_ += valueToQuotedStringN(name.data(), static_cast(name.length())); - document_ += yamlCompatiblityEnabled_ ? ": " : ":"; - writeValue(value[name]); - } - document_ += '}'; - } break; - } -} - -// Class StyledWriter -// ////////////////////////////////////////////////////////////////// - -StyledWriter::StyledWriter() - : rightMargin_(74), indentSize_(3), addChildValues_() {} - -std::string StyledWriter::write(const Value& root) { - document_ = ""; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - document_ += "\n"; - return document_; -} - -void StyledWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - { - // Is NULL possible for value.string_? - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); - else pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - const std::string& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - document_ += " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ','; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ','; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - document_ += "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - document_ += ", "; - document_ += childValues_[index]; - } - document_ += " ]"; - } - } -} - -bool StyledWriter::isMultineArray(const Value& value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = - isMultiLine || ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (int index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledWriter::pushValue(const std::string& value) { - if (addChildValues_) - childValues_.push_back(value); - else - document_ += value; -} - -void StyledWriter::writeIndent() { - if (!document_.empty()) { - char last = document_[document_.length() - 1]; - if (last == ' ') // already indented - return; - if (last != '\n') // Comments may add new-line - document_ += '\n'; - } - document_ += indentString_; -} - -void StyledWriter::writeWithIndent(const std::string& value) { - writeIndent(); - document_ += value; -} - -void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } - -void StyledWriter::unindent() { - assert(int(indentString_.size()) >= indentSize_); - indentString_.resize(indentString_.size() - indentSize_); -} - -void StyledWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - - document_ += "\n"; - writeIndent(); - const std::string& comment = root.getComment(commentBefore); - std::string::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - document_ += *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) - writeIndent(); - ++iter; - } - - // Comments are stripped of trailing newlines, so add one here - document_ += "\n"; -} - -void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - document_ += " " + root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - document_ += "\n"; - document_ += root.getComment(commentAfter); - document_ += "\n"; - } -} - -bool StyledWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -// Class StyledStreamWriter -// ////////////////////////////////////////////////////////////////// - -StyledStreamWriter::StyledStreamWriter(std::string indentation) - : document_(NULL), rightMargin_(74), indentation_(indentation), - addChildValues_() {} - -void StyledStreamWriter::write(std::ostream& out, const Value& root) { - document_ = &out; - addChildValues_ = false; - indentString_ = ""; - indented_ = true; - writeCommentBeforeValue(root); - if (!indented_) writeIndent(); - indented_ = true; - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *document_ << "\n"; - document_ = NULL; // Forget the stream, for safety. -} - -void StyledStreamWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - { - // Is NULL possible for value.string_? - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); - else pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - const std::string& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - *document_ << " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledStreamWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - if (!indented_) writeIndent(); - indented_ = true; - writeValue(childValue); - indented_ = false; - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *document_ << "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *document_ << ", "; - *document_ << childValues_[index]; - } - *document_ << " ]"; - } - } -} - -bool StyledStreamWriter::isMultineArray(const Value& value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = - isMultiLine || ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (int index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledStreamWriter::pushValue(const std::string& value) { - if (addChildValues_) - childValues_.push_back(value); - else - *document_ << value; -} - -void StyledStreamWriter::writeIndent() { - // blep intended this to look at the so-far-written string - // to determine whether we are already indented, but - // with a stream we cannot do that. So we rely on some saved state. - // The caller checks indented_. - *document_ << '\n' << indentString_; -} - -void StyledStreamWriter::writeWithIndent(const std::string& value) { - if (!indented_) writeIndent(); - *document_ << value; - indented_ = false; -} - -void StyledStreamWriter::indent() { indentString_ += indentation_; } - -void StyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); -} - -void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - - if (!indented_) writeIndent(); - const std::string& comment = root.getComment(commentBefore); - std::string::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - *document_ << *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) - // writeIndent(); // would include newline - *document_ << indentString_; - ++iter; - } - indented_ = false; -} - -void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - *document_ << ' ' << root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - writeIndent(); - *document_ << root.getComment(commentAfter); - } - indented_ = false; -} - -bool StyledStreamWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -////////////////////////// -// BuiltStyledStreamWriter - -/// Scoped enums are not available until C++11. -struct CommentStyle { - /// Decide whether to write comments. - enum Enum { - None, ///< Drop all comments. - Most, ///< Recover odd behavior of previous versions (not implemented yet). - All ///< Keep all comments. - }; -}; - -struct BuiltStyledStreamWriter : public StreamWriter -{ - BuiltStyledStreamWriter( - std::string const& indentation, - CommentStyle::Enum cs, - std::string const& colonSymbol, - std::string const& nullSymbol, - std::string const& endingLineFeedSymbol); - virtual int write(Value const& root, std::ostream* sout); -private: - void writeValue(Value const& value); - void writeArrayValue(Value const& value); - bool isMultineArray(Value const& value); - void pushValue(std::string const& value); - void writeIndent(); - void writeWithIndent(std::string const& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(Value const& root); - void writeCommentAfterValueOnSameLine(Value const& root); - static bool hasCommentForValue(const Value& value); - - typedef std::vector ChildValues; - - ChildValues childValues_; - std::string indentString_; - int rightMargin_; - std::string indentation_; - CommentStyle::Enum cs_; - std::string colonSymbol_; - std::string nullSymbol_; - std::string endingLineFeedSymbol_; - bool addChildValues_ : 1; - bool indented_ : 1; -}; -BuiltStyledStreamWriter::BuiltStyledStreamWriter( - std::string const& indentation, - CommentStyle::Enum cs, - std::string const& colonSymbol, - std::string const& nullSymbol, - std::string const& endingLineFeedSymbol) - : rightMargin_(74) - , indentation_(indentation) - , cs_(cs) - , colonSymbol_(colonSymbol) - , nullSymbol_(nullSymbol) - , endingLineFeedSymbol_(endingLineFeedSymbol) - , addChildValues_(false) - , indented_(false) -{ -} -int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout) -{ - sout_ = sout; - addChildValues_ = false; - indented_ = true; - indentString_ = ""; - writeCommentBeforeValue(root); - if (!indented_) writeIndent(); - indented_ = true; - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *sout_ << endingLineFeedSymbol_; - sout_ = NULL; - return 0; -} -void BuiltStyledStreamWriter::writeValue(Value const& value) { - switch (value.type()) { - case nullValue: - pushValue(nullSymbol_); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: - { - // Is NULL is possible for value.string_? - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast(end-str))); - else pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - Value::Members::iterator it = members.begin(); - for (;;) { - std::string const& name = *it; - Value const& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedStringN(name.data(), static_cast(name.length()))); - *sout_ << colonSymbol_; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *sout_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); - if (isMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - Value const& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - if (!indented_) writeIndent(); - indented_ = true; - writeValue(childValue); - indented_ = false; - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *sout_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *sout_ << "["; - if (!indentation_.empty()) *sout_ << " "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *sout_ << ", "; - *sout_ << childValues_[index]; - } - if (!indentation_.empty()) *sout_ << " "; - *sout_ << "]"; - } - } -} - -bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { - int size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (int index = 0; index < size && !isMultiLine; ++index) { - Value const& childValue = value[index]; - isMultiLine = - isMultiLine || ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (int index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += int(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void BuiltStyledStreamWriter::pushValue(std::string const& value) { - if (addChildValues_) - childValues_.push_back(value); - else - *sout_ << value; -} - -void BuiltStyledStreamWriter::writeIndent() { - // blep intended this to look at the so-far-written string - // to determine whether we are already indented, but - // with a stream we cannot do that. So we rely on some saved state. - // The caller checks indented_. - - if (!indentation_.empty()) { - // In this case, drop newlines too. - *sout_ << '\n' << indentString_; - } -} - -void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) { - if (!indented_) writeIndent(); - *sout_ << value; - indented_ = false; -} - -void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } - -void BuiltStyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); -} - -void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { - if (cs_ == CommentStyle::None) return; - if (!root.hasComment(commentBefore)) - return; - - if (!indented_) writeIndent(); - const std::string& comment = root.getComment(commentBefore); - std::string::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - *sout_ << *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) - // writeIndent(); // would write extra newline - *sout_ << indentString_; - ++iter; - } - indented_ = false; -} - -void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) { - if (cs_ == CommentStyle::None) return; - if (root.hasComment(commentAfterOnSameLine)) - *sout_ << " " + root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - writeIndent(); - *sout_ << root.getComment(commentAfter); - } -} - -// static -bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -/////////////// -// StreamWriter - -StreamWriter::StreamWriter() - : sout_(NULL) -{ -} -StreamWriter::~StreamWriter() -{ -} -StreamWriter::Factory::~Factory() -{} -StreamWriterBuilder::StreamWriterBuilder() -{ - setDefaults(&settings_); -} -StreamWriterBuilder::~StreamWriterBuilder() -{} -StreamWriter* StreamWriterBuilder::newStreamWriter() const -{ - std::string indentation = settings_["indentation"].asString(); - std::string cs_str = settings_["commentStyle"].asString(); - bool eyc = settings_["enableYAMLCompatibility"].asBool(); - bool dnp = settings_["dropNullPlaceholders"].asBool(); - CommentStyle::Enum cs = CommentStyle::All; - if (cs_str == "All") { - cs = CommentStyle::All; - } else if (cs_str == "None") { - cs = CommentStyle::None; - } else { - throwRuntimeError("commentStyle must be 'All' or 'None'"); - } - std::string colonSymbol = " : "; - if (eyc) { - colonSymbol = ": "; - } else if (indentation.empty()) { - colonSymbol = ":"; - } - std::string nullSymbol = "null"; - if (dnp) { - nullSymbol = ""; - } - std::string endingLineFeedSymbol = ""; - return new BuiltStyledStreamWriter( - indentation, cs, - colonSymbol, nullSymbol, endingLineFeedSymbol); -} -static void getValidWriterKeys(std::set* valid_keys) -{ - valid_keys->clear(); - valid_keys->insert("indentation"); - valid_keys->insert("commentStyle"); - valid_keys->insert("enableYAMLCompatibility"); - valid_keys->insert("dropNullPlaceholders"); -} -bool StreamWriterBuilder::validate(Json::Value* invalid) const -{ - Json::Value my_invalid; - if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL - Json::Value& inv = *invalid; - std::set valid_keys; - getValidWriterKeys(&valid_keys); - Value::Members keys = settings_.getMemberNames(); - size_t n = keys.size(); - for (size_t i = 0; i < n; ++i) { - std::string const& key = keys[i]; - if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = settings_[key]; - } - } - return 0u == inv.size(); -} -Value& StreamWriterBuilder::operator[](std::string key) -{ - return settings_[key]; -} -// static -void StreamWriterBuilder::setDefaults(Json::Value* settings) -{ - //! [StreamWriterBuilderDefaults] - (*settings)["commentStyle"] = "All"; - (*settings)["indentation"] = "\t"; - (*settings)["enableYAMLCompatibility"] = false; - (*settings)["dropNullPlaceholders"] = false; - //! [StreamWriterBuilderDefaults] -} - -std::string writeString(StreamWriter::Factory const& builder, Value const& root) { - std::ostringstream sout; - StreamWriterPtr const writer(builder.newStreamWriter()); - writer->write(root, &sout); - return sout.str(); -} - -std::ostream& operator<<(std::ostream& sout, Value const& root) { - StreamWriterBuilder builder; - StreamWriterPtr const writer(builder.newStreamWriter()); - writer->write(root, &sout); - return sout; -} - -} // namespace Json diff --git a/src/lib_json/sconscript b/src/lib_json/sconscript deleted file mode 100644 index 6e7c6c8a0..000000000 --- a/src/lib_json/sconscript +++ /dev/null @@ -1,8 +0,0 @@ -Import( 'env buildLibrary' ) - -buildLibrary( env, Split( """ - json_reader.cpp - json_value.cpp - json_writer.cpp - """ ), - 'json' ) diff --git a/src/lib_json/version.h.in b/src/lib_json/version.h.in deleted file mode 100644 index 692ab5ede..000000000 --- a/src/lib_json/version.h.in +++ /dev/null @@ -1,13 +0,0 @@ -// DO NOT EDIT. This file (and "version") is generated by CMake. -// Run CMake configure step to update it. -#ifndef JSON_VERSION_H_INCLUDED -# define JSON_VERSION_H_INCLUDED - -# define JSONCPP_VERSION_STRING "@JSONCPP_VERSION@" -# define JSONCPP_VERSION_MAJOR @JSONCPP_VERSION_MAJOR@ -# define JSONCPP_VERSION_MINOR @JSONCPP_VERSION_MINOR@ -# define JSONCPP_VERSION_PATCH @JSONCPP_VERSION_PATCH@ -# define JSONCPP_VERSION_QUALIFIER -# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) - -#endif // JSON_VERSION_H_INCLUDED diff --git a/src/test_lib_json/CMakeLists.txt b/src/test_lib_json/CMakeLists.txt deleted file mode 100644 index 7000264a7..000000000 --- a/src/test_lib_json/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# vim: et ts=4 sts=4 sw=4 tw=0 - -ADD_EXECUTABLE( jsoncpp_test - jsontest.cpp - jsontest.h - main.cpp - ) - - -IF(BUILD_SHARED_LIBS) - ADD_DEFINITIONS( -DJSON_DLL ) - TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib) -ELSE(BUILD_SHARED_LIBS) - TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib_static) -ENDIF() - -# another way to solve issue #90 -#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store) - -# Run unit tests in post-build -# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?) -IF(JSONCPP_WITH_POST_BUILD_UNITTEST) - IF(BUILD_SHARED_LIBS) - # First, copy the shared lib, for Microsoft. - # Then, run the test executable. - ADD_CUSTOM_COMMAND( TARGET jsoncpp_test - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ - COMMAND $) - ELSE(BUILD_SHARED_LIBS) - # Just run the test executable. - ADD_CUSTOM_COMMAND( TARGET jsoncpp_test - POST_BUILD - COMMAND $) - ENDIF() -ENDIF() - -SET_TARGET_PROPERTIES(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test) diff --git a/src/test_lib_json/jsontest.cpp b/src/test_lib_json/jsontest.cpp deleted file mode 100644 index bd9463fa5..000000000 --- a/src/test_lib_json/jsontest.cpp +++ /dev/null @@ -1,443 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#define _CRT_SECURE_NO_WARNINGS 1 // Prevents deprecation warning with MSVC -#include "jsontest.h" -#include -#include - -#if defined(_MSC_VER) -// Used to install a report hook that prevent dialog on assertion and error. -#include -#endif // if defined(_MSC_VER) - -#if defined(_WIN32) -// Used to prevent dialog on memory fault. -// Limits headers included by Windows.h -#define WIN32_LEAN_AND_MEAN -#define NOSERVICE -#define NOMCX -#define NOIME -#define NOSOUND -#define NOCOMM -#define NORPC -#define NOGDI -#define NOUSER -#define NODRIVERS -#define NOLOGERROR -#define NOPROFILER -#define NOMEMMGR -#define NOLFILEIO -#define NOOPENFILE -#define NORESOURCE -#define NOATOM -#define NOLANGUAGE -#define NOLSTRING -#define NODBCS -#define NOKEYBOARDINFO -#define NOGDICAPMASKS -#define NOCOLOR -#define NOGDIOBJ -#define NODRAWTEXT -#define NOTEXTMETRIC -#define NOSCALABLEFONT -#define NOBITMAP -#define NORASTEROPS -#define NOMETAFILE -#define NOSYSMETRICS -#define NOSYSTEMPARAMSINFO -#define NOMSG -#define NOWINSTYLES -#define NOWINOFFSETS -#define NOSHOWWINDOW -#define NODEFERWINDOWPOS -#define NOVIRTUALKEYCODES -#define NOKEYSTATES -#define NOWH -#define NOMENUS -#define NOSCROLL -#define NOCLIPBOARD -#define NOICONS -#define NOMB -#define NOSYSCOMMANDS -#define NOMDI -#define NOCTLMGR -#define NOWINMESSAGES -#include -#endif // if defined(_WIN32) - -namespace JsonTest { - -// class TestResult -// ////////////////////////////////////////////////////////////////// - -TestResult::TestResult() - : predicateId_(1), lastUsedPredicateId_(0), messageTarget_(0) { - // The root predicate has id 0 - rootPredicateNode_.id_ = 0; - rootPredicateNode_.next_ = 0; - predicateStackTail_ = &rootPredicateNode_; -} - -void TestResult::setTestName(const std::string& name) { name_ = name; } - -TestResult& -TestResult::addFailure(const char* file, unsigned int line, const char* expr) { - /// Walks the PredicateContext stack adding them to failures_ if not already - /// added. - unsigned int nestingLevel = 0; - PredicateContext* lastNode = rootPredicateNode_.next_; - for (; lastNode != 0; lastNode = lastNode->next_) { - if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext - { - lastUsedPredicateId_ = lastNode->id_; - addFailureInfo( - lastNode->file_, lastNode->line_, lastNode->expr_, nestingLevel); - // Link the PredicateContext to the failure for message target when - // popping the PredicateContext. - lastNode->failure_ = &(failures_.back()); - } - ++nestingLevel; - } - - // Adds the failed assertion - addFailureInfo(file, line, expr, nestingLevel); - messageTarget_ = &(failures_.back()); - return *this; -} - -void TestResult::addFailureInfo(const char* file, - unsigned int line, - const char* expr, - unsigned int nestingLevel) { - Failure failure; - failure.file_ = file; - failure.line_ = line; - if (expr) { - failure.expr_ = expr; - } - failure.nestingLevel_ = nestingLevel; - failures_.push_back(failure); -} - -TestResult& TestResult::popPredicateContext() { - PredicateContext* lastNode = &rootPredicateNode_; - while (lastNode->next_ != 0 && lastNode->next_->next_ != 0) { - lastNode = lastNode->next_; - } - // Set message target to popped failure - PredicateContext* tail = lastNode->next_; - if (tail != 0 && tail->failure_ != 0) { - messageTarget_ = tail->failure_; - } - // Remove tail from list - predicateStackTail_ = lastNode; - lastNode->next_ = 0; - return *this; -} - -bool TestResult::failed() const { return !failures_.empty(); } - -unsigned int TestResult::getAssertionNestingLevel() const { - unsigned int level = 0; - const PredicateContext* lastNode = &rootPredicateNode_; - while (lastNode->next_ != 0) { - lastNode = lastNode->next_; - ++level; - } - return level; -} - -void TestResult::printFailure(bool printTestName) const { - if (failures_.empty()) { - return; - } - - if (printTestName) { - printf("* Detail of %s test failure:\n", name_.c_str()); - } - - // 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()); - } - } -} - -std::string TestResult::indentText(const std::string& text, - const std::string& indent) { - 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::addToLastFailure(const std::string& message) { - if (messageTarget_ != 0) { - messageTarget_->message_ += message; - } - return *this; -} - -TestResult& TestResult::operator<<(Json::Int64 value) { - return addToLastFailure(Json::valueToString(value)); -} - -TestResult& TestResult::operator<<(Json::UInt64 value) { - return addToLastFailure(Json::valueToString(value)); -} - -TestResult& TestResult::operator<<(bool value) { - return addToLastFailure(value ? "true" : "false"); -} - -// class TestCase -// ////////////////////////////////////////////////////////////////// - -TestCase::TestCase() : result_(0) {} - -TestCase::~TestCase() {} - -void TestCase::run(TestResult& result) { - result_ = &result; - runTestCase(); -} - -// class Runner -// ////////////////////////////////////////////////////////////////// - -Runner::Runner() {} - -Runner& Runner::add(TestCaseFactory factory) { - tests_.push_back(factory); - return *this; -} - -unsigned int Runner::testCount() const { - return static_cast(tests_.size()); -} - -std::string Runner::testNameAt(unsigned int index) const { - TestCase* test = tests_[index](); - 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 - try { -#endif // if JSON_USE_EXCEPTION - test->run(result); -#if JSON_USE_EXCEPTION - } - catch (const std::exception& e) { - result.addFailure(__FILE__, __LINE__, "Unexpected exception caught:") - << e.what(); - } -#endif // if JSON_USE_EXCEPTION - delete test; - const char* status = result.failed() ? "FAILED" : "OK"; - printf("%s\n", status); - fflush(stdout); -} - -bool Runner::runAllTest(bool printSummary) const { - unsigned int count = testCount(); - std::deque failures; - for (unsigned int index = 0; index < count; ++index) { - TestResult result; - runTestAt(index, result); - if (result.failed()) { - failures.push_back(result); - } - } - - if (failures.empty()) { - if (printSummary) { - printf("All %d tests passed\n", count); - } - return true; - } else { - for (unsigned int index = 0; index < failures.size(); ++index) { - TestResult& result = failures[index]; - result.printFailure(count > 1); - } - - if (printSummary) { - unsigned int failedCount = static_cast(failures.size()); - unsigned int passedCount = count - failedCount; - printf("%d/%d tests passed (%d failure(s))\n", - 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 false; -} - -void Runner::listTests() const { - unsigned int count = testCount(); - for (unsigned int index = 0; index < count; ++index) { - printf("%s\n", testNameAt(index).c_str()); - } -} - -int Runner::runCommandLine(int argc, const char* argv[]) const { - // typedef std::deque 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 -static int -msvcrtSilentReportHook(int reportType, char* message, int* /*returnValue*/) { - // The default CRT handling of error and assertion is to display - // an error dialog to the user. - // Instead, when an error or an assertion occurs, we force the - // application to terminate using abort() after display - // the message on stderr. - if (reportType == _CRT_ERROR || reportType == _CRT_ASSERT) { - // calling abort() cause the ReportHook to be called - // The following is used to detect this case and let's the - // error handler fallback on its default behaviour ( - // display a warning message) - static volatile bool isAborting = false; - if (isAborting) { - return TRUE; - } - isAborting = true; - - fprintf(stderr, "CRT Error/Assert:\n%s\n", message); - fflush(stderr); - abort(); - } - // Let's other reportType (_CRT_WARNING) be handled as they would by default - return FALSE; -} -#endif // if defined(_MSC_VER) - -void Runner::preventDialogOnCrash() { -#if defined(_MSC_VER) && defined(_DEBUG) - // Install a hook to prevent MSVCRT error and assertion from - // popping a dialog - // This function a NO-OP in release configuration - // (which cause warning since msvcrtSilentReportHook is not referenced) - _CrtSetReportHook(&msvcrtSilentReportHook); -#endif // if defined(_MSC_VER) - -// @todo investiguate this handler (for buffer overflow) -// _set_security_error_handler - -#if defined(_WIN32) - // Prevents the system from popping a dialog for debugging if the - // application fails due to invalid memory access. - SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | - SEM_NOOPENFILEERRORBOX); -#endif // if defined(_WIN32) -} - -void Runner::printUsage(const char* appName) { - printf("Usage: %s [options]\n" - "\n" - "If --test is not specified, then all the test cases be run.\n" - "\n" - "Valid options:\n" - "--list-tests: print the name of all test cases on the standard\n" - " output and exit.\n" - "--test TESTNAME: executes the test case with the specified name.\n" - " May be repeated.\n" - "--test-auto: prevent dialog prompting for debugging on crash.\n", - appName); -} - -// Assertion functions -// ////////////////////////////////////////////////////////////////// - -TestResult& checkStringEqual(TestResult& result, - const std::string& expected, - const std::string& actual, - const char* file, - unsigned int line, - const char* expr) { - if (expected != actual) { - result.addFailure(file, line, expr); - result << "Expected: '" << expected << "'\n"; - result << "Actual : '" << actual << "'"; - } - return result; -} - -} // namespace JsonTest diff --git a/src/test_lib_json/jsontest.h b/src/test_lib_json/jsontest.h deleted file mode 100644 index d6b7cf386..000000000 --- a/src/test_lib_json/jsontest.h +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSONTEST_H_INCLUDED -#define JSONTEST_H_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// Mini Unit Testing framework -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/** \brief Unit testing framework. - * \warning: all assertions are non-aborting, test case execution will continue - * even if an assertion namespace. - * This constraint is for portability: the framework needs to compile - * on Visual Studio 6 and must not require exception usage. - */ -namespace JsonTest { - -class Failure { -public: - const char* file_; - unsigned int line_; - std::string expr_; - std::string message_; - unsigned int nestingLevel_; -}; - -/// Context used to create the assertion callstack on failure. -/// Must be a POD to allow inline initialisation without stepping -/// into the debugger. -struct PredicateContext { - 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 { -public: - TestResult(); - - /// \internal Implementation detail for assertion macros - /// 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 - PredicateContext* predicateStackTail_; - - void setTestName(const std::string& name); - - /// Adds an assertion failure. - TestResult& - addFailure(const char* file, unsigned int line, const char* expr = 0); - - /// Removes the last PredicateContext added to the predicate stack - /// chained list. - /// Next messages will be targed at the PredicateContext that was removed. - TestResult& popPredicateContext(); - - bool failed() const; - - void printFailure(bool printTestName) const; - - // Generic operator that will work with anything ostream can deal with. - template TestResult& operator<<(const T& value) { - std::ostringstream oss; - oss.precision(16); - oss.setf(std::ios_base::floatfield); - oss << value; - return addToLastFailure(oss.str()); - } - - // 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); - -private: - TestResult& addToLastFailure(const std::string& message); - unsigned int getAssertionNestingLevel() const; - /// 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 Failures; - Failures failures_; - std::string name_; - PredicateContext rootPredicateNode_; - PredicateContext::Id lastUsedPredicateId_; - /// Failure which is the target of the messages added using operator << - Failure* messageTarget_; -}; - -class TestCase { -public: - TestCase(); - - virtual ~TestCase(); - - void run(TestResult& result); - - virtual const char* testName() const = 0; - -protected: - TestResult* result_; - -private: - virtual void runTestCase() = 0; -}; - -/// Function pointer type for TestCase factory -typedef TestCase* (*TestCaseFactory)(); - -class Runner { -public: - Runner(); - - /// Adds a test to the suite - Runner& add(TestCaseFactory factory); - - /// Runs test as specified on the command-line - /// 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 is provided, then run test testname. - int runCommandLine(int argc, const char* argv[]) const; - - /// Runs all the test cases - bool runAllTest(bool printSummary) const; - - /// Returns the number of test case in the suite - unsigned int testCount() const; - - /// Returns the name of the test case at the specified index - std::string testNameAt(unsigned int index) const; - - /// Runs the test case at the specified index using the specified TestResult - void runTestAt(unsigned int index, TestResult& result) const; - - static void printUsage(const char* appName); - -private: // prevents copy construction and assignment - Runner(const Runner& other); - Runner& operator=(const Runner& other); - -private: - void listTests() const; - bool testIndex(const std::string& testName, unsigned int& index) const; - static void preventDialogOnCrash(); - -private: - typedef std::deque Factories; - Factories tests_; -}; - -template -TestResult& checkEqual(TestResult& result, - T expected, - U actual, - const char* file, - unsigned int line, - const char* expr) { - if (static_cast(expected) != actual) { - result.addFailure(file, line, expr); - result << "Expected: " << static_cast(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 - -/// \brief Asserts that the given expression is true. -/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y; -/// JSONTEST_ASSERT( x == y ); -#define JSONTEST_ASSERT(expr) \ - if (expr) { \ - } else \ - result_->addFailure(__FILE__, __LINE__, #expr) - -/// \brief Asserts that the given predicate is true. -/// The predicate may do other assertions and be a member function of the -/// fixture. -#define JSONTEST_ASSERT_PRED(expr) \ - { \ - JsonTest::PredicateContext _minitest_Context = { \ - result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL \ - }; \ - result_->predicateStackTail_->next_ = &_minitest_Context; \ - result_->predicateId_ += 1; \ - result_->predicateStackTail_ = &_minitest_Context; \ - (expr); \ - result_->popPredicateContext(); \ - } - -/// \brief Asserts that two values are equals. -#define JSONTEST_ASSERT_EQUAL(expected, actual) \ - JsonTest::checkEqual(*result_, \ - expected, \ - actual, \ - __FILE__, \ - __LINE__, \ - #expected " == " #actual) - -/// \brief Asserts that two values are equals. -#define JSONTEST_ASSERT_STRING_EQUAL(expected, actual) \ - JsonTest::checkStringEqual(*result_, \ - std::string(expected), \ - std::string(actual), \ - __FILE__, \ - __LINE__, \ - #expected " == " #actual) - -/// \brief Asserts that a given expression throws an exception -#define JSONTEST_ASSERT_THROWS(expr) \ - { \ - bool _threw = false; \ - try { \ - expr; \ - } \ - catch (...) { \ - _threw = true; \ - } \ - if (!_threw) \ - result_->addFailure( \ - __FILE__, __LINE__, "expected exception thrown: " #expr); \ - } - -/// \brief Begin a fixture test case. -#define JSONTEST_FIXTURE(FixtureType, name) \ - class Test##FixtureType##name : public FixtureType { \ - public: \ - static JsonTest::TestCase* factory() { \ - return new Test##FixtureType##name(); \ - } \ - \ - public: /* overidden from TestCase */ \ - virtual const char* testName() const { return #FixtureType "/" #name; } \ - virtual void runTestCase(); \ - }; \ - \ - void Test##FixtureType##name::runTestCase() - -#define JSONTEST_FIXTURE_FACTORY(FixtureType, name) \ - &Test##FixtureType##name::factory - -#define JSONTEST_REGISTER_FIXTURE(runner, FixtureType, name) \ - (runner).add(JSONTEST_FIXTURE_FACTORY(FixtureType, name)) - -#endif // ifndef JSONTEST_H_INCLUDED diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp deleted file mode 100644 index 364195975..000000000 --- a/src/test_lib_json/main.cpp +++ /dev/null @@ -1,2406 +0,0 @@ -// Copyright 2007-2010 Baptiste Lepilleur -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#include "jsontest.h" -#include -#include -#include - -// Make numeric limits more convenient to talk about. -// Assumes int type in 32 bits. -#define kint32max Json::Value::maxInt -#define kint32min Json::Value::minInt -#define kuint32max Json::Value::maxUInt -#define kint64max Json::Value::maxInt64 -#define kint64min Json::Value::minInt64 -#define kuint64max Json::Value::maxUInt64 - -//static const double kdint64max = double(kint64max); -//static const float kfint64max = float(kint64max); -static const float kfint32max = float(kint32max); -static const float kfuint32max = float(kuint32max); - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// Json Library test cases -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -static inline double uint64ToDouble(Json::UInt64 value) { - return static_cast(value); -} -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -static inline double uint64ToDouble(Json::UInt64 value) { - return static_cast(Json::Int64(value / 2)) * 2.0 + - Json::Int64(value & 1); -} -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - -struct ValueTest : JsonTest::TestCase { - Json::Value null_; - Json::Value emptyArray_; - Json::Value emptyObject_; - Json::Value integer_; - Json::Value unsignedInteger_; - Json::Value smallUnsignedInteger_; - Json::Value real_; - Json::Value float_; - Json::Value array1_; - Json::Value object1_; - Json::Value emptyString_; - Json::Value string1_; - Json::Value string_; - Json::Value true_; - Json::Value false_; - - ValueTest() - : emptyArray_(Json::arrayValue), emptyObject_(Json::objectValue), - integer_(123456789), unsignedInteger_(34567890u), - smallUnsignedInteger_(Json::Value::UInt(Json::Value::maxInt)), - real_(1234.56789), float_(0.00390625f), emptyString_(""), string1_("a"), - string_("sometext with space"), true_(true), false_(false) { - array1_.append(1234); - object1_["id"] = 1234; - } - - struct IsCheck { - /// Initialize all checks to \c false by default. - IsCheck(); - - bool isObject_; - bool isArray_; - bool isBool_; - bool isString_; - bool isNull_; - - bool isInt_; - bool isInt64_; - bool isUInt_; - bool isUInt64_; - bool isIntegral_; - bool isDouble_; - bool isNumeric_; - }; - - void checkConstMemberCount(const Json::Value& value, - unsigned int expectedCount); - - void checkMemberCount(Json::Value& value, unsigned int expectedCount); - - void checkIs(const Json::Value& value, const IsCheck& check); - - void checkIsLess(const Json::Value& x, const Json::Value& y); - - void checkIsEqual(const Json::Value& x, const Json::Value& y); - - /// Normalize the representation of floating-point number by stripped leading - /// 0 in exponent. - static std::string normalizeFloatingPointStr(const std::string& s); -}; - -std::string ValueTest::normalizeFloatingPointStr(const std::string& s) { - std::string::size_type index = s.find_last_of("eE"); - 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 - { - exponent = s.substr(indexDigit); - } - return normalized + exponent; - } - return s; -} - -JSONTEST_FIXTURE(ValueTest, checkNormalizeFloatingPointStr) { - JSONTEST_ASSERT_STRING_EQUAL("0.0", normalizeFloatingPointStr("0.0")); - JSONTEST_ASSERT_STRING_EQUAL("0e0", normalizeFloatingPointStr("0e0")); - JSONTEST_ASSERT_STRING_EQUAL("1234.0", normalizeFloatingPointStr("1234.0")); - JSONTEST_ASSERT_STRING_EQUAL("1234.0e0", - normalizeFloatingPointStr("1234.0e0")); - JSONTEST_ASSERT_STRING_EQUAL("1234.0e+0", - normalizeFloatingPointStr("1234.0e+0")); - JSONTEST_ASSERT_STRING_EQUAL("1234e-1", normalizeFloatingPointStr("1234e-1")); - JSONTEST_ASSERT_STRING_EQUAL("1234e10", normalizeFloatingPointStr("1234e10")); - JSONTEST_ASSERT_STRING_EQUAL("1234e10", - normalizeFloatingPointStr("1234e010")); - JSONTEST_ASSERT_STRING_EQUAL("1234e+10", - normalizeFloatingPointStr("1234e+010")); - JSONTEST_ASSERT_STRING_EQUAL("1234e-10", - normalizeFloatingPointStr("1234e-010")); - JSONTEST_ASSERT_STRING_EQUAL("1234e+100", - normalizeFloatingPointStr("1234e+100")); - JSONTEST_ASSERT_STRING_EQUAL("1234e-100", - normalizeFloatingPointStr("1234e-100")); - JSONTEST_ASSERT_STRING_EQUAL("1234e+1", - normalizeFloatingPointStr("1234e+001")); -} - -JSONTEST_FIXTURE(ValueTest, memberCount) { - JSONTEST_ASSERT_PRED(checkMemberCount(emptyArray_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(emptyObject_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(array1_, 1)); - JSONTEST_ASSERT_PRED(checkMemberCount(object1_, 1)); - JSONTEST_ASSERT_PRED(checkMemberCount(null_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(integer_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(unsignedInteger_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(smallUnsignedInteger_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(real_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(emptyString_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(string_, 0)); - JSONTEST_ASSERT_PRED(checkMemberCount(true_, 0)); -} - -JSONTEST_FIXTURE(ValueTest, objects) { - // Types - IsCheck checks; - checks.isObject_ = true; - JSONTEST_ASSERT_PRED(checkIs(emptyObject_, checks)); - JSONTEST_ASSERT_PRED(checkIs(object1_, checks)); - - JSONTEST_ASSERT_EQUAL(Json::objectValue, emptyObject_.type()); - - // Empty object okay - JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::nullValue)); - - // Non-empty object not okay - JSONTEST_ASSERT(!object1_.isConvertibleTo(Json::nullValue)); - - // Always okay - JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::objectValue)); - - // Never okay - JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::stringValue)); - - // Access through const reference - const Json::Value& constObject = object1_; - - JSONTEST_ASSERT_EQUAL(Json::Value(1234), constObject["id"]); - JSONTEST_ASSERT_EQUAL(Json::Value(), constObject["unknown id"]); - - // Access through non-const reference - JSONTEST_ASSERT_EQUAL(Json::Value(1234), object1_["id"]); - JSONTEST_ASSERT_EQUAL(Json::Value(), object1_["unknown id"]); - - object1_["some other id"] = "foo"; - JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]); - JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]); - - // Remove. - Json::Value got; - bool did; - did = object1_.removeMember("some other id", &got); - JSONTEST_ASSERT_EQUAL(Json::Value("foo"), got); - JSONTEST_ASSERT_EQUAL(true, did); - got = Json::Value("bar"); - did = object1_.removeMember("some other id", &got); - JSONTEST_ASSERT_EQUAL(Json::Value("bar"), got); - JSONTEST_ASSERT_EQUAL(false, did); -} - -JSONTEST_FIXTURE(ValueTest, arrays) { - const unsigned int index0 = 0; - - // Types - IsCheck checks; - checks.isArray_ = true; - JSONTEST_ASSERT_PRED(checkIs(emptyArray_, checks)); - JSONTEST_ASSERT_PRED(checkIs(array1_, checks)); - - JSONTEST_ASSERT_EQUAL(Json::arrayValue, array1_.type()); - - // Empty array okay - JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::nullValue)); - - // Non-empty array not okay - JSONTEST_ASSERT(!array1_.isConvertibleTo(Json::nullValue)); - - // Always okay - JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::arrayValue)); - - // Never okay - JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::objectValue)); - JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::stringValue)); - - // Access through const reference - const Json::Value& constArray = array1_; - JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[index0]); - JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[0]); - - // Access through non-const reference - JSONTEST_ASSERT_EQUAL(Json::Value(1234), array1_[index0]); - JSONTEST_ASSERT_EQUAL(Json::Value(1234), array1_[0]); - - array1_[2] = Json::Value(17); - JSONTEST_ASSERT_EQUAL(Json::Value(), array1_[1]); - JSONTEST_ASSERT_EQUAL(Json::Value(17), array1_[2]); - Json::Value got; - JSONTEST_ASSERT_EQUAL(true, array1_.removeIndex(2, &got)); - JSONTEST_ASSERT_EQUAL(Json::Value(17), got); - JSONTEST_ASSERT_EQUAL(false, array1_.removeIndex(2, &got)); // gone now -} -JSONTEST_FIXTURE(ValueTest, arrayIssue252) -{ - int count = 5; - Json::Value root; - Json::Value item; - root["array"] = Json::Value::nullRef; - for (int i = 0; i < count; i++) - { - item["a"] = i; - item["b"] = i; - root["array"][i] = item; - } - //JSONTEST_ASSERT_EQUAL(5, root["array"].size()); -} - -JSONTEST_FIXTURE(ValueTest, null) { - JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type()); - - IsCheck checks; - checks.isNull_ = true; - JSONTEST_ASSERT_PRED(checkIs(null_, checks)); - - JSONTEST_ASSERT(null_.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(null_.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(null_.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(null_.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(null_.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(null_.isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(null_.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(null_.isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT_EQUAL(Json::Int(0), null_.asInt()); - JSONTEST_ASSERT_EQUAL(Json::LargestInt(0), null_.asLargestInt()); - JSONTEST_ASSERT_EQUAL(Json::UInt(0), null_.asUInt()); - JSONTEST_ASSERT_EQUAL(Json::LargestUInt(0), null_.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(0.0, null_.asDouble()); - JSONTEST_ASSERT_EQUAL(0.0, null_.asFloat()); - JSONTEST_ASSERT_STRING_EQUAL("", null_.asString()); - - JSONTEST_ASSERT_EQUAL(Json::Value::null, null_); -} - -JSONTEST_FIXTURE(ValueTest, strings) { - JSONTEST_ASSERT_EQUAL(Json::stringValue, string1_.type()); - - IsCheck checks; - checks.isString_ = true; - JSONTEST_ASSERT_PRED(checkIs(emptyString_, checks)); - JSONTEST_ASSERT_PRED(checkIs(string_, checks)); - JSONTEST_ASSERT_PRED(checkIs(string1_, checks)); - - // Empty string okay - JSONTEST_ASSERT(emptyString_.isConvertibleTo(Json::nullValue)); - - // Non-empty string not okay - JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::nullValue)); - - // Always okay - JSONTEST_ASSERT(string1_.isConvertibleTo(Json::stringValue)); - - // Never okay - JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::objectValue)); - JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::realValue)); - - JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asString()); - JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asCString()); -} - -JSONTEST_FIXTURE(ValueTest, bools) { - JSONTEST_ASSERT_EQUAL(Json::booleanValue, false_.type()); - - IsCheck checks; - checks.isBool_ = true; - JSONTEST_ASSERT_PRED(checkIs(false_, checks)); - JSONTEST_ASSERT_PRED(checkIs(true_, checks)); - - // False okay - JSONTEST_ASSERT(false_.isConvertibleTo(Json::nullValue)); - - // True not okay - JSONTEST_ASSERT(!true_.isConvertibleTo(Json::nullValue)); - - // Always okay - JSONTEST_ASSERT(true_.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(true_.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(true_.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(true_.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(true_.isConvertibleTo(Json::stringValue)); - - // Never okay - JSONTEST_ASSERT(!true_.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!true_.isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT_EQUAL(true, true_.asBool()); - JSONTEST_ASSERT_EQUAL(1, true_.asInt()); - JSONTEST_ASSERT_EQUAL(1, true_.asLargestInt()); - JSONTEST_ASSERT_EQUAL(1, true_.asUInt()); - JSONTEST_ASSERT_EQUAL(1, true_.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(1.0, true_.asDouble()); - JSONTEST_ASSERT_EQUAL(1.0, true_.asFloat()); - - JSONTEST_ASSERT_EQUAL(false, false_.asBool()); - JSONTEST_ASSERT_EQUAL(0, false_.asInt()); - JSONTEST_ASSERT_EQUAL(0, false_.asLargestInt()); - JSONTEST_ASSERT_EQUAL(0, false_.asUInt()); - JSONTEST_ASSERT_EQUAL(0, false_.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(0.0, false_.asDouble()); - JSONTEST_ASSERT_EQUAL(0.0, false_.asFloat()); -} - -JSONTEST_FIXTURE(ValueTest, integers) { - IsCheck checks; - Json::Value val; - - // Conversions that don't depend on the value. - JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::objectValue)); - - // Default int - val = Json::Value(Json::intValue); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(0, val.asInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(0, val.asUInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); - JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); - JSONTEST_ASSERT_EQUAL(false, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); - - // Default uint - val = Json::Value(Json::uintValue); - - JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(0, val.asInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(0, val.asUInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); - JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); - JSONTEST_ASSERT_EQUAL(false, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); - - // Default real - val = Json::Value(Json::realValue); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT_EQUAL(0, val.asInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(0, val.asUInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); - JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); - JSONTEST_ASSERT_EQUAL(false, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); - - // Zero (signed constructor arg) - val = Json::Value(0); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(0, val.asInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(0, val.asUInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); - JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); - JSONTEST_ASSERT_EQUAL(false, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); - - // Zero (unsigned constructor arg) - val = Json::Value(0u); - - JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(0, val.asInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(0, val.asUInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); - JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); - JSONTEST_ASSERT_EQUAL(false, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); - - // Zero (floating-point constructor arg) - val = Json::Value(0.0); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(0, val.asInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(0, val.asUInt()); - JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); - JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); - JSONTEST_ASSERT_EQUAL(false, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); - - // 2^20 (signed constructor arg) - val = Json::Value(1 << 20); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString()); - - // 2^20 (unsigned constructor arg) - val = Json::Value(Json::UInt(1 << 20)); - - JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString()); - - // 2^20 (floating-point constructor arg) - val = Json::Value((1 << 20) / 1.0); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); - JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1048576", - normalizeFloatingPointStr(val.asString())); - - // -2^20 - val = Json::Value(-(1 << 20)); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asInt()); - JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asDouble()); - JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("-1048576", val.asString()); - - // int32 max - val = Json::Value(kint32max); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(kint32max, val.asInt()); - JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(kint32max, val.asUInt()); - JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(kint32max, val.asDouble()); - JSONTEST_ASSERT_EQUAL(kfint32max, val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("2147483647", val.asString()); - - // int32 min - val = Json::Value(kint32min); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt_ = true; - checks.isInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(kint32min, val.asInt()); - JSONTEST_ASSERT_EQUAL(kint32min, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(kint32min, val.asDouble()); - JSONTEST_ASSERT_EQUAL(kint32min, val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("-2147483648", val.asString()); - - // uint32 max - val = Json::Value(kuint32max); - - JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); - - checks = IsCheck(); - checks.isInt64_ = true; - checks.isUInt_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - -#ifndef JSON_NO_INT64 - JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestInt()); -#endif - JSONTEST_ASSERT_EQUAL(kuint32max, val.asUInt()); - JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(kuint32max, val.asDouble()); - JSONTEST_ASSERT_EQUAL(kfuint32max, val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("4294967295", val.asString()); - -#ifdef JSON_NO_INT64 - // int64 max - val = Json::Value(double(kint64max)); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("9.22337e+18", val.asString()); - - // int64 min - val = Json::Value(double(kint64min)); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("-9.22337e+18", val.asString()); - - // uint64 max - val = Json::Value(double(kuint64max)); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(double(kuint64max), val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(kuint64max), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1.84467e+19", val.asString()); -#else // ifdef JSON_NO_INT64 - // 2^40 (signed constructor arg) - val = Json::Value(Json::Int64(1) << 40); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt64_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString()); - - // 2^40 (unsigned constructor arg) - val = Json::Value(Json::UInt64(1) << 40); - - JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); - - checks = IsCheck(); - checks.isInt64_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString()); - - // 2^40 (floating-point constructor arg) - val = Json::Value((Json::Int64(1) << 40) / 1.0); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isInt64_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1099511627776", - normalizeFloatingPointStr(val.asString())); - - // -2^40 - val = Json::Value(-(Json::Int64(1) << 40)); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asInt64()); - JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asDouble()); - JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("-1099511627776", val.asString()); - - // int64 max - val = Json::Value(Json::Int64(kint64max)); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt64_ = true; - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(kint64max, val.asInt64()); - JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(kint64max, val.asUInt64()); - JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("9223372036854775807", val.asString()); - - // int64 max (floating point constructor). Note that kint64max is not exactly - // representable as a double, and will be rounded up to be higher. - val = Json::Value(double(kint64max)); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(Json::UInt64(1) << 63, val.asUInt64()); - JSONTEST_ASSERT_EQUAL(Json::UInt64(1) << 63, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(uint64ToDouble(Json::UInt64(1) << 63), val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(Json::UInt64(1) << 63)), - val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("9.2233720368547758e+18", - normalizeFloatingPointStr(val.asString())); - - // int64 min - val = Json::Value(Json::Int64(kint64min)); - - JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); - - checks = IsCheck(); - checks.isInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64()); - JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("-9223372036854775808", val.asString()); - - // int64 min (floating point constructor). Note that kint64min *is* exactly - // representable as a double. - val = Json::Value(double(kint64min)); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64()); - JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble()); - JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("-9.2233720368547758e+18", - normalizeFloatingPointStr(val.asString())); - - // 10^19 - const Json::UInt64 ten_to_19 = static_cast(1e19); - val = Json::Value(Json::UInt64(ten_to_19)); - - JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); - - checks = IsCheck(); - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(ten_to_19, val.asUInt64()); - JSONTEST_ASSERT_EQUAL(ten_to_19, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(uint64ToDouble(ten_to_19), val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(ten_to_19)), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("10000000000000000000", val.asString()); - - // 10^19 (double constructor). Note that 10^19 is not exactly representable - // as a double. - val = Json::Value(uint64ToDouble(ten_to_19)); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(1e19, val.asDouble()); - JSONTEST_ASSERT_EQUAL(1e19, val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1e+19", - normalizeFloatingPointStr(val.asString())); - - // uint64 max - val = Json::Value(Json::UInt64(kuint64max)); - - JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); - - checks = IsCheck(); - checks.isUInt64_ = true; - checks.isIntegral_ = true; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(kuint64max, val.asUInt64()); - JSONTEST_ASSERT_EQUAL(kuint64max, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(uint64ToDouble(kuint64max), val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(kuint64max)), val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("18446744073709551615", val.asString()); - - // uint64 max (floating point constructor). Note that kuint64max is not - // exactly representable as a double, and will be rounded up to be higher. - val = Json::Value(uint64ToDouble(kuint64max)); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - - JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asDouble()); - JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_STRING_EQUAL("1.8446744073709552e+19", - normalizeFloatingPointStr(val.asString())); -#endif -} - -JSONTEST_FIXTURE(ValueTest, nonIntegers) { - IsCheck checks; - Json::Value val; - - // Small positive number - val = Json::Value(1.5); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT_EQUAL(1.5, val.asDouble()); - JSONTEST_ASSERT_EQUAL(1.5, val.asFloat()); - JSONTEST_ASSERT_EQUAL(1, val.asInt()); - JSONTEST_ASSERT_EQUAL(1, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(1, val.asUInt()); - JSONTEST_ASSERT_EQUAL(1, val.asLargestUInt()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_EQUAL("1.5", val.asString()); - - // Small negative number - val = Json::Value(-1.5); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT_EQUAL(-1.5, val.asDouble()); - JSONTEST_ASSERT_EQUAL(-1.5, val.asFloat()); - JSONTEST_ASSERT_EQUAL(-1, val.asInt()); - JSONTEST_ASSERT_EQUAL(-1, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_EQUAL("-1.5", val.asString()); - - // A bit over int32 max - val = Json::Value(kint32max + 0.5); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT_EQUAL(2147483647.5, val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(2147483647.5), val.asFloat()); - JSONTEST_ASSERT_EQUAL(2147483647U, val.asUInt()); -#ifdef JSON_HAS_INT64 - JSONTEST_ASSERT_EQUAL(2147483647L, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL(2147483647U, val.asLargestUInt()); -#endif - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_EQUAL("2147483647.5", - normalizeFloatingPointStr(val.asString())); - - // A bit under int32 min - val = Json::Value(kint32min - 0.5); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT_EQUAL(-2147483648.5, val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(-2147483648.5), val.asFloat()); -#ifdef JSON_HAS_INT64 - JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 31), val.asLargestInt()); -#endif - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_EQUAL("-2147483648.5", - normalizeFloatingPointStr(val.asString())); - - // A bit over uint32 max - val = Json::Value(kuint32max + 0.5); - - JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); - - checks = IsCheck(); - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED(checkIs(val, checks)); - - JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); - JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); - JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); - - JSONTEST_ASSERT_EQUAL(4294967295.5, val.asDouble()); - JSONTEST_ASSERT_EQUAL(float(4294967295.5), val.asFloat()); -#ifdef JSON_HAS_INT64 - JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 32) - 1, val.asLargestInt()); - JSONTEST_ASSERT_EQUAL((Json::UInt64(1) << 32) - Json::UInt64(1), - val.asLargestUInt()); -#endif - JSONTEST_ASSERT_EQUAL(true, val.asBool()); - JSONTEST_ASSERT_EQUAL("4294967295.5", - normalizeFloatingPointStr(val.asString())); - - val = Json::Value(1.2345678901234); - JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234001", - normalizeFloatingPointStr(val.asString())); - - // A 16-digit floating point number. - val = Json::Value(2199023255552000.0f); - JSONTEST_ASSERT_EQUAL(float(2199023255552000), val.asFloat()); - JSONTEST_ASSERT_STRING_EQUAL("2199023255552000", - normalizeFloatingPointStr(val.asString())); - - // A very large floating point number. - val = Json::Value(3.402823466385289e38); - JSONTEST_ASSERT_EQUAL(float(3.402823466385289e38), val.asFloat()); - JSONTEST_ASSERT_STRING_EQUAL("3.402823466385289e+38", - normalizeFloatingPointStr(val.asString())); - - // An even larger floating point number. - val = Json::Value(1.2345678e300); - JSONTEST_ASSERT_EQUAL(double(1.2345678e300), val.asDouble()); - JSONTEST_ASSERT_STRING_EQUAL("1.2345678e+300", - normalizeFloatingPointStr(val.asString())); -} - -void ValueTest::checkConstMemberCount(const Json::Value& value, - unsigned int expectedCount) { - unsigned int count = 0; - Json::Value::const_iterator itEnd = value.end(); - for (Json::Value::const_iterator it = value.begin(); it != itEnd; ++it) { - ++count; - } - JSONTEST_ASSERT_EQUAL(expectedCount, count) << "Json::Value::const_iterator"; -} - -void ValueTest::checkMemberCount(Json::Value& value, - unsigned int expectedCount) { - JSONTEST_ASSERT_EQUAL(expectedCount, value.size()); - - unsigned int count = 0; - Json::Value::iterator itEnd = value.end(); - for (Json::Value::iterator it = value.begin(); it != itEnd; ++it) { - ++count; - } - JSONTEST_ASSERT_EQUAL(expectedCount, count) << "Json::Value::iterator"; - - JSONTEST_ASSERT_PRED(checkConstMemberCount(value, expectedCount)); -} - -ValueTest::IsCheck::IsCheck() - : isObject_(false), isArray_(false), isBool_(false), isString_(false), - isNull_(false), isInt_(false), isInt64_(false), isUInt_(false), - isUInt64_(false), isIntegral_(false), isDouble_(false), - isNumeric_(false) {} - -void ValueTest::checkIs(const Json::Value& value, const IsCheck& check) { - JSONTEST_ASSERT_EQUAL(check.isObject_, value.isObject()); - JSONTEST_ASSERT_EQUAL(check.isArray_, value.isArray()); - JSONTEST_ASSERT_EQUAL(check.isBool_, value.isBool()); - JSONTEST_ASSERT_EQUAL(check.isDouble_, value.isDouble()); - JSONTEST_ASSERT_EQUAL(check.isInt_, value.isInt()); - JSONTEST_ASSERT_EQUAL(check.isUInt_, value.isUInt()); - JSONTEST_ASSERT_EQUAL(check.isIntegral_, value.isIntegral()); - JSONTEST_ASSERT_EQUAL(check.isNumeric_, value.isNumeric()); - JSONTEST_ASSERT_EQUAL(check.isString_, value.isString()); - JSONTEST_ASSERT_EQUAL(check.isNull_, value.isNull()); - -#ifdef JSON_HAS_INT64 - JSONTEST_ASSERT_EQUAL(check.isInt64_, value.isInt64()); - JSONTEST_ASSERT_EQUAL(check.isUInt64_, value.isUInt64()); -#else - JSONTEST_ASSERT_EQUAL(false, value.isInt64()); - JSONTEST_ASSERT_EQUAL(false, value.isUInt64()); -#endif -} - -JSONTEST_FIXTURE(ValueTest, compareNull) { - JSONTEST_ASSERT_PRED(checkIsEqual(Json::Value(), Json::Value())); -} - -JSONTEST_FIXTURE(ValueTest, compareInt) { - JSONTEST_ASSERT_PRED(checkIsLess(0, 10)); - JSONTEST_ASSERT_PRED(checkIsEqual(10, 10)); - JSONTEST_ASSERT_PRED(checkIsEqual(-10, -10)); - JSONTEST_ASSERT_PRED(checkIsLess(-10, 0)); -} - -JSONTEST_FIXTURE(ValueTest, compareUInt) { - JSONTEST_ASSERT_PRED(checkIsLess(0u, 10u)); - JSONTEST_ASSERT_PRED(checkIsLess(0u, Json::Value::maxUInt)); - JSONTEST_ASSERT_PRED(checkIsEqual(10u, 10u)); -} - -JSONTEST_FIXTURE(ValueTest, compareDouble) { - JSONTEST_ASSERT_PRED(checkIsLess(0.0, 10.0)); - JSONTEST_ASSERT_PRED(checkIsEqual(10.0, 10.0)); - JSONTEST_ASSERT_PRED(checkIsEqual(-10.0, -10.0)); - JSONTEST_ASSERT_PRED(checkIsLess(-10.0, 0.0)); -} - -JSONTEST_FIXTURE(ValueTest, compareString) { - JSONTEST_ASSERT_PRED(checkIsLess("", " ")); - JSONTEST_ASSERT_PRED(checkIsLess("", "a")); - JSONTEST_ASSERT_PRED(checkIsLess("abcd", "zyui")); - JSONTEST_ASSERT_PRED(checkIsLess("abc", "abcd")); - JSONTEST_ASSERT_PRED(checkIsEqual("abcd", "abcd")); - JSONTEST_ASSERT_PRED(checkIsEqual(" ", " ")); - JSONTEST_ASSERT_PRED(checkIsLess("ABCD", "abcd")); - JSONTEST_ASSERT_PRED(checkIsEqual("ABCD", "ABCD")); -} - -JSONTEST_FIXTURE(ValueTest, compareBoolean) { - JSONTEST_ASSERT_PRED(checkIsLess(false, true)); - JSONTEST_ASSERT_PRED(checkIsEqual(false, false)); - JSONTEST_ASSERT_PRED(checkIsEqual(true, true)); -} - -JSONTEST_FIXTURE(ValueTest, compareArray) { - // array compare size then content - Json::Value emptyArray(Json::arrayValue); - Json::Value l1aArray; - l1aArray.append(0); - Json::Value l1bArray; - l1bArray.append(10); - Json::Value l2aArray; - l2aArray.append(0); - l2aArray.append(0); - Json::Value l2bArray; - l2bArray.append(0); - l2bArray.append(10); - JSONTEST_ASSERT_PRED(checkIsLess(emptyArray, l1aArray)); - JSONTEST_ASSERT_PRED(checkIsLess(emptyArray, l2aArray)); - JSONTEST_ASSERT_PRED(checkIsLess(l1aArray, l2aArray)); - JSONTEST_ASSERT_PRED(checkIsLess(l2aArray, l2bArray)); - JSONTEST_ASSERT_PRED(checkIsEqual(emptyArray, Json::Value(emptyArray))); - JSONTEST_ASSERT_PRED(checkIsEqual(l1aArray, Json::Value(l1aArray))); - JSONTEST_ASSERT_PRED(checkIsEqual(l2bArray, Json::Value(l2bArray))); -} - -JSONTEST_FIXTURE(ValueTest, compareObject) { - // object compare size then content - Json::Value emptyObject(Json::objectValue); - Json::Value l1aObject; - l1aObject["key1"] = 0; - Json::Value l1bObject; - l1aObject["key1"] = 10; - Json::Value l2aObject; - l2aObject["key1"] = 0; - l2aObject["key2"] = 0; - JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l1aObject)); - JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l2aObject)); - JSONTEST_ASSERT_PRED(checkIsLess(l1aObject, l2aObject)); - JSONTEST_ASSERT_PRED(checkIsEqual(emptyObject, Json::Value(emptyObject))); - JSONTEST_ASSERT_PRED(checkIsEqual(l1aObject, Json::Value(l1aObject))); - JSONTEST_ASSERT_PRED(checkIsEqual(l2aObject, Json::Value(l2aObject))); -} - -JSONTEST_FIXTURE(ValueTest, compareType) { - // object of different type are ordered according to their type - JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(), Json::Value(1))); - JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1), Json::Value(1u))); - JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1u), Json::Value(1.0))); - JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1.0), Json::Value("a"))); - JSONTEST_ASSERT_PRED(checkIsLess(Json::Value("a"), Json::Value(true))); - JSONTEST_ASSERT_PRED( - checkIsLess(Json::Value(true), Json::Value(Json::arrayValue))); - JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(Json::arrayValue), - Json::Value(Json::objectValue))); -} - -void ValueTest::checkIsLess(const Json::Value& x, const Json::Value& y) { - JSONTEST_ASSERT(x < y); - JSONTEST_ASSERT(y > x); - JSONTEST_ASSERT(x <= y); - JSONTEST_ASSERT(y >= x); - JSONTEST_ASSERT(!(x == y)); - JSONTEST_ASSERT(!(y == x)); - JSONTEST_ASSERT(!(x >= y)); - JSONTEST_ASSERT(!(y <= x)); - JSONTEST_ASSERT(!(x > y)); - JSONTEST_ASSERT(!(y < x)); - JSONTEST_ASSERT(x.compare(y) < 0); - JSONTEST_ASSERT(y.compare(x) >= 0); -} - -void ValueTest::checkIsEqual(const Json::Value& x, const Json::Value& y) { - JSONTEST_ASSERT(x == y); - JSONTEST_ASSERT(y == x); - JSONTEST_ASSERT(x <= y); - JSONTEST_ASSERT(y <= x); - JSONTEST_ASSERT(x >= y); - JSONTEST_ASSERT(y >= x); - JSONTEST_ASSERT(!(x < y)); - JSONTEST_ASSERT(!(y < x)); - JSONTEST_ASSERT(!(x > y)); - JSONTEST_ASSERT(!(y > x)); - JSONTEST_ASSERT(x.compare(y) == 0); - JSONTEST_ASSERT(y.compare(x) == 0); -} - -JSONTEST_FIXTURE(ValueTest, typeChecksThrowExceptions) { -#if JSON_USE_EXCEPTION - - Json::Value intVal(1); - Json::Value strVal("Test"); - Json::Value objVal(Json::objectValue); - Json::Value arrVal(Json::arrayValue); - - JSONTEST_ASSERT_THROWS(intVal["test"]); - JSONTEST_ASSERT_THROWS(strVal["test"]); - JSONTEST_ASSERT_THROWS(arrVal["test"]); - - JSONTEST_ASSERT_THROWS(intVal.removeMember("test")); - JSONTEST_ASSERT_THROWS(strVal.removeMember("test")); - JSONTEST_ASSERT_THROWS(arrVal.removeMember("test")); - - JSONTEST_ASSERT_THROWS(intVal.getMemberNames()); - JSONTEST_ASSERT_THROWS(strVal.getMemberNames()); - JSONTEST_ASSERT_THROWS(arrVal.getMemberNames()); - - JSONTEST_ASSERT_THROWS(intVal[0]); - JSONTEST_ASSERT_THROWS(objVal[0]); - JSONTEST_ASSERT_THROWS(strVal[0]); - - JSONTEST_ASSERT_THROWS(intVal.clear()); - - JSONTEST_ASSERT_THROWS(intVal.resize(1)); - JSONTEST_ASSERT_THROWS(strVal.resize(1)); - JSONTEST_ASSERT_THROWS(objVal.resize(1)); - - JSONTEST_ASSERT_THROWS(intVal.asCString()); - - JSONTEST_ASSERT_THROWS(objVal.asString()); - JSONTEST_ASSERT_THROWS(arrVal.asString()); - - JSONTEST_ASSERT_THROWS(strVal.asInt()); - JSONTEST_ASSERT_THROWS(objVal.asInt()); - JSONTEST_ASSERT_THROWS(arrVal.asInt()); - - JSONTEST_ASSERT_THROWS(strVal.asUInt()); - JSONTEST_ASSERT_THROWS(objVal.asUInt()); - JSONTEST_ASSERT_THROWS(arrVal.asUInt()); - - JSONTEST_ASSERT_THROWS(strVal.asInt64()); - JSONTEST_ASSERT_THROWS(objVal.asInt64()); - JSONTEST_ASSERT_THROWS(arrVal.asInt64()); - - JSONTEST_ASSERT_THROWS(strVal.asUInt64()); - JSONTEST_ASSERT_THROWS(objVal.asUInt64()); - JSONTEST_ASSERT_THROWS(arrVal.asUInt64()); - - JSONTEST_ASSERT_THROWS(strVal.asDouble()); - JSONTEST_ASSERT_THROWS(objVal.asDouble()); - JSONTEST_ASSERT_THROWS(arrVal.asDouble()); - - JSONTEST_ASSERT_THROWS(strVal.asFloat()); - JSONTEST_ASSERT_THROWS(objVal.asFloat()); - JSONTEST_ASSERT_THROWS(arrVal.asFloat()); - - JSONTEST_ASSERT_THROWS(strVal.asBool()); - JSONTEST_ASSERT_THROWS(objVal.asBool()); - JSONTEST_ASSERT_THROWS(arrVal.asBool()); - -#endif -} - -JSONTEST_FIXTURE(ValueTest, offsetAccessors) { - Json::Value x; - JSONTEST_ASSERT(x.getOffsetStart() == 0); - JSONTEST_ASSERT(x.getOffsetLimit() == 0); - x.setOffsetStart(10); - x.setOffsetLimit(20); - JSONTEST_ASSERT(x.getOffsetStart() == 10); - JSONTEST_ASSERT(x.getOffsetLimit() == 20); - Json::Value y(x); - JSONTEST_ASSERT(y.getOffsetStart() == 10); - JSONTEST_ASSERT(y.getOffsetLimit() == 20); - Json::Value z; - z.swap(y); - JSONTEST_ASSERT(z.getOffsetStart() == 10); - JSONTEST_ASSERT(z.getOffsetLimit() == 20); - JSONTEST_ASSERT(y.getOffsetStart() == 0); - JSONTEST_ASSERT(y.getOffsetLimit() == 0); -} - -JSONTEST_FIXTURE(ValueTest, StaticString) { - char mutant[] = "hello"; - Json::StaticString ss(mutant); - std::string regular(mutant); - mutant[1] = 'a'; - JSONTEST_ASSERT_STRING_EQUAL("hallo", ss.c_str()); - JSONTEST_ASSERT_STRING_EQUAL("hello", regular.c_str()); - { - Json::Value root; - root["top"] = ss; - JSONTEST_ASSERT_STRING_EQUAL("hallo", root["top"].asString()); - mutant[1] = 'u'; - JSONTEST_ASSERT_STRING_EQUAL("hullo", root["top"].asString()); - } - { - Json::Value root; - root["top"] = regular; - JSONTEST_ASSERT_STRING_EQUAL("hello", root["top"].asString()); - mutant[1] = 'u'; - JSONTEST_ASSERT_STRING_EQUAL("hello", root["top"].asString()); - } -} - -JSONTEST_FIXTURE(ValueTest, CommentBefore) { - Json::Value val; // fill val - val.setComment(std::string("// this comment should appear before"), Json::commentBefore); - Json::StreamWriterBuilder wbuilder; - wbuilder.settings_["commentStyle"] = "All"; - { - char const expected[] = "// this comment should appear before\nnull"; - std::string result = Json::writeString(wbuilder, val); - JSONTEST_ASSERT_STRING_EQUAL(expected, result); - std::string res2 = val.toStyledString(); - std::string exp2 = "\n"; - exp2 += expected; - exp2 += "\n"; - JSONTEST_ASSERT_STRING_EQUAL(exp2, res2); - } - Json::Value other = "hello"; - val.swapPayload(other); - { - char const expected[] = "// this comment should appear before\n\"hello\""; - std::string result = Json::writeString(wbuilder, val); - JSONTEST_ASSERT_STRING_EQUAL(expected, result); - std::string res2 = val.toStyledString(); - std::string exp2 = "\n"; - exp2 += expected; - exp2 += "\n"; - JSONTEST_ASSERT_STRING_EQUAL(exp2, res2); - JSONTEST_ASSERT_STRING_EQUAL("null\n", other.toStyledString()); - } - val = "hello"; - // val.setComment("// this comment should appear before", Json::CommentPlacement::commentBefore); - // Assignment over-writes comments. - { - char const expected[] = "\"hello\""; - std::string result = Json::writeString(wbuilder, val); - JSONTEST_ASSERT_STRING_EQUAL(expected, result); - std::string res2 = val.toStyledString(); - std::string exp2 = ""; - exp2 += expected; - exp2 += "\n"; - JSONTEST_ASSERT_STRING_EQUAL(exp2, res2); - } -} - -JSONTEST_FIXTURE(ValueTest, zeroes) { - char const cstr[] = "h\0i"; - std::string binary(cstr, sizeof(cstr)); // include trailing 0 - JSONTEST_ASSERT_EQUAL(4U, binary.length()); - Json::StreamWriterBuilder b; - { - Json::Value root; - root = binary; - JSONTEST_ASSERT_STRING_EQUAL(binary, root.asString()); - } - { - char const top[] = "top"; - Json::Value root; - root[top] = binary; - JSONTEST_ASSERT_STRING_EQUAL(binary, root[top].asString()); - Json::Value removed; - bool did; - did = root.removeMember(top, top + sizeof(top) - 1U, - &removed); - JSONTEST_ASSERT(did); - JSONTEST_ASSERT_STRING_EQUAL(binary, removed.asString()); - did = root.removeMember(top, top + sizeof(top) - 1U, - &removed); - JSONTEST_ASSERT(!did); - JSONTEST_ASSERT_STRING_EQUAL(binary, removed.asString()); // still - } -} - -JSONTEST_FIXTURE(ValueTest, zeroesInKeys) { - char const cstr[] = "h\0i"; - std::string binary(cstr, sizeof(cstr)); // include trailing 0 - JSONTEST_ASSERT_EQUAL(4U, binary.length()); - { - Json::Value root; - root[binary] = "there"; - JSONTEST_ASSERT_STRING_EQUAL("there", root[binary].asString()); - JSONTEST_ASSERT(!root.isMember("h")); - JSONTEST_ASSERT(root.isMember(binary)); - JSONTEST_ASSERT_STRING_EQUAL("there", root.get(binary, Json::Value::nullRef).asString()); - Json::Value removed; - bool did; - did = root.removeMember(binary.data(), binary.data() + binary.length(), - &removed); - JSONTEST_ASSERT(did); - JSONTEST_ASSERT_STRING_EQUAL("there", removed.asString()); - did = root.removeMember(binary.data(), binary.data() + binary.length(), - &removed); - JSONTEST_ASSERT(!did); - JSONTEST_ASSERT_STRING_EQUAL("there", removed.asString()); // still - JSONTEST_ASSERT(!root.isMember(binary)); - JSONTEST_ASSERT_STRING_EQUAL("", root.get(binary, Json::Value::nullRef).asString()); - } -} - -struct WriterTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) { - Json::FastWriter writer; - Json::Value nullValue; - JSONTEST_ASSERT(writer.write(nullValue) == "null\n"); - - writer.dropNullPlaceholders(); - JSONTEST_ASSERT(writer.write(nullValue) == "\n"); -} - -struct StreamWriterTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(StreamWriterTest, dropNullPlaceholders) { - Json::StreamWriterBuilder b; - Json::Value nullValue; - b.settings_["dropNullPlaceholders"] = false; - JSONTEST_ASSERT(Json::writeString(b, nullValue) == "null"); - b.settings_["dropNullPlaceholders"] = true; - JSONTEST_ASSERT(Json::writeString(b, nullValue) == ""); -} - -JSONTEST_FIXTURE(StreamWriterTest, writeZeroes) { - std::string binary("hi", 3); // include trailing 0 - JSONTEST_ASSERT_EQUAL(3, binary.length()); - std::string expected("\"hi\\u0000\""); // unicoded zero - Json::StreamWriterBuilder b; - { - Json::Value root; - root = binary; - JSONTEST_ASSERT_STRING_EQUAL(binary, root.asString()); - std::string out = Json::writeString(b, root); - JSONTEST_ASSERT_EQUAL(expected.size(), out.size()); - JSONTEST_ASSERT_STRING_EQUAL(expected, out); - } - { - Json::Value root; - root["top"] = binary; - JSONTEST_ASSERT_STRING_EQUAL(binary, root["top"].asString()); - std::string out = Json::writeString(b, root["top"]); - JSONTEST_ASSERT_STRING_EQUAL(expected, out); - } -} - -struct ReaderTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(ReaderTest, parseWithNoErrors) { - Json::Reader reader; - Json::Value root; - bool ok = reader.parse("{ \"property\" : \"value\" }", root); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0); - JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0); -} - -JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) { - Json::Reader reader; - Json::Value root; - bool ok = reader.parse("{ \"property\" : [\"value\", \"value2\"], \"obj\" : " - "{ \"nested\" : 123, \"bool\" : true}, \"null\" : " - "null, \"false\" : false }", - root); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0); - JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0); - JSONTEST_ASSERT(root["property"].getOffsetStart() == 15); - JSONTEST_ASSERT(root["property"].getOffsetLimit() == 34); - JSONTEST_ASSERT(root["property"][0].getOffsetStart() == 16); - JSONTEST_ASSERT(root["property"][0].getOffsetLimit() == 23); - JSONTEST_ASSERT(root["property"][1].getOffsetStart() == 25); - JSONTEST_ASSERT(root["property"][1].getOffsetLimit() == 33); - JSONTEST_ASSERT(root["obj"].getOffsetStart() == 44); - JSONTEST_ASSERT(root["obj"].getOffsetLimit() == 76); - JSONTEST_ASSERT(root["obj"]["nested"].getOffsetStart() == 57); - JSONTEST_ASSERT(root["obj"]["nested"].getOffsetLimit() == 60); - JSONTEST_ASSERT(root["obj"]["bool"].getOffsetStart() == 71); - JSONTEST_ASSERT(root["obj"]["bool"].getOffsetLimit() == 75); - JSONTEST_ASSERT(root["null"].getOffsetStart() == 87); - JSONTEST_ASSERT(root["null"].getOffsetLimit() == 91); - JSONTEST_ASSERT(root["false"].getOffsetStart() == 103); - JSONTEST_ASSERT(root["false"].getOffsetLimit() == 108); - JSONTEST_ASSERT(root.getOffsetStart() == 0); - JSONTEST_ASSERT(root.getOffsetLimit() == 110); -} - -JSONTEST_FIXTURE(ReaderTest, parseWithOneError) { - Json::Reader reader; - Json::Value root; - bool ok = reader.parse("{ \"property\" :: \"value\" }", root); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == - "* Line 1, Column 15\n Syntax error: value, object or array " - "expected.\n"); - std::vector errors = - reader.getStructuredErrors(); - JSONTEST_ASSERT(errors.size() == 1); - JSONTEST_ASSERT(errors.at(0).offset_start == 14); - JSONTEST_ASSERT(errors.at(0).offset_limit == 15); - JSONTEST_ASSERT(errors.at(0).message == - "Syntax error: value, object or array expected."); -} - -JSONTEST_FIXTURE(ReaderTest, parseChineseWithOneError) { - Json::Reader reader; - Json::Value root; - bool ok = reader.parse("{ \"pr佐藤erty\" :: \"value\" }", root); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == - "* Line 1, Column 19\n Syntax error: value, object or array " - "expected.\n"); - std::vector errors = - reader.getStructuredErrors(); - JSONTEST_ASSERT(errors.size() == 1); - JSONTEST_ASSERT(errors.at(0).offset_start == 18); - JSONTEST_ASSERT(errors.at(0).offset_limit == 19); - JSONTEST_ASSERT(errors.at(0).message == - "Syntax error: value, object or array expected."); -} - -JSONTEST_FIXTURE(ReaderTest, parseWithDetailError) { - Json::Reader reader; - Json::Value root; - bool ok = reader.parse("{ \"property\" : \"v\\alue\" }", root); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == - "* Line 1, Column 16\n Bad escape sequence in string\nSee " - "Line 1, Column 20 for detail.\n"); - std::vector errors = - reader.getStructuredErrors(); - JSONTEST_ASSERT(errors.size() == 1); - JSONTEST_ASSERT(errors.at(0).offset_start == 15); - JSONTEST_ASSERT(errors.at(0).offset_limit == 23); - JSONTEST_ASSERT(errors.at(0).message == "Bad escape sequence in string"); -} - -struct CharReaderTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrors) { - Json::CharReaderBuilder b; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - Json::Value root; - char const doc[] = "{ \"property\" : \"value\" }"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs.size() == 0); - delete reader; -} - -JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrorsTestingOffsets) { - Json::CharReaderBuilder b; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - Json::Value root; - char const doc[] = - "{ \"property\" : [\"value\", \"value2\"], \"obj\" : " - "{ \"nested\" : 123, \"bool\" : true}, \"null\" : " - "null, \"false\" : false }"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs.size() == 0); - delete reader; -} - -JSONTEST_FIXTURE(CharReaderTest, parseWithOneError) { - Json::CharReaderBuilder b; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - Json::Value root; - char const doc[] = - "{ \"property\" :: \"value\" }"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT(errs == - "* Line 1, Column 15\n Syntax error: value, object or array " - "expected.\n"); - delete reader; -} - -JSONTEST_FIXTURE(CharReaderTest, parseChineseWithOneError) { - Json::CharReaderBuilder b; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - Json::Value root; - char const doc[] = - "{ \"pr佐藤erty\" :: \"value\" }"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT(errs == - "* Line 1, Column 19\n Syntax error: value, object or array " - "expected.\n"); - delete reader; -} - -JSONTEST_FIXTURE(CharReaderTest, parseWithDetailError) { - Json::CharReaderBuilder b; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - Json::Value root; - char const doc[] = - "{ \"property\" : \"v\\alue\" }"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT(errs == - "* Line 1, Column 16\n Bad escape sequence in string\nSee " - "Line 1, Column 20 for detail.\n"); - delete reader; -} - -JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) { - Json::CharReaderBuilder b; - Json::Value root; - char const doc[] = - "{ \"property\" : \"value\" }"; - { - b.settings_["stackLimit"] = 2; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs == ""); - JSONTEST_ASSERT_EQUAL("value", root["property"]); - delete reader; - } - { - b.settings_["stackLimit"] = 1; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - JSONTEST_ASSERT_THROWS(reader->parse( - doc, doc + std::strlen(doc), - &root, &errs)); - delete reader; - } -} - -struct CharReaderStrictModeTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(CharReaderStrictModeTest, dupKeys) { - Json::CharReaderBuilder b; - Json::Value root; - char const doc[] = - "{ \"property\" : \"value\", \"key\" : \"val1\", \"key\" : \"val2\" }"; - { - b.strictMode(&b.settings_); - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT_STRING_EQUAL( - "* Line 1, Column 41\n" - " Duplicate key: 'key'\n", - errs); - JSONTEST_ASSERT_EQUAL("val1", root["key"]); // so far - delete reader; - } -} -struct CharReaderFailIfExtraTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) { - // This is interpretted as a string value followed by a colon. - Json::CharReaderBuilder b; - Json::Value root; - char const doc[] = - " \"property\" : \"value\" }"; - { - b.settings_["failIfExtra"] = false; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs == ""); - JSONTEST_ASSERT_EQUAL("property", root); - delete reader; - } - { - b.settings_["failIfExtra"] = true; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT_STRING_EQUAL(errs, - "* Line 1, Column 13\n" - " Extra non-whitespace after JSON value.\n"); - JSONTEST_ASSERT_EQUAL("property", root); - delete reader; - } - { - b.settings_["failIfExtra"] = false; - b.strictMode(&b.settings_); - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT_STRING_EQUAL(errs, - "* Line 1, Column 13\n" - " Extra non-whitespace after JSON value.\n"); - JSONTEST_ASSERT_EQUAL("property", root); - delete reader; - } -} -JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue107) { - // This is interpretted as an int value followed by a colon. - Json::CharReaderBuilder b; - Json::Value root; - char const doc[] = - "1:2:3"; - b.settings_["failIfExtra"] = true; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(!ok); - JSONTEST_ASSERT_STRING_EQUAL( - "* Line 1, Column 2\n" - " Extra non-whitespace after JSON value.\n", - errs); - JSONTEST_ASSERT_EQUAL(1, root.asInt()); - delete reader; -} -JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterObject) { - Json::CharReaderBuilder b; - Json::Value root; - { - char const doc[] = - "{ \"property\" : \"value\" } //trailing\n//comment\n"; - b.settings_["failIfExtra"] = true; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL("value", root["property"]); - delete reader; - } -} -JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterArray) { - Json::CharReaderBuilder b; - Json::Value root; - char const doc[] = - "[ \"property\" , \"value\" ] //trailing\n//comment\n"; - b.settings_["failIfExtra"] = true; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL("value", root[1u]); - delete reader; -} -JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterBool) { - Json::CharReaderBuilder b; - Json::Value root; - char const doc[] = - " true /*trailing\ncomment*/"; - b.settings_["failIfExtra"] = true; - Json::CharReader* reader(b.newCharReader()); - std::string errs; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(true, root.asBool()); - delete reader; -} -struct CharReaderAllowDropNullTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) { - Json::CharReaderBuilder b; - b.settings_["allowDroppedNullPlaceholders"] = true; - Json::Value root; - std::string errs; - Json::CharReader* reader(b.newCharReader()); - { - char const doc[] = "{\"a\":,\"b\":true}"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(2u, root.size()); - JSONTEST_ASSERT_EQUAL(Json::nullValue, root.get("a", true)); - } - { - char const doc[] = "{\"a\":}"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(1u, root.size()); - JSONTEST_ASSERT_EQUAL(Json::nullValue, root.get("a", true)); - } - { - char const doc[] = "[]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs == ""); - JSONTEST_ASSERT_EQUAL(0u, root.size()); - JSONTEST_ASSERT_EQUAL(Json::arrayValue, root); - } - { - char const doc[] = "[null]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs == ""); - JSONTEST_ASSERT_EQUAL(1u, root.size()); - } - { - char const doc[] = "[,]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(2u, root.size()); - } - { - char const doc[] = "[,,,]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(4u, root.size()); - } - { - char const doc[] = "[null,]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(2u, root.size()); - } - { - char const doc[] = "[,null]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs == ""); - JSONTEST_ASSERT_EQUAL(2u, root.size()); - } - { - char const doc[] = "[,,]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(3u, root.size()); - } - { - char const doc[] = "[null,,]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(3u, root.size()); - } - { - char const doc[] = "[,null,]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(3u, root.size()); - } - { - char const doc[] = "[,,null]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs == ""); - JSONTEST_ASSERT_EQUAL(3u, root.size()); - } - { - char const doc[] = "[[],,,]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(4u, root.size()); - JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[0u]); - } - { - char const doc[] = "[,[],,]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(4u, root.size()); - JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[1u]); - } - { - char const doc[] = "[,,,[]]"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT(errs == ""); - JSONTEST_ASSERT_EQUAL(4u, root.size()); - JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[3u]); - } - delete reader; -} - -struct CharReaderAllowSingleQuotesTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(CharReaderAllowSingleQuotesTest, issue182) { - Json::CharReaderBuilder b; - b.settings_["allowSingleQuotes"] = true; - Json::Value root; - std::string errs; - Json::CharReader* reader(b.newCharReader()); - { - char const doc[] = "{'a':true,\"b\":true}"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(2u, root.size()); - JSONTEST_ASSERT_EQUAL(true, root.get("a", false)); - JSONTEST_ASSERT_EQUAL(true, root.get("b", false)); - } - { - char const doc[] = "{'a': 'x', \"b\":'y'}"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(2u, root.size()); - JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString()); - JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString()); - } - delete reader; -} - -struct CharReaderAllowZeroesTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(CharReaderAllowZeroesTest, issue176) { - Json::CharReaderBuilder b; - b.settings_["allowSingleQuotes"] = true; - Json::Value root; - std::string errs; - Json::CharReader* reader(b.newCharReader()); - { - char const doc[] = "{'a':true,\"b\":true}"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(2u, root.size()); - JSONTEST_ASSERT_EQUAL(true, root.get("a", false)); - JSONTEST_ASSERT_EQUAL(true, root.get("b", false)); - } - { - char const doc[] = "{'a': 'x', \"b\":'y'}"; - bool ok = reader->parse( - doc, doc + std::strlen(doc), - &root, &errs); - JSONTEST_ASSERT(ok); - JSONTEST_ASSERT_STRING_EQUAL("", errs); - JSONTEST_ASSERT_EQUAL(2u, root.size()); - JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString()); - JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString()); - } - delete reader; -} - -struct BuilderTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(BuilderTest, settings) { - { - Json::Value errs; - Json::CharReaderBuilder rb; - JSONTEST_ASSERT_EQUAL(false, rb.settings_.isMember("foo")); - JSONTEST_ASSERT_EQUAL(true, rb.validate(&errs)); - rb["foo"] = "bar"; - JSONTEST_ASSERT_EQUAL(true, rb.settings_.isMember("foo")); - JSONTEST_ASSERT_EQUAL(false, rb.validate(&errs)); - } - { - Json::Value errs; - Json::StreamWriterBuilder wb; - JSONTEST_ASSERT_EQUAL(false, wb.settings_.isMember("foo")); - JSONTEST_ASSERT_EQUAL(true, wb.validate(&errs)); - wb["foo"] = "bar"; - JSONTEST_ASSERT_EQUAL(true, wb.settings_.isMember("foo")); - JSONTEST_ASSERT_EQUAL(false, wb.validate(&errs)); - } -} - -struct IteratorTest : JsonTest::TestCase {}; - -JSONTEST_FIXTURE(IteratorTest, distance) { - Json::Value json; - json["k1"] = "a"; - json["k2"] = "b"; - int dist = 0; - std::string str; - for (Json::ValueIterator it = json.begin(); it != json.end(); ++it) { - dist = it - json.begin(); - str = it->asString().c_str(); - } - JSONTEST_ASSERT_EQUAL(1, dist); - JSONTEST_ASSERT_STRING_EQUAL("b", str); -} - -JSONTEST_FIXTURE(IteratorTest, names) { - Json::Value json; - json["k1"] = "a"; - json["k2"] = "b"; - Json::ValueIterator it = json.begin(); - JSONTEST_ASSERT(it != json.end()); - JSONTEST_ASSERT_EQUAL(Json::Value("k1"), it.key()); - JSONTEST_ASSERT_STRING_EQUAL("k1", it.name()); - JSONTEST_ASSERT_EQUAL(-1, it.index()); - ++it; - JSONTEST_ASSERT(it != json.end()); - JSONTEST_ASSERT_EQUAL(Json::Value("k2"), it.key()); - JSONTEST_ASSERT_STRING_EQUAL("k2", it.name()); - JSONTEST_ASSERT_EQUAL(-1, it.index()); - ++it; - JSONTEST_ASSERT(it == json.end()); -} - -JSONTEST_FIXTURE(IteratorTest, indexes) { - Json::Value json; - json[0] = "a"; - json[1] = "b"; - Json::ValueIterator it = json.begin(); - JSONTEST_ASSERT(it != json.end()); - JSONTEST_ASSERT_EQUAL(Json::Value(Json::ArrayIndex(0)), it.key()); - JSONTEST_ASSERT_STRING_EQUAL("", it.name()); - JSONTEST_ASSERT_EQUAL(0, it.index()); - ++it; - JSONTEST_ASSERT(it != json.end()); - JSONTEST_ASSERT_EQUAL(Json::Value(Json::ArrayIndex(1)), it.key()); - JSONTEST_ASSERT_STRING_EQUAL("", it.name()); - JSONTEST_ASSERT_EQUAL(1, it.index()); - ++it; - JSONTEST_ASSERT(it == json.end()); -} - -int main(int argc, const char* argv[]) { - JsonTest::Runner runner; - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, memberCount); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, objects); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrays); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrayIssue252); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, null); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, strings); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, bools); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, integers); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nonIntegers); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareNull); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareInt); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareUInt); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareDouble); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareString); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareBoolean); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareArray); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareObject); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareType); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, offsetAccessors); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, typeChecksThrowExceptions); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, StaticString); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, CommentBefore); - //JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nulls); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroes); - JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys); - - JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders); - JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders); - JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, writeZeroes); - - JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithNoErrors); - JSONTEST_REGISTER_FIXTURE( - runner, ReaderTest, parseWithNoErrorsTestingOffsets); - JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithOneError); - JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseChineseWithOneError); - JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithDetailError); - - JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithNoErrors); - JSONTEST_REGISTER_FIXTURE( - runner, CharReaderTest, parseWithNoErrorsTestingOffsets); - JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithOneError); - JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseChineseWithOneError); - JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError); - JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit); - - JSONTEST_REGISTER_FIXTURE(runner, CharReaderStrictModeTest, dupKeys); - - JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue164); - JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue107); - JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterObject); - JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterArray); - JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterBool); - - JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowDropNullTest, issue178); - - JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowSingleQuotesTest, issue182); - - JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowZeroesTest, issue176); - - JSONTEST_REGISTER_FIXTURE(runner, BuilderTest, settings); - - JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, distance); - JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, names); - JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, indexes); - - return runner.runCommandLine(argc, argv); -} diff --git a/src/test_lib_json/sconscript b/src/test_lib_json/sconscript deleted file mode 100644 index 915fd01c0..000000000 --- a/src/test_lib_json/sconscript +++ /dev/null @@ -1,10 +0,0 @@ -Import( 'env_testing buildUnitTests' ) - -buildUnitTests( env_testing, Split( """ - main.cpp - jsontest.cpp - """ ), - 'test_lib_json' ) - -# For 'check' to work, 'libs' must be built first. -env_testing.Depends('test_lib_json', '#libs') diff --git a/test/cleantests.py b/test/cleantests.py deleted file mode 100644 index 9772d542b..000000000 --- a/test/cleantests.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2007 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -"""Removes all files created during testing.""" - -import glob -import os - -paths = [] -for pattern in [ '*.actual', '*.actual-rewrite', '*.rewrite', '*.process-output' ]: - paths += glob.glob('data/' + pattern) - -for path in paths: - os.unlink(path) diff --git a/test/data/fail_test_array_01.json b/test/data/fail_test_array_01.json deleted file mode 100644 index f72a6d077..000000000 --- a/test/data/fail_test_array_01.json +++ /dev/null @@ -1 +0,0 @@ -[ 1 2 3] diff --git a/test/data/test_array_01.expected b/test/data/test_array_01.expected deleted file mode 100644 index a341ff753..000000000 --- a/test/data/test_array_01.expected +++ /dev/null @@ -1 +0,0 @@ -.=[] diff --git a/test/data/test_array_01.json b/test/data/test_array_01.json deleted file mode 100644 index fe51488c7..000000000 --- a/test/data/test_array_01.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/test/data/test_array_02.expected b/test/data/test_array_02.expected deleted file mode 100644 index ef1f2623d..000000000 --- a/test/data/test_array_02.expected +++ /dev/null @@ -1,2 +0,0 @@ -.=[] -.[0]=1 diff --git a/test/data/test_array_02.json b/test/data/test_array_02.json deleted file mode 100644 index 7660873d1..000000000 --- a/test/data/test_array_02.json +++ /dev/null @@ -1 +0,0 @@ -[1] diff --git a/test/data/test_array_03.expected b/test/data/test_array_03.expected deleted file mode 100644 index 3d8dc18eb..000000000 --- a/test/data/test_array_03.expected +++ /dev/null @@ -1,6 +0,0 @@ -.=[] -.[0]=1 -.[1]=2 -.[2]=3 -.[3]=4 -.[4]=5 diff --git a/test/data/test_array_03.json b/test/data/test_array_03.json deleted file mode 100644 index 9b3f92475..000000000 --- a/test/data/test_array_03.json +++ /dev/null @@ -1 +0,0 @@ -[ 1, 2 , 3,4,5] diff --git a/test/data/test_array_04.expected b/test/data/test_array_04.expected deleted file mode 100644 index ad4add979..000000000 --- a/test/data/test_array_04.expected +++ /dev/null @@ -1,5 +0,0 @@ -.=[] -.[0]=1 -.[1]="abc" -.[2]=12.3 -.[3]=-4 diff --git a/test/data/test_array_04.json b/test/data/test_array_04.json deleted file mode 100644 index ecca546b2..000000000 --- a/test/data/test_array_04.json +++ /dev/null @@ -1 +0,0 @@ -[1, "abc" , 12.3, -4] diff --git a/test/data/test_array_05.expected b/test/data/test_array_05.expected deleted file mode 100644 index 76cff87c2..000000000 --- a/test/data/test_array_05.expected +++ /dev/null @@ -1,100 +0,0 @@ -.=[] -.[0]=1 -.[1]=2 -.[2]=3 -.[3]=4 -.[4]=5 -.[5]=6 -.[6]=7 -.[7]=8 -.[8]=9 -.[9]=10 -.[10]=11 -.[11]=12 -.[12]=13 -.[13]=14 -.[14]=15 -.[15]=16 -.[16]=17 -.[17]=18 -.[18]=19 -.[19]=20 -.[20]=21 -.[21]=22 -.[22]=23 -.[23]=24 -.[24]=25 -.[25]=26 -.[26]=27 -.[27]=28 -.[28]=29 -.[29]=30 -.[30]=31 -.[31]=32 -.[32]=33 -.[33]=34 -.[34]=35 -.[35]=36 -.[36]=37 -.[37]=38 -.[38]=39 -.[39]=40 -.[40]=41 -.[41]=42 -.[42]=43 -.[43]=44 -.[44]=45 -.[45]=46 -.[46]=47 -.[47]=48 -.[48]=49 -.[49]=50 -.[50]=51 -.[51]=52 -.[52]=53 -.[53]=54 -.[54]=55 -.[55]=56 -.[56]=57 -.[57]=58 -.[58]=59 -.[59]=60 -.[60]=61 -.[61]=62 -.[62]=63 -.[63]=64 -.[64]=65 -.[65]=66 -.[66]=67 -.[67]=68 -.[68]=69 -.[69]=70 -.[70]=71 -.[71]=72 -.[72]=73 -.[73]=74 -.[74]=75 -.[75]=76 -.[76]=77 -.[77]=78 -.[78]=79 -.[79]=80 -.[80]=81 -.[81]=82 -.[82]=83 -.[83]=84 -.[84]=85 -.[85]=86 -.[86]=87 -.[87]=88 -.[88]=89 -.[89]=90 -.[90]=91 -.[91]=92 -.[92]=93 -.[93]=94 -.[94]=95 -.[95]=96 -.[96]=97 -.[97]=98 -.[98]=99 diff --git a/test/data/test_array_05.json b/test/data/test_array_05.json deleted file mode 100644 index 7809d6c9a..000000000 --- a/test/data/test_array_05.json +++ /dev/null @@ -1 +0,0 @@ -[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] \ No newline at end of file diff --git a/test/data/test_array_06.expected b/test/data/test_array_06.expected deleted file mode 100644 index 5c9f48eaa..000000000 --- a/test/data/test_array_06.expected +++ /dev/null @@ -1,5 +0,0 @@ -.=[] -.[0]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -.[1]="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" -.[2]="ccccccccccccccccccccccc" -.[3]="dddddddddddddddddddddddddddddddddddddddddddddddddddd" diff --git a/test/data/test_array_06.json b/test/data/test_array_06.json deleted file mode 100644 index 7f6c516af..000000000 --- a/test/data/test_array_06.json +++ /dev/null @@ -1,4 +0,0 @@ -[ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", - "ccccccccccccccccccccccc", - "dddddddddddddddddddddddddddddddddddddddddddddddddddd" ] \ No newline at end of file diff --git a/test/data/test_array_07.expected b/test/data/test_array_07.expected deleted file mode 100644 index ee2fafc01..000000000 --- a/test/data/test_array_07.expected +++ /dev/null @@ -1,2122 +0,0 @@ -.=[] -.[0]=[] -.[0][0]="A" -.[0][1]=0 -.[0][2]=1 -.[0][3]=2 -.[0][4]=3 -.[0][5]=4 -.[0][6]=5 -.[0][7]=6 -.[0][8]=7 -.[0][9]=8 -.[0][10]=9 -.[0][11]=10 -.[0][12]=11 -.[0][13]=12 -.[0][14]=13 -.[0][15]=14 -.[0][16]=15 -.[0][17]=16 -.[0][18]=17 -.[0][19]=18 -.[0][20]=19 -.[0][21]=20 -.[0][22]=21 -.[0][23]=22 -.[0][24]=23 -.[0][25]=24 -.[0][26]=25 -.[0][27]=26 -.[0][28]=27 -.[0][29]=28 -.[0][30]=29 -.[0][31]=30 -.[0][32]=31 -.[0][33]=32 -.[0][34]=33 -.[0][35]=34 -.[0][36]=35 -.[0][37]=36 -.[0][38]=37 -.[0][39]=38 -.[0][40]=39 -.[0][41]=40 -.[0][42]=41 -.[0][43]=42 -.[0][44]=43 -.[0][45]=44 -.[0][46]=45 -.[0][47]=46 -.[0][48]=47 -.[0][49]=48 -.[0][50]=49 -.[0][51]=50 -.[0][52]=51 -.[0][53]=52 -.[0][54]=53 -.[0][55]=54 -.[0][56]=55 -.[0][57]=56 -.[0][58]=57 -.[0][59]=58 -.[0][60]=59 -.[0][61]=60 -.[0][62]=61 -.[0][63]=62 -.[0][64]=63 -.[0][65]=64 -.[0][66]=65 -.[0][67]=66 -.[0][68]=67 -.[0][69]=68 -.[0][70]=69 -.[0][71]=70 -.[0][72]=71 -.[0][73]=72 -.[0][74]=73 -.[0][75]=74 -.[0][76]=75 -.[0][77]=76 -.[0][78]=77 -.[0][79]=78 -.[0][80]=79 -.[0][81]=80 -.[0][82]=81 -.[0][83]=82 -.[0][84]=83 -.[0][85]=84 -.[0][86]=85 -.[0][87]=86 -.[0][88]=87 -.[0][89]=88 -.[0][90]=89 -.[0][91]=90 -.[0][92]=91 -.[0][93]=92 -.[0][94]=93 -.[0][95]=94 -.[0][96]=95 -.[0][97]=96 -.[0][98]=97 -.[0][99]=98 -.[0][100]=99 -.[0][101]=100 -.[0][102]=101 -.[0][103]=102 -.[0][104]=103 -.[0][105]=104 -.[0][106]=105 -.[0][107]=106 -.[0][108]=107 -.[0][109]=108 -.[0][110]=109 -.[0][111]=110 -.[0][112]=111 -.[0][113]=112 -.[0][114]=113 -.[0][115]=114 -.[0][116]=115 -.[0][117]=116 -.[0][118]=117 -.[0][119]=118 -.[0][120]=119 -.[0][121]=120 -.[0][122]=121 -.[0][123]=122 -.[0][124]=123 -.[0][125]=124 -.[0][126]=125 -.[0][127]=126 -.[0][128]=127 -.[0][129]=128 -.[0][130]=129 -.[0][131]=130 -.[0][132]=131 -.[0][133]=132 -.[0][134]=133 -.[0][135]=134 -.[0][136]=135 -.[0][137]=136 -.[0][138]=137 -.[0][139]=138 -.[0][140]=139 -.[0][141]=140 -.[0][142]=141 -.[0][143]=142 -.[0][144]=143 -.[0][145]=144 -.[0][146]=145 -.[0][147]=146 -.[0][148]=147 -.[0][149]=148 -.[0][150]=149 -.[0][151]=150 -.[0][152]=151 -.[0][153]=152 -.[0][154]=153 -.[0][155]=154 -.[0][156]=155 -.[0][157]=156 -.[0][158]=157 -.[0][159]=158 -.[0][160]=159 -.[0][161]=160 -.[0][162]=161 -.[0][163]=162 -.[0][164]=163 -.[0][165]=164 -.[0][166]=165 -.[0][167]=166 -.[0][168]=167 -.[0][169]=168 -.[0][170]=169 -.[0][171]=170 -.[0][172]=171 -.[0][173]=172 -.[0][174]=173 -.[0][175]=174 -.[0][176]=175 -.[0][177]=176 -.[0][178]=177 -.[0][179]=178 -.[0][180]=179 -.[0][181]=180 -.[0][182]=181 -.[0][183]=182 -.[0][184]=183 -.[0][185]=184 -.[0][186]=185 -.[0][187]=186 -.[0][188]=187 -.[0][189]=188 -.[0][190]=189 -.[0][191]=190 -.[0][192]=191 -.[0][193]=192 -.[0][194]=193 -.[0][195]=194 -.[0][196]=195 -.[0][197]=196 -.[0][198]=197 -.[0][199]=198 -.[0][200]=199 -.[0][201]=200 -.[0][202]=201 -.[0][203]=202 -.[0][204]=203 -.[0][205]=204 -.[0][206]=205 -.[0][207]=206 -.[0][208]=207 -.[0][209]=208 -.[0][210]=209 -.[0][211]=210 -.[0][212]=211 -.[0][213]=212 -.[0][214]=213 -.[0][215]=214 -.[0][216]=215 -.[0][217]=216 -.[0][218]=217 -.[0][219]=218 -.[0][220]=219 -.[0][221]=220 -.[0][222]=221 -.[0][223]=222 -.[0][224]=223 -.[0][225]=224 -.[0][226]=225 -.[0][227]=226 -.[0][228]=227 -.[0][229]=228 -.[0][230]=229 -.[0][231]=230 -.[0][232]=231 -.[0][233]=232 -.[0][234]=233 -.[0][235]=234 -.[0][236]=235 -.[0][237]=236 -.[0][238]=237 -.[0][239]=238 -.[0][240]=239 -.[0][241]=240 -.[0][242]=241 -.[0][243]=242 -.[0][244]=243 -.[0][245]=244 -.[0][246]=245 -.[0][247]=246 -.[0][248]=247 -.[0][249]=248 -.[0][250]=249 -.[0][251]=250 -.[0][252]=251 -.[0][253]=252 -.[0][254]=253 -.[0][255]=254 -.[0][256]=255 -.[0][257]=256 -.[0][258]=257 -.[0][259]=258 -.[0][260]=259 -.[0][261]=260 -.[0][262]=261 -.[0][263]=262 -.[0][264]=263 -.[0][265]=264 -.[0][266]=265 -.[0][267]=266 -.[0][268]=267 -.[0][269]=268 -.[0][270]=269 -.[0][271]=270 -.[0][272]=271 -.[0][273]=272 -.[0][274]=273 -.[0][275]=274 -.[0][276]=275 -.[0][277]=276 -.[0][278]=277 -.[0][279]=278 -.[0][280]=279 -.[0][281]=280 -.[0][282]=281 -.[0][283]=282 -.[0][284]=283 -.[0][285]=284 -.[0][286]=285 -.[0][287]=286 -.[0][288]=287 -.[0][289]=288 -.[0][290]=289 -.[0][291]=290 -.[0][292]=291 -.[0][293]=292 -.[0][294]=293 -.[0][295]=294 -.[0][296]=295 -.[0][297]=296 -.[0][298]=297 -.[0][299]=298 -.[0][300]=299 -.[0][301]=300 -.[0][302]=301 -.[0][303]=302 -.[0][304]=303 -.[0][305]=304 -.[0][306]=305 -.[0][307]=306 -.[0][308]=307 -.[0][309]=308 -.[0][310]=309 -.[0][311]=310 -.[0][312]=311 -.[0][313]=312 -.[0][314]=313 -.[0][315]=314 -.[0][316]=315 -.[0][317]=316 -.[0][318]=317 -.[0][319]=318 -.[0][320]=319 -.[0][321]=320 -.[0][322]=321 -.[0][323]=322 -.[0][324]=323 -.[0][325]=324 -.[0][326]=325 -.[0][327]=326 -.[0][328]=327 -.[0][329]=328 -.[0][330]=329 -.[0][331]=330 -.[0][332]=331 -.[0][333]=332 -.[0][334]=333 -.[0][335]=334 -.[0][336]=335 -.[0][337]=336 -.[0][338]=337 -.[0][339]=338 -.[0][340]=339 -.[0][341]=340 -.[0][342]=341 -.[0][343]=342 -.[0][344]=343 -.[0][345]=344 -.[0][346]=345 -.[0][347]=346 -.[0][348]=347 -.[0][349]=348 -.[0][350]=349 -.[0][351]=350 -.[0][352]=351 -.[0][353]=352 -.[0][354]=353 -.[0][355]=354 -.[0][356]=355 -.[0][357]=356 -.[0][358]=357 -.[0][359]=358 -.[0][360]=359 -.[0][361]=360 -.[0][362]=361 -.[0][363]=362 -.[0][364]=363 -.[0][365]=364 -.[0][366]=365 -.[0][367]=366 -.[0][368]=367 -.[0][369]=368 -.[0][370]=369 -.[0][371]=370 -.[0][372]=371 -.[0][373]=372 -.[0][374]=373 -.[0][375]=374 -.[0][376]=375 -.[0][377]=376 -.[0][378]=377 -.[0][379]=378 -.[0][380]=379 -.[0][381]=380 -.[0][382]=381 -.[0][383]=382 -.[0][384]=383 -.[0][385]=384 -.[0][386]=385 -.[0][387]=386 -.[0][388]=387 -.[0][389]=388 -.[0][390]=389 -.[0][391]=390 -.[0][392]=391 -.[0][393]=392 -.[0][394]=393 -.[0][395]=394 -.[0][396]=395 -.[0][397]=396 -.[0][398]=397 -.[0][399]=398 -.[0][400]=399 -.[0][401]=400 -.[0][402]=401 -.[0][403]=402 -.[0][404]=403 -.[0][405]=404 -.[0][406]=405 -.[0][407]=406 -.[0][408]=407 -.[0][409]=408 -.[0][410]=409 -.[0][411]=410 -.[0][412]=411 -.[0][413]=412 -.[0][414]=413 -.[0][415]=414 -.[0][416]=415 -.[0][417]=416 -.[0][418]=417 -.[0][419]=418 -.[0][420]=419 -.[0][421]=420 -.[0][422]=421 -.[0][423]=422 -.[0][424]=423 -.[0][425]=424 -.[0][426]=425 -.[0][427]=426 -.[0][428]=427 -.[0][429]=428 -.[0][430]=429 -.[0][431]=430 -.[0][432]=431 -.[0][433]=432 -.[0][434]=433 -.[0][435]=434 -.[0][436]=435 -.[0][437]=436 -.[0][438]=437 -.[0][439]=438 -.[0][440]=439 -.[0][441]=440 -.[0][442]=441 -.[0][443]=442 -.[0][444]=443 -.[0][445]=444 -.[0][446]=445 -.[0][447]=446 -.[0][448]=447 -.[0][449]=448 -.[0][450]=449 -.[0][451]=450 -.[0][452]=451 -.[0][453]=452 -.[0][454]=453 -.[0][455]=454 -.[0][456]=455 -.[0][457]=456 -.[0][458]=457 -.[0][459]=458 -.[0][460]=459 -.[0][461]=460 -.[0][462]=461 -.[0][463]=462 -.[0][464]=463 -.[0][465]=464 -.[0][466]=465 -.[0][467]=466 -.[0][468]=467 -.[0][469]=468 -.[0][470]=469 -.[0][471]=470 -.[0][472]=471 -.[0][473]=472 -.[0][474]=473 -.[0][475]=474 -.[0][476]=475 -.[0][477]=476 -.[0][478]=477 -.[0][479]=478 -.[0][480]=479 -.[0][481]=480 -.[0][482]=481 -.[0][483]=482 -.[0][484]=483 -.[0][485]=484 -.[0][486]=485 -.[0][487]=486 -.[0][488]=487 -.[0][489]=488 -.[0][490]=489 -.[0][491]=490 -.[0][492]=491 -.[0][493]=492 -.[0][494]=493 -.[0][495]=494 -.[0][496]=495 -.[0][497]=496 -.[0][498]=497 -.[0][499]=498 -.[0][500]=499 -.[0][501]=500 -.[0][502]=501 -.[0][503]=502 -.[0][504]=503 -.[0][505]=504 -.[0][506]=505 -.[0][507]=506 -.[0][508]=507 -.[0][509]=508 -.[0][510]=509 -.[0][511]=510 -.[0][512]=511 -.[0][513]=512 -.[0][514]=513 -.[0][515]=514 -.[0][516]=515 -.[0][517]=516 -.[0][518]=517 -.[0][519]=518 -.[0][520]=519 -.[0][521]=520 -.[0][522]=521 -.[0][523]=522 -.[0][524]=523 -.[0][525]=524 -.[0][526]=525 -.[0][527]=526 -.[0][528]=527 -.[0][529]=528 -.[0][530]=529 -.[0][531]=530 -.[0][532]=531 -.[0][533]=532 -.[0][534]=533 -.[0][535]=534 -.[0][536]=535 -.[0][537]=536 -.[0][538]=537 -.[0][539]=538 -.[0][540]=539 -.[0][541]=540 -.[0][542]=541 -.[0][543]=542 -.[0][544]=543 -.[0][545]=544 -.[0][546]=545 -.[0][547]=546 -.[0][548]=547 -.[0][549]=548 -.[0][550]=549 -.[0][551]=550 -.[0][552]=551 -.[0][553]=552 -.[0][554]=553 -.[0][555]=554 -.[0][556]=555 -.[0][557]=556 -.[0][558]=557 -.[0][559]=558 -.[0][560]=559 -.[0][561]=560 -.[0][562]=561 -.[0][563]=562 -.[0][564]=563 -.[0][565]=564 -.[0][566]=565 -.[0][567]=566 -.[0][568]=567 -.[0][569]=568 -.[0][570]=569 -.[0][571]=570 -.[0][572]=571 -.[0][573]=572 -.[0][574]=573 -.[0][575]=574 -.[0][576]=575 -.[0][577]=576 -.[0][578]=577 -.[0][579]=578 -.[0][580]=579 -.[0][581]=580 -.[0][582]=581 -.[0][583]=582 -.[0][584]=583 -.[0][585]=584 -.[0][586]=585 -.[0][587]=586 -.[0][588]=587 -.[0][589]=588 -.[0][590]=589 -.[0][591]=590 -.[0][592]=591 -.[0][593]=592 -.[0][594]=593 -.[0][595]=594 -.[0][596]=595 -.[0][597]=596 -.[0][598]=597 -.[0][599]=598 -.[0][600]=599 -.[0][601]=600 -.[0][602]=601 -.[0][603]=602 -.[0][604]=603 -.[0][605]=604 -.[0][606]=605 -.[0][607]=606 -.[0][608]=607 -.[0][609]=608 -.[0][610]=609 -.[0][611]=610 -.[0][612]=611 -.[0][613]=612 -.[0][614]=613 -.[0][615]=614 -.[0][616]=615 -.[0][617]=616 -.[0][618]=617 -.[0][619]=618 -.[0][620]=619 -.[0][621]=620 -.[0][622]=621 -.[0][623]=622 -.[0][624]=623 -.[0][625]=624 -.[0][626]=625 -.[0][627]=626 -.[0][628]=627 -.[0][629]=628 -.[0][630]=629 -.[0][631]=630 -.[0][632]=631 -.[0][633]=632 -.[0][634]=633 -.[0][635]=634 -.[0][636]=635 -.[0][637]=636 -.[0][638]=637 -.[0][639]=638 -.[0][640]=639 -.[0][641]=640 -.[0][642]=641 -.[0][643]=642 -.[0][644]=643 -.[0][645]=644 -.[0][646]=645 -.[0][647]=646 -.[0][648]=647 -.[0][649]=648 -.[0][650]=649 -.[0][651]=650 -.[0][652]=651 -.[0][653]=652 -.[0][654]=653 -.[0][655]=654 -.[0][656]=655 -.[0][657]=656 -.[0][658]=657 -.[0][659]=658 -.[0][660]=659 -.[0][661]=660 -.[0][662]=661 -.[0][663]=662 -.[0][664]=663 -.[0][665]=664 -.[0][666]=665 -.[0][667]=666 -.[0][668]=667 -.[0][669]=668 -.[0][670]=669 -.[0][671]=670 -.[0][672]=671 -.[0][673]=672 -.[0][674]=673 -.[0][675]=674 -.[0][676]=675 -.[0][677]=676 -.[0][678]=677 -.[0][679]=678 -.[0][680]=679 -.[0][681]=680 -.[0][682]=681 -.[0][683]=682 -.[0][684]=683 -.[0][685]=684 -.[0][686]=685 -.[0][687]=686 -.[0][688]=687 -.[0][689]=688 -.[0][690]=689 -.[0][691]=690 -.[0][692]=691 -.[0][693]=692 -.[0][694]=693 -.[0][695]=694 -.[0][696]=695 -.[0][697]=696 -.[0][698]=697 -.[0][699]=698 -.[0][700]=699 -.[0][701]=700 -.[0][702]=701 -.[0][703]=702 -.[0][704]=703 -.[0][705]=704 -.[0][706]=705 -.[0][707]=706 -.[0][708]=707 -.[0][709]=708 -.[0][710]=709 -.[0][711]=710 -.[0][712]=711 -.[0][713]=712 -.[0][714]=713 -.[0][715]=714 -.[0][716]=715 -.[0][717]=716 -.[0][718]=717 -.[0][719]=718 -.[0][720]=719 -.[0][721]=720 -.[0][722]=721 -.[0][723]=722 -.[0][724]=723 -.[0][725]=724 -.[0][726]=725 -.[0][727]=726 -.[0][728]=727 -.[0][729]=728 -.[0][730]=729 -.[0][731]=730 -.[0][732]=731 -.[0][733]=732 -.[0][734]=733 -.[0][735]=734 -.[0][736]=735 -.[0][737]=736 -.[0][738]=737 -.[0][739]=738 -.[0][740]=739 -.[0][741]=740 -.[0][742]=741 -.[0][743]=742 -.[0][744]=743 -.[0][745]=744 -.[0][746]=745 -.[0][747]=746 -.[0][748]=747 -.[0][749]=748 -.[0][750]=749 -.[0][751]=750 -.[0][752]=751 -.[0][753]=752 -.[0][754]=753 -.[0][755]=754 -.[0][756]=755 -.[0][757]=756 -.[0][758]=757 -.[0][759]=758 -.[0][760]=759 -.[0][761]=760 -.[0][762]=761 -.[0][763]=762 -.[0][764]=763 -.[0][765]=764 -.[0][766]=765 -.[0][767]=766 -.[0][768]=767 -.[0][769]=768 -.[0][770]=769 -.[0][771]=770 -.[0][772]=771 -.[0][773]=772 -.[0][774]=773 -.[0][775]=774 -.[0][776]=775 -.[0][777]=776 -.[0][778]=777 -.[0][779]=778 -.[0][780]=779 -.[0][781]=780 -.[0][782]=781 -.[0][783]=782 -.[0][784]=783 -.[0][785]=784 -.[0][786]=785 -.[0][787]=786 -.[0][788]=787 -.[0][789]=788 -.[0][790]=789 -.[0][791]=790 -.[0][792]=791 -.[0][793]=792 -.[0][794]=793 -.[0][795]=794 -.[0][796]=795 -.[0][797]=796 -.[0][798]=797 -.[0][799]=798 -.[0][800]=799 -.[0][801]=800 -.[0][802]=801 -.[0][803]=802 -.[0][804]=803 -.[0][805]=804 -.[0][806]=805 -.[0][807]=806 -.[0][808]=807 -.[0][809]=808 -.[0][810]=809 -.[0][811]=810 -.[0][812]=811 -.[0][813]=812 -.[0][814]=813 -.[0][815]=814 -.[0][816]=815 -.[0][817]=816 -.[0][818]=817 -.[0][819]=818 -.[0][820]=819 -.[0][821]=820 -.[0][822]=821 -.[0][823]=822 -.[0][824]=823 -.[0][825]=824 -.[0][826]=825 -.[0][827]=826 -.[0][828]=827 -.[0][829]=828 -.[0][830]=829 -.[0][831]=830 -.[0][832]=831 -.[0][833]=832 -.[0][834]=833 -.[0][835]=834 -.[0][836]=835 -.[0][837]=836 -.[0][838]=837 -.[0][839]=838 -.[0][840]=839 -.[0][841]=840 -.[0][842]=841 -.[0][843]=842 -.[0][844]=843 -.[0][845]=844 -.[0][846]=845 -.[0][847]=846 -.[0][848]=847 -.[0][849]=848 -.[0][850]=849 -.[0][851]=850 -.[0][852]=851 -.[0][853]=852 -.[0][854]=853 -.[0][855]=854 -.[0][856]=855 -.[0][857]=856 -.[0][858]=857 -.[0][859]=858 -.[0][860]=859 -.[0][861]=860 -.[0][862]=861 -.[0][863]=862 -.[0][864]=863 -.[0][865]=864 -.[0][866]=865 -.[0][867]=866 -.[0][868]=867 -.[0][869]=868 -.[0][870]=869 -.[0][871]=870 -.[0][872]=871 -.[0][873]=872 -.[0][874]=873 -.[0][875]=874 -.[0][876]=875 -.[0][877]=876 -.[0][878]=877 -.[0][879]=878 -.[0][880]=879 -.[0][881]=880 -.[0][882]=881 -.[0][883]=882 -.[0][884]=883 -.[0][885]=884 -.[0][886]=885 -.[0][887]=886 -.[0][888]=887 -.[0][889]=888 -.[0][890]=889 -.[0][891]=890 -.[0][892]=891 -.[0][893]=892 -.[0][894]=893 -.[0][895]=894 -.[0][896]=895 -.[0][897]=896 -.[0][898]=897 -.[0][899]=898 -.[0][900]=899 -.[0][901]=900 -.[0][902]=901 -.[0][903]=902 -.[0][904]=903 -.[0][905]=904 -.[0][906]=905 -.[0][907]=906 -.[0][908]=907 -.[0][909]=908 -.[0][910]=909 -.[0][911]=910 -.[0][912]=911 -.[0][913]=912 -.[0][914]=913 -.[0][915]=914 -.[0][916]=915 -.[0][917]=916 -.[0][918]=917 -.[0][919]=918 -.[0][920]=919 -.[0][921]=920 -.[0][922]=921 -.[0][923]=922 -.[0][924]=923 -.[0][925]=924 -.[0][926]=925 -.[0][927]=926 -.[0][928]=927 -.[0][929]=928 -.[0][930]=929 -.[0][931]=930 -.[0][932]=931 -.[0][933]=932 -.[0][934]=933 -.[0][935]=934 -.[0][936]=935 -.[0][937]=936 -.[0][938]=937 -.[0][939]=938 -.[0][940]=939 -.[0][941]=940 -.[0][942]=941 -.[0][943]=942 -.[0][944]=943 -.[0][945]=944 -.[0][946]=945 -.[0][947]=946 -.[0][948]=947 -.[0][949]=948 -.[0][950]=949 -.[0][951]=950 -.[0][952]=951 -.[0][953]=952 -.[0][954]=953 -.[0][955]=954 -.[0][956]=955 -.[0][957]=956 -.[0][958]=957 -.[0][959]=958 -.[0][960]=959 -.[0][961]=960 -.[0][962]=961 -.[0][963]=962 -.[0][964]=963 -.[0][965]=964 -.[0][966]=965 -.[0][967]=966 -.[0][968]=967 -.[0][969]=968 -.[0][970]=969 -.[0][971]=970 -.[0][972]=971 -.[0][973]=972 -.[0][974]=973 -.[0][975]=974 -.[0][976]=975 -.[0][977]=976 -.[0][978]=977 -.[0][979]=978 -.[0][980]=979 -.[0][981]=980 -.[0][982]=981 -.[0][983]=982 -.[0][984]=983 -.[0][985]=984 -.[0][986]=985 -.[0][987]=986 -.[0][988]=987 -.[0][989]=988 -.[0][990]=989 -.[0][991]=990 -.[0][992]=991 -.[0][993]=992 -.[0][994]=993 -.[0][995]=994 -.[0][996]=995 -.[0][997]=996 -.[0][998]=997 -.[0][999]=998 -.[0][1000]=999 -.[0][1001]=1000 -.[0][1002]=1001 -.[0][1003]=1002 -.[0][1004]=1003 -.[0][1005]=1004 -.[0][1006]=1005 -.[0][1007]=1006 -.[0][1008]=1007 -.[0][1009]=1008 -.[0][1010]=1009 -.[0][1011]=1010 -.[0][1012]=1011 -.[0][1013]=1012 -.[0][1014]=1013 -.[0][1015]=1014 -.[0][1016]=1015 -.[0][1017]=1016 -.[0][1018]=1017 -.[0][1019]=1018 -.[0][1020]=1019 -.[0][1021]=1020 -.[0][1022]=1021 -.[0][1023]=1022 -.[0][1024]=1023 -.[0][1025]=1024 -.[0][1026]=1025 -.[0][1027]=1026 -.[0][1028]=1027 -.[0][1029]=1028 -.[0][1030]=1029 -.[0][1031]=1030 -.[0][1032]=1031 -.[0][1033]=1032 -.[0][1034]=1033 -.[0][1035]=1034 -.[0][1036]=1035 -.[0][1037]=1036 -.[0][1038]=1037 -.[0][1039]=1038 -.[0][1040]=1039 -.[0][1041]=1040 -.[0][1042]=1041 -.[0][1043]=1042 -.[0][1044]=1043 -.[0][1045]=1044 -.[0][1046]=1045 -.[0][1047]=1046 -.[0][1048]=1047 -.[0][1049]=1048 -.[0][1050]=1049 -.[0][1051]=1050 -.[0][1052]=1051 -.[0][1053]=1052 -.[0][1054]=1053 -.[0][1055]=1054 -.[0][1056]=1055 -.[0][1057]=1056 -.[0][1058]=1057 -.[0][1059]=1058 -.[0][1060]=1059 -.[0][1061]=1060 -.[0][1062]=1061 -.[0][1063]=1062 -.[0][1064]=1063 -.[0][1065]=1064 -.[0][1066]=1065 -.[0][1067]=1066 -.[0][1068]=1067 -.[0][1069]=1068 -.[0][1070]=1069 -.[0][1071]=1070 -.[0][1072]=1071 -.[0][1073]=1072 -.[0][1074]=1073 -.[0][1075]=1074 -.[0][1076]=1075 -.[0][1077]=1076 -.[0][1078]=1077 -.[0][1079]=1078 -.[0][1080]=1079 -.[0][1081]=1080 -.[0][1082]=1081 -.[0][1083]=1082 -.[0][1084]=1083 -.[0][1085]=1084 -.[0][1086]=1085 -.[0][1087]=1086 -.[0][1088]=1087 -.[0][1089]=1088 -.[0][1090]=1089 -.[0][1091]=1090 -.[0][1092]=1091 -.[0][1093]=1092 -.[0][1094]=1093 -.[0][1095]=1094 -.[0][1096]=1095 -.[0][1097]=1096 -.[0][1098]=1097 -.[0][1099]=1098 -.[0][1100]=1099 -.[0][1101]=1100 -.[0][1102]=1101 -.[0][1103]=1102 -.[0][1104]=1103 -.[0][1105]=1104 -.[0][1106]=1105 -.[0][1107]=1106 -.[0][1108]=1107 -.[0][1109]=1108 -.[0][1110]=1109 -.[0][1111]=1110 -.[0][1112]=1111 -.[0][1113]=1112 -.[0][1114]=1113 -.[0][1115]=1114 -.[0][1116]=1115 -.[0][1117]=1116 -.[0][1118]=1117 -.[0][1119]=1118 -.[0][1120]=1119 -.[0][1121]=1120 -.[0][1122]=1121 -.[0][1123]=1122 -.[0][1124]=1123 -.[0][1125]=1124 -.[0][1126]=1125 -.[0][1127]=1126 -.[0][1128]=1127 -.[0][1129]=1128 -.[0][1130]=1129 -.[0][1131]=1130 -.[0][1132]=1131 -.[0][1133]=1132 -.[0][1134]=1133 -.[0][1135]=1134 -.[0][1136]=1135 -.[0][1137]=1136 -.[0][1138]=1137 -.[0][1139]=1138 -.[0][1140]=1139 -.[0][1141]=1140 -.[0][1142]=1141 -.[0][1143]=1142 -.[0][1144]=1143 -.[0][1145]=1144 -.[0][1146]=1145 -.[0][1147]=1146 -.[0][1148]=1147 -.[0][1149]=1148 -.[0][1150]=1149 -.[0][1151]=1150 -.[0][1152]=1151 -.[0][1153]=1152 -.[0][1154]=1153 -.[0][1155]=1154 -.[0][1156]=1155 -.[0][1157]=1156 -.[0][1158]=1157 -.[0][1159]=1158 -.[0][1160]=1159 -.[0][1161]=1160 -.[0][1162]=1161 -.[0][1163]=1162 -.[0][1164]=1163 -.[0][1165]=1164 -.[0][1166]=1165 -.[0][1167]=1166 -.[0][1168]=1167 -.[0][1169]=1168 -.[0][1170]=1169 -.[0][1171]=1170 -.[0][1172]=1171 -.[0][1173]=1172 -.[0][1174]=1173 -.[0][1175]=1174 -.[0][1176]=1175 -.[0][1177]=1176 -.[0][1178]=1177 -.[0][1179]=1178 -.[0][1180]=1179 -.[0][1181]=1180 -.[0][1182]=1181 -.[0][1183]=1182 -.[0][1184]=1183 -.[0][1185]=1184 -.[0][1186]=1185 -.[0][1187]=1186 -.[0][1188]=1187 -.[0][1189]=1188 -.[0][1190]=1189 -.[0][1191]=1190 -.[0][1192]=1191 -.[0][1193]=1192 -.[0][1194]=1193 -.[0][1195]=1194 -.[0][1196]=1195 -.[0][1197]=1196 -.[0][1198]=1197 -.[0][1199]=1198 -.[0][1200]=1199 -.[0][1201]=1200 -.[0][1202]=1201 -.[0][1203]=1202 -.[0][1204]=1203 -.[0][1205]=1204 -.[0][1206]=1205 -.[0][1207]=1206 -.[0][1208]=1207 -.[0][1209]=1208 -.[0][1210]=1209 -.[0][1211]=1210 -.[0][1212]=1211 -.[0][1213]=1212 -.[0][1214]=1213 -.[0][1215]=1214 -.[0][1216]=1215 -.[0][1217]=1216 -.[0][1218]=1217 -.[0][1219]=1218 -.[0][1220]=1219 -.[0][1221]=1220 -.[0][1222]=1221 -.[0][1223]=1222 -.[0][1224]=1223 -.[0][1225]=1224 -.[0][1226]=1225 -.[0][1227]=1226 -.[0][1228]=1227 -.[0][1229]=1228 -.[0][1230]=1229 -.[0][1231]=1230 -.[0][1232]=1231 -.[0][1233]=1232 -.[0][1234]=1233 -.[0][1235]=1234 -.[0][1236]=1235 -.[0][1237]=1236 -.[0][1238]=1237 -.[0][1239]=1238 -.[0][1240]=1239 -.[0][1241]=1240 -.[0][1242]=1241 -.[0][1243]=1242 -.[0][1244]=1243 -.[0][1245]=1244 -.[0][1246]=1245 -.[0][1247]=1246 -.[0][1248]=1247 -.[0][1249]=1248 -.[0][1250]=1249 -.[0][1251]=1250 -.[0][1252]=1251 -.[0][1253]=1252 -.[0][1254]=1253 -.[0][1255]=1254 -.[0][1256]=1255 -.[0][1257]=1256 -.[0][1258]=1257 -.[0][1259]=1258 -.[0][1260]=1259 -.[0][1261]=1260 -.[0][1262]=1261 -.[0][1263]=1262 -.[0][1264]=1263 -.[0][1265]=1264 -.[0][1266]=1265 -.[0][1267]=1266 -.[0][1268]=1267 -.[0][1269]=1268 -.[0][1270]=1269 -.[0][1271]=1270 -.[0][1272]=1271 -.[0][1273]=1272 -.[0][1274]=1273 -.[0][1275]=1274 -.[0][1276]=1275 -.[0][1277]=1276 -.[0][1278]=1277 -.[0][1279]=1278 -.[0][1280]=1279 -.[0][1281]=1280 -.[0][1282]=1281 -.[0][1283]=1282 -.[0][1284]=1283 -.[0][1285]=1284 -.[0][1286]=1285 -.[0][1287]=1286 -.[0][1288]=1287 -.[0][1289]=1288 -.[0][1290]=1289 -.[0][1291]=1290 -.[0][1292]=1291 -.[0][1293]=1292 -.[0][1294]=1293 -.[0][1295]=1294 -.[0][1296]=1295 -.[0][1297]=1296 -.[0][1298]=1297 -.[0][1299]=1298 -.[0][1300]=1299 -.[0][1301]=1300 -.[0][1302]=1301 -.[0][1303]=1302 -.[0][1304]=1303 -.[0][1305]=1304 -.[0][1306]=1305 -.[0][1307]=1306 -.[0][1308]=1307 -.[0][1309]=1308 -.[0][1310]=1309 -.[0][1311]=1310 -.[0][1312]=1311 -.[0][1313]=1312 -.[0][1314]=1313 -.[0][1315]=1314 -.[0][1316]=1315 -.[0][1317]=1316 -.[0][1318]=1317 -.[0][1319]=1318 -.[0][1320]=1319 -.[0][1321]=1320 -.[0][1322]=1321 -.[0][1323]=1322 -.[0][1324]=1323 -.[0][1325]=1324 -.[0][1326]=1325 -.[0][1327]=1326 -.[0][1328]=1327 -.[0][1329]=1328 -.[0][1330]=1329 -.[0][1331]=1330 -.[0][1332]=1331 -.[0][1333]=1332 -.[0][1334]=1333 -.[0][1335]=1334 -.[0][1336]=1335 -.[0][1337]=1336 -.[0][1338]=1337 -.[0][1339]=1338 -.[0][1340]=1339 -.[0][1341]=1340 -.[0][1342]=1341 -.[0][1343]=1342 -.[0][1344]=1343 -.[0][1345]=1344 -.[0][1346]=1345 -.[0][1347]=1346 -.[0][1348]=1347 -.[0][1349]=1348 -.[0][1350]=1349 -.[0][1351]=1350 -.[0][1352]=1351 -.[0][1353]=1352 -.[0][1354]=1353 -.[0][1355]=1354 -.[0][1356]=1355 -.[0][1357]=1356 -.[0][1358]=1357 -.[0][1359]=1358 -.[0][1360]=1359 -.[0][1361]=1360 -.[0][1362]=1361 -.[0][1363]=1362 -.[0][1364]=1363 -.[0][1365]=1364 -.[0][1366]=1365 -.[0][1367]=1366 -.[0][1368]=1367 -.[0][1369]=1368 -.[0][1370]=1369 -.[0][1371]=1370 -.[0][1372]=1371 -.[0][1373]=1372 -.[0][1374]=1373 -.[0][1375]=1374 -.[0][1376]=1375 -.[0][1377]=1376 -.[0][1378]=1377 -.[0][1379]=1378 -.[0][1380]=1379 -.[0][1381]=1380 -.[0][1382]=1381 -.[0][1383]=1382 -.[0][1384]=1383 -.[0][1385]=1384 -.[0][1386]=1385 -.[0][1387]=1386 -.[0][1388]=1387 -.[0][1389]=1388 -.[0][1390]=1389 -.[0][1391]=1390 -.[0][1392]=1391 -.[0][1393]=1392 -.[0][1394]=1393 -.[0][1395]=1394 -.[0][1396]=1395 -.[0][1397]=1396 -.[0][1398]=1397 -.[0][1399]=1398 -.[0][1400]=1399 -.[0][1401]=1400 -.[0][1402]=1401 -.[0][1403]=1402 -.[0][1404]=1403 -.[0][1405]=1404 -.[0][1406]=1405 -.[0][1407]=1406 -.[0][1408]=1407 -.[0][1409]=1408 -.[0][1410]=1409 -.[0][1411]=1410 -.[0][1412]=1411 -.[0][1413]=1412 -.[0][1414]=1413 -.[0][1415]=1414 -.[0][1416]=1415 -.[0][1417]=1416 -.[0][1418]=1417 -.[0][1419]=1418 -.[0][1420]=1419 -.[0][1421]=1420 -.[0][1422]=1421 -.[0][1423]=1422 -.[0][1424]=1423 -.[0][1425]=1424 -.[0][1426]=1425 -.[0][1427]=1426 -.[0][1428]=1427 -.[0][1429]=1428 -.[0][1430]=1429 -.[0][1431]=1430 -.[0][1432]=1431 -.[0][1433]=1432 -.[0][1434]=1433 -.[0][1435]=1434 -.[0][1436]=1435 -.[0][1437]=1436 -.[0][1438]=1437 -.[0][1439]=1438 -.[0][1440]=1439 -.[0][1441]=1440 -.[0][1442]=1441 -.[0][1443]=1442 -.[0][1444]=1443 -.[0][1445]=1444 -.[0][1446]=1445 -.[0][1447]=1446 -.[0][1448]=1447 -.[0][1449]=1448 -.[0][1450]=1449 -.[0][1451]=1450 -.[0][1452]=1451 -.[0][1453]=1452 -.[0][1454]=1453 -.[0][1455]=1454 -.[0][1456]=1455 -.[0][1457]=1456 -.[0][1458]=1457 -.[0][1459]=1458 -.[0][1460]=1459 -.[0][1461]=1460 -.[0][1462]=1461 -.[0][1463]=1462 -.[0][1464]=1463 -.[0][1465]=1464 -.[0][1466]=1465 -.[0][1467]=1466 -.[0][1468]=1467 -.[0][1469]=1468 -.[0][1470]=1469 -.[0][1471]=1470 -.[0][1472]=1471 -.[0][1473]=1472 -.[0][1474]=1473 -.[0][1475]=1474 -.[0][1476]=1475 -.[0][1477]=1476 -.[0][1478]=1477 -.[0][1479]=1478 -.[0][1480]=1479 -.[0][1481]=1480 -.[0][1482]=1481 -.[0][1483]=1482 -.[0][1484]=1483 -.[0][1485]=1484 -.[0][1486]=1485 -.[0][1487]=1486 -.[0][1488]=1487 -.[0][1489]=1488 -.[0][1490]=1489 -.[0][1491]=1490 -.[0][1492]=1491 -.[0][1493]=1492 -.[0][1494]=1493 -.[0][1495]=1494 -.[0][1496]=1495 -.[0][1497]=1496 -.[0][1498]=1497 -.[0][1499]=1498 -.[0][1500]=1499 -.[0][1501]=1500 -.[0][1502]=1501 -.[0][1503]=1502 -.[0][1504]=1503 -.[0][1505]=1504 -.[0][1506]=1505 -.[0][1507]=1506 -.[0][1508]=1507 -.[0][1509]=1508 -.[0][1510]=1509 -.[0][1511]=1510 -.[0][1512]=1511 -.[0][1513]=1512 -.[0][1514]=1513 -.[0][1515]=1514 -.[0][1516]=1515 -.[0][1517]=1516 -.[0][1518]=1517 -.[0][1519]=1518 -.[0][1520]=1519 -.[0][1521]=1520 -.[0][1522]=1521 -.[0][1523]=1522 -.[0][1524]=1523 -.[0][1525]=1524 -.[0][1526]=1525 -.[0][1527]=1526 -.[0][1528]=1527 -.[0][1529]=1528 -.[0][1530]=1529 -.[0][1531]=1530 -.[0][1532]=1531 -.[0][1533]=1532 -.[0][1534]=1533 -.[0][1535]=1534 -.[0][1536]=1535 -.[0][1537]=1536 -.[0][1538]=1537 -.[0][1539]=1538 -.[0][1540]=1539 -.[0][1541]=1540 -.[0][1542]=1541 -.[0][1543]=1542 -.[0][1544]=1543 -.[0][1545]=1544 -.[0][1546]=1545 -.[0][1547]=1546 -.[0][1548]=1547 -.[0][1549]=1548 -.[0][1550]=1549 -.[0][1551]=1550 -.[0][1552]=1551 -.[0][1553]=1552 -.[0][1554]=1553 -.[0][1555]=1554 -.[0][1556]=1555 -.[0][1557]=1556 -.[0][1558]=1557 -.[0][1559]=1558 -.[0][1560]=1559 -.[0][1561]=1560 -.[0][1562]=1561 -.[0][1563]=1562 -.[0][1564]=1563 -.[0][1565]=1564 -.[0][1566]=1565 -.[0][1567]=1566 -.[0][1568]=1567 -.[0][1569]=1568 -.[0][1570]=1569 -.[0][1571]=1570 -.[0][1572]=1571 -.[0][1573]=1572 -.[0][1574]=1573 -.[0][1575]=1574 -.[0][1576]=1575 -.[0][1577]=1576 -.[0][1578]=1577 -.[0][1579]=1578 -.[0][1580]=1579 -.[0][1581]=1580 -.[0][1582]=1581 -.[0][1583]=1582 -.[0][1584]=1583 -.[0][1585]=1584 -.[0][1586]=1585 -.[0][1587]=1586 -.[0][1588]=1587 -.[0][1589]=1588 -.[0][1590]=1589 -.[0][1591]=1590 -.[0][1592]=1591 -.[0][1593]=1592 -.[0][1594]=1593 -.[0][1595]=1594 -.[0][1596]=1595 -.[0][1597]=1596 -.[0][1598]=1597 -.[0][1599]=1598 -.[0][1600]=1599 -.[0][1601]=1600 -.[0][1602]=1601 -.[0][1603]=1602 -.[0][1604]=1603 -.[0][1605]=1604 -.[0][1606]=1605 -.[0][1607]=1606 -.[0][1608]=1607 -.[0][1609]=1608 -.[0][1610]=1609 -.[0][1611]=1610 -.[0][1612]=1611 -.[0][1613]=1612 -.[0][1614]=1613 -.[0][1615]=1614 -.[0][1616]=1615 -.[0][1617]=1616 -.[0][1618]=1617 -.[0][1619]=1618 -.[0][1620]=1619 -.[0][1621]=1620 -.[0][1622]=1621 -.[0][1623]=1622 -.[0][1624]=1623 -.[0][1625]=1624 -.[0][1626]=1625 -.[0][1627]=1626 -.[0][1628]=1627 -.[0][1629]=1628 -.[0][1630]=1629 -.[0][1631]=1630 -.[0][1632]=1631 -.[0][1633]=1632 -.[0][1634]=1633 -.[0][1635]=1634 -.[0][1636]=1635 -.[0][1637]=1636 -.[0][1638]=1637 -.[0][1639]=1638 -.[0][1640]=1639 -.[0][1641]=1640 -.[0][1642]=1641 -.[0][1643]=1642 -.[0][1644]=1643 -.[0][1645]=1644 -.[0][1646]=1645 -.[0][1647]=1646 -.[0][1648]=1647 -.[0][1649]=1648 -.[0][1650]=1649 -.[0][1651]=1650 -.[0][1652]=1651 -.[0][1653]=1652 -.[0][1654]=1653 -.[0][1655]=1654 -.[0][1656]=1655 -.[0][1657]=1656 -.[0][1658]=1657 -.[0][1659]=1658 -.[0][1660]=1659 -.[0][1661]=1660 -.[0][1662]=1661 -.[0][1663]=1662 -.[0][1664]=1663 -.[0][1665]=1664 -.[0][1666]=1665 -.[0][1667]=1666 -.[0][1668]=1667 -.[0][1669]=1668 -.[0][1670]=1669 -.[0][1671]=1670 -.[0][1672]=1671 -.[0][1673]=1672 -.[0][1674]=1673 -.[0][1675]=1674 -.[0][1676]=1675 -.[0][1677]=1676 -.[0][1678]=1677 -.[0][1679]=1678 -.[0][1680]=1679 -.[0][1681]=1680 -.[0][1682]=1681 -.[0][1683]=1682 -.[0][1684]=1683 -.[0][1685]=1684 -.[0][1686]=1685 -.[0][1687]=1686 -.[0][1688]=1687 -.[0][1689]=1688 -.[0][1690]=1689 -.[0][1691]=1690 -.[0][1692]=1691 -.[0][1693]=1692 -.[0][1694]=1693 -.[0][1695]=1694 -.[0][1696]=1695 -.[0][1697]=1696 -.[0][1698]=1697 -.[0][1699]=1698 -.[0][1700]=1699 -.[0][1701]=1700 -.[0][1702]=1701 -.[0][1703]=1702 -.[0][1704]=1703 -.[0][1705]=1704 -.[0][1706]=1705 -.[0][1707]=1706 -.[0][1708]=1707 -.[0][1709]=1708 -.[0][1710]=1709 -.[0][1711]=1710 -.[0][1712]=1711 -.[0][1713]=1712 -.[0][1714]=1713 -.[0][1715]=1714 -.[0][1716]=1715 -.[0][1717]=1716 -.[0][1718]=1717 -.[0][1719]=1718 -.[0][1720]=1719 -.[0][1721]=1720 -.[0][1722]=1721 -.[0][1723]=1722 -.[0][1724]=1723 -.[0][1725]=1724 -.[0][1726]=1725 -.[0][1727]=1726 -.[0][1728]=1727 -.[0][1729]=1728 -.[0][1730]=1729 -.[0][1731]=1730 -.[0][1732]=1731 -.[0][1733]=1732 -.[0][1734]=1733 -.[0][1735]=1734 -.[0][1736]=1735 -.[0][1737]=1736 -.[0][1738]=1737 -.[0][1739]=1738 -.[0][1740]=1739 -.[0][1741]=1740 -.[0][1742]=1741 -.[0][1743]=1742 -.[0][1744]=1743 -.[0][1745]=1744 -.[0][1746]=1745 -.[0][1747]=1746 -.[0][1748]=1747 -.[0][1749]=1748 -.[0][1750]=1749 -.[0][1751]=1750 -.[0][1752]=1751 -.[0][1753]=1752 -.[0][1754]=1753 -.[0][1755]=1754 -.[0][1756]=1755 -.[0][1757]=1756 -.[0][1758]=1757 -.[0][1759]=1758 -.[0][1760]=1759 -.[0][1761]=1760 -.[0][1762]=1761 -.[0][1763]=1762 -.[0][1764]=1763 -.[0][1765]=1764 -.[0][1766]=1765 -.[0][1767]=1766 -.[0][1768]=1767 -.[0][1769]=1768 -.[0][1770]=1769 -.[0][1771]=1770 -.[0][1772]=1771 -.[0][1773]=1772 -.[0][1774]=1773 -.[0][1775]=1774 -.[0][1776]=1775 -.[0][1777]=1776 -.[0][1778]=1777 -.[0][1779]=1778 -.[0][1780]=1779 -.[0][1781]=1780 -.[0][1782]=1781 -.[0][1783]=1782 -.[0][1784]=1783 -.[0][1785]=1784 -.[0][1786]=1785 -.[0][1787]=1786 -.[0][1788]=1787 -.[0][1789]=1788 -.[0][1790]=1789 -.[0][1791]=1790 -.[0][1792]=1791 -.[0][1793]=1792 -.[0][1794]=1793 -.[0][1795]=1794 -.[0][1796]=1795 -.[0][1797]=1796 -.[0][1798]=1797 -.[0][1799]=1798 -.[0][1800]=1799 -.[0][1801]=1800 -.[0][1802]=1801 -.[0][1803]=1802 -.[0][1804]=1803 -.[0][1805]=1804 -.[0][1806]=1805 -.[0][1807]=1806 -.[0][1808]=1807 -.[0][1809]=1808 -.[0][1810]=1809 -.[0][1811]=1810 -.[0][1812]=1811 -.[0][1813]=1812 -.[0][1814]=1813 -.[0][1815]=1814 -.[0][1816]=1815 -.[0][1817]=1816 -.[0][1818]=1817 -.[0][1819]=1818 -.[0][1820]=1819 -.[0][1821]=1820 -.[0][1822]=1821 -.[0][1823]=1822 -.[0][1824]=1823 -.[0][1825]=1824 -.[0][1826]=1825 -.[0][1827]=1826 -.[0][1828]=1827 -.[0][1829]=1828 -.[0][1830]=1829 -.[0][1831]=1830 -.[0][1832]=1831 -.[0][1833]=1832 -.[0][1834]=1833 -.[0][1835]=1834 -.[0][1836]=1835 -.[0][1837]=1836 -.[0][1838]=1837 -.[0][1839]=1838 -.[0][1840]=1839 -.[0][1841]=1840 -.[0][1842]=1841 -.[0][1843]=1842 -.[0][1844]=1843 -.[0][1845]=1844 -.[0][1846]=1845 -.[0][1847]=1846 -.[0][1848]=1847 -.[0][1849]=1848 -.[0][1850]=1849 -.[0][1851]=1850 -.[0][1852]=1851 -.[0][1853]=1852 -.[0][1854]=1853 -.[0][1855]=1854 -.[0][1856]=1855 -.[0][1857]=1856 -.[0][1858]=1857 -.[0][1859]=1858 -.[0][1860]=1859 -.[0][1861]=1860 -.[0][1862]=1861 -.[0][1863]=1862 -.[0][1864]=1863 -.[0][1865]=1864 -.[0][1866]=1865 -.[0][1867]=1866 -.[0][1868]=1867 -.[0][1869]=1868 -.[0][1870]=1869 -.[0][1871]=1870 -.[0][1872]=1871 -.[0][1873]=1872 -.[0][1874]=1873 -.[0][1875]=1874 -.[0][1876]=1875 -.[0][1877]=1876 -.[0][1878]=1877 -.[0][1879]=1878 -.[0][1880]=1879 -.[0][1881]=1880 -.[0][1882]=1881 -.[0][1883]=1882 -.[0][1884]=1883 -.[0][1885]=1884 -.[0][1886]=1885 -.[0][1887]=1886 -.[0][1888]=1887 -.[0][1889]=1888 -.[0][1890]=1889 -.[0][1891]=1890 -.[0][1892]=1891 -.[0][1893]=1892 -.[0][1894]=1893 -.[0][1895]=1894 -.[0][1896]=1895 -.[0][1897]=1896 -.[0][1898]=1897 -.[0][1899]=1898 -.[0][1900]=1899 -.[0][1901]=1900 -.[0][1902]=1901 -.[0][1903]=1902 -.[0][1904]=1903 -.[0][1905]=1904 -.[0][1906]=1905 -.[0][1907]=1906 -.[0][1908]=1907 -.[0][1909]=1908 -.[0][1910]=1909 -.[0][1911]=1910 -.[0][1912]=1911 -.[0][1913]=1912 -.[0][1914]=1913 -.[0][1915]=1914 -.[0][1916]=1915 -.[0][1917]=1916 -.[0][1918]=1917 -.[0][1919]=1918 -.[0][1920]=1919 -.[0][1921]=1920 -.[0][1922]=1921 -.[0][1923]=1922 -.[0][1924]=1923 -.[0][1925]=1924 -.[0][1926]=1925 -.[0][1927]=1926 -.[0][1928]=1927 -.[0][1929]=1928 -.[0][1930]=1929 -.[0][1931]=1930 -.[0][1932]=1931 -.[0][1933]=1932 -.[0][1934]=1933 -.[0][1935]=1934 -.[0][1936]=1935 -.[0][1937]=1936 -.[0][1938]=1937 -.[0][1939]=1938 -.[0][1940]=1939 -.[0][1941]=1940 -.[0][1942]=1941 -.[0][1943]=1942 -.[0][1944]=1943 -.[0][1945]=1944 -.[0][1946]=1945 -.[0][1947]=1946 -.[0][1948]=1947 -.[0][1949]=1948 -.[0][1950]=1949 -.[0][1951]=1950 -.[0][1952]=1951 -.[0][1953]=1952 -.[0][1954]=1953 -.[0][1955]=1954 -.[0][1956]=1955 -.[0][1957]=1956 -.[0][1958]=1957 -.[0][1959]=1958 -.[0][1960]=1959 -.[0][1961]=1960 -.[0][1962]=1961 -.[0][1963]=1962 -.[0][1964]=1963 -.[0][1965]=1964 -.[0][1966]=1965 -.[0][1967]=1966 -.[0][1968]=1967 -.[0][1969]=1968 -.[0][1970]=1969 -.[0][1971]=1970 -.[0][1972]=1971 -.[0][1973]=1972 -.[0][1974]=1973 -.[0][1975]=1974 -.[0][1976]=1975 -.[0][1977]=1976 -.[0][1978]=1977 -.[0][1979]=1978 -.[0][1980]=1979 -.[0][1981]=1980 -.[0][1982]=1981 -.[0][1983]=1982 -.[0][1984]=1983 -.[0][1985]=1984 -.[0][1986]=1985 -.[0][1987]=1986 -.[0][1988]=1987 -.[0][1989]=1988 -.[0][1990]=1989 -.[0][1991]=1990 -.[0][1992]=1991 -.[0][1993]=1992 -.[0][1994]=1993 -.[0][1995]=1994 -.[0][1996]=1995 -.[0][1997]=1996 -.[0][1998]=1997 -.[0][1999]=1998 -.[0][2000]=1999 -.[0][2001]=2000 -.[0][2002]=2001 -.[0][2003]=2002 -.[0][2004]=2003 -.[0][2005]=2004 -.[0][2006]=2005 -.[0][2007]=2006 -.[0][2008]=2007 -.[0][2009]=2008 -.[0][2010]=2009 -.[0][2011]=2010 -.[0][2012]=2011 -.[0][2013]=2012 -.[0][2014]=2013 -.[0][2015]=2014 -.[0][2016]=2015 -.[0][2017]=2016 -.[0][2018]=2017 -.[0][2019]=2018 -.[0][2020]=2019 -.[0][2021]=2020 -.[0][2022]=2021 -.[0][2023]=2022 -.[0][2024]=2023 -.[0][2025]=2024 -.[0][2026]=2025 -.[0][2027]=2026 -.[0][2028]=2027 -.[0][2029]=2028 -.[0][2030]=2029 -.[0][2031]=2030 -.[0][2032]=2031 -.[0][2033]=2032 -.[0][2034]=2033 -.[0][2035]=2034 -.[0][2036]=2035 -.[0][2037]=2036 -.[0][2038]=2037 -.[0][2039]=2038 -.[0][2040]=2039 -.[0][2041]=2040 -.[0][2042]=2041 -.[0][2043]=2042 -.[0][2044]=2043 -.[0][2045]=2044 -.[0][2046]=2045 -.[0][2047]=2046 -.[0][2048]=2047 -.[0][2049]=2048 -.[0][2050]=2049 -.[0][2051]=2050 -.[0][2052]=2051 -.[0][2053]=2052 -.[0][2054]=2053 -.[0][2055]=2054 -.[0][2056]=2055 -.[0][2057]=2056 -.[0][2058]=2057 -.[0][2059]=2058 -.[0][2060]=2059 -.[0][2061]=2060 -.[0][2062]=2061 -.[0][2063]=2062 -.[0][2064]=2063 -.[0][2065]=2064 -.[0][2066]=2065 -.[0][2067]=2066 -.[0][2068]=2067 -.[0][2069]=2068 -.[0][2070]=2069 -.[0][2071]=2070 -.[0][2072]=2071 -.[0][2073]=2072 -.[0][2074]=2073 -.[0][2075]=2074 -.[0][2076]=2075 -.[0][2077]=2076 -.[0][2078]=2077 -.[0][2079]=2078 -.[0][2080]=2079 -.[0][2081]=2080 -.[0][2082]=2081 -.[0][2083]=2082 -.[0][2084]=2083 -.[0][2085]=2084 -.[0][2086]=2085 -.[0][2087]=2086 -.[0][2088]=2087 -.[0][2089]=2088 -.[0][2090]=2089 -.[0][2091]=2090 -.[0][2092]=2091 -.[0][2093]=2092 -.[0][2094]=2093 -.[0][2095]=2094 -.[0][2096]=2095 -.[0][2097]=2096 -.[0][2098]=2097 -.[0][2099]=2098 -.[0][2100]=2099 -.[0][2101]=2100 -.[0][2102]=2101 -.[0][2103]=2102 -.[0][2104]=2103 -.[0][2105]=2104 -.[0][2106]=2105 -.[0][2107]=2106 -.[0][2108]=2107 -.[0][2109]=2108 -.[0][2110]=2109 -.[0][2111]=2110 -.[0][2112]=2111 -.[0][2113]=2112 -.[0][2114]=2113 -.[0][2115]=2114 -.[0][2116]=2115 -.[0][2117]=2116 -.[0][2118]=2117 -.[0][2119]=2118 diff --git a/test/data/test_array_07.json b/test/data/test_array_07.json deleted file mode 100644 index e4ab4cd43..000000000 --- a/test/data/test_array_07.json +++ /dev/null @@ -1,2 +0,0 @@ -[["A",0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118] -] \ No newline at end of file diff --git a/test/data/test_basic_01.expected b/test/data/test_basic_01.expected deleted file mode 100644 index d761fce1c..000000000 --- a/test/data/test_basic_01.expected +++ /dev/null @@ -1 +0,0 @@ -.=123456789 diff --git a/test/data/test_basic_01.json b/test/data/test_basic_01.json deleted file mode 100644 index 11f11f9be..000000000 --- a/test/data/test_basic_01.json +++ /dev/null @@ -1 +0,0 @@ -0123456789 diff --git a/test/data/test_basic_02.expected b/test/data/test_basic_02.expected deleted file mode 100644 index 650e37cba..000000000 --- a/test/data/test_basic_02.expected +++ /dev/null @@ -1 +0,0 @@ -.=-123456789 diff --git a/test/data/test_basic_02.json b/test/data/test_basic_02.json deleted file mode 100644 index bf11bceac..000000000 --- a/test/data/test_basic_02.json +++ /dev/null @@ -1 +0,0 @@ --0123456789 diff --git a/test/data/test_basic_03.expected b/test/data/test_basic_03.expected deleted file mode 100644 index 1da2d395b..000000000 --- a/test/data/test_basic_03.expected +++ /dev/null @@ -1,3 +0,0 @@ -.=1.2345678 - - diff --git a/test/data/test_basic_03.json b/test/data/test_basic_03.json deleted file mode 100644 index a92b6bd28..000000000 --- a/test/data/test_basic_03.json +++ /dev/null @@ -1,3 +0,0 @@ -1.2345678 - - diff --git a/test/data/test_basic_04.expected b/test/data/test_basic_04.expected deleted file mode 100644 index 013f424f9..000000000 --- a/test/data/test_basic_04.expected +++ /dev/null @@ -1,2 +0,0 @@ -.="abcdef" - diff --git a/test/data/test_basic_04.json b/test/data/test_basic_04.json deleted file mode 100644 index 17eeb99e0..000000000 --- a/test/data/test_basic_04.json +++ /dev/null @@ -1,2 +0,0 @@ -"abcdef" - diff --git a/test/data/test_basic_05.expected b/test/data/test_basic_05.expected deleted file mode 100644 index c8db822e5..000000000 --- a/test/data/test_basic_05.expected +++ /dev/null @@ -1,2 +0,0 @@ -.=null - diff --git a/test/data/test_basic_05.json b/test/data/test_basic_05.json deleted file mode 100644 index d0aaea212..000000000 --- a/test/data/test_basic_05.json +++ /dev/null @@ -1,2 +0,0 @@ -null - diff --git a/test/data/test_basic_06.expected b/test/data/test_basic_06.expected deleted file mode 100644 index 49be55a96..000000000 --- a/test/data/test_basic_06.expected +++ /dev/null @@ -1,2 +0,0 @@ -.=true - diff --git a/test/data/test_basic_06.json b/test/data/test_basic_06.json deleted file mode 100644 index 7eead1ee7..000000000 --- a/test/data/test_basic_06.json +++ /dev/null @@ -1,2 +0,0 @@ -true - diff --git a/test/data/test_basic_07.expected b/test/data/test_basic_07.expected deleted file mode 100644 index fe55a6a85..000000000 --- a/test/data/test_basic_07.expected +++ /dev/null @@ -1,2 +0,0 @@ -.=false - diff --git a/test/data/test_basic_07.json b/test/data/test_basic_07.json deleted file mode 100644 index a864bc487..000000000 --- a/test/data/test_basic_07.json +++ /dev/null @@ -1,2 +0,0 @@ -false - diff --git a/test/data/test_basic_08.expected b/test/data/test_basic_08.expected deleted file mode 100644 index caf5352a1..000000000 --- a/test/data/test_basic_08.expected +++ /dev/null @@ -1,3 +0,0 @@ -// C++ style comment -.=null - diff --git a/test/data/test_basic_08.json b/test/data/test_basic_08.json deleted file mode 100644 index fd78837c0..000000000 --- a/test/data/test_basic_08.json +++ /dev/null @@ -1,3 +0,0 @@ -// C++ style comment -null - diff --git a/test/data/test_basic_09.expected b/test/data/test_basic_09.expected deleted file mode 100644 index 8b129da42..000000000 --- a/test/data/test_basic_09.expected +++ /dev/null @@ -1,4 +0,0 @@ -/* C style comment - */ -.=null - diff --git a/test/data/test_basic_09.json b/test/data/test_basic_09.json deleted file mode 100644 index fc95f0f51..000000000 --- a/test/data/test_basic_09.json +++ /dev/null @@ -1,4 +0,0 @@ -/* C style comment - */ -null - diff --git a/test/data/test_comment_00.expected b/test/data/test_comment_00.expected deleted file mode 100644 index 284a797d7..000000000 --- a/test/data/test_comment_00.expected +++ /dev/null @@ -1,4 +0,0 @@ -// Comment for array -.=[] -// Comment within array -.[0]="one-element" diff --git a/test/data/test_comment_00.json b/test/data/test_comment_00.json deleted file mode 100644 index 4df577a8a..000000000 --- a/test/data/test_comment_00.json +++ /dev/null @@ -1,5 +0,0 @@ -// Comment for array -[ - // Comment within array - "one-element" -] diff --git a/test/data/test_comment_01.expected b/test/data/test_comment_01.expected deleted file mode 100644 index 1ed01ba10..000000000 --- a/test/data/test_comment_01.expected +++ /dev/null @@ -1,10 +0,0 @@ -.={} -// Comment for array -.test=[] -// Comment within array -.test[0]={} -.test[0].a="aaa" -.test[1]={} -.test[1].b="bbb" -.test[2]={} -.test[2].c="ccc" diff --git a/test/data/test_comment_01.json b/test/data/test_comment_01.json deleted file mode 100644 index 6defe4004..000000000 --- a/test/data/test_comment_01.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "test": - // Comment for array - [ - // Comment within array - { "a" : "aaa" }, // Comment for a - { "b" : "bbb" }, // Comment for b - { "c" : "ccc" } // Comment for c - ] -} diff --git a/test/data/test_comment_02.expected b/test/data/test_comment_02.expected deleted file mode 100644 index 8986dbac0..000000000 --- a/test/data/test_comment_02.expected +++ /dev/null @@ -1,23 +0,0 @@ -.={} -/* C-style comment - - C-style-2 comment */ -.c-test={} -.c-test.a=1 -/* Internal comment c-style */ -.c-test.b=2 -// C++-style comment -.cpp-test={} -// Multiline comment cpp-style -// Second line -.cpp-test.c=3 -// Comment before double -.cpp-test.d=4.1 -// Comment before string -.cpp-test.e="e-string" -// Comment before true -.cpp-test.f=true -// Comment before false -.cpp-test.g=false -// Comment before null -.cpp-test.h=null diff --git a/test/data/test_comment_02.json b/test/data/test_comment_02.json deleted file mode 100644 index f5042e0dd..000000000 --- a/test/data/test_comment_02.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - /* C-style comment - - C-style-2 comment */ - "c-test" : { - "a" : 1, - /* Internal comment c-style */ - "b" : 2 - }, - // C++-style comment - "cpp-test" : { - // Multiline comment cpp-style - // Second line - "c" : 3, - // Comment before double - "d" : 4.1, - // Comment before string - "e" : "e-string", - // Comment before true - "f" : true, - // Comment before false - "g" : false, - // Comment before null - "h" : null - } -} diff --git a/test/data/test_complex_01.expected b/test/data/test_complex_01.expected deleted file mode 100644 index 7573c8812..000000000 --- a/test/data/test_complex_01.expected +++ /dev/null @@ -1,20 +0,0 @@ -.={} -.attribute=[] -.attribute[0]="random" -.attribute[1]="short" -.attribute[2]="bold" -.attribute[3]=12 -.attribute[4]={} -.attribute[4].height=7 -.attribute[4].width=64 -.count=1234 -.name={} -.name.aka="T.E.S.T." -.name.id=123987 -.test={} -.test.1={} -.test.1.2={} -.test.1.2.3={} -.test.1.2.3.coord=[] -.test.1.2.3.coord[0]=1 -.test.1.2.3.coord[1]=2 diff --git a/test/data/test_complex_01.json b/test/data/test_complex_01.json deleted file mode 100644 index cc0f30f5c..000000000 --- a/test/data/test_complex_01.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "count" : 1234, - "name" : { "aka" : "T.E.S.T.", "id" : 123987 }, - "attribute" : [ - "random", - "short", - "bold", - 12, - { "height" : 7, "width" : 64 } - ], - "test": { "1" : - { "2" : - { "3" : { "coord" : [ 1,2] } - } - } - } -} diff --git a/test/data/test_integer_01.expected b/test/data/test_integer_01.expected deleted file mode 100644 index 463e149de..000000000 --- a/test/data/test_integer_01.expected +++ /dev/null @@ -1,2 +0,0 @@ -// Max signed integer -.=2147483647 diff --git a/test/data/test_integer_01.json b/test/data/test_integer_01.json deleted file mode 100644 index 5ab12ffee..000000000 --- a/test/data/test_integer_01.json +++ /dev/null @@ -1,2 +0,0 @@ -// Max signed integer -2147483647 diff --git a/test/data/test_integer_02.expected b/test/data/test_integer_02.expected deleted file mode 100644 index 0773e0851..000000000 --- a/test/data/test_integer_02.expected +++ /dev/null @@ -1,2 +0,0 @@ -// Min signed integer -.=-2147483648 diff --git a/test/data/test_integer_02.json b/test/data/test_integer_02.json deleted file mode 100644 index 056c85006..000000000 --- a/test/data/test_integer_02.json +++ /dev/null @@ -1,2 +0,0 @@ -// Min signed integer --2147483648 diff --git a/test/data/test_integer_03.expected b/test/data/test_integer_03.expected deleted file mode 100644 index c7efff799..000000000 --- a/test/data/test_integer_03.expected +++ /dev/null @@ -1,2 +0,0 @@ -// Max unsigned integer -.=4294967295 diff --git a/test/data/test_integer_03.json b/test/data/test_integer_03.json deleted file mode 100644 index 12ef3fbb8..000000000 --- a/test/data/test_integer_03.json +++ /dev/null @@ -1,2 +0,0 @@ -// Max unsigned integer -4294967295 diff --git a/test/data/test_integer_04.expected b/test/data/test_integer_04.expected deleted file mode 100644 index 39f856704..000000000 --- a/test/data/test_integer_04.expected +++ /dev/null @@ -1,3 +0,0 @@ -// Min unsigned integer -.=0 - diff --git a/test/data/test_integer_04.json b/test/data/test_integer_04.json deleted file mode 100644 index bf8149945..000000000 --- a/test/data/test_integer_04.json +++ /dev/null @@ -1,3 +0,0 @@ -// Min unsigned integer -0 - diff --git a/test/data/test_integer_05.expected b/test/data/test_integer_05.expected deleted file mode 100644 index 0caea9d3f..000000000 --- a/test/data/test_integer_05.expected +++ /dev/null @@ -1,2 +0,0 @@ -.=1 - diff --git a/test/data/test_integer_05.json b/test/data/test_integer_05.json deleted file mode 100644 index d474e1b4d..000000000 --- a/test/data/test_integer_05.json +++ /dev/null @@ -1,2 +0,0 @@ -1 - diff --git a/test/data/test_integer_06_64bits.expected b/test/data/test_integer_06_64bits.expected deleted file mode 100644 index 131b085ff..000000000 --- a/test/data/test_integer_06_64bits.expected +++ /dev/null @@ -1 +0,0 @@ -.=9223372036854775808 diff --git a/test/data/test_integer_06_64bits.json b/test/data/test_integer_06_64bits.json deleted file mode 100644 index cfedfe5e8..000000000 --- a/test/data/test_integer_06_64bits.json +++ /dev/null @@ -1,2 +0,0 @@ -9223372036854775808 - diff --git a/test/data/test_integer_07_64bits.expected b/test/data/test_integer_07_64bits.expected deleted file mode 100644 index c8524a32c..000000000 --- a/test/data/test_integer_07_64bits.expected +++ /dev/null @@ -1 +0,0 @@ -.=-9223372036854775808 diff --git a/test/data/test_integer_07_64bits.json b/test/data/test_integer_07_64bits.json deleted file mode 100644 index a964ad2ed..000000000 --- a/test/data/test_integer_07_64bits.json +++ /dev/null @@ -1,2 +0,0 @@ --9223372036854775808 - diff --git a/test/data/test_integer_08_64bits.expected b/test/data/test_integer_08_64bits.expected deleted file mode 100644 index 321bba5a7..000000000 --- a/test/data/test_integer_08_64bits.expected +++ /dev/null @@ -1 +0,0 @@ -.=18446744073709551615 diff --git a/test/data/test_integer_08_64bits.json b/test/data/test_integer_08_64bits.json deleted file mode 100644 index 4c15a01b4..000000000 --- a/test/data/test_integer_08_64bits.json +++ /dev/null @@ -1,2 +0,0 @@ -18446744073709551615 - diff --git a/test/data/test_large_01.expected b/test/data/test_large_01.expected deleted file mode 100644 index ee2fafc01..000000000 --- a/test/data/test_large_01.expected +++ /dev/null @@ -1,2122 +0,0 @@ -.=[] -.[0]=[] -.[0][0]="A" -.[0][1]=0 -.[0][2]=1 -.[0][3]=2 -.[0][4]=3 -.[0][5]=4 -.[0][6]=5 -.[0][7]=6 -.[0][8]=7 -.[0][9]=8 -.[0][10]=9 -.[0][11]=10 -.[0][12]=11 -.[0][13]=12 -.[0][14]=13 -.[0][15]=14 -.[0][16]=15 -.[0][17]=16 -.[0][18]=17 -.[0][19]=18 -.[0][20]=19 -.[0][21]=20 -.[0][22]=21 -.[0][23]=22 -.[0][24]=23 -.[0][25]=24 -.[0][26]=25 -.[0][27]=26 -.[0][28]=27 -.[0][29]=28 -.[0][30]=29 -.[0][31]=30 -.[0][32]=31 -.[0][33]=32 -.[0][34]=33 -.[0][35]=34 -.[0][36]=35 -.[0][37]=36 -.[0][38]=37 -.[0][39]=38 -.[0][40]=39 -.[0][41]=40 -.[0][42]=41 -.[0][43]=42 -.[0][44]=43 -.[0][45]=44 -.[0][46]=45 -.[0][47]=46 -.[0][48]=47 -.[0][49]=48 -.[0][50]=49 -.[0][51]=50 -.[0][52]=51 -.[0][53]=52 -.[0][54]=53 -.[0][55]=54 -.[0][56]=55 -.[0][57]=56 -.[0][58]=57 -.[0][59]=58 -.[0][60]=59 -.[0][61]=60 -.[0][62]=61 -.[0][63]=62 -.[0][64]=63 -.[0][65]=64 -.[0][66]=65 -.[0][67]=66 -.[0][68]=67 -.[0][69]=68 -.[0][70]=69 -.[0][71]=70 -.[0][72]=71 -.[0][73]=72 -.[0][74]=73 -.[0][75]=74 -.[0][76]=75 -.[0][77]=76 -.[0][78]=77 -.[0][79]=78 -.[0][80]=79 -.[0][81]=80 -.[0][82]=81 -.[0][83]=82 -.[0][84]=83 -.[0][85]=84 -.[0][86]=85 -.[0][87]=86 -.[0][88]=87 -.[0][89]=88 -.[0][90]=89 -.[0][91]=90 -.[0][92]=91 -.[0][93]=92 -.[0][94]=93 -.[0][95]=94 -.[0][96]=95 -.[0][97]=96 -.[0][98]=97 -.[0][99]=98 -.[0][100]=99 -.[0][101]=100 -.[0][102]=101 -.[0][103]=102 -.[0][104]=103 -.[0][105]=104 -.[0][106]=105 -.[0][107]=106 -.[0][108]=107 -.[0][109]=108 -.[0][110]=109 -.[0][111]=110 -.[0][112]=111 -.[0][113]=112 -.[0][114]=113 -.[0][115]=114 -.[0][116]=115 -.[0][117]=116 -.[0][118]=117 -.[0][119]=118 -.[0][120]=119 -.[0][121]=120 -.[0][122]=121 -.[0][123]=122 -.[0][124]=123 -.[0][125]=124 -.[0][126]=125 -.[0][127]=126 -.[0][128]=127 -.[0][129]=128 -.[0][130]=129 -.[0][131]=130 -.[0][132]=131 -.[0][133]=132 -.[0][134]=133 -.[0][135]=134 -.[0][136]=135 -.[0][137]=136 -.[0][138]=137 -.[0][139]=138 -.[0][140]=139 -.[0][141]=140 -.[0][142]=141 -.[0][143]=142 -.[0][144]=143 -.[0][145]=144 -.[0][146]=145 -.[0][147]=146 -.[0][148]=147 -.[0][149]=148 -.[0][150]=149 -.[0][151]=150 -.[0][152]=151 -.[0][153]=152 -.[0][154]=153 -.[0][155]=154 -.[0][156]=155 -.[0][157]=156 -.[0][158]=157 -.[0][159]=158 -.[0][160]=159 -.[0][161]=160 -.[0][162]=161 -.[0][163]=162 -.[0][164]=163 -.[0][165]=164 -.[0][166]=165 -.[0][167]=166 -.[0][168]=167 -.[0][169]=168 -.[0][170]=169 -.[0][171]=170 -.[0][172]=171 -.[0][173]=172 -.[0][174]=173 -.[0][175]=174 -.[0][176]=175 -.[0][177]=176 -.[0][178]=177 -.[0][179]=178 -.[0][180]=179 -.[0][181]=180 -.[0][182]=181 -.[0][183]=182 -.[0][184]=183 -.[0][185]=184 -.[0][186]=185 -.[0][187]=186 -.[0][188]=187 -.[0][189]=188 -.[0][190]=189 -.[0][191]=190 -.[0][192]=191 -.[0][193]=192 -.[0][194]=193 -.[0][195]=194 -.[0][196]=195 -.[0][197]=196 -.[0][198]=197 -.[0][199]=198 -.[0][200]=199 -.[0][201]=200 -.[0][202]=201 -.[0][203]=202 -.[0][204]=203 -.[0][205]=204 -.[0][206]=205 -.[0][207]=206 -.[0][208]=207 -.[0][209]=208 -.[0][210]=209 -.[0][211]=210 -.[0][212]=211 -.[0][213]=212 -.[0][214]=213 -.[0][215]=214 -.[0][216]=215 -.[0][217]=216 -.[0][218]=217 -.[0][219]=218 -.[0][220]=219 -.[0][221]=220 -.[0][222]=221 -.[0][223]=222 -.[0][224]=223 -.[0][225]=224 -.[0][226]=225 -.[0][227]=226 -.[0][228]=227 -.[0][229]=228 -.[0][230]=229 -.[0][231]=230 -.[0][232]=231 -.[0][233]=232 -.[0][234]=233 -.[0][235]=234 -.[0][236]=235 -.[0][237]=236 -.[0][238]=237 -.[0][239]=238 -.[0][240]=239 -.[0][241]=240 -.[0][242]=241 -.[0][243]=242 -.[0][244]=243 -.[0][245]=244 -.[0][246]=245 -.[0][247]=246 -.[0][248]=247 -.[0][249]=248 -.[0][250]=249 -.[0][251]=250 -.[0][252]=251 -.[0][253]=252 -.[0][254]=253 -.[0][255]=254 -.[0][256]=255 -.[0][257]=256 -.[0][258]=257 -.[0][259]=258 -.[0][260]=259 -.[0][261]=260 -.[0][262]=261 -.[0][263]=262 -.[0][264]=263 -.[0][265]=264 -.[0][266]=265 -.[0][267]=266 -.[0][268]=267 -.[0][269]=268 -.[0][270]=269 -.[0][271]=270 -.[0][272]=271 -.[0][273]=272 -.[0][274]=273 -.[0][275]=274 -.[0][276]=275 -.[0][277]=276 -.[0][278]=277 -.[0][279]=278 -.[0][280]=279 -.[0][281]=280 -.[0][282]=281 -.[0][283]=282 -.[0][284]=283 -.[0][285]=284 -.[0][286]=285 -.[0][287]=286 -.[0][288]=287 -.[0][289]=288 -.[0][290]=289 -.[0][291]=290 -.[0][292]=291 -.[0][293]=292 -.[0][294]=293 -.[0][295]=294 -.[0][296]=295 -.[0][297]=296 -.[0][298]=297 -.[0][299]=298 -.[0][300]=299 -.[0][301]=300 -.[0][302]=301 -.[0][303]=302 -.[0][304]=303 -.[0][305]=304 -.[0][306]=305 -.[0][307]=306 -.[0][308]=307 -.[0][309]=308 -.[0][310]=309 -.[0][311]=310 -.[0][312]=311 -.[0][313]=312 -.[0][314]=313 -.[0][315]=314 -.[0][316]=315 -.[0][317]=316 -.[0][318]=317 -.[0][319]=318 -.[0][320]=319 -.[0][321]=320 -.[0][322]=321 -.[0][323]=322 -.[0][324]=323 -.[0][325]=324 -.[0][326]=325 -.[0][327]=326 -.[0][328]=327 -.[0][329]=328 -.[0][330]=329 -.[0][331]=330 -.[0][332]=331 -.[0][333]=332 -.[0][334]=333 -.[0][335]=334 -.[0][336]=335 -.[0][337]=336 -.[0][338]=337 -.[0][339]=338 -.[0][340]=339 -.[0][341]=340 -.[0][342]=341 -.[0][343]=342 -.[0][344]=343 -.[0][345]=344 -.[0][346]=345 -.[0][347]=346 -.[0][348]=347 -.[0][349]=348 -.[0][350]=349 -.[0][351]=350 -.[0][352]=351 -.[0][353]=352 -.[0][354]=353 -.[0][355]=354 -.[0][356]=355 -.[0][357]=356 -.[0][358]=357 -.[0][359]=358 -.[0][360]=359 -.[0][361]=360 -.[0][362]=361 -.[0][363]=362 -.[0][364]=363 -.[0][365]=364 -.[0][366]=365 -.[0][367]=366 -.[0][368]=367 -.[0][369]=368 -.[0][370]=369 -.[0][371]=370 -.[0][372]=371 -.[0][373]=372 -.[0][374]=373 -.[0][375]=374 -.[0][376]=375 -.[0][377]=376 -.[0][378]=377 -.[0][379]=378 -.[0][380]=379 -.[0][381]=380 -.[0][382]=381 -.[0][383]=382 -.[0][384]=383 -.[0][385]=384 -.[0][386]=385 -.[0][387]=386 -.[0][388]=387 -.[0][389]=388 -.[0][390]=389 -.[0][391]=390 -.[0][392]=391 -.[0][393]=392 -.[0][394]=393 -.[0][395]=394 -.[0][396]=395 -.[0][397]=396 -.[0][398]=397 -.[0][399]=398 -.[0][400]=399 -.[0][401]=400 -.[0][402]=401 -.[0][403]=402 -.[0][404]=403 -.[0][405]=404 -.[0][406]=405 -.[0][407]=406 -.[0][408]=407 -.[0][409]=408 -.[0][410]=409 -.[0][411]=410 -.[0][412]=411 -.[0][413]=412 -.[0][414]=413 -.[0][415]=414 -.[0][416]=415 -.[0][417]=416 -.[0][418]=417 -.[0][419]=418 -.[0][420]=419 -.[0][421]=420 -.[0][422]=421 -.[0][423]=422 -.[0][424]=423 -.[0][425]=424 -.[0][426]=425 -.[0][427]=426 -.[0][428]=427 -.[0][429]=428 -.[0][430]=429 -.[0][431]=430 -.[0][432]=431 -.[0][433]=432 -.[0][434]=433 -.[0][435]=434 -.[0][436]=435 -.[0][437]=436 -.[0][438]=437 -.[0][439]=438 -.[0][440]=439 -.[0][441]=440 -.[0][442]=441 -.[0][443]=442 -.[0][444]=443 -.[0][445]=444 -.[0][446]=445 -.[0][447]=446 -.[0][448]=447 -.[0][449]=448 -.[0][450]=449 -.[0][451]=450 -.[0][452]=451 -.[0][453]=452 -.[0][454]=453 -.[0][455]=454 -.[0][456]=455 -.[0][457]=456 -.[0][458]=457 -.[0][459]=458 -.[0][460]=459 -.[0][461]=460 -.[0][462]=461 -.[0][463]=462 -.[0][464]=463 -.[0][465]=464 -.[0][466]=465 -.[0][467]=466 -.[0][468]=467 -.[0][469]=468 -.[0][470]=469 -.[0][471]=470 -.[0][472]=471 -.[0][473]=472 -.[0][474]=473 -.[0][475]=474 -.[0][476]=475 -.[0][477]=476 -.[0][478]=477 -.[0][479]=478 -.[0][480]=479 -.[0][481]=480 -.[0][482]=481 -.[0][483]=482 -.[0][484]=483 -.[0][485]=484 -.[0][486]=485 -.[0][487]=486 -.[0][488]=487 -.[0][489]=488 -.[0][490]=489 -.[0][491]=490 -.[0][492]=491 -.[0][493]=492 -.[0][494]=493 -.[0][495]=494 -.[0][496]=495 -.[0][497]=496 -.[0][498]=497 -.[0][499]=498 -.[0][500]=499 -.[0][501]=500 -.[0][502]=501 -.[0][503]=502 -.[0][504]=503 -.[0][505]=504 -.[0][506]=505 -.[0][507]=506 -.[0][508]=507 -.[0][509]=508 -.[0][510]=509 -.[0][511]=510 -.[0][512]=511 -.[0][513]=512 -.[0][514]=513 -.[0][515]=514 -.[0][516]=515 -.[0][517]=516 -.[0][518]=517 -.[0][519]=518 -.[0][520]=519 -.[0][521]=520 -.[0][522]=521 -.[0][523]=522 -.[0][524]=523 -.[0][525]=524 -.[0][526]=525 -.[0][527]=526 -.[0][528]=527 -.[0][529]=528 -.[0][530]=529 -.[0][531]=530 -.[0][532]=531 -.[0][533]=532 -.[0][534]=533 -.[0][535]=534 -.[0][536]=535 -.[0][537]=536 -.[0][538]=537 -.[0][539]=538 -.[0][540]=539 -.[0][541]=540 -.[0][542]=541 -.[0][543]=542 -.[0][544]=543 -.[0][545]=544 -.[0][546]=545 -.[0][547]=546 -.[0][548]=547 -.[0][549]=548 -.[0][550]=549 -.[0][551]=550 -.[0][552]=551 -.[0][553]=552 -.[0][554]=553 -.[0][555]=554 -.[0][556]=555 -.[0][557]=556 -.[0][558]=557 -.[0][559]=558 -.[0][560]=559 -.[0][561]=560 -.[0][562]=561 -.[0][563]=562 -.[0][564]=563 -.[0][565]=564 -.[0][566]=565 -.[0][567]=566 -.[0][568]=567 -.[0][569]=568 -.[0][570]=569 -.[0][571]=570 -.[0][572]=571 -.[0][573]=572 -.[0][574]=573 -.[0][575]=574 -.[0][576]=575 -.[0][577]=576 -.[0][578]=577 -.[0][579]=578 -.[0][580]=579 -.[0][581]=580 -.[0][582]=581 -.[0][583]=582 -.[0][584]=583 -.[0][585]=584 -.[0][586]=585 -.[0][587]=586 -.[0][588]=587 -.[0][589]=588 -.[0][590]=589 -.[0][591]=590 -.[0][592]=591 -.[0][593]=592 -.[0][594]=593 -.[0][595]=594 -.[0][596]=595 -.[0][597]=596 -.[0][598]=597 -.[0][599]=598 -.[0][600]=599 -.[0][601]=600 -.[0][602]=601 -.[0][603]=602 -.[0][604]=603 -.[0][605]=604 -.[0][606]=605 -.[0][607]=606 -.[0][608]=607 -.[0][609]=608 -.[0][610]=609 -.[0][611]=610 -.[0][612]=611 -.[0][613]=612 -.[0][614]=613 -.[0][615]=614 -.[0][616]=615 -.[0][617]=616 -.[0][618]=617 -.[0][619]=618 -.[0][620]=619 -.[0][621]=620 -.[0][622]=621 -.[0][623]=622 -.[0][624]=623 -.[0][625]=624 -.[0][626]=625 -.[0][627]=626 -.[0][628]=627 -.[0][629]=628 -.[0][630]=629 -.[0][631]=630 -.[0][632]=631 -.[0][633]=632 -.[0][634]=633 -.[0][635]=634 -.[0][636]=635 -.[0][637]=636 -.[0][638]=637 -.[0][639]=638 -.[0][640]=639 -.[0][641]=640 -.[0][642]=641 -.[0][643]=642 -.[0][644]=643 -.[0][645]=644 -.[0][646]=645 -.[0][647]=646 -.[0][648]=647 -.[0][649]=648 -.[0][650]=649 -.[0][651]=650 -.[0][652]=651 -.[0][653]=652 -.[0][654]=653 -.[0][655]=654 -.[0][656]=655 -.[0][657]=656 -.[0][658]=657 -.[0][659]=658 -.[0][660]=659 -.[0][661]=660 -.[0][662]=661 -.[0][663]=662 -.[0][664]=663 -.[0][665]=664 -.[0][666]=665 -.[0][667]=666 -.[0][668]=667 -.[0][669]=668 -.[0][670]=669 -.[0][671]=670 -.[0][672]=671 -.[0][673]=672 -.[0][674]=673 -.[0][675]=674 -.[0][676]=675 -.[0][677]=676 -.[0][678]=677 -.[0][679]=678 -.[0][680]=679 -.[0][681]=680 -.[0][682]=681 -.[0][683]=682 -.[0][684]=683 -.[0][685]=684 -.[0][686]=685 -.[0][687]=686 -.[0][688]=687 -.[0][689]=688 -.[0][690]=689 -.[0][691]=690 -.[0][692]=691 -.[0][693]=692 -.[0][694]=693 -.[0][695]=694 -.[0][696]=695 -.[0][697]=696 -.[0][698]=697 -.[0][699]=698 -.[0][700]=699 -.[0][701]=700 -.[0][702]=701 -.[0][703]=702 -.[0][704]=703 -.[0][705]=704 -.[0][706]=705 -.[0][707]=706 -.[0][708]=707 -.[0][709]=708 -.[0][710]=709 -.[0][711]=710 -.[0][712]=711 -.[0][713]=712 -.[0][714]=713 -.[0][715]=714 -.[0][716]=715 -.[0][717]=716 -.[0][718]=717 -.[0][719]=718 -.[0][720]=719 -.[0][721]=720 -.[0][722]=721 -.[0][723]=722 -.[0][724]=723 -.[0][725]=724 -.[0][726]=725 -.[0][727]=726 -.[0][728]=727 -.[0][729]=728 -.[0][730]=729 -.[0][731]=730 -.[0][732]=731 -.[0][733]=732 -.[0][734]=733 -.[0][735]=734 -.[0][736]=735 -.[0][737]=736 -.[0][738]=737 -.[0][739]=738 -.[0][740]=739 -.[0][741]=740 -.[0][742]=741 -.[0][743]=742 -.[0][744]=743 -.[0][745]=744 -.[0][746]=745 -.[0][747]=746 -.[0][748]=747 -.[0][749]=748 -.[0][750]=749 -.[0][751]=750 -.[0][752]=751 -.[0][753]=752 -.[0][754]=753 -.[0][755]=754 -.[0][756]=755 -.[0][757]=756 -.[0][758]=757 -.[0][759]=758 -.[0][760]=759 -.[0][761]=760 -.[0][762]=761 -.[0][763]=762 -.[0][764]=763 -.[0][765]=764 -.[0][766]=765 -.[0][767]=766 -.[0][768]=767 -.[0][769]=768 -.[0][770]=769 -.[0][771]=770 -.[0][772]=771 -.[0][773]=772 -.[0][774]=773 -.[0][775]=774 -.[0][776]=775 -.[0][777]=776 -.[0][778]=777 -.[0][779]=778 -.[0][780]=779 -.[0][781]=780 -.[0][782]=781 -.[0][783]=782 -.[0][784]=783 -.[0][785]=784 -.[0][786]=785 -.[0][787]=786 -.[0][788]=787 -.[0][789]=788 -.[0][790]=789 -.[0][791]=790 -.[0][792]=791 -.[0][793]=792 -.[0][794]=793 -.[0][795]=794 -.[0][796]=795 -.[0][797]=796 -.[0][798]=797 -.[0][799]=798 -.[0][800]=799 -.[0][801]=800 -.[0][802]=801 -.[0][803]=802 -.[0][804]=803 -.[0][805]=804 -.[0][806]=805 -.[0][807]=806 -.[0][808]=807 -.[0][809]=808 -.[0][810]=809 -.[0][811]=810 -.[0][812]=811 -.[0][813]=812 -.[0][814]=813 -.[0][815]=814 -.[0][816]=815 -.[0][817]=816 -.[0][818]=817 -.[0][819]=818 -.[0][820]=819 -.[0][821]=820 -.[0][822]=821 -.[0][823]=822 -.[0][824]=823 -.[0][825]=824 -.[0][826]=825 -.[0][827]=826 -.[0][828]=827 -.[0][829]=828 -.[0][830]=829 -.[0][831]=830 -.[0][832]=831 -.[0][833]=832 -.[0][834]=833 -.[0][835]=834 -.[0][836]=835 -.[0][837]=836 -.[0][838]=837 -.[0][839]=838 -.[0][840]=839 -.[0][841]=840 -.[0][842]=841 -.[0][843]=842 -.[0][844]=843 -.[0][845]=844 -.[0][846]=845 -.[0][847]=846 -.[0][848]=847 -.[0][849]=848 -.[0][850]=849 -.[0][851]=850 -.[0][852]=851 -.[0][853]=852 -.[0][854]=853 -.[0][855]=854 -.[0][856]=855 -.[0][857]=856 -.[0][858]=857 -.[0][859]=858 -.[0][860]=859 -.[0][861]=860 -.[0][862]=861 -.[0][863]=862 -.[0][864]=863 -.[0][865]=864 -.[0][866]=865 -.[0][867]=866 -.[0][868]=867 -.[0][869]=868 -.[0][870]=869 -.[0][871]=870 -.[0][872]=871 -.[0][873]=872 -.[0][874]=873 -.[0][875]=874 -.[0][876]=875 -.[0][877]=876 -.[0][878]=877 -.[0][879]=878 -.[0][880]=879 -.[0][881]=880 -.[0][882]=881 -.[0][883]=882 -.[0][884]=883 -.[0][885]=884 -.[0][886]=885 -.[0][887]=886 -.[0][888]=887 -.[0][889]=888 -.[0][890]=889 -.[0][891]=890 -.[0][892]=891 -.[0][893]=892 -.[0][894]=893 -.[0][895]=894 -.[0][896]=895 -.[0][897]=896 -.[0][898]=897 -.[0][899]=898 -.[0][900]=899 -.[0][901]=900 -.[0][902]=901 -.[0][903]=902 -.[0][904]=903 -.[0][905]=904 -.[0][906]=905 -.[0][907]=906 -.[0][908]=907 -.[0][909]=908 -.[0][910]=909 -.[0][911]=910 -.[0][912]=911 -.[0][913]=912 -.[0][914]=913 -.[0][915]=914 -.[0][916]=915 -.[0][917]=916 -.[0][918]=917 -.[0][919]=918 -.[0][920]=919 -.[0][921]=920 -.[0][922]=921 -.[0][923]=922 -.[0][924]=923 -.[0][925]=924 -.[0][926]=925 -.[0][927]=926 -.[0][928]=927 -.[0][929]=928 -.[0][930]=929 -.[0][931]=930 -.[0][932]=931 -.[0][933]=932 -.[0][934]=933 -.[0][935]=934 -.[0][936]=935 -.[0][937]=936 -.[0][938]=937 -.[0][939]=938 -.[0][940]=939 -.[0][941]=940 -.[0][942]=941 -.[0][943]=942 -.[0][944]=943 -.[0][945]=944 -.[0][946]=945 -.[0][947]=946 -.[0][948]=947 -.[0][949]=948 -.[0][950]=949 -.[0][951]=950 -.[0][952]=951 -.[0][953]=952 -.[0][954]=953 -.[0][955]=954 -.[0][956]=955 -.[0][957]=956 -.[0][958]=957 -.[0][959]=958 -.[0][960]=959 -.[0][961]=960 -.[0][962]=961 -.[0][963]=962 -.[0][964]=963 -.[0][965]=964 -.[0][966]=965 -.[0][967]=966 -.[0][968]=967 -.[0][969]=968 -.[0][970]=969 -.[0][971]=970 -.[0][972]=971 -.[0][973]=972 -.[0][974]=973 -.[0][975]=974 -.[0][976]=975 -.[0][977]=976 -.[0][978]=977 -.[0][979]=978 -.[0][980]=979 -.[0][981]=980 -.[0][982]=981 -.[0][983]=982 -.[0][984]=983 -.[0][985]=984 -.[0][986]=985 -.[0][987]=986 -.[0][988]=987 -.[0][989]=988 -.[0][990]=989 -.[0][991]=990 -.[0][992]=991 -.[0][993]=992 -.[0][994]=993 -.[0][995]=994 -.[0][996]=995 -.[0][997]=996 -.[0][998]=997 -.[0][999]=998 -.[0][1000]=999 -.[0][1001]=1000 -.[0][1002]=1001 -.[0][1003]=1002 -.[0][1004]=1003 -.[0][1005]=1004 -.[0][1006]=1005 -.[0][1007]=1006 -.[0][1008]=1007 -.[0][1009]=1008 -.[0][1010]=1009 -.[0][1011]=1010 -.[0][1012]=1011 -.[0][1013]=1012 -.[0][1014]=1013 -.[0][1015]=1014 -.[0][1016]=1015 -.[0][1017]=1016 -.[0][1018]=1017 -.[0][1019]=1018 -.[0][1020]=1019 -.[0][1021]=1020 -.[0][1022]=1021 -.[0][1023]=1022 -.[0][1024]=1023 -.[0][1025]=1024 -.[0][1026]=1025 -.[0][1027]=1026 -.[0][1028]=1027 -.[0][1029]=1028 -.[0][1030]=1029 -.[0][1031]=1030 -.[0][1032]=1031 -.[0][1033]=1032 -.[0][1034]=1033 -.[0][1035]=1034 -.[0][1036]=1035 -.[0][1037]=1036 -.[0][1038]=1037 -.[0][1039]=1038 -.[0][1040]=1039 -.[0][1041]=1040 -.[0][1042]=1041 -.[0][1043]=1042 -.[0][1044]=1043 -.[0][1045]=1044 -.[0][1046]=1045 -.[0][1047]=1046 -.[0][1048]=1047 -.[0][1049]=1048 -.[0][1050]=1049 -.[0][1051]=1050 -.[0][1052]=1051 -.[0][1053]=1052 -.[0][1054]=1053 -.[0][1055]=1054 -.[0][1056]=1055 -.[0][1057]=1056 -.[0][1058]=1057 -.[0][1059]=1058 -.[0][1060]=1059 -.[0][1061]=1060 -.[0][1062]=1061 -.[0][1063]=1062 -.[0][1064]=1063 -.[0][1065]=1064 -.[0][1066]=1065 -.[0][1067]=1066 -.[0][1068]=1067 -.[0][1069]=1068 -.[0][1070]=1069 -.[0][1071]=1070 -.[0][1072]=1071 -.[0][1073]=1072 -.[0][1074]=1073 -.[0][1075]=1074 -.[0][1076]=1075 -.[0][1077]=1076 -.[0][1078]=1077 -.[0][1079]=1078 -.[0][1080]=1079 -.[0][1081]=1080 -.[0][1082]=1081 -.[0][1083]=1082 -.[0][1084]=1083 -.[0][1085]=1084 -.[0][1086]=1085 -.[0][1087]=1086 -.[0][1088]=1087 -.[0][1089]=1088 -.[0][1090]=1089 -.[0][1091]=1090 -.[0][1092]=1091 -.[0][1093]=1092 -.[0][1094]=1093 -.[0][1095]=1094 -.[0][1096]=1095 -.[0][1097]=1096 -.[0][1098]=1097 -.[0][1099]=1098 -.[0][1100]=1099 -.[0][1101]=1100 -.[0][1102]=1101 -.[0][1103]=1102 -.[0][1104]=1103 -.[0][1105]=1104 -.[0][1106]=1105 -.[0][1107]=1106 -.[0][1108]=1107 -.[0][1109]=1108 -.[0][1110]=1109 -.[0][1111]=1110 -.[0][1112]=1111 -.[0][1113]=1112 -.[0][1114]=1113 -.[0][1115]=1114 -.[0][1116]=1115 -.[0][1117]=1116 -.[0][1118]=1117 -.[0][1119]=1118 -.[0][1120]=1119 -.[0][1121]=1120 -.[0][1122]=1121 -.[0][1123]=1122 -.[0][1124]=1123 -.[0][1125]=1124 -.[0][1126]=1125 -.[0][1127]=1126 -.[0][1128]=1127 -.[0][1129]=1128 -.[0][1130]=1129 -.[0][1131]=1130 -.[0][1132]=1131 -.[0][1133]=1132 -.[0][1134]=1133 -.[0][1135]=1134 -.[0][1136]=1135 -.[0][1137]=1136 -.[0][1138]=1137 -.[0][1139]=1138 -.[0][1140]=1139 -.[0][1141]=1140 -.[0][1142]=1141 -.[0][1143]=1142 -.[0][1144]=1143 -.[0][1145]=1144 -.[0][1146]=1145 -.[0][1147]=1146 -.[0][1148]=1147 -.[0][1149]=1148 -.[0][1150]=1149 -.[0][1151]=1150 -.[0][1152]=1151 -.[0][1153]=1152 -.[0][1154]=1153 -.[0][1155]=1154 -.[0][1156]=1155 -.[0][1157]=1156 -.[0][1158]=1157 -.[0][1159]=1158 -.[0][1160]=1159 -.[0][1161]=1160 -.[0][1162]=1161 -.[0][1163]=1162 -.[0][1164]=1163 -.[0][1165]=1164 -.[0][1166]=1165 -.[0][1167]=1166 -.[0][1168]=1167 -.[0][1169]=1168 -.[0][1170]=1169 -.[0][1171]=1170 -.[0][1172]=1171 -.[0][1173]=1172 -.[0][1174]=1173 -.[0][1175]=1174 -.[0][1176]=1175 -.[0][1177]=1176 -.[0][1178]=1177 -.[0][1179]=1178 -.[0][1180]=1179 -.[0][1181]=1180 -.[0][1182]=1181 -.[0][1183]=1182 -.[0][1184]=1183 -.[0][1185]=1184 -.[0][1186]=1185 -.[0][1187]=1186 -.[0][1188]=1187 -.[0][1189]=1188 -.[0][1190]=1189 -.[0][1191]=1190 -.[0][1192]=1191 -.[0][1193]=1192 -.[0][1194]=1193 -.[0][1195]=1194 -.[0][1196]=1195 -.[0][1197]=1196 -.[0][1198]=1197 -.[0][1199]=1198 -.[0][1200]=1199 -.[0][1201]=1200 -.[0][1202]=1201 -.[0][1203]=1202 -.[0][1204]=1203 -.[0][1205]=1204 -.[0][1206]=1205 -.[0][1207]=1206 -.[0][1208]=1207 -.[0][1209]=1208 -.[0][1210]=1209 -.[0][1211]=1210 -.[0][1212]=1211 -.[0][1213]=1212 -.[0][1214]=1213 -.[0][1215]=1214 -.[0][1216]=1215 -.[0][1217]=1216 -.[0][1218]=1217 -.[0][1219]=1218 -.[0][1220]=1219 -.[0][1221]=1220 -.[0][1222]=1221 -.[0][1223]=1222 -.[0][1224]=1223 -.[0][1225]=1224 -.[0][1226]=1225 -.[0][1227]=1226 -.[0][1228]=1227 -.[0][1229]=1228 -.[0][1230]=1229 -.[0][1231]=1230 -.[0][1232]=1231 -.[0][1233]=1232 -.[0][1234]=1233 -.[0][1235]=1234 -.[0][1236]=1235 -.[0][1237]=1236 -.[0][1238]=1237 -.[0][1239]=1238 -.[0][1240]=1239 -.[0][1241]=1240 -.[0][1242]=1241 -.[0][1243]=1242 -.[0][1244]=1243 -.[0][1245]=1244 -.[0][1246]=1245 -.[0][1247]=1246 -.[0][1248]=1247 -.[0][1249]=1248 -.[0][1250]=1249 -.[0][1251]=1250 -.[0][1252]=1251 -.[0][1253]=1252 -.[0][1254]=1253 -.[0][1255]=1254 -.[0][1256]=1255 -.[0][1257]=1256 -.[0][1258]=1257 -.[0][1259]=1258 -.[0][1260]=1259 -.[0][1261]=1260 -.[0][1262]=1261 -.[0][1263]=1262 -.[0][1264]=1263 -.[0][1265]=1264 -.[0][1266]=1265 -.[0][1267]=1266 -.[0][1268]=1267 -.[0][1269]=1268 -.[0][1270]=1269 -.[0][1271]=1270 -.[0][1272]=1271 -.[0][1273]=1272 -.[0][1274]=1273 -.[0][1275]=1274 -.[0][1276]=1275 -.[0][1277]=1276 -.[0][1278]=1277 -.[0][1279]=1278 -.[0][1280]=1279 -.[0][1281]=1280 -.[0][1282]=1281 -.[0][1283]=1282 -.[0][1284]=1283 -.[0][1285]=1284 -.[0][1286]=1285 -.[0][1287]=1286 -.[0][1288]=1287 -.[0][1289]=1288 -.[0][1290]=1289 -.[0][1291]=1290 -.[0][1292]=1291 -.[0][1293]=1292 -.[0][1294]=1293 -.[0][1295]=1294 -.[0][1296]=1295 -.[0][1297]=1296 -.[0][1298]=1297 -.[0][1299]=1298 -.[0][1300]=1299 -.[0][1301]=1300 -.[0][1302]=1301 -.[0][1303]=1302 -.[0][1304]=1303 -.[0][1305]=1304 -.[0][1306]=1305 -.[0][1307]=1306 -.[0][1308]=1307 -.[0][1309]=1308 -.[0][1310]=1309 -.[0][1311]=1310 -.[0][1312]=1311 -.[0][1313]=1312 -.[0][1314]=1313 -.[0][1315]=1314 -.[0][1316]=1315 -.[0][1317]=1316 -.[0][1318]=1317 -.[0][1319]=1318 -.[0][1320]=1319 -.[0][1321]=1320 -.[0][1322]=1321 -.[0][1323]=1322 -.[0][1324]=1323 -.[0][1325]=1324 -.[0][1326]=1325 -.[0][1327]=1326 -.[0][1328]=1327 -.[0][1329]=1328 -.[0][1330]=1329 -.[0][1331]=1330 -.[0][1332]=1331 -.[0][1333]=1332 -.[0][1334]=1333 -.[0][1335]=1334 -.[0][1336]=1335 -.[0][1337]=1336 -.[0][1338]=1337 -.[0][1339]=1338 -.[0][1340]=1339 -.[0][1341]=1340 -.[0][1342]=1341 -.[0][1343]=1342 -.[0][1344]=1343 -.[0][1345]=1344 -.[0][1346]=1345 -.[0][1347]=1346 -.[0][1348]=1347 -.[0][1349]=1348 -.[0][1350]=1349 -.[0][1351]=1350 -.[0][1352]=1351 -.[0][1353]=1352 -.[0][1354]=1353 -.[0][1355]=1354 -.[0][1356]=1355 -.[0][1357]=1356 -.[0][1358]=1357 -.[0][1359]=1358 -.[0][1360]=1359 -.[0][1361]=1360 -.[0][1362]=1361 -.[0][1363]=1362 -.[0][1364]=1363 -.[0][1365]=1364 -.[0][1366]=1365 -.[0][1367]=1366 -.[0][1368]=1367 -.[0][1369]=1368 -.[0][1370]=1369 -.[0][1371]=1370 -.[0][1372]=1371 -.[0][1373]=1372 -.[0][1374]=1373 -.[0][1375]=1374 -.[0][1376]=1375 -.[0][1377]=1376 -.[0][1378]=1377 -.[0][1379]=1378 -.[0][1380]=1379 -.[0][1381]=1380 -.[0][1382]=1381 -.[0][1383]=1382 -.[0][1384]=1383 -.[0][1385]=1384 -.[0][1386]=1385 -.[0][1387]=1386 -.[0][1388]=1387 -.[0][1389]=1388 -.[0][1390]=1389 -.[0][1391]=1390 -.[0][1392]=1391 -.[0][1393]=1392 -.[0][1394]=1393 -.[0][1395]=1394 -.[0][1396]=1395 -.[0][1397]=1396 -.[0][1398]=1397 -.[0][1399]=1398 -.[0][1400]=1399 -.[0][1401]=1400 -.[0][1402]=1401 -.[0][1403]=1402 -.[0][1404]=1403 -.[0][1405]=1404 -.[0][1406]=1405 -.[0][1407]=1406 -.[0][1408]=1407 -.[0][1409]=1408 -.[0][1410]=1409 -.[0][1411]=1410 -.[0][1412]=1411 -.[0][1413]=1412 -.[0][1414]=1413 -.[0][1415]=1414 -.[0][1416]=1415 -.[0][1417]=1416 -.[0][1418]=1417 -.[0][1419]=1418 -.[0][1420]=1419 -.[0][1421]=1420 -.[0][1422]=1421 -.[0][1423]=1422 -.[0][1424]=1423 -.[0][1425]=1424 -.[0][1426]=1425 -.[0][1427]=1426 -.[0][1428]=1427 -.[0][1429]=1428 -.[0][1430]=1429 -.[0][1431]=1430 -.[0][1432]=1431 -.[0][1433]=1432 -.[0][1434]=1433 -.[0][1435]=1434 -.[0][1436]=1435 -.[0][1437]=1436 -.[0][1438]=1437 -.[0][1439]=1438 -.[0][1440]=1439 -.[0][1441]=1440 -.[0][1442]=1441 -.[0][1443]=1442 -.[0][1444]=1443 -.[0][1445]=1444 -.[0][1446]=1445 -.[0][1447]=1446 -.[0][1448]=1447 -.[0][1449]=1448 -.[0][1450]=1449 -.[0][1451]=1450 -.[0][1452]=1451 -.[0][1453]=1452 -.[0][1454]=1453 -.[0][1455]=1454 -.[0][1456]=1455 -.[0][1457]=1456 -.[0][1458]=1457 -.[0][1459]=1458 -.[0][1460]=1459 -.[0][1461]=1460 -.[0][1462]=1461 -.[0][1463]=1462 -.[0][1464]=1463 -.[0][1465]=1464 -.[0][1466]=1465 -.[0][1467]=1466 -.[0][1468]=1467 -.[0][1469]=1468 -.[0][1470]=1469 -.[0][1471]=1470 -.[0][1472]=1471 -.[0][1473]=1472 -.[0][1474]=1473 -.[0][1475]=1474 -.[0][1476]=1475 -.[0][1477]=1476 -.[0][1478]=1477 -.[0][1479]=1478 -.[0][1480]=1479 -.[0][1481]=1480 -.[0][1482]=1481 -.[0][1483]=1482 -.[0][1484]=1483 -.[0][1485]=1484 -.[0][1486]=1485 -.[0][1487]=1486 -.[0][1488]=1487 -.[0][1489]=1488 -.[0][1490]=1489 -.[0][1491]=1490 -.[0][1492]=1491 -.[0][1493]=1492 -.[0][1494]=1493 -.[0][1495]=1494 -.[0][1496]=1495 -.[0][1497]=1496 -.[0][1498]=1497 -.[0][1499]=1498 -.[0][1500]=1499 -.[0][1501]=1500 -.[0][1502]=1501 -.[0][1503]=1502 -.[0][1504]=1503 -.[0][1505]=1504 -.[0][1506]=1505 -.[0][1507]=1506 -.[0][1508]=1507 -.[0][1509]=1508 -.[0][1510]=1509 -.[0][1511]=1510 -.[0][1512]=1511 -.[0][1513]=1512 -.[0][1514]=1513 -.[0][1515]=1514 -.[0][1516]=1515 -.[0][1517]=1516 -.[0][1518]=1517 -.[0][1519]=1518 -.[0][1520]=1519 -.[0][1521]=1520 -.[0][1522]=1521 -.[0][1523]=1522 -.[0][1524]=1523 -.[0][1525]=1524 -.[0][1526]=1525 -.[0][1527]=1526 -.[0][1528]=1527 -.[0][1529]=1528 -.[0][1530]=1529 -.[0][1531]=1530 -.[0][1532]=1531 -.[0][1533]=1532 -.[0][1534]=1533 -.[0][1535]=1534 -.[0][1536]=1535 -.[0][1537]=1536 -.[0][1538]=1537 -.[0][1539]=1538 -.[0][1540]=1539 -.[0][1541]=1540 -.[0][1542]=1541 -.[0][1543]=1542 -.[0][1544]=1543 -.[0][1545]=1544 -.[0][1546]=1545 -.[0][1547]=1546 -.[0][1548]=1547 -.[0][1549]=1548 -.[0][1550]=1549 -.[0][1551]=1550 -.[0][1552]=1551 -.[0][1553]=1552 -.[0][1554]=1553 -.[0][1555]=1554 -.[0][1556]=1555 -.[0][1557]=1556 -.[0][1558]=1557 -.[0][1559]=1558 -.[0][1560]=1559 -.[0][1561]=1560 -.[0][1562]=1561 -.[0][1563]=1562 -.[0][1564]=1563 -.[0][1565]=1564 -.[0][1566]=1565 -.[0][1567]=1566 -.[0][1568]=1567 -.[0][1569]=1568 -.[0][1570]=1569 -.[0][1571]=1570 -.[0][1572]=1571 -.[0][1573]=1572 -.[0][1574]=1573 -.[0][1575]=1574 -.[0][1576]=1575 -.[0][1577]=1576 -.[0][1578]=1577 -.[0][1579]=1578 -.[0][1580]=1579 -.[0][1581]=1580 -.[0][1582]=1581 -.[0][1583]=1582 -.[0][1584]=1583 -.[0][1585]=1584 -.[0][1586]=1585 -.[0][1587]=1586 -.[0][1588]=1587 -.[0][1589]=1588 -.[0][1590]=1589 -.[0][1591]=1590 -.[0][1592]=1591 -.[0][1593]=1592 -.[0][1594]=1593 -.[0][1595]=1594 -.[0][1596]=1595 -.[0][1597]=1596 -.[0][1598]=1597 -.[0][1599]=1598 -.[0][1600]=1599 -.[0][1601]=1600 -.[0][1602]=1601 -.[0][1603]=1602 -.[0][1604]=1603 -.[0][1605]=1604 -.[0][1606]=1605 -.[0][1607]=1606 -.[0][1608]=1607 -.[0][1609]=1608 -.[0][1610]=1609 -.[0][1611]=1610 -.[0][1612]=1611 -.[0][1613]=1612 -.[0][1614]=1613 -.[0][1615]=1614 -.[0][1616]=1615 -.[0][1617]=1616 -.[0][1618]=1617 -.[0][1619]=1618 -.[0][1620]=1619 -.[0][1621]=1620 -.[0][1622]=1621 -.[0][1623]=1622 -.[0][1624]=1623 -.[0][1625]=1624 -.[0][1626]=1625 -.[0][1627]=1626 -.[0][1628]=1627 -.[0][1629]=1628 -.[0][1630]=1629 -.[0][1631]=1630 -.[0][1632]=1631 -.[0][1633]=1632 -.[0][1634]=1633 -.[0][1635]=1634 -.[0][1636]=1635 -.[0][1637]=1636 -.[0][1638]=1637 -.[0][1639]=1638 -.[0][1640]=1639 -.[0][1641]=1640 -.[0][1642]=1641 -.[0][1643]=1642 -.[0][1644]=1643 -.[0][1645]=1644 -.[0][1646]=1645 -.[0][1647]=1646 -.[0][1648]=1647 -.[0][1649]=1648 -.[0][1650]=1649 -.[0][1651]=1650 -.[0][1652]=1651 -.[0][1653]=1652 -.[0][1654]=1653 -.[0][1655]=1654 -.[0][1656]=1655 -.[0][1657]=1656 -.[0][1658]=1657 -.[0][1659]=1658 -.[0][1660]=1659 -.[0][1661]=1660 -.[0][1662]=1661 -.[0][1663]=1662 -.[0][1664]=1663 -.[0][1665]=1664 -.[0][1666]=1665 -.[0][1667]=1666 -.[0][1668]=1667 -.[0][1669]=1668 -.[0][1670]=1669 -.[0][1671]=1670 -.[0][1672]=1671 -.[0][1673]=1672 -.[0][1674]=1673 -.[0][1675]=1674 -.[0][1676]=1675 -.[0][1677]=1676 -.[0][1678]=1677 -.[0][1679]=1678 -.[0][1680]=1679 -.[0][1681]=1680 -.[0][1682]=1681 -.[0][1683]=1682 -.[0][1684]=1683 -.[0][1685]=1684 -.[0][1686]=1685 -.[0][1687]=1686 -.[0][1688]=1687 -.[0][1689]=1688 -.[0][1690]=1689 -.[0][1691]=1690 -.[0][1692]=1691 -.[0][1693]=1692 -.[0][1694]=1693 -.[0][1695]=1694 -.[0][1696]=1695 -.[0][1697]=1696 -.[0][1698]=1697 -.[0][1699]=1698 -.[0][1700]=1699 -.[0][1701]=1700 -.[0][1702]=1701 -.[0][1703]=1702 -.[0][1704]=1703 -.[0][1705]=1704 -.[0][1706]=1705 -.[0][1707]=1706 -.[0][1708]=1707 -.[0][1709]=1708 -.[0][1710]=1709 -.[0][1711]=1710 -.[0][1712]=1711 -.[0][1713]=1712 -.[0][1714]=1713 -.[0][1715]=1714 -.[0][1716]=1715 -.[0][1717]=1716 -.[0][1718]=1717 -.[0][1719]=1718 -.[0][1720]=1719 -.[0][1721]=1720 -.[0][1722]=1721 -.[0][1723]=1722 -.[0][1724]=1723 -.[0][1725]=1724 -.[0][1726]=1725 -.[0][1727]=1726 -.[0][1728]=1727 -.[0][1729]=1728 -.[0][1730]=1729 -.[0][1731]=1730 -.[0][1732]=1731 -.[0][1733]=1732 -.[0][1734]=1733 -.[0][1735]=1734 -.[0][1736]=1735 -.[0][1737]=1736 -.[0][1738]=1737 -.[0][1739]=1738 -.[0][1740]=1739 -.[0][1741]=1740 -.[0][1742]=1741 -.[0][1743]=1742 -.[0][1744]=1743 -.[0][1745]=1744 -.[0][1746]=1745 -.[0][1747]=1746 -.[0][1748]=1747 -.[0][1749]=1748 -.[0][1750]=1749 -.[0][1751]=1750 -.[0][1752]=1751 -.[0][1753]=1752 -.[0][1754]=1753 -.[0][1755]=1754 -.[0][1756]=1755 -.[0][1757]=1756 -.[0][1758]=1757 -.[0][1759]=1758 -.[0][1760]=1759 -.[0][1761]=1760 -.[0][1762]=1761 -.[0][1763]=1762 -.[0][1764]=1763 -.[0][1765]=1764 -.[0][1766]=1765 -.[0][1767]=1766 -.[0][1768]=1767 -.[0][1769]=1768 -.[0][1770]=1769 -.[0][1771]=1770 -.[0][1772]=1771 -.[0][1773]=1772 -.[0][1774]=1773 -.[0][1775]=1774 -.[0][1776]=1775 -.[0][1777]=1776 -.[0][1778]=1777 -.[0][1779]=1778 -.[0][1780]=1779 -.[0][1781]=1780 -.[0][1782]=1781 -.[0][1783]=1782 -.[0][1784]=1783 -.[0][1785]=1784 -.[0][1786]=1785 -.[0][1787]=1786 -.[0][1788]=1787 -.[0][1789]=1788 -.[0][1790]=1789 -.[0][1791]=1790 -.[0][1792]=1791 -.[0][1793]=1792 -.[0][1794]=1793 -.[0][1795]=1794 -.[0][1796]=1795 -.[0][1797]=1796 -.[0][1798]=1797 -.[0][1799]=1798 -.[0][1800]=1799 -.[0][1801]=1800 -.[0][1802]=1801 -.[0][1803]=1802 -.[0][1804]=1803 -.[0][1805]=1804 -.[0][1806]=1805 -.[0][1807]=1806 -.[0][1808]=1807 -.[0][1809]=1808 -.[0][1810]=1809 -.[0][1811]=1810 -.[0][1812]=1811 -.[0][1813]=1812 -.[0][1814]=1813 -.[0][1815]=1814 -.[0][1816]=1815 -.[0][1817]=1816 -.[0][1818]=1817 -.[0][1819]=1818 -.[0][1820]=1819 -.[0][1821]=1820 -.[0][1822]=1821 -.[0][1823]=1822 -.[0][1824]=1823 -.[0][1825]=1824 -.[0][1826]=1825 -.[0][1827]=1826 -.[0][1828]=1827 -.[0][1829]=1828 -.[0][1830]=1829 -.[0][1831]=1830 -.[0][1832]=1831 -.[0][1833]=1832 -.[0][1834]=1833 -.[0][1835]=1834 -.[0][1836]=1835 -.[0][1837]=1836 -.[0][1838]=1837 -.[0][1839]=1838 -.[0][1840]=1839 -.[0][1841]=1840 -.[0][1842]=1841 -.[0][1843]=1842 -.[0][1844]=1843 -.[0][1845]=1844 -.[0][1846]=1845 -.[0][1847]=1846 -.[0][1848]=1847 -.[0][1849]=1848 -.[0][1850]=1849 -.[0][1851]=1850 -.[0][1852]=1851 -.[0][1853]=1852 -.[0][1854]=1853 -.[0][1855]=1854 -.[0][1856]=1855 -.[0][1857]=1856 -.[0][1858]=1857 -.[0][1859]=1858 -.[0][1860]=1859 -.[0][1861]=1860 -.[0][1862]=1861 -.[0][1863]=1862 -.[0][1864]=1863 -.[0][1865]=1864 -.[0][1866]=1865 -.[0][1867]=1866 -.[0][1868]=1867 -.[0][1869]=1868 -.[0][1870]=1869 -.[0][1871]=1870 -.[0][1872]=1871 -.[0][1873]=1872 -.[0][1874]=1873 -.[0][1875]=1874 -.[0][1876]=1875 -.[0][1877]=1876 -.[0][1878]=1877 -.[0][1879]=1878 -.[0][1880]=1879 -.[0][1881]=1880 -.[0][1882]=1881 -.[0][1883]=1882 -.[0][1884]=1883 -.[0][1885]=1884 -.[0][1886]=1885 -.[0][1887]=1886 -.[0][1888]=1887 -.[0][1889]=1888 -.[0][1890]=1889 -.[0][1891]=1890 -.[0][1892]=1891 -.[0][1893]=1892 -.[0][1894]=1893 -.[0][1895]=1894 -.[0][1896]=1895 -.[0][1897]=1896 -.[0][1898]=1897 -.[0][1899]=1898 -.[0][1900]=1899 -.[0][1901]=1900 -.[0][1902]=1901 -.[0][1903]=1902 -.[0][1904]=1903 -.[0][1905]=1904 -.[0][1906]=1905 -.[0][1907]=1906 -.[0][1908]=1907 -.[0][1909]=1908 -.[0][1910]=1909 -.[0][1911]=1910 -.[0][1912]=1911 -.[0][1913]=1912 -.[0][1914]=1913 -.[0][1915]=1914 -.[0][1916]=1915 -.[0][1917]=1916 -.[0][1918]=1917 -.[0][1919]=1918 -.[0][1920]=1919 -.[0][1921]=1920 -.[0][1922]=1921 -.[0][1923]=1922 -.[0][1924]=1923 -.[0][1925]=1924 -.[0][1926]=1925 -.[0][1927]=1926 -.[0][1928]=1927 -.[0][1929]=1928 -.[0][1930]=1929 -.[0][1931]=1930 -.[0][1932]=1931 -.[0][1933]=1932 -.[0][1934]=1933 -.[0][1935]=1934 -.[0][1936]=1935 -.[0][1937]=1936 -.[0][1938]=1937 -.[0][1939]=1938 -.[0][1940]=1939 -.[0][1941]=1940 -.[0][1942]=1941 -.[0][1943]=1942 -.[0][1944]=1943 -.[0][1945]=1944 -.[0][1946]=1945 -.[0][1947]=1946 -.[0][1948]=1947 -.[0][1949]=1948 -.[0][1950]=1949 -.[0][1951]=1950 -.[0][1952]=1951 -.[0][1953]=1952 -.[0][1954]=1953 -.[0][1955]=1954 -.[0][1956]=1955 -.[0][1957]=1956 -.[0][1958]=1957 -.[0][1959]=1958 -.[0][1960]=1959 -.[0][1961]=1960 -.[0][1962]=1961 -.[0][1963]=1962 -.[0][1964]=1963 -.[0][1965]=1964 -.[0][1966]=1965 -.[0][1967]=1966 -.[0][1968]=1967 -.[0][1969]=1968 -.[0][1970]=1969 -.[0][1971]=1970 -.[0][1972]=1971 -.[0][1973]=1972 -.[0][1974]=1973 -.[0][1975]=1974 -.[0][1976]=1975 -.[0][1977]=1976 -.[0][1978]=1977 -.[0][1979]=1978 -.[0][1980]=1979 -.[0][1981]=1980 -.[0][1982]=1981 -.[0][1983]=1982 -.[0][1984]=1983 -.[0][1985]=1984 -.[0][1986]=1985 -.[0][1987]=1986 -.[0][1988]=1987 -.[0][1989]=1988 -.[0][1990]=1989 -.[0][1991]=1990 -.[0][1992]=1991 -.[0][1993]=1992 -.[0][1994]=1993 -.[0][1995]=1994 -.[0][1996]=1995 -.[0][1997]=1996 -.[0][1998]=1997 -.[0][1999]=1998 -.[0][2000]=1999 -.[0][2001]=2000 -.[0][2002]=2001 -.[0][2003]=2002 -.[0][2004]=2003 -.[0][2005]=2004 -.[0][2006]=2005 -.[0][2007]=2006 -.[0][2008]=2007 -.[0][2009]=2008 -.[0][2010]=2009 -.[0][2011]=2010 -.[0][2012]=2011 -.[0][2013]=2012 -.[0][2014]=2013 -.[0][2015]=2014 -.[0][2016]=2015 -.[0][2017]=2016 -.[0][2018]=2017 -.[0][2019]=2018 -.[0][2020]=2019 -.[0][2021]=2020 -.[0][2022]=2021 -.[0][2023]=2022 -.[0][2024]=2023 -.[0][2025]=2024 -.[0][2026]=2025 -.[0][2027]=2026 -.[0][2028]=2027 -.[0][2029]=2028 -.[0][2030]=2029 -.[0][2031]=2030 -.[0][2032]=2031 -.[0][2033]=2032 -.[0][2034]=2033 -.[0][2035]=2034 -.[0][2036]=2035 -.[0][2037]=2036 -.[0][2038]=2037 -.[0][2039]=2038 -.[0][2040]=2039 -.[0][2041]=2040 -.[0][2042]=2041 -.[0][2043]=2042 -.[0][2044]=2043 -.[0][2045]=2044 -.[0][2046]=2045 -.[0][2047]=2046 -.[0][2048]=2047 -.[0][2049]=2048 -.[0][2050]=2049 -.[0][2051]=2050 -.[0][2052]=2051 -.[0][2053]=2052 -.[0][2054]=2053 -.[0][2055]=2054 -.[0][2056]=2055 -.[0][2057]=2056 -.[0][2058]=2057 -.[0][2059]=2058 -.[0][2060]=2059 -.[0][2061]=2060 -.[0][2062]=2061 -.[0][2063]=2062 -.[0][2064]=2063 -.[0][2065]=2064 -.[0][2066]=2065 -.[0][2067]=2066 -.[0][2068]=2067 -.[0][2069]=2068 -.[0][2070]=2069 -.[0][2071]=2070 -.[0][2072]=2071 -.[0][2073]=2072 -.[0][2074]=2073 -.[0][2075]=2074 -.[0][2076]=2075 -.[0][2077]=2076 -.[0][2078]=2077 -.[0][2079]=2078 -.[0][2080]=2079 -.[0][2081]=2080 -.[0][2082]=2081 -.[0][2083]=2082 -.[0][2084]=2083 -.[0][2085]=2084 -.[0][2086]=2085 -.[0][2087]=2086 -.[0][2088]=2087 -.[0][2089]=2088 -.[0][2090]=2089 -.[0][2091]=2090 -.[0][2092]=2091 -.[0][2093]=2092 -.[0][2094]=2093 -.[0][2095]=2094 -.[0][2096]=2095 -.[0][2097]=2096 -.[0][2098]=2097 -.[0][2099]=2098 -.[0][2100]=2099 -.[0][2101]=2100 -.[0][2102]=2101 -.[0][2103]=2102 -.[0][2104]=2103 -.[0][2105]=2104 -.[0][2106]=2105 -.[0][2107]=2106 -.[0][2108]=2107 -.[0][2109]=2108 -.[0][2110]=2109 -.[0][2111]=2110 -.[0][2112]=2111 -.[0][2113]=2112 -.[0][2114]=2113 -.[0][2115]=2114 -.[0][2116]=2115 -.[0][2117]=2116 -.[0][2118]=2117 -.[0][2119]=2118 diff --git a/test/data/test_large_01.json b/test/data/test_large_01.json deleted file mode 100644 index e4ab4cd43..000000000 --- a/test/data/test_large_01.json +++ /dev/null @@ -1,2 +0,0 @@ -[["A",0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118] -] \ No newline at end of file diff --git a/test/data/test_object_01.expected b/test/data/test_object_01.expected deleted file mode 100644 index 67444e579..000000000 --- a/test/data/test_object_01.expected +++ /dev/null @@ -1 +0,0 @@ -.={} diff --git a/test/data/test_object_01.json b/test/data/test_object_01.json deleted file mode 100644 index 0967ef424..000000000 --- a/test/data/test_object_01.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/test/data/test_object_02.expected b/test/data/test_object_02.expected deleted file mode 100644 index 79391c2a6..000000000 --- a/test/data/test_object_02.expected +++ /dev/null @@ -1,2 +0,0 @@ -.={} -.count=1234 diff --git a/test/data/test_object_02.json b/test/data/test_object_02.json deleted file mode 100644 index d0f2facac..000000000 --- a/test/data/test_object_02.json +++ /dev/null @@ -1 +0,0 @@ -{ "count" : 1234 } diff --git a/test/data/test_object_03.expected b/test/data/test_object_03.expected deleted file mode 100644 index 5e9611379..000000000 --- a/test/data/test_object_03.expected +++ /dev/null @@ -1,4 +0,0 @@ -.={} -.attribute="random" -.count=1234 -.name="test" diff --git a/test/data/test_object_03.json b/test/data/test_object_03.json deleted file mode 100644 index 4fcd4d821..000000000 --- a/test/data/test_object_03.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "count" : 1234, - "name" : "test", - "attribute" : "random" -} diff --git a/test/data/test_object_04.expected b/test/data/test_object_04.expected deleted file mode 100644 index 812965b0c..000000000 --- a/test/data/test_object_04.expected +++ /dev/null @@ -1,2 +0,0 @@ -.={} -.=1234 diff --git a/test/data/test_object_04.json b/test/data/test_object_04.json deleted file mode 100644 index 450762d71..000000000 --- a/test/data/test_object_04.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "" : 1234 -} diff --git a/test/data/test_preserve_comment_01.expected b/test/data/test_preserve_comment_01.expected deleted file mode 100644 index 2797aa7d6..000000000 --- a/test/data/test_preserve_comment_01.expected +++ /dev/null @@ -1,11 +0,0 @@ -/* A comment - at the beginning of the file. - */ -.={} -.first=1 -/* Comment before 'second' - */ -.second=2 -/* A comment at - the end of the file. - */ diff --git a/test/data/test_preserve_comment_01.json b/test/data/test_preserve_comment_01.json deleted file mode 100644 index fabd55dd9..000000000 --- a/test/data/test_preserve_comment_01.json +++ /dev/null @@ -1,14 +0,0 @@ -/* A comment - at the beginning of the file. - */ -{ - "first" : 1, // comment after 'first' on the same line - -/* Comment before 'second' - */ - "second" : 2 -} - -/* A comment at - the end of the file. - */ diff --git a/test/data/test_real_01.expected b/test/data/test_real_01.expected deleted file mode 100644 index 951482708..000000000 --- a/test/data/test_real_01.expected +++ /dev/null @@ -1,3 +0,0 @@ -// 2^33 => out of integer range, switch to double -.=8589934592 - diff --git a/test/data/test_real_01.json b/test/data/test_real_01.json deleted file mode 100644 index 358452d38..000000000 --- a/test/data/test_real_01.json +++ /dev/null @@ -1,3 +0,0 @@ -// 2^33 => out of integer range, switch to double -8589934592 - diff --git a/test/data/test_real_02.expected b/test/data/test_real_02.expected deleted file mode 100644 index b80c00481..000000000 --- a/test/data/test_real_02.expected +++ /dev/null @@ -1,3 +0,0 @@ -// -2^32 => out of signed integer range, switch to double -.=-4294967295 - diff --git a/test/data/test_real_02.json b/test/data/test_real_02.json deleted file mode 100644 index 936c706b6..000000000 --- a/test/data/test_real_02.json +++ /dev/null @@ -1,3 +0,0 @@ -// -2^32 => out of signed integer range, switch to double --4294967295 - diff --git a/test/data/test_real_03.expected b/test/data/test_real_03.expected deleted file mode 100644 index b80c00481..000000000 --- a/test/data/test_real_03.expected +++ /dev/null @@ -1,3 +0,0 @@ -// -2^32 => out of signed integer range, switch to double -.=-4294967295 - diff --git a/test/data/test_real_03.json b/test/data/test_real_03.json deleted file mode 100644 index 936c706b6..000000000 --- a/test/data/test_real_03.json +++ /dev/null @@ -1,3 +0,0 @@ -// -2^32 => out of signed integer range, switch to double --4294967295 - diff --git a/test/data/test_real_04.expected b/test/data/test_real_04.expected deleted file mode 100644 index ff71a23e1..000000000 --- a/test/data/test_real_04.expected +++ /dev/null @@ -1,3 +0,0 @@ -// 1.2345678 -.=1.2345678 - diff --git a/test/data/test_real_04.json b/test/data/test_real_04.json deleted file mode 100644 index a8eb6d0c9..000000000 --- a/test/data/test_real_04.json +++ /dev/null @@ -1,3 +0,0 @@ -// 1.2345678 -12345678e-7 - diff --git a/test/data/test_real_05.expected b/test/data/test_real_05.expected deleted file mode 100644 index 7a460932d..000000000 --- a/test/data/test_real_05.expected +++ /dev/null @@ -1,4 +0,0 @@ -// 1234567.8 -.=1234567.8 - - diff --git a/test/data/test_real_05.json b/test/data/test_real_05.json deleted file mode 100644 index f7923bab8..000000000 --- a/test/data/test_real_05.json +++ /dev/null @@ -1,3 +0,0 @@ -// 1234567.8 -0.12345678e7 - diff --git a/test/data/test_real_06.expected b/test/data/test_real_06.expected deleted file mode 100644 index a4a004deb..000000000 --- a/test/data/test_real_06.expected +++ /dev/null @@ -1,4 +0,0 @@ -// -1.2345678 -.=-1.2345678 - - diff --git a/test/data/test_real_06.json b/test/data/test_real_06.json deleted file mode 100644 index 485419a27..000000000 --- a/test/data/test_real_06.json +++ /dev/null @@ -1,3 +0,0 @@ -// -1.2345678 --12345678e-7 - diff --git a/test/data/test_real_07.expected b/test/data/test_real_07.expected deleted file mode 100644 index dc02a8958..000000000 --- a/test/data/test_real_07.expected +++ /dev/null @@ -1,4 +0,0 @@ -// -1234567.8 -.=-1234567.8 - - diff --git a/test/data/test_real_07.json b/test/data/test_real_07.json deleted file mode 100644 index 8013eb5c9..000000000 --- a/test/data/test_real_07.json +++ /dev/null @@ -1,3 +0,0 @@ -// -1234567.8 --0.12345678e7 - diff --git a/test/data/test_real_08.expected b/test/data/test_real_08.expected deleted file mode 100644 index b1deef919..000000000 --- a/test/data/test_real_08.expected +++ /dev/null @@ -1,4 +0,0 @@ -// Out of 32-bit integer range, switch to double in 32-bit mode. Length the -// same as UINT_MAX in base 10 and digit less than UINT_MAX's last digit in -// order to catch a bug in the parsing code. -.=4300000001 diff --git a/test/data/test_real_08.json b/test/data/test_real_08.json deleted file mode 100644 index cca950d93..000000000 --- a/test/data/test_real_08.json +++ /dev/null @@ -1,4 +0,0 @@ -// Out of 32-bit integer range, switch to double in 32-bit mode. Length the -// same as UINT_MAX in base 10 and digit less than UINT_MAX's last digit in -// order to catch a bug in the parsing code. -4300000001 diff --git a/test/data/test_real_09.expected b/test/data/test_real_09.expected deleted file mode 100644 index aa2dbb284..000000000 --- a/test/data/test_real_09.expected +++ /dev/null @@ -1,4 +0,0 @@ -// Out of 64-bit integer range, switch to double in all modes. Length the same -// as ULONG_MAX in base 10 and digit less than ULONG_MAX's last digit in order -// to catch a bug in the parsing code. -.=1.9e+19 diff --git a/test/data/test_real_09.json b/test/data/test_real_09.json deleted file mode 100644 index e65d50c97..000000000 --- a/test/data/test_real_09.json +++ /dev/null @@ -1,4 +0,0 @@ -// Out of 64-bit integer range, switch to double in all modes. Length the same -// as ULONG_MAX in base 10 and digit less than ULONG_MAX's last digit in order -// to catch a bug in the parsing code. -19000000000000000001 diff --git a/test/data/test_real_10.expected b/test/data/test_real_10.expected deleted file mode 100644 index d28a430ea..000000000 --- a/test/data/test_real_10.expected +++ /dev/null @@ -1,4 +0,0 @@ -// Out of 32-bit signed integer range, switch to double in all modes. Length -// the same as INT_MIN in base 10 and digit less than INT_MIN's last digit in -// order to catch a bug in the parsing code. -.=-2200000001 diff --git a/test/data/test_real_10.json b/test/data/test_real_10.json deleted file mode 100644 index a6a8bcef5..000000000 --- a/test/data/test_real_10.json +++ /dev/null @@ -1,4 +0,0 @@ -// Out of 32-bit signed integer range, switch to double in all modes. Length -// the same as INT_MIN in base 10 and digit less than INT_MIN's last digit in -// order to catch a bug in the parsing code. --2200000001 diff --git a/test/data/test_real_11.expected b/test/data/test_real_11.expected deleted file mode 100644 index 2551946f5..000000000 --- a/test/data/test_real_11.expected +++ /dev/null @@ -1,4 +0,0 @@ -// Out of 64-bit signed integer range, switch to double in all modes. Length -// the same as LONG_MIN in base 10 and digit less than LONG_MIN's last digit in -// order to catch a bug in the parsing code. -.=-9.3e+18 diff --git a/test/data/test_real_11.json b/test/data/test_real_11.json deleted file mode 100644 index 63cdb36f4..000000000 --- a/test/data/test_real_11.json +++ /dev/null @@ -1,4 +0,0 @@ -// Out of 64-bit signed integer range, switch to double in all modes. Length -// the same as LONG_MIN in base 10 and digit less than LONG_MIN's last digit in -// order to catch a bug in the parsing code. --9300000000000000001 diff --git a/test/data/test_real_12.expected b/test/data/test_real_12.expected deleted file mode 100644 index 93e2417d3..000000000 --- a/test/data/test_real_12.expected +++ /dev/null @@ -1,2 +0,0 @@ -// 2^64 -> switch to double. -.=1.844674407370955e+19 diff --git a/test/data/test_real_12.json b/test/data/test_real_12.json deleted file mode 100644 index 0a13eed22..000000000 --- a/test/data/test_real_12.json +++ /dev/null @@ -1,2 +0,0 @@ -// 2^64 -> switch to double. -18446744073709551616 diff --git a/test/data/test_string_01.expected b/test/data/test_string_01.expected deleted file mode 100644 index 8fd37b1e0..000000000 --- a/test/data/test_string_01.expected +++ /dev/null @@ -1 +0,0 @@ -.="!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~" \ No newline at end of file diff --git a/test/data/test_string_01.json b/test/data/test_string_01.json deleted file mode 100644 index 6cd0db44d..000000000 --- a/test/data/test_string_01.json +++ /dev/null @@ -1 +0,0 @@ -"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" diff --git a/test/data/test_string_02.expected b/test/data/test_string_02.expected deleted file mode 100644 index 0443bc364..000000000 --- a/test/data/test_string_02.expected +++ /dev/null @@ -1 +0,0 @@ -.="!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~" \ No newline at end of file diff --git a/test/data/test_string_02.json b/test/data/test_string_02.json deleted file mode 100644 index 9a7e5dcad..000000000 --- a/test/data/test_string_02.json +++ /dev/null @@ -1 +0,0 @@ -"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" diff --git a/test/data/test_string_03.expected b/test/data/test_string_03.expected deleted file mode 100644 index 6ed627a85..000000000 --- a/test/data/test_string_03.expected +++ /dev/null @@ -1 +0,0 @@ -.="http://jsoncpp.sourceforge.net/" \ No newline at end of file diff --git a/test/data/test_string_03.json b/test/data/test_string_03.json deleted file mode 100644 index 2d38180ae..000000000 --- a/test/data/test_string_03.json +++ /dev/null @@ -1 +0,0 @@ -"http:\/\/jsoncpp.sourceforge.net\/" diff --git a/test/data/test_string_04.expected b/test/data/test_string_04.expected deleted file mode 100644 index f57d5256c..000000000 --- a/test/data/test_string_04.expected +++ /dev/null @@ -1,2 +0,0 @@ -.=""abc\def"" - diff --git a/test/data/test_string_04.json b/test/data/test_string_04.json deleted file mode 100644 index 01fe7524c..000000000 --- a/test/data/test_string_04.json +++ /dev/null @@ -1,2 +0,0 @@ -"\"abc\\def\"" - diff --git a/test/data/test_string_05.expected b/test/data/test_string_05.expected deleted file mode 100644 index 9794dddb4..000000000 --- a/test/data/test_string_05.expected +++ /dev/null @@ -1,2 +0,0 @@ -.="\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" - diff --git a/test/data/test_string_05.json b/test/data/test_string_05.json deleted file mode 100644 index e156024d5..000000000 --- a/test/data/test_string_05.json +++ /dev/null @@ -1,2 +0,0 @@ -"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" - diff --git a/test/data/test_string_unicode_01.expected b/test/data/test_string_unicode_01.expected deleted file mode 100644 index 1f3be7fb6..000000000 --- a/test/data/test_string_unicode_01.expected +++ /dev/null @@ -1 +0,0 @@ -.="a" diff --git a/test/data/test_string_unicode_01.json b/test/data/test_string_unicode_01.json deleted file mode 100644 index 024114bc0..000000000 --- a/test/data/test_string_unicode_01.json +++ /dev/null @@ -1 +0,0 @@ -"\u0061" \ No newline at end of file diff --git a/test/data/test_string_unicode_02.expected b/test/data/test_string_unicode_02.expected deleted file mode 100644 index 1388f5394..000000000 --- a/test/data/test_string_unicode_02.expected +++ /dev/null @@ -1 +0,0 @@ -.="¢" diff --git a/test/data/test_string_unicode_02.json b/test/data/test_string_unicode_02.json deleted file mode 100644 index 4961024fa..000000000 --- a/test/data/test_string_unicode_02.json +++ /dev/null @@ -1 +0,0 @@ -"\u00A2" \ No newline at end of file diff --git a/test/data/test_string_unicode_03.expected b/test/data/test_string_unicode_03.expected deleted file mode 100644 index 9b80b2719..000000000 --- a/test/data/test_string_unicode_03.expected +++ /dev/null @@ -1 +0,0 @@ -.="€" diff --git a/test/data/test_string_unicode_03.json b/test/data/test_string_unicode_03.json deleted file mode 100644 index e7e1a9e13..000000000 --- a/test/data/test_string_unicode_03.json +++ /dev/null @@ -1 +0,0 @@ -"\u20AC" \ No newline at end of file diff --git a/test/data/test_string_unicode_04.expected b/test/data/test_string_unicode_04.expected deleted file mode 100644 index b9e7fe3b7..000000000 --- a/test/data/test_string_unicode_04.expected +++ /dev/null @@ -1 +0,0 @@ -.="𝄞" diff --git a/test/data/test_string_unicode_04.json b/test/data/test_string_unicode_04.json deleted file mode 100644 index dae65c515..000000000 --- a/test/data/test_string_unicode_04.json +++ /dev/null @@ -1 +0,0 @@ -"\uD834\uDD1E" \ No newline at end of file diff --git a/test/data/test_string_unicode_05.expected b/test/data/test_string_unicode_05.expected deleted file mode 100644 index c2e67f998..000000000 --- a/test/data/test_string_unicode_05.expected +++ /dev/null @@ -1,2 +0,0 @@ -.="Zażółć gęślą jaźń" - diff --git a/test/data/test_string_unicode_05.json b/test/data/test_string_unicode_05.json deleted file mode 100644 index 877041094..000000000 --- a/test/data/test_string_unicode_05.json +++ /dev/null @@ -1 +0,0 @@ -"Zażółć gęślą jaźń" \ No newline at end of file diff --git a/test/generate_expected.py b/test/generate_expected.py deleted file mode 100644 index 0b74f51ce..000000000 --- a/test/generate_expected.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2007 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -from __future__ import print_function -import glob -import os.path -for path in glob.glob('*.json'): - text = file(path,'rt').read() - target = os.path.splitext(path)[0] + '.expected' - if os.path.exists(target): - print('skipping:', target) - else: - print('creating:', target) - file(target,'wt').write(text) - diff --git a/test/jsonchecker/fail1.json b/test/jsonchecker/fail1.json deleted file mode 100644 index 6216b865f..000000000 --- a/test/jsonchecker/fail1.json +++ /dev/null @@ -1 +0,0 @@ -"A JSON payload should be an object or array, not a string." \ No newline at end of file diff --git a/test/jsonchecker/fail10.json b/test/jsonchecker/fail10.json deleted file mode 100644 index 5d8c0047b..000000000 --- a/test/jsonchecker/fail10.json +++ /dev/null @@ -1 +0,0 @@ -{"Extra value after close": true} "misplaced quoted value" \ No newline at end of file diff --git a/test/jsonchecker/fail11.json b/test/jsonchecker/fail11.json deleted file mode 100644 index 76eb95b45..000000000 --- a/test/jsonchecker/fail11.json +++ /dev/null @@ -1 +0,0 @@ -{"Illegal expression": 1 + 2} \ No newline at end of file diff --git a/test/jsonchecker/fail12.json b/test/jsonchecker/fail12.json deleted file mode 100644 index 77580a452..000000000 --- a/test/jsonchecker/fail12.json +++ /dev/null @@ -1 +0,0 @@ -{"Illegal invocation": alert()} \ No newline at end of file diff --git a/test/jsonchecker/fail13.json b/test/jsonchecker/fail13.json deleted file mode 100644 index 379406b59..000000000 --- a/test/jsonchecker/fail13.json +++ /dev/null @@ -1 +0,0 @@ -{"Numbers cannot have leading zeroes": 013} \ No newline at end of file diff --git a/test/jsonchecker/fail14.json b/test/jsonchecker/fail14.json deleted file mode 100644 index 0ed366b38..000000000 --- a/test/jsonchecker/fail14.json +++ /dev/null @@ -1 +0,0 @@ -{"Numbers cannot be hex": 0x14} \ No newline at end of file diff --git a/test/jsonchecker/fail15.json b/test/jsonchecker/fail15.json deleted file mode 100644 index fc8376b60..000000000 --- a/test/jsonchecker/fail15.json +++ /dev/null @@ -1 +0,0 @@ -["Illegal backslash escape: \x15"] \ No newline at end of file diff --git a/test/jsonchecker/fail16.json b/test/jsonchecker/fail16.json deleted file mode 100644 index 3fe21d4b5..000000000 --- a/test/jsonchecker/fail16.json +++ /dev/null @@ -1 +0,0 @@ -[\naked] \ No newline at end of file diff --git a/test/jsonchecker/fail17.json b/test/jsonchecker/fail17.json deleted file mode 100644 index 62b9214ae..000000000 --- a/test/jsonchecker/fail17.json +++ /dev/null @@ -1 +0,0 @@ -["Illegal backslash escape: \017"] \ No newline at end of file diff --git a/test/jsonchecker/fail18.json b/test/jsonchecker/fail18.json deleted file mode 100644 index edac92716..000000000 --- a/test/jsonchecker/fail18.json +++ /dev/null @@ -1 +0,0 @@ -[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] \ No newline at end of file diff --git a/test/jsonchecker/fail19.json b/test/jsonchecker/fail19.json deleted file mode 100644 index 3b9c46fa9..000000000 --- a/test/jsonchecker/fail19.json +++ /dev/null @@ -1 +0,0 @@ -{"Missing colon" null} \ No newline at end of file diff --git a/test/jsonchecker/fail2.json b/test/jsonchecker/fail2.json deleted file mode 100644 index 6b7c11e5a..000000000 --- a/test/jsonchecker/fail2.json +++ /dev/null @@ -1 +0,0 @@ -["Unclosed array" \ No newline at end of file diff --git a/test/jsonchecker/fail20.json b/test/jsonchecker/fail20.json deleted file mode 100644 index 27c1af3e7..000000000 --- a/test/jsonchecker/fail20.json +++ /dev/null @@ -1 +0,0 @@ -{"Double colon":: null} \ No newline at end of file diff --git a/test/jsonchecker/fail21.json b/test/jsonchecker/fail21.json deleted file mode 100644 index 62474573b..000000000 --- a/test/jsonchecker/fail21.json +++ /dev/null @@ -1 +0,0 @@ -{"Comma instead of colon", null} \ No newline at end of file diff --git a/test/jsonchecker/fail22.json b/test/jsonchecker/fail22.json deleted file mode 100644 index a7752581b..000000000 --- a/test/jsonchecker/fail22.json +++ /dev/null @@ -1 +0,0 @@ -["Colon instead of comma": false] \ No newline at end of file diff --git a/test/jsonchecker/fail23.json b/test/jsonchecker/fail23.json deleted file mode 100644 index 494add1ca..000000000 --- a/test/jsonchecker/fail23.json +++ /dev/null @@ -1 +0,0 @@ -["Bad value", truth] \ No newline at end of file diff --git a/test/jsonchecker/fail24.json b/test/jsonchecker/fail24.json deleted file mode 100644 index caff239bf..000000000 --- a/test/jsonchecker/fail24.json +++ /dev/null @@ -1 +0,0 @@ -['single quote'] \ No newline at end of file diff --git a/test/jsonchecker/fail25.json b/test/jsonchecker/fail25.json deleted file mode 100644 index 8b7ad23e0..000000000 --- a/test/jsonchecker/fail25.json +++ /dev/null @@ -1 +0,0 @@ -[" tab character in string "] \ No newline at end of file diff --git a/test/jsonchecker/fail26.json b/test/jsonchecker/fail26.json deleted file mode 100644 index 845d26a6a..000000000 --- a/test/jsonchecker/fail26.json +++ /dev/null @@ -1 +0,0 @@ -["tab\ character\ in\ string\ "] \ No newline at end of file diff --git a/test/jsonchecker/fail27.json b/test/jsonchecker/fail27.json deleted file mode 100644 index 6b01a2ca4..000000000 --- a/test/jsonchecker/fail27.json +++ /dev/null @@ -1,2 +0,0 @@ -["line -break"] \ No newline at end of file diff --git a/test/jsonchecker/fail28.json b/test/jsonchecker/fail28.json deleted file mode 100644 index 621a0101c..000000000 --- a/test/jsonchecker/fail28.json +++ /dev/null @@ -1,2 +0,0 @@ -["line\ -break"] \ No newline at end of file diff --git a/test/jsonchecker/fail29.json b/test/jsonchecker/fail29.json deleted file mode 100644 index 47ec421bb..000000000 --- a/test/jsonchecker/fail29.json +++ /dev/null @@ -1 +0,0 @@ -[0e] \ No newline at end of file diff --git a/test/jsonchecker/fail3.json b/test/jsonchecker/fail3.json deleted file mode 100644 index 168c81eb7..000000000 --- a/test/jsonchecker/fail3.json +++ /dev/null @@ -1 +0,0 @@ -{unquoted_key: "keys must be quoted"} \ No newline at end of file diff --git a/test/jsonchecker/fail30.json b/test/jsonchecker/fail30.json deleted file mode 100644 index 8ab0bc4b8..000000000 --- a/test/jsonchecker/fail30.json +++ /dev/null @@ -1 +0,0 @@ -[0e+] \ No newline at end of file diff --git a/test/jsonchecker/fail31.json b/test/jsonchecker/fail31.json deleted file mode 100644 index 1cce602b5..000000000 --- a/test/jsonchecker/fail31.json +++ /dev/null @@ -1 +0,0 @@ -[0e+-1] \ No newline at end of file diff --git a/test/jsonchecker/fail32.json b/test/jsonchecker/fail32.json deleted file mode 100644 index 45cba7396..000000000 --- a/test/jsonchecker/fail32.json +++ /dev/null @@ -1 +0,0 @@ -{"Comma instead if closing brace": true, \ No newline at end of file diff --git a/test/jsonchecker/fail33.json b/test/jsonchecker/fail33.json deleted file mode 100644 index ca5eb19dc..000000000 --- a/test/jsonchecker/fail33.json +++ /dev/null @@ -1 +0,0 @@ -["mismatch"} \ No newline at end of file diff --git a/test/jsonchecker/fail4.json b/test/jsonchecker/fail4.json deleted file mode 100644 index 9de168bf3..000000000 --- a/test/jsonchecker/fail4.json +++ /dev/null @@ -1 +0,0 @@ -["extra comma",] \ No newline at end of file diff --git a/test/jsonchecker/fail5.json b/test/jsonchecker/fail5.json deleted file mode 100644 index ddf3ce3d2..000000000 --- a/test/jsonchecker/fail5.json +++ /dev/null @@ -1 +0,0 @@ -["double extra comma",,] \ No newline at end of file diff --git a/test/jsonchecker/fail6.json b/test/jsonchecker/fail6.json deleted file mode 100644 index ed91580e1..000000000 --- a/test/jsonchecker/fail6.json +++ /dev/null @@ -1 +0,0 @@ -[ , "<-- missing value"] \ No newline at end of file diff --git a/test/jsonchecker/fail7.json b/test/jsonchecker/fail7.json deleted file mode 100644 index 8a96af3e4..000000000 --- a/test/jsonchecker/fail7.json +++ /dev/null @@ -1 +0,0 @@ -["Comma after the close"], \ No newline at end of file diff --git a/test/jsonchecker/fail8.json b/test/jsonchecker/fail8.json deleted file mode 100644 index b28479c6e..000000000 --- a/test/jsonchecker/fail8.json +++ /dev/null @@ -1 +0,0 @@ -["Extra close"]] \ No newline at end of file diff --git a/test/jsonchecker/fail9.json b/test/jsonchecker/fail9.json deleted file mode 100644 index 5815574f3..000000000 --- a/test/jsonchecker/fail9.json +++ /dev/null @@ -1 +0,0 @@ -{"Extra comma": true,} \ No newline at end of file diff --git a/test/jsonchecker/pass1.json b/test/jsonchecker/pass1.json deleted file mode 100644 index 70e268543..000000000 --- a/test/jsonchecker/pass1.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - "JSON Test Pattern pass1", - {"object with 1 member":["array with 1 element"]}, - {}, - [], - -42, - true, - false, - null, - { - "integer": 1234567890, - "real": -9876.543210, - "e": 0.123456789e-12, - "E": 1.234567890E+34, - "": 23456789012E66, - "zero": 0, - "one": 1, - "space": " ", - "quote": "\"", - "backslash": "\\", - "controls": "\b\f\n\r\t", - "slash": "/ & \/", - "alpha": "abcdefghijklmnopqrstuvwyz", - "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", - "digit": "0123456789", - "0123456789": "digit", - "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", - "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", - "true": true, - "false": false, - "null": null, - "array":[ ], - "object":{ }, - "address": "50 St. James Street", - "url": "http://www.json.org/", - "comment": "// /* */": " ", - " s p a c e d " :[1,2 , 3 - -, - -4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], - "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", - "quotes": "" \u0022 %22 0x22 034 "", - "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" -: "A key can be any string" - }, - 0.5 ,98.6 -, -99.44 -, - -1066, -1e1, -0.1e1, -1e-1, -1e00,2e+00,2e-00 -,"rosebud"] \ No newline at end of file diff --git a/test/jsonchecker/pass2.json b/test/jsonchecker/pass2.json deleted file mode 100644 index d3c63c7ad..000000000 --- a/test/jsonchecker/pass2.json +++ /dev/null @@ -1 +0,0 @@ -[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] \ No newline at end of file diff --git a/test/jsonchecker/pass3.json b/test/jsonchecker/pass3.json deleted file mode 100644 index 4528d51f1..000000000 --- a/test/jsonchecker/pass3.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "JSON Test Pattern pass3": { - "The outermost value": "must be an object or array.", - "In this test": "It is an object." - } -} diff --git a/test/jsonchecker/readme.txt b/test/jsonchecker/readme.txt deleted file mode 100644 index 321d89d99..000000000 --- a/test/jsonchecker/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Test suite from http://json.org/JSON_checker/. - -If the JSON_checker is working correctly, it must accept all of the pass*.json files and reject all of the fail*.json files. diff --git a/test/pyjsontestrunner.py b/test/pyjsontestrunner.py deleted file mode 100644 index 7f38356ae..000000000 --- a/test/pyjsontestrunner.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2007 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -"""Simple implementation of a json test runner to run the test against -json-py.""" - -from __future__ import print_function -import sys -import os.path -import json -import types - -if len(sys.argv) != 2: - print("Usage: %s input-json-file", sys.argv[0]) - sys.exit(3) - -input_path = sys.argv[1] -base_path = os.path.splitext(input_path)[0] -actual_path = base_path + '.actual' -rewrite_path = base_path + '.rewrite' -rewrite_actual_path = base_path + '.actual-rewrite' - -def valueTreeToString(fout, value, path = '.'): - ty = type(value) - if ty is types.DictType: - fout.write('%s={}\n' % path) - suffix = path[-1] != '.' and '.' or '' - names = value.keys() - names.sort() - for name in names: - valueTreeToString(fout, value[name], path + suffix + name) - elif ty is types.ListType: - fout.write('%s=[]\n' % path) - for index, childValue in zip(xrange(0,len(value)), value): - valueTreeToString(fout, childValue, path + '[%d]' % index) - elif ty is types.StringType: - fout.write('%s="%s"\n' % (path,value)) - elif ty is types.IntType: - fout.write('%s=%d\n' % (path,value)) - elif ty is types.FloatType: - fout.write('%s=%.16g\n' % (path,value)) - elif value is True: - fout.write('%s=true\n' % path) - elif value is False: - fout.write('%s=false\n' % path) - elif value is None: - fout.write('%s=null\n' % path) - else: - assert False and "Unexpected value type" - -def parseAndSaveValueTree(input, actual_path): - root = json.loads(input) - fout = file(actual_path, 'wt') - valueTreeToString(fout, root) - fout.close() - return root - -def rewriteValueTree(value, rewrite_path): - rewrite = json.dumps(value) - #rewrite = rewrite[1:-1] # Somehow the string is quoted ! jsonpy bug ? - file(rewrite_path, 'wt').write(rewrite + '\n') - return rewrite - -input = file(input_path, 'rt').read() -root = parseAndSaveValueTree(input, actual_path) -rewrite = rewriteValueTree(json.write(root), rewrite_path) -rewrite_root = parseAndSaveValueTree(rewrite, rewrite_actual_path) - -sys.exit(0) diff --git a/test/runjsontests.py b/test/runjsontests.py deleted file mode 100644 index d21c02f38..000000000 --- a/test/runjsontests.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright 2007 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -from __future__ import print_function -from __future__ import unicode_literals -from io import open -from glob import glob -import sys -import os -import os.path -import optparse - -VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes ' - -def getStatusOutput(cmd): - """ - Return int, unicode (for both Python 2 and 3). - Note: os.popen().close() would return None for 0. - """ - print(cmd, file=sys.stderr) - pipe = os.popen(cmd) - process_output = pipe.read() - try: - # We have been using os.popen(). When we read() the result - # we get 'str' (bytes) in py2, and 'str' (unicode) in py3. - # Ugh! There must be a better way to handle this. - process_output = process_output.decode('utf-8') - except AttributeError: - pass # python3 - status = pipe.close() - return status, process_output -def compareOutputs(expected, actual, message): - expected = expected.strip().replace('\r','').split('\n') - actual = actual.strip().replace('\r','').split('\n') - diff_line = 0 - max_line_to_compare = min(len(expected), len(actual)) - for index in range(0,max_line_to_compare): - if expected[index].strip() != actual[index].strip(): - diff_line = index + 1 - break - if diff_line == 0 and len(expected) != len(actual): - diff_line = max_line_to_compare+1 - if diff_line == 0: - return None - def safeGetLine(lines, index): - index += -1 - if index >= len(lines): - return '' - return lines[index].strip() - return """ Difference in %s at line %d: - Expected: '%s' - Actual: '%s' -""" % (message, diff_line, - safeGetLine(expected,diff_line), - safeGetLine(actual,diff_line)) - -def safeReadFile(path): - try: - return open(path, 'rt', encoding = 'utf-8').read() - except IOError as e: - return '' % (path,e) - -def runAllTests(jsontest_executable_path, input_dir = None, - use_valgrind=False, with_json_checker=False, - writerClass='StyledWriter'): - if not input_dir: - input_dir = os.path.join(os.getcwd(), 'data') - tests = glob(os.path.join(input_dir, '*.json')) - if with_json_checker: - test_jsonchecker = glob(os.path.join(input_dir, '../jsonchecker', '*.json')) - else: - test_jsonchecker = [] - failed_tests = [] - valgrind_path = use_valgrind and VALGRIND_CMD or '' - for input_path in tests + test_jsonchecker: - expect_failure = os.path.basename(input_path).startswith('fail') - is_json_checker_test = (input_path in test_jsonchecker) or expect_failure - print('TESTING:', input_path, end=' ') - options = is_json_checker_test and '--json-checker' or '' - options += ' --json-writer %s'%writerClass - cmd = '%s%s %s "%s"' % ( valgrind_path, jsontest_executable_path, options, - input_path) - status, process_output = getStatusOutput(cmd) - if is_json_checker_test: - if expect_failure: - if not status: - print('FAILED') - failed_tests.append((input_path, 'Parsing should have failed:\n%s' % - safeReadFile(input_path))) - else: - print('OK') - else: - if status: - print('FAILED') - failed_tests.append((input_path, 'Parsing failed:\n' + process_output)) - else: - print('OK') - else: - base_path = os.path.splitext(input_path)[0] - actual_output = safeReadFile(base_path + '.actual') - actual_rewrite_output = safeReadFile(base_path + '.actual-rewrite') - open(base_path + '.process-output', 'wt', encoding = 'utf-8').write(process_output) - if status: - print('parsing failed') - failed_tests.append((input_path, 'Parsing failed:\n' + process_output)) - else: - expected_output_path = os.path.splitext(input_path)[0] + '.expected' - expected_output = open(expected_output_path, 'rt', encoding = 'utf-8').read() - detail = (compareOutputs(expected_output, actual_output, 'input') - or compareOutputs(expected_output, actual_rewrite_output, 'rewrite')) - if detail: - print('FAILED') - failed_tests.append((input_path, detail)) - else: - print('OK') - - if failed_tests: - print() - print('Failure details:') - for failed_test in failed_tests: - print('* Test', failed_test[0]) - print(failed_test[1]) - print() - print('Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests), - len(failed_tests))) - return 1 - else: - print('All %d tests passed.' % len(tests)) - return 0 - -def main(): - from optparse import OptionParser - parser = OptionParser(usage="%prog [options] [test case directory]") - parser.add_option("--valgrind", - action="http://github.com/store_true", dest="valgrind", default=False, - help="run all the tests using valgrind to detect memory leaks") - parser.add_option("-c", "--with-json-checker", - action="http://github.com/store_true", dest="with_json_checker", default=False, - help="run all the tests from the official JSONChecker test suite of json.org") - parser.enable_interspersed_args() - options, args = parser.parse_args() - - if len(args) < 1 or len(args) > 2: - parser.error('Must provides at least path to jsontestrunner executable.') - sys.exit(1) - - jsontest_executable_path = os.path.normpath(os.path.abspath(args[0])) - if len(args) > 1: - input_path = os.path.normpath(os.path.abspath(args[1])) - else: - input_path = None - status = runAllTests(jsontest_executable_path, input_path, - use_valgrind=options.valgrind, - with_json_checker=options.with_json_checker, - writerClass='StyledWriter') - if status: - sys.exit(status) - status = runAllTests(jsontest_executable_path, input_path, - use_valgrind=options.valgrind, - with_json_checker=options.with_json_checker, - writerClass='StyledStreamWriter') - if status: - sys.exit(status) - status = runAllTests(jsontest_executable_path, input_path, - use_valgrind=options.valgrind, - with_json_checker=options.with_json_checker, - writerClass='BuiltStyledStreamWriter') - if status: - sys.exit(status) - -if __name__ == '__main__': - main() diff --git a/test/rununittests.py b/test/rununittests.py deleted file mode 100644 index 08850ec1a..000000000 --- a/test/rununittests.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2009 Baptiste Lepilleur -# Distributed under MIT license, or public domain if desired and -# recognized in your jurisdiction. -# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -from __future__ import print_function -from __future__ import unicode_literals -from io import open -from glob import glob -import sys -import os -import os.path -import subprocess -import optparse - -VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes' - -class TestProxy(object): - def __init__(self, test_exe_path, use_valgrind=False): - self.test_exe_path = os.path.normpath(os.path.abspath(test_exe_path)) - self.use_valgrind = use_valgrind - - def run(self, options): - if self.use_valgrind: - cmd = VALGRIND_CMD.split() - else: - cmd = [] - cmd.extend([self.test_exe_path, '--test-auto'] + options) - try: - process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - except: - print(cmd) - raise - stdout = process.communicate()[0] - if process.returncode: - return False, stdout - return True, stdout - -def runAllTests(exe_path, use_valgrind=False): - test_proxy = TestProxy(exe_path, use_valgrind=use_valgrind) - status, test_names = test_proxy.run(['--list-tests']) - if not status: - print("Failed to obtain unit tests list:\n" + test_names, file=sys.stderr) - return 1 - test_names = [name.strip() for name in test_names.decode('utf-8').strip().split('\n')] - failures = [] - for name in test_names: - print('TESTING %s:' % name, end=' ') - succeed, result = test_proxy.run(['--test', name]) - if succeed: - print('OK') - else: - failures.append((name, result)) - print('FAILED') - failed_count = len(failures) - pass_count = len(test_names) - failed_count - if failed_count: - print() - for name, result in failures: - print(result) - print('%d/%d tests passed (%d failure(s))' % ( pass_count, len(test_names), failed_count)) - return 1 - else: - print('All %d tests passed' % len(test_names)) - return 0 - -def main(): - from optparse import OptionParser - parser = OptionParser(usage="%prog [options] ") - parser.add_option("--valgrind", - action="http://github.com/store_true", dest="valgrind", default=False, - help="run all the tests using valgrind to detect memory leaks") - parser.enable_interspersed_args() - options, args = parser.parse_args() - - if len(args) != 1: - parser.error('Must provides at least path to test_lib_json executable.') - sys.exit(1) - - exit_code = runAllTests(args[0], use_valgrind=options.valgrind) - sys.exit(exit_code) - -if __name__ == '__main__': - main() diff --git a/travis.sh b/travis.sh deleted file mode 100755 index 2b25f4766..000000000 --- a/travis.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env sh -# This is called by `.travis.yml` via Travis CI. -# Travis supplies $TRAVIS_OS_NAME. -# http://docs.travis-ci.com/user/multi-os/ -# Our .travis.yml also defines: -# - SHARED_LIB=ON/OFF -# - STATIC_LIB=ON/OFF -# - CMAKE_PKG=ON/OFF -# - BUILD_TYPE=release/debug -# - VERBOSE_MAKE=false/true -# - VERBOSE (set or not) - -# -e: fail on error -# -v: show commands -# -x: show expanded commands -set -vex - -env | sort - -cmake -DJSONCPP_WITH_CMAKE_PACKAGE=$CMAKE_PKG -DBUILD_SHARED_LIBS=$SHARED_LIB -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_VERBOSE_MAKEFILE=$VERBOSE_MAKE . -make - -# Python is not available in Travis for osx. -# https://github.com/travis-ci/travis-ci/issues/2320 -if [ "$TRAVIS_OS_NAME" != "osx" ] -then - make jsoncpp_check - valgrind --error-exitcode=42 --leak-check=full ./src/test_lib_json/jsoncpp_test -fi diff --git a/version b/version deleted file mode 100644 index 9f05f9f2c..000000000 --- a/version +++ /dev/null @@ -1 +0,0 @@ -1.6.5 diff --git a/version.in b/version.in deleted file mode 100644 index bfc03f7dd..000000000 --- a/version.in +++ /dev/null @@ -1 +0,0 @@ -@JSONCPP_VERSION@