From dab707bdca625fc2a5841727d5af4b86516120e7 Mon Sep 17 00:00:00 2001 From: Judith Silverman Date: Tue, 7 Apr 2020 12:17:17 -0700 Subject: [PATCH 1/3] Apply dos2unix to source files --- json5_parser/json5_parser.h | 36 +- json5_parser/json5_parser_error_position.h | 108 +- json5_parser/json5_parser_reader.cpp | 274 +-- json5_parser/json5_parser_reader.h | 124 +- json5_parser/json5_parser_reader_template.h | 1402 ++++++------- json5_parser/json5_parser_stream_reader.h | 140 +- json5_parser/json5_parser_utils.h | 126 +- json5_parser/json5_parser_value.cpp | 12 +- json5_parser/json5_parser_value.h | 1210 +++++------ json5_parser/json5_parser_writer.cpp | 192 +- json5_parser/json5_parser_writer.h | 130 +- json5_parser/json5_parser_writer_options.h | 70 +- json5_parser/json5_parser_writer_template.h | 650 +++--- json_demo/json_demo.cpp | 298 +-- .../json_headers_only_demo.cpp | 302 +-- json_map_demo/json_map_demo.cpp | 264 +-- json_test/json5_parser_reader_test.cpp | 1850 ++++++++--------- json_test/json5_parser_reader_test.h | 36 +- json_test/json5_parser_stream_reader_test.cpp | 274 +-- json_test/json5_parser_stream_reader_test.h | 36 +- json_test/json5_parser_utils_test.cpp | 286 +-- json_test/json5_parser_utils_test.h | 36 +- json_test/json5_parser_value_test.cpp | 1058 +++++----- json_test/json5_parser_value_test.h | 36 +- json_test/json5_parser_writer_test.cpp | 1576 +++++++------- json_test/json5_parser_writer_test.h | 36 +- json_test/json_test.cpp | 58 +- json_test/utils_test.cpp | 30 +- json_test/utils_test.h | 72 +- 29 files changed, 5361 insertions(+), 5361 deletions(-) diff --git a/json5_parser/json5_parser.h b/json5_parser/json5_parser.h index 1f84a48..fc592da 100644 --- a/json5_parser/json5_parser.h +++ b/json5_parser/json5_parser.h @@ -1,18 +1,18 @@ -#ifndef JSON_SPIRIT -#define JSON_SPIRIT - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include "json5_parser_value.h" -#include "json5_parser_reader.h" -#include "json5_parser_writer.h" -#include "json5_parser_utils.h" - -#endif +#ifndef JSON_SPIRIT +#define JSON_SPIRIT + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include "json5_parser_value.h" +#include "json5_parser_reader.h" +#include "json5_parser_writer.h" +#include "json5_parser_utils.h" + +#endif diff --git a/json5_parser/json5_parser_error_position.h b/json5_parser/json5_parser_error_position.h index 6e0432d..20c1967 100644 --- a/json5_parser/json5_parser_error_position.h +++ b/json5_parser/json5_parser_error_position.h @@ -1,54 +1,54 @@ -#ifndef JSON_SPIRIT_ERROR_POSITION -#define JSON_SPIRIT_ERROR_POSITION - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include - -namespace json5_parser -{ - // An Error_position exception is thrown by the "read_or_throw" functions below on finding an error. - // Note the "read_or_throw" functions are around 3 times slower than the standard functions "read" - // functions that return a bool. - // - struct Error_position - { - Error_position(); - Error_position( unsigned int line, unsigned int column, const std::string& reason ); - bool operator==( const Error_position& lhs ) const; - unsigned int line_; - unsigned int column_; - std::string reason_; - }; - - inline Error_position::Error_position() - : line_( 0 ) - , column_( 0 ) - { - } - - inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason ) - : line_( line ) - , column_( column ) - , reason_( reason ) - { - } - - inline bool Error_position::operator==( const Error_position& lhs ) const - { - if( this == &lhs ) return true; - - return ( reason_ == lhs.reason_ ) && - ( line_ == lhs.line_ ) && - ( column_ == lhs.column_ ); - } -} - -#endif +#ifndef JSON_SPIRIT_ERROR_POSITION +#define JSON_SPIRIT_ERROR_POSITION + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +namespace json5_parser +{ + // An Error_position exception is thrown by the "read_or_throw" functions below on finding an error. + // Note the "read_or_throw" functions are around 3 times slower than the standard functions "read" + // functions that return a bool. + // + struct Error_position + { + Error_position(); + Error_position( unsigned int line, unsigned int column, const std::string& reason ); + bool operator==( const Error_position& lhs ) const; + unsigned int line_; + unsigned int column_; + std::string reason_; + }; + + inline Error_position::Error_position() + : line_( 0 ) + , column_( 0 ) + { + } + + inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason ) + : line_( line ) + , column_( column ) + , reason_( reason ) + { + } + + inline bool Error_position::operator==( const Error_position& lhs ) const + { + if( this == &lhs ) return true; + + return ( reason_ == lhs.reason_ ) && + ( line_ == lhs.line_ ) && + ( column_ == lhs.column_ ); + } +} + +#endif diff --git a/json5_parser/json5_parser_reader.cpp b/json5_parser/json5_parser_reader.cpp index c6adb75..c30b667 100644 --- a/json5_parser/json5_parser_reader.cpp +++ b/json5_parser/json5_parser_reader.cpp @@ -1,137 +1,137 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_reader.h" -#include "json5_parser_reader_template.h" - -using namespace json5_parser; - -#ifdef JSON_SPIRIT_VALUE_ENABLED - bool json5_parser::read( const std::string& s, Value& value ) - { - return read_string( s, value ); - } - - void json5_parser::read_or_throw( const std::string& s, Value& value ) - { - read_string_or_throw( s, value ); - } - - bool json5_parser::read( std::istream& is, Value& value ) - { - return read_stream( is, value ); - } - - void json5_parser::read_or_throw( std::istream& is, Value& value ) - { - read_stream_or_throw( is, value ); - } - - bool json5_parser::read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ) - { - return read_range( begin, end, value ); - } - - void json5_parser::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ) - { - begin = read_range_or_throw( begin, end, value ); - } -#endif - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - bool json5_parser::read( const std::wstring& s, wValue& value ) - { - return read_string( s, value ); - } - - void json5_parser::read_or_throw( const std::wstring& s, wValue& value ) - { - read_string_or_throw( s, value ); - } - - bool json5_parser::read( std::wistream& is, wValue& value ) - { - return read_stream( is, value ); - } - - void json5_parser::read_or_throw( std::wistream& is, wValue& value ) - { - read_stream_or_throw( is, value ); - } - - bool json5_parser::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ) - { - return read_range( begin, end, value ); - } - - void json5_parser::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ) - { - begin = read_range_or_throw( begin, end, value ); - } -#endif - -#ifdef JSON_SPIRIT_MVALUE_ENABLED - bool json5_parser::read( const std::string& s, mValue& value ) - { - return read_string( s, value ); - } - - void json5_parser::read_or_throw( const std::string& s, mValue& value ) - { - read_string_or_throw( s, value ); - } - - bool json5_parser::read( std::istream& is, mValue& value ) - { - return read_stream( is, value ); - } - - void json5_parser::read_or_throw( std::istream& is, mValue& value ) - { - read_stream_or_throw( is, value ); - } - - bool json5_parser::read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ) - { - return read_range( begin, end, value ); - } - - void json5_parser::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ) - { - begin = read_range_or_throw( begin, end, value ); - } -#endif - -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - bool json5_parser::read( const std::wstring& s, wmValue& value ) - { - return read_string( s, value ); - } - - void json5_parser::read_or_throw( const std::wstring& s, wmValue& value ) - { - read_string_or_throw( s, value ); - } - - bool json5_parser::read( std::wistream& is, wmValue& value ) - { - return read_stream( is, value ); - } - - void json5_parser::read_or_throw( std::wistream& is, wmValue& value ) - { - read_stream_or_throw( is, value ); - } - - bool json5_parser::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ) - { - return read_range( begin, end, value ); - } - - void json5_parser::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ) - { - begin = read_range_or_throw( begin, end, value ); - } -#endif +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_reader.h" +#include "json5_parser_reader_template.h" + +using namespace json5_parser; + +#ifdef JSON_SPIRIT_VALUE_ENABLED + bool json5_parser::read( const std::string& s, Value& value ) + { + return read_string( s, value ); + } + + void json5_parser::read_or_throw( const std::string& s, Value& value ) + { + read_string_or_throw( s, value ); + } + + bool json5_parser::read( std::istream& is, Value& value ) + { + return read_stream( is, value ); + } + + void json5_parser::read_or_throw( std::istream& is, Value& value ) + { + read_stream_or_throw( is, value ); + } + + bool json5_parser::read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ) + { + return read_range( begin, end, value ); + } + + void json5_parser::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ) + { + begin = read_range_or_throw( begin, end, value ); + } +#endif + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + bool json5_parser::read( const std::wstring& s, wValue& value ) + { + return read_string( s, value ); + } + + void json5_parser::read_or_throw( const std::wstring& s, wValue& value ) + { + read_string_or_throw( s, value ); + } + + bool json5_parser::read( std::wistream& is, wValue& value ) + { + return read_stream( is, value ); + } + + void json5_parser::read_or_throw( std::wistream& is, wValue& value ) + { + read_stream_or_throw( is, value ); + } + + bool json5_parser::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ) + { + return read_range( begin, end, value ); + } + + void json5_parser::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ) + { + begin = read_range_or_throw( begin, end, value ); + } +#endif + +#ifdef JSON_SPIRIT_MVALUE_ENABLED + bool json5_parser::read( const std::string& s, mValue& value ) + { + return read_string( s, value ); + } + + void json5_parser::read_or_throw( const std::string& s, mValue& value ) + { + read_string_or_throw( s, value ); + } + + bool json5_parser::read( std::istream& is, mValue& value ) + { + return read_stream( is, value ); + } + + void json5_parser::read_or_throw( std::istream& is, mValue& value ) + { + read_stream_or_throw( is, value ); + } + + bool json5_parser::read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ) + { + return read_range( begin, end, value ); + } + + void json5_parser::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ) + { + begin = read_range_or_throw( begin, end, value ); + } +#endif + +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + bool json5_parser::read( const std::wstring& s, wmValue& value ) + { + return read_string( s, value ); + } + + void json5_parser::read_or_throw( const std::wstring& s, wmValue& value ) + { + read_string_or_throw( s, value ); + } + + bool json5_parser::read( std::wistream& is, wmValue& value ) + { + return read_stream( is, value ); + } + + void json5_parser::read_or_throw( std::wistream& is, wmValue& value ) + { + read_stream_or_throw( is, value ); + } + + bool json5_parser::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ) + { + return read_range( begin, end, value ); + } + + void json5_parser::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ) + { + begin = read_range_or_throw( begin, end, value ); + } +#endif diff --git a/json5_parser/json5_parser_reader.h b/json5_parser/json5_parser_reader.h index 023c18c..152b73f 100644 --- a/json5_parser/json5_parser_reader.h +++ b/json5_parser/json5_parser_reader.h @@ -1,62 +1,62 @@ -#ifndef JSON_SPIRIT_READER -#define JSON_SPIRIT_READER - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include "json5_parser_value.h" -#include "json5_parser_error_position.h" -#include - -namespace json5_parser -{ - // functions to reads a JSON values - -#ifdef JSON_SPIRIT_VALUE_ENABLED - bool read( const std::string& s, Value& value ); - bool read( std::istream& is, Value& value ); - bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); - - void read_or_throw( const std::string& s, Value& value ); - void read_or_throw( std::istream& is, Value& value ); - void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); -#endif - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - bool read( const std::wstring& s, wValue& value ); - bool read( std::wistream& is, wValue& value ); - bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); - - void read_or_throw( const std::wstring& s, wValue& value ); - void read_or_throw( std::wistream& is, wValue& value ); - void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); -#endif - -#ifdef JSON_SPIRIT_MVALUE_ENABLED - bool read( const std::string& s, mValue& value ); - bool read( std::istream& is, mValue& value ); - bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); - - void read_or_throw( const std::string& s, mValue& value ); - void read_or_throw( std::istream& is, mValue& value ); - void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); -#endif - -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - bool read( const std::wstring& s, wmValue& value ); - bool read( std::wistream& is, wmValue& value ); - bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); - - void read_or_throw( const std::wstring& s, wmValue& value ); - void read_or_throw( std::wistream& is, wmValue& value ); - void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); -#endif -} - -#endif +#ifndef JSON_SPIRIT_READER +#define JSON_SPIRIT_READER + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include "json5_parser_value.h" +#include "json5_parser_error_position.h" +#include + +namespace json5_parser +{ + // functions to reads a JSON values + +#ifdef JSON_SPIRIT_VALUE_ENABLED + bool read( const std::string& s, Value& value ); + bool read( std::istream& is, Value& value ); + bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); + + void read_or_throw( const std::string& s, Value& value ); + void read_or_throw( std::istream& is, Value& value ); + void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); +#endif + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + bool read( const std::wstring& s, wValue& value ); + bool read( std::wistream& is, wValue& value ); + bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); + + void read_or_throw( const std::wstring& s, wValue& value ); + void read_or_throw( std::wistream& is, wValue& value ); + void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); +#endif + +#ifdef JSON_SPIRIT_MVALUE_ENABLED + bool read( const std::string& s, mValue& value ); + bool read( std::istream& is, mValue& value ); + bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); + + void read_or_throw( const std::string& s, mValue& value ); + void read_or_throw( std::istream& is, mValue& value ); + void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); +#endif + +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + bool read( const std::wstring& s, wmValue& value ); + bool read( std::wistream& is, wmValue& value ); + bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); + + void read_or_throw( const std::wstring& s, wmValue& value ); + void read_or_throw( std::wistream& is, wmValue& value ); + void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); +#endif +} + +#endif diff --git a/json5_parser/json5_parser_reader_template.h b/json5_parser/json5_parser_reader_template.h index 557035b..d62867e 100644 --- a/json5_parser/json5_parser_reader_template.h +++ b/json5_parser/json5_parser_reader_template.h @@ -1,701 +1,701 @@ -#ifndef JSON_SPIRIT_READER_TEMPLATE -#define JSON_SPIRIT_READER_TEMPLATE - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include "json5_parser_value.h" -#include "json5_parser_error_position.h" - -#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread - -#include -#include -#include - -#if BOOST_VERSION >= 103800 - #include - #include - #include - #include - #include - #define spirit_namespace boost::spirit::classic -#else - #include - #include - #include - #include - #include - #define spirit_namespace boost::spirit -#endif - -namespace json5_parser -{ - const spirit_namespace::int_parser < boost::int64_t > int64_p = spirit_namespace::int_parser < boost::int64_t >(); - const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >(); - - template< class Iter_type > - bool is_eq( Iter_type first, Iter_type last, const char* c_str ) - { - for( Iter_type i = first; i != last; ++i, ++c_str ) - { - if( *c_str == 0 ) return false; - - if( *i != *c_str ) return false; - } - - return true; - } - - template< class Char_type > - Char_type hex_to_num( const Char_type c ) - { - if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0'; - if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10; - if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10; - return 0; - } - - template< class Char_type, class Iter_type > - Char_type hex_str_to_char( Iter_type& begin ) - { - const Char_type c1( *( ++begin ) ); - const Char_type c2( *( ++begin ) ); - - return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 ); - } - - template< class Char_type, class Iter_type > - Char_type unicode_str_to_char( Iter_type& begin ) - { - const Char_type c1( *( ++begin ) ); - const Char_type c2( *( ++begin ) ); - const Char_type c3( *( ++begin ) ); - const Char_type c4( *( ++begin ) ); - - return ( hex_to_num( c1 ) << 12 ) + - ( hex_to_num( c2 ) << 8 ) + - ( hex_to_num( c3 ) << 4 ) + - hex_to_num( c4 ); - } - - template< class String_type > - void append_esc_char_and_incr_iter( String_type& s, - typename String_type::const_iterator& begin, - typename String_type::const_iterator end ) - { - typedef typename String_type::value_type Char_type; - - const Char_type c2( *begin ); - - switch( c2 ) - { - case 't': s += '\t'; break; - case 'b': s += '\b'; break; - case 'f': s += '\f'; break; - case 'n': s += '\n'; break; - case 'r': s += '\r'; break; - case '\\': s += '\\'; break; - case '/': s += '/'; break; - case '"': s += '"'; break; - case 'x': - { - if( end - begin >= 3 ) // expecting "xHH..." - { - s += hex_str_to_char< Char_type >( begin ); - } - break; - } - case 'u': - { - if( end - begin >= 5 ) // expecting "uHHHH..." - { - s += unicode_str_to_char< Char_type >( begin ); - } - break; - } - case '\n': break; // skip escaped newlines - } - } - - template< class String_type > - String_type substitute_esc_chars( typename String_type::const_iterator begin, - typename String_type::const_iterator end ) - { - typedef typename String_type::const_iterator Iter_type; - - if( end - begin < 2 ) return String_type( begin, end ); - - String_type result; - - result.reserve( end - begin ); - - const Iter_type end_minus_1( end - 1 ); - - Iter_type substr_start = begin; - Iter_type i = begin; - - for( ; i < end_minus_1; ++i ) - { - if( *i == '\\' ) - { - result.append( substr_start, i ); - - ++i; // skip the '\' - - append_esc_char_and_incr_iter( result, i, end ); - - substr_start = i + 1; - } - } - - result.append( substr_start, end ); - - return result; - } - - template< class String_type > - String_type get_str_( typename String_type::const_iterator begin, - typename String_type::const_iterator end ) - { - assert( end - begin >= 2 ); - - typedef typename String_type::const_iterator Iter_type; - - Iter_type str_without_quotes( ++begin ); - Iter_type end_without_quotes( --end ); - - return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes ); - } - - inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end ) - { - return get_str_< std::string >( begin, end ); - } - - inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end ) - { - return get_str_< std::wstring >( begin, end ); - } - - template< class String_type, class Iter_type > - String_type get_str( Iter_type begin, Iter_type end ) - { - const String_type tmp( begin, end ); // convert multipass iterators to string iterators - - return get_str( tmp.begin(), tmp.end() ); - } - - // this class's methods get called by the spirit parse resulting - // in the creation of a JSON object or array - // - // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator - // - template< class Value_type, class Iter_type > - class Semantic_actions - { - public: - - typedef typename Value_type::Config_type Config_type; - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename String_type::value_type Char_type; - - Semantic_actions( Value_type& value ) - : value_( value ) - , current_p_( 0 ) - { - } - - void begin_obj( Char_type c ) - { - assert( c == '{' ); - - begin_compound< Object_type >(); - } - - void end_obj( Char_type c ) - { - assert( c == '}' ); - - end_compound(); - } - - void begin_array( Char_type c ) - { - assert( c == '[' ); - - begin_compound< Array_type >(); - } - - void end_array( Char_type c ) - { - assert( c == ']' ); - - end_compound(); - } - - void new_name( Iter_type begin, Iter_type end ) - { - assert( current_p_->type() == obj_type ); - - name_ = get_str< String_type >( begin, end ); - } - - void new_identifier( Iter_type begin, Iter_type end ) - { - assert( current_p_->type() == obj_type ); - - String_type result; - result.append(begin,end); - name_ = result; - } - - void new_str( Iter_type begin, Iter_type end ) - { - add_to_current( get_str< String_type >( begin, end ) ); - } - - void new_true( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "true" ) ); - - add_to_current( true ); - } - - void new_false( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "false" ) ); - - add_to_current( false ); - } - - void new_null( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "null" ) ); - - add_to_current( Value_type() ); - } - - void new_int( boost::int64_t i ) - { - add_to_current( i ); - } - - void new_uint64( boost::uint64_t ui ) - { - add_to_current( ui ); - } - - void new_real( double d ) - { - add_to_current( d ); - } - - void new_infinity( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "Infinity" ) ); - - add_to_current( std::numeric_limits::infinity() ); - } - - void new_minus_infinity( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "-Infinity" ) ); - - add_to_current( -std::numeric_limits::infinity() ); - } - - private: - - Semantic_actions& operator=( const Semantic_actions& ); - // to prevent "assignment operator could not be generated" warning - - Value_type* add_first( const Value_type& value ) - { - assert( current_p_ == 0 ); - - value_ = value; - current_p_ = &value_; - return current_p_; - } - - template< class Array_or_obj > - void begin_compound() - { - if( current_p_ == 0 ) - { - add_first( Array_or_obj() ); - } - else - { - stack_.push_back( current_p_ ); - - Array_or_obj new_array_or_obj; // avoid copy by building new array or object in place - - current_p_ = add_to_current( new_array_or_obj ); - } - } - - void end_compound() - { - if( current_p_ != &value_ ) - { - current_p_ = stack_.back(); - - stack_.pop_back(); - } - } - - Value_type* add_to_current( const Value_type& value ) - { - if( current_p_ == 0 ) - { - return add_first( value ); - } - else if( current_p_->type() == array_type ) - { - current_p_->get_array().push_back( value ); - - return ¤t_p_->get_array().back(); - } - - assert( current_p_->type() == obj_type ); - - return &Config_type::add( current_p_->get_obj(), name_, value ); - } - - Value_type& value_; // this is the object or array that is being created - Value_type* current_p_; // the child object or array that is currently being constructed - - std::vector< Value_type* > stack_; // previous child objects and arrays - - String_type name_; // of current name/value pair - }; - - template< typename Iter_type > - void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason ) - { - throw Error_position( i.get_position().line, i.get_position().column, reason ); - } - - template< typename Iter_type > - void throw_error( Iter_type , const std::string& reason ) - { - throw reason; - } - - // the spirit grammer - // - template< class Value_type, class Iter_type > - class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > > - { - public: - - typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t; - - Json_grammer( Semantic_actions_t& semantic_actions ) - : actions_( semantic_actions ) - { - } - - static void throw_not_value( Iter_type begin, Iter_type ) - { - throw_error( begin, "not a value" ); - } - - static void throw_not_hex( Iter_type begin, Iter_type ) - { - throw_error( begin, "not a hexadecimal number" ); - } - - static void throw_not_array( Iter_type begin, Iter_type ) - { - throw_error( begin, "not an array" ); - } - - static void throw_not_object( Iter_type begin, Iter_type ) - { - throw_error( begin, "not an object" ); - } - - static void throw_not_pair( Iter_type begin, Iter_type ) - { - throw_error( begin, "not a pair" ); - } - - static void throw_not_colon( Iter_type begin, Iter_type ) - { - throw_error( begin, "no colon in pair" ); - } - - static void throw_not_string( Iter_type begin, Iter_type ) - { - throw_error( begin, "not a string" ); - } - - template< typename ScannerT > - class definition - { - public: - - definition( const Json_grammer& self ) - { - using namespace spirit_namespace; - - typedef typename Value_type::String_type::value_type Char_type; - - // first we convert the semantic action class methods to functors with the - // parameter signature expected by spirit - - typedef boost::function< void( Char_type ) > Char_action; - typedef boost::function< void( Iter_type, Iter_type ) > Str_action; - typedef boost::function< void( double ) > Real_action; - typedef boost::function< void( boost::int64_t ) > Int_action; - typedef boost::function< void( boost::uint64_t ) > Uint64_action; - - Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) ); - Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) ); - Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) ); - Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) ); - Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) ); - Str_action new_identifier( boost::bind( &Semantic_actions_t::new_identifier, &self.actions_, _1, _2 ) ); - Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) ); - Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) ); - Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) ); - Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) ); - Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) ); - Str_action new_infinity ( boost::bind( &Semantic_actions_t::new_infinity, &self.actions_, _1, _2 ) ); - Str_action new_minus_infinity ( boost::bind( &Semantic_actions_t::new_minus_infinity, &self.actions_, _1, _2 ) ); - Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) ); - Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) ); - - // actual grammer - - json_ - = value_ | eps_p[ &throw_not_value ] - ; - - value_ - = single_quoted_string_[ new_str ] - | double_quoted_string_[ new_str ] - | number_ - | object_ - | array_ - | str_p( "true" ) [ new_true ] - | str_p( "false" )[ new_false ] - | str_p( "null" ) [ new_null ] - | (!ch_p('+') >> str_p( "Infinity" ) [ new_infinity ]) - | str_p( "-Infinity" ) [ new_minus_infinity ] - ; - - object_ - = ch_p('{')[ begin_obj ] - >> !members_ - >> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] ) - ; - - members_ - = pair_ >> *( ',' >> pair_ ) >> !ch_p(',') - ; - - pair_ - = (double_quoted_string_[ new_name ] | identifier_[ new_identifier ]) - >> ( ':' | eps_p[ &throw_not_colon ] ) - >> ( value_ | eps_p[ &throw_not_value ] ) - ; - - array_ - = ch_p('[')[ begin_array ] - >> !elements_ - >> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] ) - ; - - elements_ - = value_ >> *( ',' >> value_ ) >> !ch_p(',') - ; - - double_quoted_string_ - = lexeme_d // this causes white space and what would appear to be comments inside a string to be retained - [ - confix_p - ( - '"', - *lex_escape_ch_p, - '"' - ) - ] - ; - - single_quoted_string_ - = lexeme_d // this causes white space and what would appear to be comments inside a string to be retained - [ - confix_p - ( - '\'', - *lex_escape_ch_p, - '\'' - ) - ] - ; - - identifier_ - = (alpha_p | ch_p('_') | ch_p('$')) >> *(alnum_p | ch_p('_') | ch_p('$')); - - number_ - = ( str_p("0x") >> (hex_p[ new_int ] | eps_p[ &throw_not_hex ] ) ) - | strict_real_p[ new_real ] - | int64_p [ new_int ] - | uint64_p [ new_uint64 ] - ; - } - - spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, single_quoted_string_, double_quoted_string_, number_, identifier_; - - const spirit_namespace::rule< ScannerT >& start() const { return json_; } - }; - - private: - - Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning - - Semantic_actions_t& actions_; - }; - - template< class Iter_type, class Value_type > - void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) - { - typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t; - - const Posn_iter_t posn_begin( begin, end ); - const Posn_iter_t posn_end( end, end ); - - read_range_or_throw( posn_begin, posn_end, value ); - } - - template< class Istream_type > - struct Multi_pass_iters - { - typedef typename Istream_type::char_type Char_type; - typedef std::istream_iterator< Char_type, Char_type > istream_iter; - typedef spirit_namespace::multi_pass< istream_iter > Mp_iter; - - Multi_pass_iters( Istream_type& is ) - { - is.unsetf( std::ios::skipws ); - - begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) ); - end_ = spirit_namespace::make_multi_pass( istream_iter() ); - } - - Mp_iter begin_; - Mp_iter end_; - }; - - // reads a JSON Value from a pair of input iterators throwing an exception on invalid input, e.g. - // - // string::const_iterator start = str.begin(); - // const string::const_iterator next = read_range_or_throw( str.begin(), str.end(), value ); - // - // The iterator 'next' will point to the character past the - // last one read. - // - template< class Iter_type, class Value_type > - Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) - { - Semantic_actions< Value_type, Iter_type > semantic_actions( value ); - - const spirit_namespace::parse_info< Iter_type > info = - spirit_namespace::parse( begin, end, - Json_grammer< Value_type, Iter_type >( semantic_actions ), - spirit_namespace::space_p | - spirit_namespace::comment_p("//") | - spirit_namespace::comment_p("/*", "*/") ); - - if( !info.hit ) - { - assert( false ); // in theory exception should already have been thrown - throw_error( info.stop, "error" ); - } - - return info.stop; - } - - // reads a JSON Value from a pair of input iterators, e.g. - // - // string::const_iterator start = str.begin(); - // const bool success = read_string( start, str.end(), value ); - // - // The iterator 'start' will point to the character past the - // last one read. - // - template< class Iter_type, class Value_type > - bool read_range( Iter_type& begin, Iter_type end, Value_type& value ) - { - try - { - begin = read_range_or_throw( begin, end, value ); - - return true; - } - catch( ... ) - { - return false; - } - } - - // reads a JSON Value from a string, e.g. - // - // const bool success = read_string( str, value ); - // - template< class String_type, class Value_type > - bool read_string( const String_type& s, Value_type& value ) - { - typename String_type::const_iterator begin = s.begin(); - - return read_range( begin, s.end(), value ); - } - - // reads a JSON Value from a string throwing an exception on invalid input, e.g. - // - // read_string_or_throw( is, value ); - // - template< class String_type, class Value_type > - void read_string_or_throw( const String_type& s, Value_type& value ) - { - add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value ); - } - - // reads a JSON Value from a stream, e.g. - // - // const bool success = read_stream( is, value ); - // - template< class Istream_type, class Value_type > - bool read_stream( Istream_type& is, Value_type& value ) - { - Multi_pass_iters< Istream_type > mp_iters( is ); - - return read_range( mp_iters.begin_, mp_iters.end_, value ); - } - - // reads a JSON Value from a stream throwing an exception on invalid input, e.g. - // - // read_stream_or_throw( is, value ); - // - template< class Istream_type, class Value_type > - void read_stream_or_throw( Istream_type& is, Value_type& value ) - { - const Multi_pass_iters< Istream_type > mp_iters( is ); - - add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value ); - } -} - -#endif +#ifndef JSON_SPIRIT_READER_TEMPLATE +#define JSON_SPIRIT_READER_TEMPLATE + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include "json5_parser_value.h" +#include "json5_parser_error_position.h" + +#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread + +#include +#include +#include + +#if BOOST_VERSION >= 103800 + #include + #include + #include + #include + #include + #define spirit_namespace boost::spirit::classic +#else + #include + #include + #include + #include + #include + #define spirit_namespace boost::spirit +#endif + +namespace json5_parser +{ + const spirit_namespace::int_parser < boost::int64_t > int64_p = spirit_namespace::int_parser < boost::int64_t >(); + const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >(); + + template< class Iter_type > + bool is_eq( Iter_type first, Iter_type last, const char* c_str ) + { + for( Iter_type i = first; i != last; ++i, ++c_str ) + { + if( *c_str == 0 ) return false; + + if( *i != *c_str ) return false; + } + + return true; + } + + template< class Char_type > + Char_type hex_to_num( const Char_type c ) + { + if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0'; + if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10; + if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10; + return 0; + } + + template< class Char_type, class Iter_type > + Char_type hex_str_to_char( Iter_type& begin ) + { + const Char_type c1( *( ++begin ) ); + const Char_type c2( *( ++begin ) ); + + return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 ); + } + + template< class Char_type, class Iter_type > + Char_type unicode_str_to_char( Iter_type& begin ) + { + const Char_type c1( *( ++begin ) ); + const Char_type c2( *( ++begin ) ); + const Char_type c3( *( ++begin ) ); + const Char_type c4( *( ++begin ) ); + + return ( hex_to_num( c1 ) << 12 ) + + ( hex_to_num( c2 ) << 8 ) + + ( hex_to_num( c3 ) << 4 ) + + hex_to_num( c4 ); + } + + template< class String_type > + void append_esc_char_and_incr_iter( String_type& s, + typename String_type::const_iterator& begin, + typename String_type::const_iterator end ) + { + typedef typename String_type::value_type Char_type; + + const Char_type c2( *begin ); + + switch( c2 ) + { + case 't': s += '\t'; break; + case 'b': s += '\b'; break; + case 'f': s += '\f'; break; + case 'n': s += '\n'; break; + case 'r': s += '\r'; break; + case '\\': s += '\\'; break; + case '/': s += '/'; break; + case '"': s += '"'; break; + case 'x': + { + if( end - begin >= 3 ) // expecting "xHH..." + { + s += hex_str_to_char< Char_type >( begin ); + } + break; + } + case 'u': + { + if( end - begin >= 5 ) // expecting "uHHHH..." + { + s += unicode_str_to_char< Char_type >( begin ); + } + break; + } + case '\n': break; // skip escaped newlines + } + } + + template< class String_type > + String_type substitute_esc_chars( typename String_type::const_iterator begin, + typename String_type::const_iterator end ) + { + typedef typename String_type::const_iterator Iter_type; + + if( end - begin < 2 ) return String_type( begin, end ); + + String_type result; + + result.reserve( end - begin ); + + const Iter_type end_minus_1( end - 1 ); + + Iter_type substr_start = begin; + Iter_type i = begin; + + for( ; i < end_minus_1; ++i ) + { + if( *i == '\\' ) + { + result.append( substr_start, i ); + + ++i; // skip the '\' + + append_esc_char_and_incr_iter( result, i, end ); + + substr_start = i + 1; + } + } + + result.append( substr_start, end ); + + return result; + } + + template< class String_type > + String_type get_str_( typename String_type::const_iterator begin, + typename String_type::const_iterator end ) + { + assert( end - begin >= 2 ); + + typedef typename String_type::const_iterator Iter_type; + + Iter_type str_without_quotes( ++begin ); + Iter_type end_without_quotes( --end ); + + return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes ); + } + + inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end ) + { + return get_str_< std::string >( begin, end ); + } + + inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end ) + { + return get_str_< std::wstring >( begin, end ); + } + + template< class String_type, class Iter_type > + String_type get_str( Iter_type begin, Iter_type end ) + { + const String_type tmp( begin, end ); // convert multipass iterators to string iterators + + return get_str( tmp.begin(), tmp.end() ); + } + + // this class's methods get called by the spirit parse resulting + // in the creation of a JSON object or array + // + // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator + // + template< class Value_type, class Iter_type > + class Semantic_actions + { + public: + + typedef typename Value_type::Config_type Config_type; + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename String_type::value_type Char_type; + + Semantic_actions( Value_type& value ) + : value_( value ) + , current_p_( 0 ) + { + } + + void begin_obj( Char_type c ) + { + assert( c == '{' ); + + begin_compound< Object_type >(); + } + + void end_obj( Char_type c ) + { + assert( c == '}' ); + + end_compound(); + } + + void begin_array( Char_type c ) + { + assert( c == '[' ); + + begin_compound< Array_type >(); + } + + void end_array( Char_type c ) + { + assert( c == ']' ); + + end_compound(); + } + + void new_name( Iter_type begin, Iter_type end ) + { + assert( current_p_->type() == obj_type ); + + name_ = get_str< String_type >( begin, end ); + } + + void new_identifier( Iter_type begin, Iter_type end ) + { + assert( current_p_->type() == obj_type ); + + String_type result; + result.append(begin,end); + name_ = result; + } + + void new_str( Iter_type begin, Iter_type end ) + { + add_to_current( get_str< String_type >( begin, end ) ); + } + + void new_true( Iter_type begin, Iter_type end ) + { + assert( is_eq( begin, end, "true" ) ); + + add_to_current( true ); + } + + void new_false( Iter_type begin, Iter_type end ) + { + assert( is_eq( begin, end, "false" ) ); + + add_to_current( false ); + } + + void new_null( Iter_type begin, Iter_type end ) + { + assert( is_eq( begin, end, "null" ) ); + + add_to_current( Value_type() ); + } + + void new_int( boost::int64_t i ) + { + add_to_current( i ); + } + + void new_uint64( boost::uint64_t ui ) + { + add_to_current( ui ); + } + + void new_real( double d ) + { + add_to_current( d ); + } + + void new_infinity( Iter_type begin, Iter_type end ) + { + assert( is_eq( begin, end, "Infinity" ) ); + + add_to_current( std::numeric_limits::infinity() ); + } + + void new_minus_infinity( Iter_type begin, Iter_type end ) + { + assert( is_eq( begin, end, "-Infinity" ) ); + + add_to_current( -std::numeric_limits::infinity() ); + } + + private: + + Semantic_actions& operator=( const Semantic_actions& ); + // to prevent "assignment operator could not be generated" warning + + Value_type* add_first( const Value_type& value ) + { + assert( current_p_ == 0 ); + + value_ = value; + current_p_ = &value_; + return current_p_; + } + + template< class Array_or_obj > + void begin_compound() + { + if( current_p_ == 0 ) + { + add_first( Array_or_obj() ); + } + else + { + stack_.push_back( current_p_ ); + + Array_or_obj new_array_or_obj; // avoid copy by building new array or object in place + + current_p_ = add_to_current( new_array_or_obj ); + } + } + + void end_compound() + { + if( current_p_ != &value_ ) + { + current_p_ = stack_.back(); + + stack_.pop_back(); + } + } + + Value_type* add_to_current( const Value_type& value ) + { + if( current_p_ == 0 ) + { + return add_first( value ); + } + else if( current_p_->type() == array_type ) + { + current_p_->get_array().push_back( value ); + + return ¤t_p_->get_array().back(); + } + + assert( current_p_->type() == obj_type ); + + return &Config_type::add( current_p_->get_obj(), name_, value ); + } + + Value_type& value_; // this is the object or array that is being created + Value_type* current_p_; // the child object or array that is currently being constructed + + std::vector< Value_type* > stack_; // previous child objects and arrays + + String_type name_; // of current name/value pair + }; + + template< typename Iter_type > + void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason ) + { + throw Error_position( i.get_position().line, i.get_position().column, reason ); + } + + template< typename Iter_type > + void throw_error( Iter_type , const std::string& reason ) + { + throw reason; + } + + // the spirit grammer + // + template< class Value_type, class Iter_type > + class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > > + { + public: + + typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t; + + Json_grammer( Semantic_actions_t& semantic_actions ) + : actions_( semantic_actions ) + { + } + + static void throw_not_value( Iter_type begin, Iter_type ) + { + throw_error( begin, "not a value" ); + } + + static void throw_not_hex( Iter_type begin, Iter_type ) + { + throw_error( begin, "not a hexadecimal number" ); + } + + static void throw_not_array( Iter_type begin, Iter_type ) + { + throw_error( begin, "not an array" ); + } + + static void throw_not_object( Iter_type begin, Iter_type ) + { + throw_error( begin, "not an object" ); + } + + static void throw_not_pair( Iter_type begin, Iter_type ) + { + throw_error( begin, "not a pair" ); + } + + static void throw_not_colon( Iter_type begin, Iter_type ) + { + throw_error( begin, "no colon in pair" ); + } + + static void throw_not_string( Iter_type begin, Iter_type ) + { + throw_error( begin, "not a string" ); + } + + template< typename ScannerT > + class definition + { + public: + + definition( const Json_grammer& self ) + { + using namespace spirit_namespace; + + typedef typename Value_type::String_type::value_type Char_type; + + // first we convert the semantic action class methods to functors with the + // parameter signature expected by spirit + + typedef boost::function< void( Char_type ) > Char_action; + typedef boost::function< void( Iter_type, Iter_type ) > Str_action; + typedef boost::function< void( double ) > Real_action; + typedef boost::function< void( boost::int64_t ) > Int_action; + typedef boost::function< void( boost::uint64_t ) > Uint64_action; + + Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) ); + Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) ); + Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) ); + Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) ); + Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) ); + Str_action new_identifier( boost::bind( &Semantic_actions_t::new_identifier, &self.actions_, _1, _2 ) ); + Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) ); + Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) ); + Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) ); + Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) ); + Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) ); + Str_action new_infinity ( boost::bind( &Semantic_actions_t::new_infinity, &self.actions_, _1, _2 ) ); + Str_action new_minus_infinity ( boost::bind( &Semantic_actions_t::new_minus_infinity, &self.actions_, _1, _2 ) ); + Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) ); + Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) ); + + // actual grammer + + json_ + = value_ | eps_p[ &throw_not_value ] + ; + + value_ + = single_quoted_string_[ new_str ] + | double_quoted_string_[ new_str ] + | number_ + | object_ + | array_ + | str_p( "true" ) [ new_true ] + | str_p( "false" )[ new_false ] + | str_p( "null" ) [ new_null ] + | (!ch_p('+') >> str_p( "Infinity" ) [ new_infinity ]) + | str_p( "-Infinity" ) [ new_minus_infinity ] + ; + + object_ + = ch_p('{')[ begin_obj ] + >> !members_ + >> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] ) + ; + + members_ + = pair_ >> *( ',' >> pair_ ) >> !ch_p(',') + ; + + pair_ + = (double_quoted_string_[ new_name ] | identifier_[ new_identifier ]) + >> ( ':' | eps_p[ &throw_not_colon ] ) + >> ( value_ | eps_p[ &throw_not_value ] ) + ; + + array_ + = ch_p('[')[ begin_array ] + >> !elements_ + >> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] ) + ; + + elements_ + = value_ >> *( ',' >> value_ ) >> !ch_p(',') + ; + + double_quoted_string_ + = lexeme_d // this causes white space and what would appear to be comments inside a string to be retained + [ + confix_p + ( + '"', + *lex_escape_ch_p, + '"' + ) + ] + ; + + single_quoted_string_ + = lexeme_d // this causes white space and what would appear to be comments inside a string to be retained + [ + confix_p + ( + '\'', + *lex_escape_ch_p, + '\'' + ) + ] + ; + + identifier_ + = (alpha_p | ch_p('_') | ch_p('$')) >> *(alnum_p | ch_p('_') | ch_p('$')); + + number_ + = ( str_p("0x") >> (hex_p[ new_int ] | eps_p[ &throw_not_hex ] ) ) + | strict_real_p[ new_real ] + | int64_p [ new_int ] + | uint64_p [ new_uint64 ] + ; + } + + spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, single_quoted_string_, double_quoted_string_, number_, identifier_; + + const spirit_namespace::rule< ScannerT >& start() const { return json_; } + }; + + private: + + Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning + + Semantic_actions_t& actions_; + }; + + template< class Iter_type, class Value_type > + void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) + { + typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t; + + const Posn_iter_t posn_begin( begin, end ); + const Posn_iter_t posn_end( end, end ); + + read_range_or_throw( posn_begin, posn_end, value ); + } + + template< class Istream_type > + struct Multi_pass_iters + { + typedef typename Istream_type::char_type Char_type; + typedef std::istream_iterator< Char_type, Char_type > istream_iter; + typedef spirit_namespace::multi_pass< istream_iter > Mp_iter; + + Multi_pass_iters( Istream_type& is ) + { + is.unsetf( std::ios::skipws ); + + begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) ); + end_ = spirit_namespace::make_multi_pass( istream_iter() ); + } + + Mp_iter begin_; + Mp_iter end_; + }; + + // reads a JSON Value from a pair of input iterators throwing an exception on invalid input, e.g. + // + // string::const_iterator start = str.begin(); + // const string::const_iterator next = read_range_or_throw( str.begin(), str.end(), value ); + // + // The iterator 'next' will point to the character past the + // last one read. + // + template< class Iter_type, class Value_type > + Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) + { + Semantic_actions< Value_type, Iter_type > semantic_actions( value ); + + const spirit_namespace::parse_info< Iter_type > info = + spirit_namespace::parse( begin, end, + Json_grammer< Value_type, Iter_type >( semantic_actions ), + spirit_namespace::space_p | + spirit_namespace::comment_p("//") | + spirit_namespace::comment_p("/*", "*/") ); + + if( !info.hit ) + { + assert( false ); // in theory exception should already have been thrown + throw_error( info.stop, "error" ); + } + + return info.stop; + } + + // reads a JSON Value from a pair of input iterators, e.g. + // + // string::const_iterator start = str.begin(); + // const bool success = read_string( start, str.end(), value ); + // + // The iterator 'start' will point to the character past the + // last one read. + // + template< class Iter_type, class Value_type > + bool read_range( Iter_type& begin, Iter_type end, Value_type& value ) + { + try + { + begin = read_range_or_throw( begin, end, value ); + + return true; + } + catch( ... ) + { + return false; + } + } + + // reads a JSON Value from a string, e.g. + // + // const bool success = read_string( str, value ); + // + template< class String_type, class Value_type > + bool read_string( const String_type& s, Value_type& value ) + { + typename String_type::const_iterator begin = s.begin(); + + return read_range( begin, s.end(), value ); + } + + // reads a JSON Value from a string throwing an exception on invalid input, e.g. + // + // read_string_or_throw( is, value ); + // + template< class String_type, class Value_type > + void read_string_or_throw( const String_type& s, Value_type& value ) + { + add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value ); + } + + // reads a JSON Value from a stream, e.g. + // + // const bool success = read_stream( is, value ); + // + template< class Istream_type, class Value_type > + bool read_stream( Istream_type& is, Value_type& value ) + { + Multi_pass_iters< Istream_type > mp_iters( is ); + + return read_range( mp_iters.begin_, mp_iters.end_, value ); + } + + // reads a JSON Value from a stream throwing an exception on invalid input, e.g. + // + // read_stream_or_throw( is, value ); + // + template< class Istream_type, class Value_type > + void read_stream_or_throw( Istream_type& is, Value_type& value ) + { + const Multi_pass_iters< Istream_type > mp_iters( is ); + + add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value ); + } +} + +#endif diff --git a/json5_parser/json5_parser_stream_reader.h b/json5_parser/json5_parser_stream_reader.h index 39e71ec..1e08e5c 100644 --- a/json5_parser/json5_parser_stream_reader.h +++ b/json5_parser/json5_parser_stream_reader.h @@ -1,70 +1,70 @@ -#ifndef JSON_SPIRIT_READ_STREAM -#define JSON_SPIRIT_READ_STREAM - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include "json5_parser_reader_template.h" - -namespace json5_parser -{ - // these classes allows you to read multiple top level contiguous values from a stream, - // the normal stream read functions have a bug that prevent multiple top level values - // from being read unless they are separated by spaces - - template< class Istream_type, class Value_type > - class Stream_reader - { - public: - - Stream_reader( Istream_type& is ) - : iters_( is ) - { - } - - bool read_next( Value_type& value ) - { - return read_range( iters_.begin_, iters_.end_, value ); - } - - private: - - typedef Multi_pass_iters< Istream_type > Mp_iters; - - Mp_iters iters_; - }; - - template< class Istream_type, class Value_type > - class Stream_reader_thrower - { - public: - - Stream_reader_thrower( Istream_type& is ) - : iters_( is ) - , posn_begin_( iters_.begin_, iters_.end_ ) - , posn_end_( iters_.end_, iters_.end_ ) - { - } - - void read_next( Value_type& value ) - { - posn_begin_ = read_range_or_throw( posn_begin_, posn_end_, value ); - } - - private: - - typedef Multi_pass_iters< Istream_type > Mp_iters; - typedef spirit_namespace::position_iterator< typename Mp_iters::Mp_iter > Posn_iter_t; - - Mp_iters iters_; - Posn_iter_t posn_begin_, posn_end_; - }; -} - -#endif +#ifndef JSON_SPIRIT_READ_STREAM +#define JSON_SPIRIT_READ_STREAM + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include "json5_parser_reader_template.h" + +namespace json5_parser +{ + // these classes allows you to read multiple top level contiguous values from a stream, + // the normal stream read functions have a bug that prevent multiple top level values + // from being read unless they are separated by spaces + + template< class Istream_type, class Value_type > + class Stream_reader + { + public: + + Stream_reader( Istream_type& is ) + : iters_( is ) + { + } + + bool read_next( Value_type& value ) + { + return read_range( iters_.begin_, iters_.end_, value ); + } + + private: + + typedef Multi_pass_iters< Istream_type > Mp_iters; + + Mp_iters iters_; + }; + + template< class Istream_type, class Value_type > + class Stream_reader_thrower + { + public: + + Stream_reader_thrower( Istream_type& is ) + : iters_( is ) + , posn_begin_( iters_.begin_, iters_.end_ ) + , posn_end_( iters_.end_, iters_.end_ ) + { + } + + void read_next( Value_type& value ) + { + posn_begin_ = read_range_or_throw( posn_begin_, posn_end_, value ); + } + + private: + + typedef Multi_pass_iters< Istream_type > Mp_iters; + typedef spirit_namespace::position_iterator< typename Mp_iters::Mp_iter > Posn_iter_t; + + Mp_iters iters_; + Posn_iter_t posn_begin_, posn_end_; + }; +} + +#endif diff --git a/json5_parser/json5_parser_utils.h b/json5_parser/json5_parser_utils.h index f9b814a..0f57c7c 100644 --- a/json5_parser/json5_parser_utils.h +++ b/json5_parser/json5_parser_utils.h @@ -1,63 +1,63 @@ -#ifndef JSON_SPIRIT_UTILS -#define JSON_SPIRIT_UTILS - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include "json5_parser_value.h" -#include - -namespace json5_parser -{ - template< class Obj_t, class Map_t > - void obj_to_map( const Obj_t& obj, Map_t& mp_obj ) - { - mp_obj.clear(); - - for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i ) - { - mp_obj[ i->name_ ] = i->value_; - } - } - - template< class Obj_t, class Map_t > - void map_to_obj( const Map_t& mp_obj, Obj_t& obj ) - { - obj.clear(); - - for( typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i ) - { - obj.push_back( typename Obj_t::value_type( i->first, i->second ) ); - } - } - -#ifdef JSON_SPIRIT_VALUE_ENABLED - typedef std::map< std::string, Value > Mapped_obj; -#endif - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - typedef std::map< std::wstring, wValue > wMapped_obj; -#endif - - template< class Object_type, class String_type > - const typename Object_type::value_type::Value_type& find_value( const Object_type& obj, const String_type& name ) - { - for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i ) - { - if( i->name_ == name ) - { - return i->value_; - } - } - - return Object_type::value_type::Value_type::null; - } -} - -#endif +#ifndef JSON_SPIRIT_UTILS +#define JSON_SPIRIT_UTILS + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include "json5_parser_value.h" +#include + +namespace json5_parser +{ + template< class Obj_t, class Map_t > + void obj_to_map( const Obj_t& obj, Map_t& mp_obj ) + { + mp_obj.clear(); + + for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i ) + { + mp_obj[ i->name_ ] = i->value_; + } + } + + template< class Obj_t, class Map_t > + void map_to_obj( const Map_t& mp_obj, Obj_t& obj ) + { + obj.clear(); + + for( typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i ) + { + obj.push_back( typename Obj_t::value_type( i->first, i->second ) ); + } + } + +#ifdef JSON_SPIRIT_VALUE_ENABLED + typedef std::map< std::string, Value > Mapped_obj; +#endif + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + typedef std::map< std::wstring, wValue > wMapped_obj; +#endif + + template< class Object_type, class String_type > + const typename Object_type::value_type::Value_type& find_value( const Object_type& obj, const String_type& name ) + { + for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i ) + { + if( i->name_ == name ) + { + return i->value_; + } + } + + return Object_type::value_type::Value_type::null; + } +} + +#endif diff --git a/json5_parser/json5_parser_value.cpp b/json5_parser/json5_parser_value.cpp index e36fb60..be67e15 100644 --- a/json5_parser/json5_parser_value.cpp +++ b/json5_parser/json5_parser_value.cpp @@ -1,6 +1,6 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_value.h" +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_value.h" diff --git a/json5_parser/json5_parser_value.h b/json5_parser/json5_parser_value.h index 0d0a83f..06b11e6 100644 --- a/json5_parser/json5_parser_value.h +++ b/json5_parser/json5_parser_value.h @@ -1,605 +1,605 @@ -#ifndef JSON_SPIRIT_VALUE -#define JSON_SPIRIT_VALUE - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// comment out the value types you don't need to reduce build times and intermediate file sizes -#define JSON_SPIRIT_VALUE_ENABLED -#define JSON_SPIRIT_WVALUE_ENABLED -#define JSON_SPIRIT_MVALUE_ENABLED -#define JSON_SPIRIT_WMVALUE_ENABLED - -namespace json5_parser -{ - enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type }; - - static inline std::string value_type_to_string( Value_type vtype ); - - struct Null{}; - - template< class Config > // Config determines whether the value uses std::string or std::wstring and - // whether JSON Objects are represented as vectors or maps - class Value_impl - { - public: - - typedef Config Config_type; - typedef typename Config::String_type String_type; - typedef typename Config::Object_type Object; - typedef typename Config::Array_type Array; - typedef typename String_type::const_pointer Const_str_ptr; // eg const char* - - Value_impl(); // creates null value - Value_impl( Const_str_ptr value ); - Value_impl( const String_type& value ); - Value_impl( const Object& value ); - Value_impl( const Array& value ); - Value_impl( bool value ); - Value_impl( int value ); - Value_impl( boost::int64_t value ); - Value_impl( boost::uint64_t value ); - Value_impl( double value ); - - template< class Iter > - Value_impl( Iter first, Iter last ); // constructor from containers, e.g. std::vector or std::list - - template< BOOST_VARIANT_ENUM_PARAMS( typename T ) > - Value_impl( const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& variant ); // constructor for compatible variant types - - Value_impl( const Value_impl& other ); - - bool operator==( const Value_impl& lhs ) const; - - Value_impl& operator=( const Value_impl& lhs ); - - Value_type type() const; - - bool is_uint64() const; - bool is_null() const; - - const String_type& get_str() const; - const Object& get_obj() const; - const Array& get_array() const; - bool get_bool() const; - int get_int() const; - boost::int64_t get_int64() const; - boost::uint64_t get_uint64() const; - double get_real() const; - - Object& get_obj(); - Array& get_array(); - - template< typename T > T get_value() const; // example usage: int i = value.get_value< int >(); - // or double d = value.get_value< double >(); - - static const Value_impl null; - - private: - - void check_type( const Value_type vtype ) const; - - typedef boost::variant< boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, - String_type, bool, boost::int64_t, double, Null, boost::uint64_t > Variant; - - Variant v_; - - class Variant_converter_visitor : public boost::static_visitor< Variant > - { - public: - - template< typename T, typename A, template< typename, typename > class Cont > - Variant operator()( const Cont< T, A >& cont ) const - { - return Array( cont.begin(), cont.end() ); - } - - Variant operator()( int i ) const - { - return static_cast< boost::int64_t >( i ); - } - - template - Variant operator()( const T& t ) const - { - return t; - } - }; - }; - - // vector objects - - template< class Config > - struct Pair_impl - { - typedef typename Config::String_type String_type; - typedef typename Config::Value_type Value_type; - - Pair_impl() - { - } - - Pair_impl( const String_type& name, const Value_type& value ); - - bool operator==( const Pair_impl& lhs ) const; - - String_type name_; - Value_type value_; - }; - -#if defined( JSON_SPIRIT_VALUE_ENABLED ) || defined( JSON_SPIRIT_WVALUE_ENABLED ) - template< class String > - struct Config_vector - { - typedef String String_type; - typedef Value_impl< Config_vector > Value_type; - typedef Pair_impl < Config_vector > Pair_type; - typedef std::vector< Value_type > Array_type; - typedef std::vector< Pair_type > Object_type; - - static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value ) - { - obj.push_back( Pair_type( name , value ) ); - - return obj.back().value_; - } - - static const String_type& get_name( const Pair_type& pair ) - { - return pair.name_; - } - - static const Value_type& get_value( const Pair_type& pair ) - { - return pair.value_; - } - }; -#endif - - // typedefs for ASCII - -#ifdef JSON_SPIRIT_VALUE_ENABLED - typedef Config_vector< std::string > Config; - - typedef Config::Value_type Value; - typedef Config::Pair_type Pair; - typedef Config::Object_type Object; - typedef Config::Array_type Array; -#endif - - // typedefs for Unicode - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - typedef Config_vector< std::wstring > wConfig; - - typedef wConfig::Value_type wValue; - typedef wConfig::Pair_type wPair; - typedef wConfig::Object_type wObject; - typedef wConfig::Array_type wArray; -#endif - - // map objects - -#if defined( JSON_SPIRIT_MVALUE_ENABLED ) || defined( JSON_SPIRIT_WMVALUE_ENABLED ) - template< class String > - struct Config_map - { - typedef String String_type; - typedef Value_impl< Config_map > Value_type; - typedef std::vector< Value_type > Array_type; - typedef std::map< String_type, Value_type > Object_type; - typedef std::pair< const String_type, Value_type > Pair_type; - - static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value ) - { - return obj[ name ] = value; - } - - static const String_type& get_name( const Pair_type& pair ) - { - return pair.first; - } - - static const Value_type& get_value( const Pair_type& pair ) - { - return pair.second; - } - }; -#endif - - // typedefs for ASCII - -#ifdef JSON_SPIRIT_MVALUE_ENABLED - typedef Config_map< std::string > mConfig; - - typedef mConfig::Value_type mValue; - typedef mConfig::Object_type mObject; - typedef mConfig::Array_type mArray; -#endif - - // typedefs for Unicode - -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - typedef Config_map< std::wstring > wmConfig; - - typedef wmConfig::Value_type wmValue; - typedef wmConfig::Object_type wmObject; - typedef wmConfig::Array_type wmArray; -#endif - - /////////////////////////////////////////////////////////////////////////////////////////////// - // - // implementation - - inline bool operator==( const Null&, const Null& ) - { - return true; - } - - template< class Config > - const Value_impl< Config > Value_impl< Config >::null; - - template< class Config > - Value_impl< Config >::Value_impl() - : v_( Null() ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( const Const_str_ptr value ) - : v_( String_type( value ) ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( const String_type& value ) - : v_( value ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( const Object& value ) - : v_( value ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( const Array& value ) - : v_( value ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( bool value ) - : v_( value ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( int value ) - : v_( static_cast< boost::int64_t >( value ) ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( boost::int64_t value ) - : v_( value ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( boost::uint64_t value ) - : v_( value ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( double value ) - : v_( value ) - { - } - - template< class Config > - Value_impl< Config >::Value_impl( const Value_impl< Config >& other ) - : v_( other.v_ ) - { - } - - template< class Config > - template< class Iter > - Value_impl< Config >::Value_impl( Iter first, Iter last ) - : v_( Array( first, last ) ) - { - } - - template< class Config > - template< BOOST_VARIANT_ENUM_PARAMS( typename T ) > - Value_impl< Config >::Value_impl( const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& variant ) - : v_( boost::apply_visitor( Variant_converter_visitor(), variant) ) - { - } - - template< class Config > - Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs ) - { - Value_impl tmp( lhs ); - - std::swap( v_, tmp.v_ ); - - return *this; - } - - template< class Config > - bool Value_impl< Config >::operator==( const Value_impl& lhs ) const - { - if( this == &lhs ) return true; - - if( type() != lhs.type() ) return false; - - return v_ == lhs.v_; - } - - template< class Config > - Value_type Value_impl< Config >::type() const - { - if( is_uint64() ) - { - return int_type; - } - - return static_cast< Value_type >( v_.which() ); - } - - template< class Config > - bool Value_impl< Config >::is_uint64() const - { - return v_.which() == null_type + 1; - } - - template< class Config > - bool Value_impl< Config >::is_null() const - { - return type() == null_type; - } - - template< class Config > - void Value_impl< Config >::check_type( const Value_type vtype ) const - { - if( type() != vtype ) - { - std::ostringstream os; - - os << "get_value< " << value_type_to_string( vtype ) << " > called on " << value_type_to_string( type() ) << " Value"; - - throw std::runtime_error( os.str() ); - } - } - - template< class Config > - const typename Config::String_type& Value_impl< Config >::get_str() const - { - check_type( str_type ); - - return *boost::get< String_type >( &v_ ); - } - - template< class Config > - const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const - { - check_type( obj_type ); - - return *boost::get< Object >( &v_ ); - } - - template< class Config > - const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const - { - check_type( array_type ); - - return *boost::get< Array >( &v_ ); - } - - template< class Config > - bool Value_impl< Config >::get_bool() const - { - check_type( bool_type ); - - return boost::get< bool >( v_ ); - } - - template< class Config > - int Value_impl< Config >::get_int() const - { - check_type( int_type ); - - return static_cast< int >( get_int64() ); - } - - template< class Config > - boost::int64_t Value_impl< Config >::get_int64() const - { - check_type( int_type ); - - if( is_uint64() ) - { - return static_cast< boost::int64_t >( get_uint64() ); - } - - return boost::get< boost::int64_t >( v_ ); - } - - template< class Config > - boost::uint64_t Value_impl< Config >::get_uint64() const - { - check_type( int_type ); - - if( !is_uint64() ) - { - return static_cast< boost::uint64_t >( get_int64() ); - } - - return boost::get< boost::uint64_t >( v_ ); - } - - template< class Config > - double Value_impl< Config >::get_real() const - { - if( type() == int_type ) - { - return is_uint64() ? static_cast< double >( get_uint64() ) - : static_cast< double >( get_int64() ); - } - - check_type( real_type ); - - return boost::get< double >( v_ ); - } - - template< class Config > - typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() - { - check_type( obj_type ); - - return *boost::get< Object >( &v_ ); - } - - template< class Config > - typename Value_impl< Config >::Array& Value_impl< Config >::get_array() - { - check_type( array_type ); - - return *boost::get< Array >( &v_ ); - } - - template< class Config > - Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value ) - : name_( name ) - , value_( value ) - { - } - - template< class Config > - bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const - { - if( this == &lhs ) return true; - - return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ ); - } - - // converts a C string, ie. 8 bit char array, to a string object - // - template < class String_type > - String_type to_str( const char* c_str ) - { - String_type result; - - for( const char* p = c_str; *p != 0; ++p ) - { - result += *p; - } - - return result; - } - - // - - namespace internal_ - { - template< typename T > - struct Type_to_type - { - }; - - template< class Value > - int get_value( const Value& value, Type_to_type< int > ) - { - return value.get_int(); - } - - template< class Value > - boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > ) - { - return value.get_int64(); - } - - template< class Value > - boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > ) - { - return value.get_uint64(); - } - - template< class Value > - double get_value( const Value& value, Type_to_type< double > ) - { - return value.get_real(); - } - - template< class Value > - typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > ) - { - return value.get_str(); - } - - template< class Value > - typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > ) - { - return value.get_array(); - } - - template< class Value > - typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > ) - { - return value.get_obj(); - } - - template< class Value > - bool get_value( const Value& value, Type_to_type< bool > ) - { - return value.get_bool(); - } - } - - template< class Config > - template< typename T > - T Value_impl< Config >::get_value() const - { - return internal_::get_value( *this, internal_::Type_to_type< T >() ); - } - - static std::string value_type_to_string( const Value_type vtype ) - { - switch( vtype ) - { - case obj_type: return "Object"; - case array_type: return "Array"; - case str_type: return "string"; - case bool_type: return "boolean"; - case int_type: return "integer"; - case real_type: return "real"; - case null_type: return "null"; - } - - assert( false ); - - return "unknown type"; - } -} - -#endif +#ifndef JSON_SPIRIT_VALUE +#define JSON_SPIRIT_VALUE + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// comment out the value types you don't need to reduce build times and intermediate file sizes +#define JSON_SPIRIT_VALUE_ENABLED +#define JSON_SPIRIT_WVALUE_ENABLED +#define JSON_SPIRIT_MVALUE_ENABLED +#define JSON_SPIRIT_WMVALUE_ENABLED + +namespace json5_parser +{ + enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type }; + + static inline std::string value_type_to_string( Value_type vtype ); + + struct Null{}; + + template< class Config > // Config determines whether the value uses std::string or std::wstring and + // whether JSON Objects are represented as vectors or maps + class Value_impl + { + public: + + typedef Config Config_type; + typedef typename Config::String_type String_type; + typedef typename Config::Object_type Object; + typedef typename Config::Array_type Array; + typedef typename String_type::const_pointer Const_str_ptr; // eg const char* + + Value_impl(); // creates null value + Value_impl( Const_str_ptr value ); + Value_impl( const String_type& value ); + Value_impl( const Object& value ); + Value_impl( const Array& value ); + Value_impl( bool value ); + Value_impl( int value ); + Value_impl( boost::int64_t value ); + Value_impl( boost::uint64_t value ); + Value_impl( double value ); + + template< class Iter > + Value_impl( Iter first, Iter last ); // constructor from containers, e.g. std::vector or std::list + + template< BOOST_VARIANT_ENUM_PARAMS( typename T ) > + Value_impl( const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& variant ); // constructor for compatible variant types + + Value_impl( const Value_impl& other ); + + bool operator==( const Value_impl& lhs ) const; + + Value_impl& operator=( const Value_impl& lhs ); + + Value_type type() const; + + bool is_uint64() const; + bool is_null() const; + + const String_type& get_str() const; + const Object& get_obj() const; + const Array& get_array() const; + bool get_bool() const; + int get_int() const; + boost::int64_t get_int64() const; + boost::uint64_t get_uint64() const; + double get_real() const; + + Object& get_obj(); + Array& get_array(); + + template< typename T > T get_value() const; // example usage: int i = value.get_value< int >(); + // or double d = value.get_value< double >(); + + static const Value_impl null; + + private: + + void check_type( const Value_type vtype ) const; + + typedef boost::variant< boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, + String_type, bool, boost::int64_t, double, Null, boost::uint64_t > Variant; + + Variant v_; + + class Variant_converter_visitor : public boost::static_visitor< Variant > + { + public: + + template< typename T, typename A, template< typename, typename > class Cont > + Variant operator()( const Cont< T, A >& cont ) const + { + return Array( cont.begin(), cont.end() ); + } + + Variant operator()( int i ) const + { + return static_cast< boost::int64_t >( i ); + } + + template + Variant operator()( const T& t ) const + { + return t; + } + }; + }; + + // vector objects + + template< class Config > + struct Pair_impl + { + typedef typename Config::String_type String_type; + typedef typename Config::Value_type Value_type; + + Pair_impl() + { + } + + Pair_impl( const String_type& name, const Value_type& value ); + + bool operator==( const Pair_impl& lhs ) const; + + String_type name_; + Value_type value_; + }; + +#if defined( JSON_SPIRIT_VALUE_ENABLED ) || defined( JSON_SPIRIT_WVALUE_ENABLED ) + template< class String > + struct Config_vector + { + typedef String String_type; + typedef Value_impl< Config_vector > Value_type; + typedef Pair_impl < Config_vector > Pair_type; + typedef std::vector< Value_type > Array_type; + typedef std::vector< Pair_type > Object_type; + + static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value ) + { + obj.push_back( Pair_type( name , value ) ); + + return obj.back().value_; + } + + static const String_type& get_name( const Pair_type& pair ) + { + return pair.name_; + } + + static const Value_type& get_value( const Pair_type& pair ) + { + return pair.value_; + } + }; +#endif + + // typedefs for ASCII + +#ifdef JSON_SPIRIT_VALUE_ENABLED + typedef Config_vector< std::string > Config; + + typedef Config::Value_type Value; + typedef Config::Pair_type Pair; + typedef Config::Object_type Object; + typedef Config::Array_type Array; +#endif + + // typedefs for Unicode + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + typedef Config_vector< std::wstring > wConfig; + + typedef wConfig::Value_type wValue; + typedef wConfig::Pair_type wPair; + typedef wConfig::Object_type wObject; + typedef wConfig::Array_type wArray; +#endif + + // map objects + +#if defined( JSON_SPIRIT_MVALUE_ENABLED ) || defined( JSON_SPIRIT_WMVALUE_ENABLED ) + template< class String > + struct Config_map + { + typedef String String_type; + typedef Value_impl< Config_map > Value_type; + typedef std::vector< Value_type > Array_type; + typedef std::map< String_type, Value_type > Object_type; + typedef std::pair< const String_type, Value_type > Pair_type; + + static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value ) + { + return obj[ name ] = value; + } + + static const String_type& get_name( const Pair_type& pair ) + { + return pair.first; + } + + static const Value_type& get_value( const Pair_type& pair ) + { + return pair.second; + } + }; +#endif + + // typedefs for ASCII + +#ifdef JSON_SPIRIT_MVALUE_ENABLED + typedef Config_map< std::string > mConfig; + + typedef mConfig::Value_type mValue; + typedef mConfig::Object_type mObject; + typedef mConfig::Array_type mArray; +#endif + + // typedefs for Unicode + +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + typedef Config_map< std::wstring > wmConfig; + + typedef wmConfig::Value_type wmValue; + typedef wmConfig::Object_type wmObject; + typedef wmConfig::Array_type wmArray; +#endif + + /////////////////////////////////////////////////////////////////////////////////////////////// + // + // implementation + + inline bool operator==( const Null&, const Null& ) + { + return true; + } + + template< class Config > + const Value_impl< Config > Value_impl< Config >::null; + + template< class Config > + Value_impl< Config >::Value_impl() + : v_( Null() ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( const Const_str_ptr value ) + : v_( String_type( value ) ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( const String_type& value ) + : v_( value ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( const Object& value ) + : v_( value ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( const Array& value ) + : v_( value ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( bool value ) + : v_( value ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( int value ) + : v_( static_cast< boost::int64_t >( value ) ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( boost::int64_t value ) + : v_( value ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( boost::uint64_t value ) + : v_( value ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( double value ) + : v_( value ) + { + } + + template< class Config > + Value_impl< Config >::Value_impl( const Value_impl< Config >& other ) + : v_( other.v_ ) + { + } + + template< class Config > + template< class Iter > + Value_impl< Config >::Value_impl( Iter first, Iter last ) + : v_( Array( first, last ) ) + { + } + + template< class Config > + template< BOOST_VARIANT_ENUM_PARAMS( typename T ) > + Value_impl< Config >::Value_impl( const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& variant ) + : v_( boost::apply_visitor( Variant_converter_visitor(), variant) ) + { + } + + template< class Config > + Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs ) + { + Value_impl tmp( lhs ); + + std::swap( v_, tmp.v_ ); + + return *this; + } + + template< class Config > + bool Value_impl< Config >::operator==( const Value_impl& lhs ) const + { + if( this == &lhs ) return true; + + if( type() != lhs.type() ) return false; + + return v_ == lhs.v_; + } + + template< class Config > + Value_type Value_impl< Config >::type() const + { + if( is_uint64() ) + { + return int_type; + } + + return static_cast< Value_type >( v_.which() ); + } + + template< class Config > + bool Value_impl< Config >::is_uint64() const + { + return v_.which() == null_type + 1; + } + + template< class Config > + bool Value_impl< Config >::is_null() const + { + return type() == null_type; + } + + template< class Config > + void Value_impl< Config >::check_type( const Value_type vtype ) const + { + if( type() != vtype ) + { + std::ostringstream os; + + os << "get_value< " << value_type_to_string( vtype ) << " > called on " << value_type_to_string( type() ) << " Value"; + + throw std::runtime_error( os.str() ); + } + } + + template< class Config > + const typename Config::String_type& Value_impl< Config >::get_str() const + { + check_type( str_type ); + + return *boost::get< String_type >( &v_ ); + } + + template< class Config > + const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const + { + check_type( obj_type ); + + return *boost::get< Object >( &v_ ); + } + + template< class Config > + const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const + { + check_type( array_type ); + + return *boost::get< Array >( &v_ ); + } + + template< class Config > + bool Value_impl< Config >::get_bool() const + { + check_type( bool_type ); + + return boost::get< bool >( v_ ); + } + + template< class Config > + int Value_impl< Config >::get_int() const + { + check_type( int_type ); + + return static_cast< int >( get_int64() ); + } + + template< class Config > + boost::int64_t Value_impl< Config >::get_int64() const + { + check_type( int_type ); + + if( is_uint64() ) + { + return static_cast< boost::int64_t >( get_uint64() ); + } + + return boost::get< boost::int64_t >( v_ ); + } + + template< class Config > + boost::uint64_t Value_impl< Config >::get_uint64() const + { + check_type( int_type ); + + if( !is_uint64() ) + { + return static_cast< boost::uint64_t >( get_int64() ); + } + + return boost::get< boost::uint64_t >( v_ ); + } + + template< class Config > + double Value_impl< Config >::get_real() const + { + if( type() == int_type ) + { + return is_uint64() ? static_cast< double >( get_uint64() ) + : static_cast< double >( get_int64() ); + } + + check_type( real_type ); + + return boost::get< double >( v_ ); + } + + template< class Config > + typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() + { + check_type( obj_type ); + + return *boost::get< Object >( &v_ ); + } + + template< class Config > + typename Value_impl< Config >::Array& Value_impl< Config >::get_array() + { + check_type( array_type ); + + return *boost::get< Array >( &v_ ); + } + + template< class Config > + Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value ) + : name_( name ) + , value_( value ) + { + } + + template< class Config > + bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const + { + if( this == &lhs ) return true; + + return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ ); + } + + // converts a C string, ie. 8 bit char array, to a string object + // + template < class String_type > + String_type to_str( const char* c_str ) + { + String_type result; + + for( const char* p = c_str; *p != 0; ++p ) + { + result += *p; + } + + return result; + } + + // + + namespace internal_ + { + template< typename T > + struct Type_to_type + { + }; + + template< class Value > + int get_value( const Value& value, Type_to_type< int > ) + { + return value.get_int(); + } + + template< class Value > + boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > ) + { + return value.get_int64(); + } + + template< class Value > + boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > ) + { + return value.get_uint64(); + } + + template< class Value > + double get_value( const Value& value, Type_to_type< double > ) + { + return value.get_real(); + } + + template< class Value > + typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > ) + { + return value.get_str(); + } + + template< class Value > + typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > ) + { + return value.get_array(); + } + + template< class Value > + typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > ) + { + return value.get_obj(); + } + + template< class Value > + bool get_value( const Value& value, Type_to_type< bool > ) + { + return value.get_bool(); + } + } + + template< class Config > + template< typename T > + T Value_impl< Config >::get_value() const + { + return internal_::get_value( *this, internal_::Type_to_type< T >() ); + } + + static std::string value_type_to_string( const Value_type vtype ) + { + switch( vtype ) + { + case obj_type: return "Object"; + case array_type: return "Array"; + case str_type: return "string"; + case bool_type: return "boolean"; + case int_type: return "integer"; + case real_type: return "real"; + case null_type: return "null"; + } + + assert( false ); + + return "unknown type"; + } +} + +#endif diff --git a/json5_parser/json5_parser_writer.cpp b/json5_parser/json5_parser_writer.cpp index 9345986..7e44c76 100644 --- a/json5_parser/json5_parser_writer.cpp +++ b/json5_parser/json5_parser_writer.cpp @@ -1,96 +1,96 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_writer.h" -#include "json5_parser_writer_template.h" - -using namespace json5_parser; - -#ifdef JSON_SPIRIT_VALUE_ENABLED - void json5_parser::write( const Value& value, std::ostream& os, int options, unsigned int precision_of_doubles ) - { - write_stream( value, os, options, precision_of_doubles ); - } - std::string json5_parser::write( const Value& value, int options, unsigned int precision_of_doubles ) - { - return write_string( value, options, precision_of_doubles ); - } - - void json5_parser::write_formatted( const Value& value, std::ostream& os, unsigned int precision_of_doubles ) - { - write_stream( value, os, pretty_print, precision_of_doubles ); - } - - std::string json5_parser::write_formatted( const Value& value, unsigned int precision_of_doubles ) - { - return write_string( value, pretty_print, precision_of_doubles ); - } -#endif - -#ifdef JSON_SPIRIT_MVALUE_ENABLED - void json5_parser::write( const mValue& value, std::ostream& os, int options, unsigned int precision_of_doubles ) - { - write_stream( value, os, options, precision_of_doubles ); - } - - std::string json5_parser::write( const mValue& value, int options, unsigned int precision_of_doubles ) - { - return write_string( value, options, precision_of_doubles ); - } - - void json5_parser::write_formatted( const mValue& value, std::ostream& os, unsigned int precision_of_doubles ) - { - write_stream( value, os, pretty_print, precision_of_doubles ); - } - - std::string json5_parser::write_formatted( const mValue& value, unsigned int precision_of_doubles ) - { - return write_string( value, pretty_print, precision_of_doubles ); - } -#endif - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void json5_parser::write( const wValue& value, std::wostream& os, int options, unsigned int precision_of_doubles ) - { - write_stream( value, os, options, precision_of_doubles ); - } - - std::wstring json5_parser::write( const wValue& value, int options, unsigned int precision_of_doubles ) - { - return write_string( value, options, precision_of_doubles ); - } - - void json5_parser::write_formatted( const wValue& value, std::wostream& os, unsigned int precision_of_doubles ) - { - write_stream( value, os, pretty_print, precision_of_doubles ); - } - - std::wstring json5_parser::write_formatted( const wValue& value, unsigned int precision_of_doubles ) - { - return write_string( value, pretty_print, precision_of_doubles ); - } -#endif - -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void json5_parser::write_formatted( const wmValue& value, std::wostream& os, unsigned int precision_of_doubles ) - { - write_stream( value, os, pretty_print, precision_of_doubles ); - } - - std::wstring json5_parser::write_formatted( const wmValue& value, unsigned int precision_of_doubles ) - { - return write_string( value, pretty_print, precision_of_doubles ); - } - - void json5_parser::write( const wmValue& value, std::wostream& os, int options, unsigned int precision_of_doubles ) - { - write_stream( value, os, options, precision_of_doubles ); - } - - std::wstring json5_parser::write( const wmValue& value, int options, unsigned int precision_of_doubles ) - { - return write_string( value, options, precision_of_doubles ); - } -#endif +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_writer.h" +#include "json5_parser_writer_template.h" + +using namespace json5_parser; + +#ifdef JSON_SPIRIT_VALUE_ENABLED + void json5_parser::write( const Value& value, std::ostream& os, int options, unsigned int precision_of_doubles ) + { + write_stream( value, os, options, precision_of_doubles ); + } + std::string json5_parser::write( const Value& value, int options, unsigned int precision_of_doubles ) + { + return write_string( value, options, precision_of_doubles ); + } + + void json5_parser::write_formatted( const Value& value, std::ostream& os, unsigned int precision_of_doubles ) + { + write_stream( value, os, pretty_print, precision_of_doubles ); + } + + std::string json5_parser::write_formatted( const Value& value, unsigned int precision_of_doubles ) + { + return write_string( value, pretty_print, precision_of_doubles ); + } +#endif + +#ifdef JSON_SPIRIT_MVALUE_ENABLED + void json5_parser::write( const mValue& value, std::ostream& os, int options, unsigned int precision_of_doubles ) + { + write_stream( value, os, options, precision_of_doubles ); + } + + std::string json5_parser::write( const mValue& value, int options, unsigned int precision_of_doubles ) + { + return write_string( value, options, precision_of_doubles ); + } + + void json5_parser::write_formatted( const mValue& value, std::ostream& os, unsigned int precision_of_doubles ) + { + write_stream( value, os, pretty_print, precision_of_doubles ); + } + + std::string json5_parser::write_formatted( const mValue& value, unsigned int precision_of_doubles ) + { + return write_string( value, pretty_print, precision_of_doubles ); + } +#endif + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + void json5_parser::write( const wValue& value, std::wostream& os, int options, unsigned int precision_of_doubles ) + { + write_stream( value, os, options, precision_of_doubles ); + } + + std::wstring json5_parser::write( const wValue& value, int options, unsigned int precision_of_doubles ) + { + return write_string( value, options, precision_of_doubles ); + } + + void json5_parser::write_formatted( const wValue& value, std::wostream& os, unsigned int precision_of_doubles ) + { + write_stream( value, os, pretty_print, precision_of_doubles ); + } + + std::wstring json5_parser::write_formatted( const wValue& value, unsigned int precision_of_doubles ) + { + return write_string( value, pretty_print, precision_of_doubles ); + } +#endif + +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + void json5_parser::write_formatted( const wmValue& value, std::wostream& os, unsigned int precision_of_doubles ) + { + write_stream( value, os, pretty_print, precision_of_doubles ); + } + + std::wstring json5_parser::write_formatted( const wmValue& value, unsigned int precision_of_doubles ) + { + return write_string( value, pretty_print, precision_of_doubles ); + } + + void json5_parser::write( const wmValue& value, std::wostream& os, int options, unsigned int precision_of_doubles ) + { + write_stream( value, os, options, precision_of_doubles ); + } + + std::wstring json5_parser::write( const wmValue& value, int options, unsigned int precision_of_doubles ) + { + return write_string( value, options, precision_of_doubles ); + } +#endif diff --git a/json5_parser/json5_parser_writer.h b/json5_parser/json5_parser_writer.h index 48874b8..ead34af 100644 --- a/json5_parser/json5_parser_writer.h +++ b/json5_parser/json5_parser_writer.h @@ -1,65 +1,65 @@ -#ifndef JSON_SPIRIT_WRITER -#define JSON_SPIRIT_WRITER - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include "json5_parser_value.h" -#include "json5_parser_writer_options.h" -#include - -namespace json5_parser -{ - // these functions to convert JSON Values to text - // note the precision used outputing doubles defaults to 17, - // unless the remove_trailing_zeros option is given in which case the default is 16 - -#ifdef JSON_SPIRIT_VALUE_ENABLED - void write( const Value& value, std::ostream& os, int options = none, unsigned int precision_of_doubles = 0 ); - std::string write( const Value& value, int options = none, unsigned int precision_of_doubles = 0 ); -#endif - -#ifdef JSON_SPIRIT_MVALUE_ENABLED - void write( const mValue& value, std::ostream& os, int options = none, unsigned int precision_of_doubles = 0 ); - std::string write( const mValue& value, int options = none, unsigned int precision_of_doubles = 0 ); -#endif - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void write( const wValue& value, std::wostream& os, int options = none, unsigned int precision_of_doubles = 0 ); - std::wstring write( const wValue& value, int options = none, unsigned int precision_of_doubles = 0 ); -#endif - -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void write( const wmValue& value, std::wostream& os, int options = none, unsigned int precision_of_doubles = 0 ); - std::wstring write( const wmValue& value, int options = none, unsigned int precision_of_doubles = 0 ); -#endif - - // these "formatted" versions of the "write" functions are the equivalent of the above functions - // with option "pretty_print" - -#ifdef JSON_SPIRIT_VALUE_ENABLED - void write_formatted( const Value& value, std::ostream& os, unsigned int precision_of_doubles = 0 ); - std::string write_formatted( const Value& value, unsigned int precision_of_doubles = 0 ); -#endif -#ifdef JSON_SPIRIT_MVALUE_ENABLED - void write_formatted( const mValue& value, std::ostream& os, unsigned int precision_of_doubles = 0 ); - std::string write_formatted( const mValue& value, unsigned int precision_of_doubles = 0 ); -#endif - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void write_formatted( const wValue& value, std::wostream& os, unsigned int precision_of_doubles = 0 ); - std::wstring write_formatted( const wValue& value, unsigned int precision_of_doubles = 0 ); -#endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void write_formatted( const wmValue& value, std::wostream& os, unsigned int precision_of_doubles = 0 ); - std::wstring write_formatted( const wmValue& value, unsigned int precision_of_doubles = 0 ); -#endif -} - -#endif +#ifndef JSON_SPIRIT_WRITER +#define JSON_SPIRIT_WRITER + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include "json5_parser_value.h" +#include "json5_parser_writer_options.h" +#include + +namespace json5_parser +{ + // these functions to convert JSON Values to text + // note the precision used outputing doubles defaults to 17, + // unless the remove_trailing_zeros option is given in which case the default is 16 + +#ifdef JSON_SPIRIT_VALUE_ENABLED + void write( const Value& value, std::ostream& os, int options = none, unsigned int precision_of_doubles = 0 ); + std::string write( const Value& value, int options = none, unsigned int precision_of_doubles = 0 ); +#endif + +#ifdef JSON_SPIRIT_MVALUE_ENABLED + void write( const mValue& value, std::ostream& os, int options = none, unsigned int precision_of_doubles = 0 ); + std::string write( const mValue& value, int options = none, unsigned int precision_of_doubles = 0 ); +#endif + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + void write( const wValue& value, std::wostream& os, int options = none, unsigned int precision_of_doubles = 0 ); + std::wstring write( const wValue& value, int options = none, unsigned int precision_of_doubles = 0 ); +#endif + +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + void write( const wmValue& value, std::wostream& os, int options = none, unsigned int precision_of_doubles = 0 ); + std::wstring write( const wmValue& value, int options = none, unsigned int precision_of_doubles = 0 ); +#endif + + // these "formatted" versions of the "write" functions are the equivalent of the above functions + // with option "pretty_print" + +#ifdef JSON_SPIRIT_VALUE_ENABLED + void write_formatted( const Value& value, std::ostream& os, unsigned int precision_of_doubles = 0 ); + std::string write_formatted( const Value& value, unsigned int precision_of_doubles = 0 ); +#endif +#ifdef JSON_SPIRIT_MVALUE_ENABLED + void write_formatted( const mValue& value, std::ostream& os, unsigned int precision_of_doubles = 0 ); + std::string write_formatted( const mValue& value, unsigned int precision_of_doubles = 0 ); +#endif + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + void write_formatted( const wValue& value, std::wostream& os, unsigned int precision_of_doubles = 0 ); + std::wstring write_formatted( const wValue& value, unsigned int precision_of_doubles = 0 ); +#endif +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + void write_formatted( const wmValue& value, std::wostream& os, unsigned int precision_of_doubles = 0 ); + std::wstring write_formatted( const wmValue& value, unsigned int precision_of_doubles = 0 ); +#endif +} + +#endif diff --git a/json5_parser/json5_parser_writer_options.h b/json5_parser/json5_parser_writer_options.h index 374db46..e84a330 100644 --- a/json5_parser/json5_parser_writer_options.h +++ b/json5_parser/json5_parser_writer_options.h @@ -1,35 +1,35 @@ -#ifndef JSON_SPIRIT_WRITER_OPTIONS -#define JSON_SPIRIT_WRITER_OPTIONS - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -namespace json5_parser -{ - enum Output_options{ none = 0, // default options - - pretty_print = 0x01, // Add whitespace to format the output nicely. - - raw_utf8 = 0x02, // This prevents non-printable characters from being escapted using "\uNNNN" notation. - // Note, this is an extension to the JSON standard. It disables the escaping of - // non-printable characters allowing UTF-8 sequences held in 8 bit char strings - // to pass through unaltered. - - remove_trailing_zeros = 0x04, - // no longer used kept for backwards compatibility - single_line_arrays = 0x08, - // pretty printing except that arrays printed on single lines unless they contain - // composite elements, i.e. objects or arrays - always_escape_nonascii = 0x10, - // all unicode wide characters are escaped, i.e. outputed as "\uXXXX", even if they are - // printable under the current locale, ascii printable chars are not escaped - }; -} - -#endif +#ifndef JSON_SPIRIT_WRITER_OPTIONS +#define JSON_SPIRIT_WRITER_OPTIONS + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace json5_parser +{ + enum Output_options{ none = 0, // default options + + pretty_print = 0x01, // Add whitespace to format the output nicely. + + raw_utf8 = 0x02, // This prevents non-printable characters from being escapted using "\uNNNN" notation. + // Note, this is an extension to the JSON standard. It disables the escaping of + // non-printable characters allowing UTF-8 sequences held in 8 bit char strings + // to pass through unaltered. + + remove_trailing_zeros = 0x04, + // no longer used kept for backwards compatibility + single_line_arrays = 0x08, + // pretty printing except that arrays printed on single lines unless they contain + // composite elements, i.e. objects or arrays + always_escape_nonascii = 0x10, + // all unicode wide characters are escaped, i.e. outputed as "\uXXXX", even if they are + // printable under the current locale, ascii printable chars are not escaped + }; +} + +#endif diff --git a/json5_parser/json5_parser_writer_template.h b/json5_parser/json5_parser_writer_template.h index b9ab62e..342400b 100644 --- a/json5_parser/json5_parser_writer_template.h +++ b/json5_parser/json5_parser_writer_template.h @@ -1,325 +1,325 @@ -#ifndef JSON_SPIRIT_WRITER_TEMPLATE -#define JSON_SPIRIT_WRITER_TEMPLATE - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include "json5_parser_value.h" -#include "json5_parser_writer_options.h" - -#include -#include -#include -#include - -namespace json5_parser -{ - inline char to_hex_char( unsigned int c ) - { - assert( c <= 0xF ); - - const char ch = static_cast< char >( c ); - - if( ch < 10 ) return '0' + ch; - - return 'A' - 10 + ch; - } - - template< class String_type > - String_type non_printable_to_string( unsigned int c ) - { - String_type result( 6, '\\' ); - - result[1] = 'u'; - - result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4; - result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4; - result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4; - result[ 2 ] = to_hex_char( c & 0x000F ); - - return result; - } - - template< typename Char_type, class String_type > - bool add_esc_char( Char_type c, String_type& s ) - { - switch( c ) - { - case '"': s += to_str< String_type >( "\\\"" ); return true; - case '\\': s += to_str< String_type >( "\\\\" ); return true; - case '\b': s += to_str< String_type >( "\\b" ); return true; - case '\f': s += to_str< String_type >( "\\f" ); return true; - case '\n': s += to_str< String_type >( "\\n" ); return true; - case '\r': s += to_str< String_type >( "\\r" ); return true; - case '\t': s += to_str< String_type >( "\\t" ); return true; - } - - return false; - } - - template< class String_type > - String_type add_esc_chars( const String_type& s, bool raw_utf8, bool esc_nonascii ) - { - typedef typename String_type::const_iterator Iter_type; - typedef typename String_type::value_type Char_type; - - String_type result; - - const Iter_type end( s.end() ); - - for( Iter_type i = s.begin(); i != end; ++i ) - { - const Char_type c( *i ); - - if( add_esc_char( c, result ) ) continue; - - if( raw_utf8 ) - { - result += c; - } - else - { - const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c ); - - if( !esc_nonascii && iswprint( unsigned_c ) ) - { - result += c; - } - else - { - result += non_printable_to_string< String_type >( unsigned_c ); - } - } - } - - return result; - } - - // this class generates the JSON text, - // it keeps track of the indentation level etc. - // - template< class Value_type, class Ostream_type > - class Generator - { - typedef typename Value_type::Config_type Config_type; - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename String_type::value_type Char_type; - typedef typename Object_type::value_type Obj_member_type; - - public: - - Generator( const Value_type& value, Ostream_type& os, int options, unsigned int precision_of_doubles ) - : os_( os ) - , indentation_level_( 0 ) - , pretty_( ( options & pretty_print ) != 0 || ( options & single_line_arrays ) != 0 ) - , raw_utf8_( ( options & raw_utf8 ) != 0 ) - , esc_nonascii_( ( options & always_escape_nonascii ) != 0 ) - , single_line_arrays_( ( options & single_line_arrays ) != 0 ) - , ios_saver_( os ) - { - if( precision_of_doubles > 0 ) - { - precision_of_doubles_ = precision_of_doubles; - } - else - { - precision_of_doubles_ = ( options & remove_trailing_zeros ) != 0 ? 16 : 17; - } - - output( value ); - } - - private: - - void output( const Value_type& value ) - { - switch( value.type() ) - { - case obj_type: output( value.get_obj() ); break; - case array_type: output( value.get_array() ); break; - case str_type: output( value.get_str() ); break; - case bool_type: output( value.get_bool() ); break; - case real_type: output( value.get_real() ); break; - case int_type: output_int( value ); break; - case null_type: os_ << "null"; break; - default: assert( false ); - } - } - - void output( const Object_type& obj ) - { - output_array_or_obj( obj, '{', '}' ); - } - - void output( const Obj_member_type& member ) - { - output( Config_type::get_name( member ) ); space(); - os_ << ':'; space(); - output( Config_type::get_value( member ) ); - } - - void output_int( const Value_type& value ) - { - if( value.is_uint64() ) - { - os_ << value.get_uint64(); - } - else - { - os_ << value.get_int64(); - } - } - - void output( const String_type& s ) - { - os_ << '"' << add_esc_chars( s, raw_utf8_, esc_nonascii_ ) << '"'; - } - - void output( bool b ) - { - os_ << to_str< String_type >( b ? "true" : "false" ); - } - - void output( double d ) - { - os_ << std::setprecision( precision_of_doubles_ ) << d; - } - - static bool contains_composite_elements( const Array_type& arr ) - { - for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i ) - { - const Value_type& val = *i; - - if( val.type() == obj_type || - val.type() == array_type ) - { - return true; - } - } - - return false; - } - - template< class Iter > - void output_composite_item( Iter i, Iter last ) - { - output( *i ); - - if( ++i != last ) - { - os_ << ','; - } - } - - void output( const Array_type& arr ) - { - if( single_line_arrays_ && !contains_composite_elements( arr ) ) - { - os_ << '['; space(); - - for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i ) - { - output_composite_item( i, arr.end() ); - - space(); - } - - os_ << ']'; - } - else - { - output_array_or_obj( arr, '[', ']' ); - } - } - - template< class T > - void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char ) - { - os_ << start_char; new_line(); - - ++indentation_level_; - - for( typename T::const_iterator i = t.begin(); i != t.end(); ++i ) - { - indent(); - - output_composite_item( i, t.end() ); - - new_line(); - } - - --indentation_level_; - - indent(); os_ << end_char; - } - - void indent() - { - if( !pretty_ ) return; - - for( int i = 0; i < indentation_level_; ++i ) - { - os_ << " "; - } - } - - void space() - { - if( pretty_ ) os_ << ' '; - } - - void new_line() - { - if( pretty_ ) os_ << '\n'; - } - - Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning - - Ostream_type& os_; - int indentation_level_; - bool pretty_; - bool raw_utf8_; - bool esc_nonascii_; - bool single_line_arrays_; - int precision_of_doubles_; - boost::io::basic_ios_all_saver< Char_type > ios_saver_; // so that ostream state is reset after control is returned to the caller - }; - - // writes JSON Value to a stream, e.g. - // - // write_stream( value, os, pretty_print ); - // - template< class Value_type, class Ostream_type > - void write_stream( const Value_type& value, Ostream_type& os, int options = none, unsigned int precision_of_doubles = 0 ) - { - os << std::dec; - Generator< Value_type, Ostream_type >( value, os, options, precision_of_doubles ); - } - - // writes JSON Value to a stream, e.g. - // - // const string json_str = write( value, pretty_print ); - // - template< class Value_type > - typename Value_type::String_type write_string( const Value_type& value, int options = none, unsigned int precision_of_doubles = 0 ) - { - typedef typename Value_type::String_type::value_type Char_type; - - std::basic_ostringstream< Char_type > os; - - write_stream( value, os, options, precision_of_doubles ); - - return os.str(); - } -} - -#endif +#ifndef JSON_SPIRIT_WRITER_TEMPLATE +#define JSON_SPIRIT_WRITER_TEMPLATE + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include "json5_parser_value.h" +#include "json5_parser_writer_options.h" + +#include +#include +#include +#include + +namespace json5_parser +{ + inline char to_hex_char( unsigned int c ) + { + assert( c <= 0xF ); + + const char ch = static_cast< char >( c ); + + if( ch < 10 ) return '0' + ch; + + return 'A' - 10 + ch; + } + + template< class String_type > + String_type non_printable_to_string( unsigned int c ) + { + String_type result( 6, '\\' ); + + result[1] = 'u'; + + result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4; + result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4; + result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4; + result[ 2 ] = to_hex_char( c & 0x000F ); + + return result; + } + + template< typename Char_type, class String_type > + bool add_esc_char( Char_type c, String_type& s ) + { + switch( c ) + { + case '"': s += to_str< String_type >( "\\\"" ); return true; + case '\\': s += to_str< String_type >( "\\\\" ); return true; + case '\b': s += to_str< String_type >( "\\b" ); return true; + case '\f': s += to_str< String_type >( "\\f" ); return true; + case '\n': s += to_str< String_type >( "\\n" ); return true; + case '\r': s += to_str< String_type >( "\\r" ); return true; + case '\t': s += to_str< String_type >( "\\t" ); return true; + } + + return false; + } + + template< class String_type > + String_type add_esc_chars( const String_type& s, bool raw_utf8, bool esc_nonascii ) + { + typedef typename String_type::const_iterator Iter_type; + typedef typename String_type::value_type Char_type; + + String_type result; + + const Iter_type end( s.end() ); + + for( Iter_type i = s.begin(); i != end; ++i ) + { + const Char_type c( *i ); + + if( add_esc_char( c, result ) ) continue; + + if( raw_utf8 ) + { + result += c; + } + else + { + const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c ); + + if( !esc_nonascii && iswprint( unsigned_c ) ) + { + result += c; + } + else + { + result += non_printable_to_string< String_type >( unsigned_c ); + } + } + } + + return result; + } + + // this class generates the JSON text, + // it keeps track of the indentation level etc. + // + template< class Value_type, class Ostream_type > + class Generator + { + typedef typename Value_type::Config_type Config_type; + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename String_type::value_type Char_type; + typedef typename Object_type::value_type Obj_member_type; + + public: + + Generator( const Value_type& value, Ostream_type& os, int options, unsigned int precision_of_doubles ) + : os_( os ) + , indentation_level_( 0 ) + , pretty_( ( options & pretty_print ) != 0 || ( options & single_line_arrays ) != 0 ) + , raw_utf8_( ( options & raw_utf8 ) != 0 ) + , esc_nonascii_( ( options & always_escape_nonascii ) != 0 ) + , single_line_arrays_( ( options & single_line_arrays ) != 0 ) + , ios_saver_( os ) + { + if( precision_of_doubles > 0 ) + { + precision_of_doubles_ = precision_of_doubles; + } + else + { + precision_of_doubles_ = ( options & remove_trailing_zeros ) != 0 ? 16 : 17; + } + + output( value ); + } + + private: + + void output( const Value_type& value ) + { + switch( value.type() ) + { + case obj_type: output( value.get_obj() ); break; + case array_type: output( value.get_array() ); break; + case str_type: output( value.get_str() ); break; + case bool_type: output( value.get_bool() ); break; + case real_type: output( value.get_real() ); break; + case int_type: output_int( value ); break; + case null_type: os_ << "null"; break; + default: assert( false ); + } + } + + void output( const Object_type& obj ) + { + output_array_or_obj( obj, '{', '}' ); + } + + void output( const Obj_member_type& member ) + { + output( Config_type::get_name( member ) ); space(); + os_ << ':'; space(); + output( Config_type::get_value( member ) ); + } + + void output_int( const Value_type& value ) + { + if( value.is_uint64() ) + { + os_ << value.get_uint64(); + } + else + { + os_ << value.get_int64(); + } + } + + void output( const String_type& s ) + { + os_ << '"' << add_esc_chars( s, raw_utf8_, esc_nonascii_ ) << '"'; + } + + void output( bool b ) + { + os_ << to_str< String_type >( b ? "true" : "false" ); + } + + void output( double d ) + { + os_ << std::setprecision( precision_of_doubles_ ) << d; + } + + static bool contains_composite_elements( const Array_type& arr ) + { + for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i ) + { + const Value_type& val = *i; + + if( val.type() == obj_type || + val.type() == array_type ) + { + return true; + } + } + + return false; + } + + template< class Iter > + void output_composite_item( Iter i, Iter last ) + { + output( *i ); + + if( ++i != last ) + { + os_ << ','; + } + } + + void output( const Array_type& arr ) + { + if( single_line_arrays_ && !contains_composite_elements( arr ) ) + { + os_ << '['; space(); + + for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i ) + { + output_composite_item( i, arr.end() ); + + space(); + } + + os_ << ']'; + } + else + { + output_array_or_obj( arr, '[', ']' ); + } + } + + template< class T > + void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char ) + { + os_ << start_char; new_line(); + + ++indentation_level_; + + for( typename T::const_iterator i = t.begin(); i != t.end(); ++i ) + { + indent(); + + output_composite_item( i, t.end() ); + + new_line(); + } + + --indentation_level_; + + indent(); os_ << end_char; + } + + void indent() + { + if( !pretty_ ) return; + + for( int i = 0; i < indentation_level_; ++i ) + { + os_ << " "; + } + } + + void space() + { + if( pretty_ ) os_ << ' '; + } + + void new_line() + { + if( pretty_ ) os_ << '\n'; + } + + Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning + + Ostream_type& os_; + int indentation_level_; + bool pretty_; + bool raw_utf8_; + bool esc_nonascii_; + bool single_line_arrays_; + int precision_of_doubles_; + boost::io::basic_ios_all_saver< Char_type > ios_saver_; // so that ostream state is reset after control is returned to the caller + }; + + // writes JSON Value to a stream, e.g. + // + // write_stream( value, os, pretty_print ); + // + template< class Value_type, class Ostream_type > + void write_stream( const Value_type& value, Ostream_type& os, int options = none, unsigned int precision_of_doubles = 0 ) + { + os << std::dec; + Generator< Value_type, Ostream_type >( value, os, options, precision_of_doubles ); + } + + // writes JSON Value to a stream, e.g. + // + // const string json_str = write( value, pretty_print ); + // + template< class Value_type > + typename Value_type::String_type write_string( const Value_type& value, int options = none, unsigned int precision_of_doubles = 0 ) + { + typedef typename Value_type::String_type::value_type Char_type; + + std::basic_ostringstream< Char_type > os; + + write_stream( value, os, options, precision_of_doubles ); + + return os.str(); + } +} + +#endif diff --git a/json_demo/json_demo.cpp b/json_demo/json_demo.cpp index d1ffed7..75941eb 100644 --- a/json_demo/json_demo.cpp +++ b/json_demo/json_demo.cpp @@ -1,149 +1,149 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -// This demo shows you how to read and write JSON objects and arrays. -// In this demo objects are stored as a vector of name/value pairs. - -#include "json5_parser.h" -#include -#include - -#ifndef JSON_SPIRIT_VALUE_ENABLED -#error Please define JSON_SPIRIT_VALUE_ENABLED for the Value type to be enabled -#endif - -using namespace std; -using namespace json5_parser; - -struct Address -{ - int house_number_; - string road_; - string town_; - string county_; - string country_; -}; - -bool operator==( const Address& a1, const Address& a2 ) -{ - return ( a1.house_number_ == a2.house_number_ ) && - ( a1.road_ == a2.road_ ) && - ( a1.town_ == a2.town_ ) && - ( a1.county_ == a2.county_ ) && - ( a1.country_ == a2.country_ ); -} - -void write_address( Array& a, const Address& addr ) -{ - Object addr_obj; - - addr_obj.push_back( Pair( "house_number", addr.house_number_ ) ); - addr_obj.push_back( Pair( "road", addr.road_ ) ); - addr_obj.push_back( Pair( "town", addr.town_ ) ); - addr_obj.push_back( Pair( "county", addr.county_ ) ); - addr_obj.push_back( Pair( "country", addr.country_ ) ); - - a.push_back( addr_obj ); -} - -Address read_address( const Object& obj ) -{ - Address addr; - - for( Object::size_type i = 0; i != obj.size(); ++i ) - { - const Pair& pair = obj[i]; - - const string& name = pair.name_; - const Value& value = pair.value_; - - if( name == "house_number" ) - { - addr.house_number_ = value.get_int(); - } - else if( name == "road" ) - { - addr.road_ = value.get_str(); - } - else if( name == "town" ) - { - addr.town_ = value.get_str(); - } - else if( name == "county" ) - { - addr.county_ = value.get_str(); - } - else if( name == "country" ) - { - addr.country_ = value.get_str(); - } - else - { - assert( false ); - } - } - - return addr; -} - -void write_addrs( const char* file_name, const Address addrs[] ) -{ - Array addr_array; - - for( int i = 0; i < 5; ++i ) - { - write_address( addr_array, addrs[i] ); - } - - ofstream os( file_name ); - - write_formatted( addr_array, os ); - - os.close(); -} - -vector< Address > read_addrs( const char* file_name ) -{ - ifstream is( file_name ); - - Value value; - - read( is, value ); - - const Array& addr_array = value.get_array(); - - vector< Address > addrs; - - for( unsigned int i = 0; i < addr_array.size(); ++i ) - { - addrs.push_back( read_address( addr_array[i].get_obj() ) ); - } - - return addrs; -} - -int main() -{ - const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, - { 1, "West Street", "Hull", "Yorkshire", "England" }, - { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, - { 45, "North Road", "Paignton", "Devon", "England" }, - { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; - - const char* file_name( "demo.txt" ); - - write_addrs( file_name, addrs ); - - vector< Address > new_addrs = read_addrs( file_name ); - - assert( new_addrs.size() == 5 ); - - for( int i = 0; i < 5; ++i ) - { - assert( new_addrs[i] == addrs[i] ); - } - - return 0; -} +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +// This demo shows you how to read and write JSON objects and arrays. +// In this demo objects are stored as a vector of name/value pairs. + +#include "json5_parser.h" +#include +#include + +#ifndef JSON_SPIRIT_VALUE_ENABLED +#error Please define JSON_SPIRIT_VALUE_ENABLED for the Value type to be enabled +#endif + +using namespace std; +using namespace json5_parser; + +struct Address +{ + int house_number_; + string road_; + string town_; + string county_; + string country_; +}; + +bool operator==( const Address& a1, const Address& a2 ) +{ + return ( a1.house_number_ == a2.house_number_ ) && + ( a1.road_ == a2.road_ ) && + ( a1.town_ == a2.town_ ) && + ( a1.county_ == a2.county_ ) && + ( a1.country_ == a2.country_ ); +} + +void write_address( Array& a, const Address& addr ) +{ + Object addr_obj; + + addr_obj.push_back( Pair( "house_number", addr.house_number_ ) ); + addr_obj.push_back( Pair( "road", addr.road_ ) ); + addr_obj.push_back( Pair( "town", addr.town_ ) ); + addr_obj.push_back( Pair( "county", addr.county_ ) ); + addr_obj.push_back( Pair( "country", addr.country_ ) ); + + a.push_back( addr_obj ); +} + +Address read_address( const Object& obj ) +{ + Address addr; + + for( Object::size_type i = 0; i != obj.size(); ++i ) + { + const Pair& pair = obj[i]; + + const string& name = pair.name_; + const Value& value = pair.value_; + + if( name == "house_number" ) + { + addr.house_number_ = value.get_int(); + } + else if( name == "road" ) + { + addr.road_ = value.get_str(); + } + else if( name == "town" ) + { + addr.town_ = value.get_str(); + } + else if( name == "county" ) + { + addr.county_ = value.get_str(); + } + else if( name == "country" ) + { + addr.country_ = value.get_str(); + } + else + { + assert( false ); + } + } + + return addr; +} + +void write_addrs( const char* file_name, const Address addrs[] ) +{ + Array addr_array; + + for( int i = 0; i < 5; ++i ) + { + write_address( addr_array, addrs[i] ); + } + + ofstream os( file_name ); + + write_formatted( addr_array, os ); + + os.close(); +} + +vector< Address > read_addrs( const char* file_name ) +{ + ifstream is( file_name ); + + Value value; + + read( is, value ); + + const Array& addr_array = value.get_array(); + + vector< Address > addrs; + + for( unsigned int i = 0; i < addr_array.size(); ++i ) + { + addrs.push_back( read_address( addr_array[i].get_obj() ) ); + } + + return addrs; +} + +int main() +{ + const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, + { 1, "West Street", "Hull", "Yorkshire", "England" }, + { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, + { 45, "North Road", "Paignton", "Devon", "England" }, + { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; + + const char* file_name( "demo.txt" ); + + write_addrs( file_name, addrs ); + + vector< Address > new_addrs = read_addrs( file_name ); + + assert( new_addrs.size() == 5 ); + + for( int i = 0; i < 5; ++i ) + { + assert( new_addrs[i] == addrs[i] ); + } + + return 0; +} diff --git a/json_headers_only_demo/json_headers_only_demo.cpp b/json_headers_only_demo/json_headers_only_demo.cpp index 87953ac..a8896d6 100644 --- a/json_headers_only_demo/json_headers_only_demo.cpp +++ b/json_headers_only_demo/json_headers_only_demo.cpp @@ -1,151 +1,151 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -// This demo shows you how to read and write JSON objects and arrays -// using header files only, i.e. not linking to the JSON Spirit object library. -// In this demo objects are stored as a vector of name/value pairs. - -#include "json5_parser_reader_template.h" -#include "json5_parser_writer_template.h" -#include -#include - -#ifndef JSON_SPIRIT_VALUE_ENABLED -#error Please define JSON_SPIRIT_VALUE_ENABLED for the Value type to be enabled -#endif - -using namespace std; -using namespace json5_parser; - -struct Address -{ - int house_number_; - string road_; - string town_; - string county_; - string country_; -}; - -bool operator==( const Address& a1, const Address& a2 ) -{ - return ( a1.house_number_ == a2.house_number_ ) && - ( a1.road_ == a2.road_ ) && - ( a1.town_ == a2.town_ ) && - ( a1.county_ == a2.county_ ) && - ( a1.country_ == a2.country_ ); -} - -void write_address( Array& a, const Address& addr ) -{ - Object addr_obj; - - addr_obj.push_back( Pair( "house_number", addr.house_number_ ) ); - addr_obj.push_back( Pair( "road", addr.road_ ) ); - addr_obj.push_back( Pair( "town", addr.town_ ) ); - addr_obj.push_back( Pair( "county", addr.county_ ) ); - addr_obj.push_back( Pair( "country", addr.country_ ) ); - - a.push_back( addr_obj ); -} - -Address read_address( const Object& obj ) -{ - Address addr; - - for( Object::size_type i = 0; i != obj.size(); ++i ) - { - const Pair& pair = obj[i]; - - const string& name = pair.name_; - const Value& value = pair.value_; - - if( name == "house_number" ) - { - addr.house_number_ = value.get_int(); - } - else if( name == "road" ) - { - addr.road_ = value.get_str(); - } - else if( name == "town" ) - { - addr.town_ = value.get_str(); - } - else if( name == "county" ) - { - addr.county_ = value.get_str(); - } - else if( name == "country" ) - { - addr.country_ = value.get_str(); - } - else - { - assert( false ); - } - } - - return addr; -} - -void write_addrs( const char* file_name, const Address addrs[] ) -{ - Array addr_array; - - for( int i = 0; i < 5; ++i ) - { - write_address( addr_array, addrs[i] ); - } - - ofstream os( file_name ); - - write_stream( Value( addr_array ), os, pretty_print ); // NB need to convert Array to a Value - - os.close(); -} - -vector< Address > read_addrs( const char* file_name ) -{ - ifstream is( file_name ); - - Value value; - - read_stream( is, value ); - - const Array& addr_array = value.get_array(); - - vector< Address > addrs; - - for( unsigned int i = 0; i < addr_array.size(); ++i ) - { - addrs.push_back( read_address( addr_array[i].get_obj() ) ); - } - - return addrs; -} - -int main() -{ - const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, - { 1, "West Street", "Hull", "Yorkshire", "England" }, - { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, - { 45, "North Road", "Paignton", "Devon", "England" }, - { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; - - const char* file_name( "demo.txt" ); - - write_addrs( file_name, addrs ); - - vector< Address > new_addrs = read_addrs( file_name ); - - assert( new_addrs.size() == 5 ); - - for( int i = 0; i < 5; ++i ) - { - assert( new_addrs[i] == addrs[i] ); - } - - return 0; -} +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +// This demo shows you how to read and write JSON objects and arrays +// using header files only, i.e. not linking to the JSON Spirit object library. +// In this demo objects are stored as a vector of name/value pairs. + +#include "json5_parser_reader_template.h" +#include "json5_parser_writer_template.h" +#include +#include + +#ifndef JSON_SPIRIT_VALUE_ENABLED +#error Please define JSON_SPIRIT_VALUE_ENABLED for the Value type to be enabled +#endif + +using namespace std; +using namespace json5_parser; + +struct Address +{ + int house_number_; + string road_; + string town_; + string county_; + string country_; +}; + +bool operator==( const Address& a1, const Address& a2 ) +{ + return ( a1.house_number_ == a2.house_number_ ) && + ( a1.road_ == a2.road_ ) && + ( a1.town_ == a2.town_ ) && + ( a1.county_ == a2.county_ ) && + ( a1.country_ == a2.country_ ); +} + +void write_address( Array& a, const Address& addr ) +{ + Object addr_obj; + + addr_obj.push_back( Pair( "house_number", addr.house_number_ ) ); + addr_obj.push_back( Pair( "road", addr.road_ ) ); + addr_obj.push_back( Pair( "town", addr.town_ ) ); + addr_obj.push_back( Pair( "county", addr.county_ ) ); + addr_obj.push_back( Pair( "country", addr.country_ ) ); + + a.push_back( addr_obj ); +} + +Address read_address( const Object& obj ) +{ + Address addr; + + for( Object::size_type i = 0; i != obj.size(); ++i ) + { + const Pair& pair = obj[i]; + + const string& name = pair.name_; + const Value& value = pair.value_; + + if( name == "house_number" ) + { + addr.house_number_ = value.get_int(); + } + else if( name == "road" ) + { + addr.road_ = value.get_str(); + } + else if( name == "town" ) + { + addr.town_ = value.get_str(); + } + else if( name == "county" ) + { + addr.county_ = value.get_str(); + } + else if( name == "country" ) + { + addr.country_ = value.get_str(); + } + else + { + assert( false ); + } + } + + return addr; +} + +void write_addrs( const char* file_name, const Address addrs[] ) +{ + Array addr_array; + + for( int i = 0; i < 5; ++i ) + { + write_address( addr_array, addrs[i] ); + } + + ofstream os( file_name ); + + write_stream( Value( addr_array ), os, pretty_print ); // NB need to convert Array to a Value + + os.close(); +} + +vector< Address > read_addrs( const char* file_name ) +{ + ifstream is( file_name ); + + Value value; + + read_stream( is, value ); + + const Array& addr_array = value.get_array(); + + vector< Address > addrs; + + for( unsigned int i = 0; i < addr_array.size(); ++i ) + { + addrs.push_back( read_address( addr_array[i].get_obj() ) ); + } + + return addrs; +} + +int main() +{ + const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, + { 1, "West Street", "Hull", "Yorkshire", "England" }, + { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, + { 45, "North Road", "Paignton", "Devon", "England" }, + { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; + + const char* file_name( "demo.txt" ); + + write_addrs( file_name, addrs ); + + vector< Address > new_addrs = read_addrs( file_name ); + + assert( new_addrs.size() == 5 ); + + for( int i = 0; i < 5; ++i ) + { + assert( new_addrs[i] == addrs[i] ); + } + + return 0; +} diff --git a/json_map_demo/json_map_demo.cpp b/json_map_demo/json_map_demo.cpp index 28778e7..e9c428c 100644 --- a/json_map_demo/json_map_demo.cpp +++ b/json_map_demo/json_map_demo.cpp @@ -1,133 +1,133 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -// This demo shows you how to read and write JSON objects and arrays. -// In this demo objects are stored as a map of names to values. - -#include "json5_parser.h" -#include -#include - -#ifndef JSON_SPIRIT_MVALUE_ENABLED -#error Please define JSON_SPIRIT_MVALUE_ENABLED for the mValue type to be enabled -#endif - -using namespace std; -using namespace json5_parser; - -struct Address -{ - int house_number_; - string road_; - string town_; - string county_; - string country_; -}; - -bool operator==( const Address& a1, const Address& a2 ) -{ - return ( a1.house_number_ == a2.house_number_ ) && - ( a1.road_ == a2.road_ ) && - ( a1.town_ == a2.town_ ) && - ( a1.county_ == a2.county_ ) && - ( a1.country_ == a2.country_ ); -} - -void write_address( mArray& a, const Address& addr ) -{ - mObject addr_obj; - - addr_obj[ "house_number" ] = addr.house_number_; - addr_obj[ "road" ] = addr.road_; - addr_obj[ "town" ] = addr.town_; - addr_obj[ "county" ] = addr.county_; - addr_obj[ "country" ] = addr.country_; - - a.push_back( addr_obj ); -} - -const mValue& find_value( const mObject& obj, const string& name ) -{ - mObject::const_iterator i = obj.find( name ); - - assert( i != obj.end() ); - assert( i->first == name ); - - return i->second; -} - -Address read_address( const mObject& obj ) -{ - Address addr; - - addr.house_number_ = find_value( obj, "house_number" ).get_int(); - addr.road_ = find_value( obj, "road" ).get_str(); - addr.town_ = find_value( obj, "town" ).get_str(); - addr.county_ = find_value( obj, "county" ).get_str(); - addr.country_ = find_value( obj, "country" ).get_str(); - - return addr; -} - -void write_addrs( const char* file_name, const Address addrs[] ) -{ - mArray addr_array; - - for( int i = 0; i < 5; ++i ) - { - write_address( addr_array, addrs[i] ); - } - - ofstream os( file_name ); - - write_formatted( addr_array, os ); - - os.close(); -} - -vector< Address > read_addrs( const char* file_name ) -{ - ifstream is( file_name ); - - mValue value; - - read( is, value ); - - const mArray& addr_array = value.get_array(); - - vector< Address > addrs; - - for( vector< Address >::size_type i = 0; i < addr_array.size(); ++i ) - { - addrs.push_back( read_address( addr_array[i].get_obj() ) ); - } - - return addrs; -} - -int main() -{ - const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, - { 1, "West Street", "Hull", "Yorkshire", "England" }, - { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, - { 45, "North Road", "Paignton", "Devon", "England" }, - { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; - - const char* file_name( "demo.txt" ); - - write_addrs( file_name, addrs ); - - vector< Address > new_addrs = read_addrs( file_name ); - - assert( new_addrs.size() == 5 ); - - for( int i = 0; i < 5; ++i ) - { - assert( new_addrs[i] == addrs[i] ); - } - - return 0; -} +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +// This demo shows you how to read and write JSON objects and arrays. +// In this demo objects are stored as a map of names to values. + +#include "json5_parser.h" +#include +#include + +#ifndef JSON_SPIRIT_MVALUE_ENABLED +#error Please define JSON_SPIRIT_MVALUE_ENABLED for the mValue type to be enabled +#endif + +using namespace std; +using namespace json5_parser; + +struct Address +{ + int house_number_; + string road_; + string town_; + string county_; + string country_; +}; + +bool operator==( const Address& a1, const Address& a2 ) +{ + return ( a1.house_number_ == a2.house_number_ ) && + ( a1.road_ == a2.road_ ) && + ( a1.town_ == a2.town_ ) && + ( a1.county_ == a2.county_ ) && + ( a1.country_ == a2.country_ ); +} + +void write_address( mArray& a, const Address& addr ) +{ + mObject addr_obj; + + addr_obj[ "house_number" ] = addr.house_number_; + addr_obj[ "road" ] = addr.road_; + addr_obj[ "town" ] = addr.town_; + addr_obj[ "county" ] = addr.county_; + addr_obj[ "country" ] = addr.country_; + + a.push_back( addr_obj ); +} + +const mValue& find_value( const mObject& obj, const string& name ) +{ + mObject::const_iterator i = obj.find( name ); + + assert( i != obj.end() ); + assert( i->first == name ); + + return i->second; +} + +Address read_address( const mObject& obj ) +{ + Address addr; + + addr.house_number_ = find_value( obj, "house_number" ).get_int(); + addr.road_ = find_value( obj, "road" ).get_str(); + addr.town_ = find_value( obj, "town" ).get_str(); + addr.county_ = find_value( obj, "county" ).get_str(); + addr.country_ = find_value( obj, "country" ).get_str(); + + return addr; +} + +void write_addrs( const char* file_name, const Address addrs[] ) +{ + mArray addr_array; + + for( int i = 0; i < 5; ++i ) + { + write_address( addr_array, addrs[i] ); + } + + ofstream os( file_name ); + + write_formatted( addr_array, os ); + + os.close(); +} + +vector< Address > read_addrs( const char* file_name ) +{ + ifstream is( file_name ); + + mValue value; + + read( is, value ); + + const mArray& addr_array = value.get_array(); + + vector< Address > addrs; + + for( vector< Address >::size_type i = 0; i < addr_array.size(); ++i ) + { + addrs.push_back( read_address( addr_array[i].get_obj() ) ); + } + + return addrs; +} + +int main() +{ + const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, + { 1, "West Street", "Hull", "Yorkshire", "England" }, + { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, + { 45, "North Road", "Paignton", "Devon", "England" }, + { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; + + const char* file_name( "demo.txt" ); + + write_addrs( file_name, addrs ); + + vector< Address > new_addrs = read_addrs( file_name ); + + assert( new_addrs.size() == 5 ); + + for( int i = 0; i < 5; ++i ) + { + assert( new_addrs[i] == addrs[i] ); + } + + return 0; +} ; \ No newline at end of file diff --git a/json_test/json5_parser_reader_test.cpp b/json_test/json5_parser_reader_test.cpp index 1137e51..eab6445 100644 --- a/json_test/json5_parser_reader_test.cpp +++ b/json_test/json5_parser_reader_test.cpp @@ -1,925 +1,925 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_reader_test.h" -#include "utils_test.h" -#include "json5_parser_reader.h" -#include "json5_parser_value.h" -#include "json5_parser_writer.h" - -#include -#include -#include -#include -#include - -using namespace json5_parser; -using namespace std; -using namespace boost; -using namespace boost::assign; - -namespace -{ - template< class String_type, class Value_type > - void test_read( const String_type& s, Value_type& value ) - { - // performs both types of read and checks they produce the same value - - read( s, value ); - - Value_type value_2; - - read_or_throw( s, value_2 ); - - assert_eq( value, value_2 ); - } - - template< class Config_type > - struct Test_runner - { - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; - typedef typename Config_type::Pair_type Pair_type; - typedef typename String_type::value_type Char_type; - typedef typename String_type::const_iterator Iter_type; - typedef std::basic_istringstream< Char_type > Istringstream_type; - typedef std::basic_istream< Char_type > Istream_type; - - String_type to_str( const char* c_str ) - { - return ::to_str< String_type >( c_str ); - } - - Test_runner() - { - } - - void check_eq( const Object_type& obj_1, const Object_type& obj_2 ) - { - const typename Object_type::size_type size( obj_1.size() ); - - assert_eq( size, obj_2.size() ); - - typename Object_type::const_iterator i1 = obj_1.begin(); - typename Object_type::const_iterator i2 = obj_2.begin(); - - for( ; i1 != obj_1.end(); ++i1, ++i2 ) - { - assert_eq( *i1, *i2 ); - } - } - - void add_value( Object_type& obj, const char* c_name, const Value_type& value ) - { - Config_type::add( obj, to_str( c_name ), value ); - } - - void add_c_str( Object_type& obj, const char* c_name, const char* c_value ) - { - add_value( obj, c_name, to_str( c_value ) ); - } - - void test_syntax( const char* c_str, bool expected_success = true ) - { - const String_type str = to_str( c_str ); - - Value_type value; - - const bool ok = read( str, value ); - - assert_eq( ok, expected_success ); - - try - { - read_or_throw( str, value ); - - assert( expected_success ); - } - catch( ... ) - { - assert( !expected_success ); - } - } - - template< typename Int > - void test_syntax( Int min_int, Int max_int ) - { - ostringstream os; - - os << "[" << min_int << "," << max_int << "]"; - - test_syntax( os.str().c_str() ); - } - - void test_syntax() - { - test_syntax( "{}" ); - test_syntax( "{ }" ); - test_syntax( "{ } " ); - test_syntax( "{ } " ); - test_syntax( "{\"\":\"\"}" ); - test_syntax( "{\"test\":\"123\"}" ); - test_syntax( "{\"test\" : \"123\"}" ); - test_syntax( "{\"testing testing testing\":\"123\"}" ); - test_syntax( "{\"\":\"abc\"}" ); - test_syntax( "{\"abc\":\"\"}" ); - test_syntax( "{\"\":\"\"}" ); - test_syntax( "{\"test\":true}" ); - test_syntax( "{\"test\":false}" ); - test_syntax( "{\"test\":null}" ); - test_syntax( "{\"test1\":\"123\",\"test2\":\"456\"}" ); - test_syntax( "{\"test1\":\"123\",\"test2\":\"456\",\"test3\":\"789\"}" ); - test_syntax( "{\"test1\":{\"test2\":\"123\",\"test3\":\"456\"}}" ); - test_syntax( "{\"test1\":{\"test2\":{\"test3\":\"456\"}}}" ); - test_syntax( "{\"test1\":[\"a\",\"bb\",\"cc\"]}" ); - test_syntax( "{\"test1\":[true,false,null]}" ); - test_syntax( "{\"test1\":[true,\"abc\",{\"a\":\"b\"},{\"d\":false},null]}" ); - test_syntax( "{\"test1\":[1,2,-3]}" ); - test_syntax( "{\"test1\":[1.1,2e4,-1.234e-34]}" ); - test_syntax( "{\n" - "\t\"test1\":\n" - "\t\t{\n" - "\t\t\t\"test2\":\"123\",\n" - "\t\t\t\"test3\":\"456\"\n" - "\t\t}\n" - "}\n" ); - test_syntax( "[]" ); - test_syntax( "[ ]" ); - test_syntax( "[1,2,3]" ); - test_syntax( "[ 1, -2, 3]" ); - test_syntax( "[ 1.2, -2e6, -3e-6 ]" ); - test_syntax( "[ 1.2, \"str\", -3e-6, { \"field\" : \"data\" } ]" ); - - test_syntax( INT_MIN, INT_MAX ); - test_syntax( LLONG_MIN, LLONG_MAX ); - test_syntax( "[1 2 3]", false ); - test_syntax( "[1,\n2,\n3,]"); - test_syntax( "[0xfreedom]",false); - test_syntax( "[0xreefer]",false); - } - - Value_type read_cstr( const char* c_str ) - { - Value_type value; - - test_read( to_str( c_str ), value ); - - return value; - } - - void read_cstr( const char* c_str, Value_type& value ) - { - test_read( to_str( c_str ), value ); - } - - void check_reading( const char* c_str ) - { - Value_type value; - - String_type in_s( to_str( c_str ) ); - - test_read( in_s, value ); - - const String_type result = write_formatted( value ); - - assert_eq( in_s, result ); - } - - template< typename Int > - void check_reading( Int min_int, Int max_int ) - { - ostringstream os; - - os << "[\n" - " " << min_int << ",\n" - " " << max_int << "\n" - "]"; - - check_reading( os.str().c_str() ); - } - - void test_reading() - { - check_reading( "{\n}" ); - - { - Object_type obj; - Value_type value; - - read_cstr( "{\n" - " name1 : 'value \\\n1',\n" - "}", value ); - - add_c_str( obj, "name1", "value 1" ); - - check_eq( value.get_obj(), obj ); - } - - Object_type obj; - Value_type value; - - read_cstr( "{\n" - " \"name 1\" : \"value 1\"\n" - "}", value ); - - add_c_str( obj, "name 1", "value 1" ); - - check_eq( value.get_obj(), obj ); - - read_cstr( "{\"name 1\":\"value 1\",\"name 2\":\"value 2\"}", value ); - - add_c_str( obj, "name 2", "value 2" ); - - check_eq( value.get_obj(), obj ); - - read_cstr( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : \"value 2\",\n" - " \"name 3\" : \"value 3\"\n" - "}", value ); - - add_c_str( obj, "name 3", "value 3" ); - - check_eq( value.get_obj(), obj ); - - check_reading( "{\n" - " \"\" : \"value\",\n" - " \"name\" : \"\"\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : {\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : \"value_4\"\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : {\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : \"value_4\",\n" - " \"name_5\" : {\n" - " \"name_6\" : \"value_6\",\n" - " \"name_7\" : \"value_7\"\n" - " }\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : {\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : {\n" - " \"name_5\" : \"value_5\",\n" - " \"name_6\" : \"value_6\"\n" - " },\n" - " \"name_7\" : \"value_7\"\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : {\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : {\n" - " \"name_5\" : \"value_5\",\n" - " \"name_6\" : \"value_6\"\n" - " },\n" - " \"name_7\" : \"value_7\"\n" - " },\n" - " \"name_8\" : \"value_8\",\n" - " \"name_9\" : {\n" - " \"name_10\" : \"value_10\"\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : {\n" - " \"name 2\" : {\n" - " \"name 3\" : {\n" - " \"name_4\" : {\n" - " \"name_5\" : \"value\"\n" - " }\n" - " }\n" - " }\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : true,\n" - " \"name 3\" : false,\n" - " \"name_4\" : \"value_4\",\n" - " \"name_5\" : true\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : null,\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : null\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : 123,\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : -567\n" - "}" ); - - check_reading( "[\n]" ); - - check_reading( "[\n" - " 1\n" - "]" ); - - check_reading( "[\n" - " 1,\n" - " 1.2,\n" - " \"john]\",\n" - " true,\n" - " false,\n" - " null\n" - "]" ); - - check_reading( "[\n" - " 1,\n" - " [\n" - " 2,\n" - " 3\n" - " ]\n" - "]" ); - - check_reading( "[\n" - " 1,\n" - " [\n" - " 2,\n" - " 3\n" - " ],\n" - " [\n" - " 4,\n" - " [\n" - " 5,\n" - " 6,\n" - " 7\n" - " ]\n" - " ]\n" - "]" ); - - check_reading( "[\n" - " {\n" - " \"name\" : \"value\"\n" - " }\n" - "]" ); - - check_reading( "{\n" - " \"name\" : [\n" - " 1\n" - " ]\n" - "}" ); - - check_reading( "[\n" - " {\n" - " \"name 1\" : \"value\",\n" - " \"name 2\" : [\n" - " 1,\n" - " 2,\n" - " 3\n" - " ]\n" - " }\n" - "]" ); - - check_reading( "{\n" - " \"name 1\" : [\n" - " 1,\n" - " {\n" - " \"name 2\" : \"value 2\"\n" - " }\n" - " ]\n" - "}" ); - - check_reading( "[\n" - " {\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : [\n" - " 1,\n" - " 2,\n" - " {\n" - " \"name 3\" : \"value 3\"\n" - " }\n" - " ]\n" - " }\n" - "]" ); - - check_reading( "{\n" - " \"name 1\" : [\n" - " 1,\n" - " {\n" - " \"name 2\" : [\n" - " 1,\n" - " 2,\n" - " 3\n" - " ]\n" - " }\n" - " ]\n" - "}" ); - - check_reading( INT_MIN, INT_MAX ); - check_reading( LLONG_MIN, LLONG_MAX ); - } - - void test_reading_reals() - { - Value_type value; - - const String_type in_s = to_str( "[1.200000000000000,1.234567890123456e+125,-1.234000000000000e-123," - " 1.000000000000000e-123,1234567890.123456,123,]" ); - - basic_istringstream< Char_type > is( in_s ); - - const bool ok = read( is, value ); - - assert_eq( ok, true ); - assert_eq( value.type(), array_type ); - - const Array_type arr = value.get_array(); - - assert_eq( arr.size(), 6u ); - assert_eq( arr[0].get_real(), 1.2, 1e-16 ); - assert_eq( arr[1].get_real(), 1.234567890123456e+125, 1e+110 ); - assert_eq( arr[2].get_real(), -1.234e-123, 1e+108 ); - assert_eq( arr[3].get_real(), 1e-123, 1e+108 ); - assert_eq( arr[4].get_real(), 1234567890.123456, 1e-7 ); - assert_eq( arr[5].get_real(), 123, 1e-13 ); - } - - void test_from_stream( const char* json_str, bool expected_success, - const Error_position& expected_error ) - { - Value_type value; - - String_type in_s( to_str( json_str ) ); - - basic_istringstream< Char_type > is( in_s ); - - const bool ok = read( is, value ); - - assert_eq( ok, expected_success ); - - if( ok ) - { - assert_eq( in_s, write( value ) ); - } - - try - { - basic_istringstream< Char_type > is( in_s ); - - read_or_throw( is, value ); - - assert_eq( expected_success, true ); - - assert_eq( in_s, write( value ) ); - } - catch( const Error_position error ) - { - assert_eq( error, expected_error ); - } - } - - void test_from_stream() - { - test_from_stream( "[1,2]", true, Error_position() ); - test_from_stream( "\n\n foo", false, Error_position( 3, 2,"not a value" ) ); - } - - void test_escape_chars( const char* json_str, const char* c_str ) - { - Value_type value; - - string s( string( "{\"" ) + json_str + "\" : \"" + json_str + "\"} " ); - - read_cstr( s.c_str(), value ); - - const Pair_type& pair( *value.get_obj().begin() ); - - assert_eq( Config_type::get_name ( pair ), to_str( c_str ) ); - assert_eq( Config_type::get_value( pair ), to_str( c_str ) ); - } - - void test_escape_chars() - { - test_escape_chars( "\\t", "\t"); - test_escape_chars( "a\\t", "a\t" ); - test_escape_chars( "\\tb", "\tb" ); - test_escape_chars( "a\\tb", "a\tb" ); - test_escape_chars( "a\\tb", "a\tb" ); - test_escape_chars( "a123\\tb", "a123\tb" ); - test_escape_chars( "\\t\\n\\\\", "\t\n\\" ); - test_escape_chars( "\\/\\r\\b\\f\\\"", "/\r\b\f\"" ); - test_escape_chars( "\\h\\j\\k", "" ); // invalid esc chars - test_escape_chars( "\\x61\\x62\\x63", "abc" ); - test_escape_chars( "a\\x62c", "abc" ); - test_escape_chars( "\\x01\\x02\\x7F", "\x01\x02\x7F" ); // NB x7F is the greatest char spirit will parse - test_escape_chars( "\\u0061\\u0062\\u0063", "abc" ); - } - - void check_is_null( const char* c_str ) - { - assert_eq( read_cstr( c_str ).type(), null_type ); - } - - template< typename T > - void check_value( const char* c_str, const T& expected_value ) - { - const Value_type v( read_cstr( c_str ) ); - - assert_eq( v.template get_value< T >(), expected_value ); - } - - void test_values() - { - check_value( "1", 1 ); - check_value( "+Infinity", std::numeric_limits::infinity() ); - check_value( "Infinity", std::numeric_limits::infinity() ); - check_value( "-Infinity", -std::numeric_limits::infinity() ); - check_value( "0xfe", 0xfe ); - check_value( "1.5", 1.5 ); - check_value( "\"Test\"", to_str( "Test" ) ); - check_value( "true", true ); - check_value( "false", false ); - check_is_null( "null" ); - } - - void check_read_fails( const char* c_str, int line, int column, const string& reason ) - { - Value_type value; - - try - { - read_cstr( c_str, value ); - - assert( false ); - } - catch( const Error_position posn ) - { - assert_eq( posn, Error_position( line, column, reason ) ); - } - } - - void test_error_cases() - { - check_read_fails( "", 1, 1, "not a value" ); - check_read_fails( "foo", 1, 1, "not a value" ); - check_read_fails( " foo", 1, 2, "not a value" ); - check_read_fails( " foo", 1, 3, "not a value" ); - check_read_fails( "\n\n foo", 3, 2, "not a value" ); - check_read_fails( "!!!", 1, 1, "not a value" ); - check_read_fails( "\"bar", 1, 1, "not a value" ); - check_read_fails( "0xreefer", 1, 3, "not a hexadecimal number" ); - check_read_fails( "bar\"", 1, 1, "not a value" ); - check_read_fails( "[1}", 1, 3, "not an array" ); - check_read_fails( "[1,2?", 1, 5, "not an array" ); - check_read_fails( "[1,2}", 1, 5, "not an array" ); - check_read_fails( "[1;2]", 1, 3, "not an array" ); - check_read_fails( "{\"name\":\"value\"]", 1, 16, "not an object" ); - check_read_fails( "{\"name\",\"value\"}", 1, 8, "no colon in pair" ); - check_read_fails( "{\n1:\"value\"}", 2, 1, "not an object" ); - check_read_fails( "{\n name\":\"value\"}", 2, 7, "no colon in pair" ); - check_read_fails( "{\"name\":foo}", 1, 9, "not a value" ); - check_read_fails( "{\"name\":0xfreedom}", 1, 12, "not an object" ); - check_read_fails( "{\"name\":value\"}", 1, 9, "not a value" ); - check_read_fails( "{'name':\"value\"}", 1, 2, "not an object" ); - } - - typedef vector< int > Ints; - - bool test_read_range( Iter_type& first, Iter_type last, Value_type& value ) - { - Iter_type first_ = first; - - const bool ok = read( first, last, value ); - - try - { - Value_type value_; - - read_or_throw( first_, last, value_ ); - - assert_eq( ok, true ); - assert_eq( value, value_ ); - } - catch( ... ) - { - assert_eq( ok, false ); - } - - return ok; - } - - void check_value_sequence( Iter_type first, Iter_type last, const Ints& expected_values, bool all_input_consumed ) - { - Value_type value; - - for( Ints::size_type i = 0; i < expected_values.size(); ++i ) - { - const bool ok = test_read_range( first, last, value ); - - assert_eq( ok, true ); - - const bool is_last( i == expected_values.size() - 1 ); - - assert_eq( first == last, is_last ? all_input_consumed : false ); - } - - const bool ok = test_read_range( first, last, value ); - - assert_eq( ok, false ); - } - - void check_value_sequence( Istream_type& is, const Ints& expected_values, bool all_input_consumed ) - { - Value_type value; - - for( Ints::size_type i = 0; i < expected_values.size(); ++i ) - { - read_or_throw( is, value ); - - assert_eq( value.get_int(), expected_values[i] ); - - const bool is_last( i == expected_values.size() - 1 ); - - assert_eq( is.eof(), is_last ? all_input_consumed : false ); - } - - try - { - read_or_throw( is, value ); - - assert( false ); - } - catch( ... ) - { - } - - assert_eq( is.eof(), true ); - } - - void check_value_sequence( const char* c_str, const Ints& expected_values, bool all_input_consumed ) - { - const String_type s( to_str( c_str ) ); - - check_value_sequence( s.begin(), s.end(), expected_values, all_input_consumed ); - - Istringstream_type is( s ); - - check_value_sequence( is, expected_values, all_input_consumed ); - } - - void check_array( const Value_type& value, typename Array_type::size_type expected_size ) - { - assert_eq( value.type(), array_type ); - - const Array_type& arr = value.get_array(); - - assert_eq( arr.size(), expected_size ); - - for( typename Array_type::size_type i = 0; i < expected_size; ++i ) - { - const Value_type& val = arr[i]; - - assert_eq( val.type(), int_type ); - assert_eq( val.get_int(), int( i + 1 ) ); - } - } - - void check_reading_array( Iter_type& begin, Iter_type end, typename Array_type::size_type expected_size ) - { - Value_type value; - - test_read_range( begin, end, value ); - - check_array( value, expected_size ); - } - - void check_reading_array( Istream_type& is, typename Array_type::size_type expected_size ) - { - Value_type value; - - read( is, value ); - - check_array( value, expected_size ); - } - - void check_reading_arrays( const char* arrays_str ) - { - const String_type str( to_str( arrays_str ) ); - - Iter_type begin = str.begin(); - const Iter_type end = str.end(); - - check_reading_array( begin, end, 0 ); - check_reading_array( begin, end, 1 ); - check_reading_array( begin, end, 2 ); - check_reading_array( begin, end, 3 ); - - Istringstream_type is( str ); - - check_reading_array( is, 0 ); - check_reading_array( is, 1 ); - check_reading_array( is, 2 ); - check_reading_array( is, 3 ); - } - - void test_sequence_of_values() - { - check_value_sequence( "", Ints(), false ); - check_value_sequence( " ", Ints(), false ); - check_value_sequence( " ", Ints(), false ); - check_value_sequence( " 10 ", list_of( 10 ), false ); - check_value_sequence( " 10 11 ", list_of( 10 )( 11 ), false ); - check_value_sequence( " 10 11 12", list_of( 10 )( 11 )( 12 ), true); - check_value_sequence( "10 11 12", list_of( 10 )( 11 )( 12 ), true); - - // - - check_reading_arrays( "[] [ 1 ] [ 1, 2 ] [ 1, 2, 3 ]" ); - // check_reading_arrays( "[][1][1,2][1,2,3]" ); // fails due to multi_pass iterator bug, - // use stream_reader class instead - } - - void test_uint64( const char* value_str, int expected_int, int64_t expected_int64, uint64_t expected_uint64 ) - { - const Value_type v( read_cstr( value_str ) ); - - assert_eq( v.get_int(), expected_int ); - assert_eq( v.get_int64(), expected_int64 ); - assert_eq( v.get_uint64(), expected_uint64 ); - } - - void test_uint64() - { - test_uint64( "0", 0, 0, 0 ); - test_uint64( "1", 1, 1, 1 ); - test_uint64( "-1", -1, -1, ULLONG_MAX ); - test_uint64( "18446744073709551615", -1, -1, ULLONG_MAX ); - } - - void test_types() - { - Value_type value; - - read( to_str( "[ \"foo\", true, false, 1, 12.3, null ]" ), value ); - - assert_eq( value.type(), array_type ); - - const Array_type& a = value.get_array(); - - assert_eq( a[0].get_str(), to_str( "foo" ) ); - assert_eq( a[1].get_bool(), true ); - assert_eq( a[2].get_bool(), false ); - assert_eq( a[3].get_int(), 1 ); - assert_eq( a[3].get_int64(), 1 ); - assert_eq( a[3].get_uint64(), 1u ); - assert_eq( a[3].get_real(), 1.0 ); - assert_eq( a[4].get_real(), 12.3 ); - assert_eq( a[5].is_null(), true ); - } - - void test_comments() - { - Value_type value_1; - - read_cstr( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : \"value 2 /* not a comment but data */\",\n" - " \"name 3\" : \"value 3 // not a comment but data\"\n" - "}", value_1 ); - - Value_type value_2; - - read_cstr( "{// a comment\n " - " \"name 1\" : /* another comment */ \"value 1\",\n" - " \"name 2\" : \"value 2 /* not a comment but data */\",\n" - " // \"name 2\" : \"value 2\",\n" - " \"name 3\" : \"value 3 // not a comment but data\"\n" - "/* multi\n" - "line\n" - "comment */}", value_2 ); - - assert_eq( value_1, value_2 ); - } - - void run_tests() - { - test_syntax(); - test_reading(); - test_reading_reals(); - test_from_stream(); - test_escape_chars(); - test_values(); - test_error_cases(); - test_sequence_of_values(); - test_uint64(); - test_types(); - test_comments(); - } - }; - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void test_wide_esc_u() - { - wValue value; - - test_read( L"[\"\\uABCD\"]", value ); - - const wstring s( value.get_array()[0].get_str() ); - - assert_eq( s.length(), static_cast< wstring::size_type >( 1u ) ); - assert_eq( s[0], 0xABCD ); - } -#endif - -#ifdef JSON_SPIRIT_VALUE_ENABLED - void test_extended_ascii( const string& s ) - { - Value value; - - test_read( "[\"" + s + "\"]", value ); - - assert_eq( value.get_array()[0].get_str(), "äöüß" ); - } - - void test_extended_ascii() - { - test_extended_ascii( "\\u00E4\\u00F6\\u00FC\\u00DF" ); - test_extended_ascii( "äöüß" ); - } -#endif -} - -//#include - -void json5_parser::test_reader() -{ -#ifdef JSON_SPIRIT_VALUE_ENABLED - Test_runner< Config >().run_tests(); - test_extended_ascii(); -#endif -#ifdef JSON_SPIRIT_MVALUE_ENABLED - Test_runner< mConfig >().run_tests(); -#endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wConfig >().run_tests(); - test_wide_esc_u(); -#endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wmConfig >().run_tests(); -#endif - -#ifndef _DEBUG - //ifstream ifs( "test.txt" ); - - //string s; - - //getline( ifs, s ); - - //timer t; - - //for( int i = 0; i < 2000; ++i ) - //{ - // Value value; - - // read( s, value ); - //} - - //cout << t.elapsed() << endl; - -// const string so = write( value ); - - //Object obj; - - //for( int i = 0; i < 100000; ++i ) - //{ - // obj.push_back( Pair( "\x01test\x7F", lexical_cast< string >( i ) ) ); - //} - - //const string s = write( obj ); - - //Value value; - - //timer t; - - //read( s, value ); - - //cout << t.elapsed() << endl; - - //cout << "obj size " << value.get_obj().size(); -#endif -} +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_reader_test.h" +#include "utils_test.h" +#include "json5_parser_reader.h" +#include "json5_parser_value.h" +#include "json5_parser_writer.h" + +#include +#include +#include +#include +#include + +using namespace json5_parser; +using namespace std; +using namespace boost; +using namespace boost::assign; + +namespace +{ + template< class String_type, class Value_type > + void test_read( const String_type& s, Value_type& value ) + { + // performs both types of read and checks they produce the same value + + read( s, value ); + + Value_type value_2; + + read_or_throw( s, value_2 ); + + assert_eq( value, value_2 ); + } + + template< class Config_type > + struct Test_runner + { + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + typedef typename Config_type::Pair_type Pair_type; + typedef typename String_type::value_type Char_type; + typedef typename String_type::const_iterator Iter_type; + typedef std::basic_istringstream< Char_type > Istringstream_type; + typedef std::basic_istream< Char_type > Istream_type; + + String_type to_str( const char* c_str ) + { + return ::to_str< String_type >( c_str ); + } + + Test_runner() + { + } + + void check_eq( const Object_type& obj_1, const Object_type& obj_2 ) + { + const typename Object_type::size_type size( obj_1.size() ); + + assert_eq( size, obj_2.size() ); + + typename Object_type::const_iterator i1 = obj_1.begin(); + typename Object_type::const_iterator i2 = obj_2.begin(); + + for( ; i1 != obj_1.end(); ++i1, ++i2 ) + { + assert_eq( *i1, *i2 ); + } + } + + void add_value( Object_type& obj, const char* c_name, const Value_type& value ) + { + Config_type::add( obj, to_str( c_name ), value ); + } + + void add_c_str( Object_type& obj, const char* c_name, const char* c_value ) + { + add_value( obj, c_name, to_str( c_value ) ); + } + + void test_syntax( const char* c_str, bool expected_success = true ) + { + const String_type str = to_str( c_str ); + + Value_type value; + + const bool ok = read( str, value ); + + assert_eq( ok, expected_success ); + + try + { + read_or_throw( str, value ); + + assert( expected_success ); + } + catch( ... ) + { + assert( !expected_success ); + } + } + + template< typename Int > + void test_syntax( Int min_int, Int max_int ) + { + ostringstream os; + + os << "[" << min_int << "," << max_int << "]"; + + test_syntax( os.str().c_str() ); + } + + void test_syntax() + { + test_syntax( "{}" ); + test_syntax( "{ }" ); + test_syntax( "{ } " ); + test_syntax( "{ } " ); + test_syntax( "{\"\":\"\"}" ); + test_syntax( "{\"test\":\"123\"}" ); + test_syntax( "{\"test\" : \"123\"}" ); + test_syntax( "{\"testing testing testing\":\"123\"}" ); + test_syntax( "{\"\":\"abc\"}" ); + test_syntax( "{\"abc\":\"\"}" ); + test_syntax( "{\"\":\"\"}" ); + test_syntax( "{\"test\":true}" ); + test_syntax( "{\"test\":false}" ); + test_syntax( "{\"test\":null}" ); + test_syntax( "{\"test1\":\"123\",\"test2\":\"456\"}" ); + test_syntax( "{\"test1\":\"123\",\"test2\":\"456\",\"test3\":\"789\"}" ); + test_syntax( "{\"test1\":{\"test2\":\"123\",\"test3\":\"456\"}}" ); + test_syntax( "{\"test1\":{\"test2\":{\"test3\":\"456\"}}}" ); + test_syntax( "{\"test1\":[\"a\",\"bb\",\"cc\"]}" ); + test_syntax( "{\"test1\":[true,false,null]}" ); + test_syntax( "{\"test1\":[true,\"abc\",{\"a\":\"b\"},{\"d\":false},null]}" ); + test_syntax( "{\"test1\":[1,2,-3]}" ); + test_syntax( "{\"test1\":[1.1,2e4,-1.234e-34]}" ); + test_syntax( "{\n" + "\t\"test1\":\n" + "\t\t{\n" + "\t\t\t\"test2\":\"123\",\n" + "\t\t\t\"test3\":\"456\"\n" + "\t\t}\n" + "}\n" ); + test_syntax( "[]" ); + test_syntax( "[ ]" ); + test_syntax( "[1,2,3]" ); + test_syntax( "[ 1, -2, 3]" ); + test_syntax( "[ 1.2, -2e6, -3e-6 ]" ); + test_syntax( "[ 1.2, \"str\", -3e-6, { \"field\" : \"data\" } ]" ); + + test_syntax( INT_MIN, INT_MAX ); + test_syntax( LLONG_MIN, LLONG_MAX ); + test_syntax( "[1 2 3]", false ); + test_syntax( "[1,\n2,\n3,]"); + test_syntax( "[0xfreedom]",false); + test_syntax( "[0xreefer]",false); + } + + Value_type read_cstr( const char* c_str ) + { + Value_type value; + + test_read( to_str( c_str ), value ); + + return value; + } + + void read_cstr( const char* c_str, Value_type& value ) + { + test_read( to_str( c_str ), value ); + } + + void check_reading( const char* c_str ) + { + Value_type value; + + String_type in_s( to_str( c_str ) ); + + test_read( in_s, value ); + + const String_type result = write_formatted( value ); + + assert_eq( in_s, result ); + } + + template< typename Int > + void check_reading( Int min_int, Int max_int ) + { + ostringstream os; + + os << "[\n" + " " << min_int << ",\n" + " " << max_int << "\n" + "]"; + + check_reading( os.str().c_str() ); + } + + void test_reading() + { + check_reading( "{\n}" ); + + { + Object_type obj; + Value_type value; + + read_cstr( "{\n" + " name1 : 'value \\\n1',\n" + "}", value ); + + add_c_str( obj, "name1", "value 1" ); + + check_eq( value.get_obj(), obj ); + } + + Object_type obj; + Value_type value; + + read_cstr( "{\n" + " \"name 1\" : \"value 1\"\n" + "}", value ); + + add_c_str( obj, "name 1", "value 1" ); + + check_eq( value.get_obj(), obj ); + + read_cstr( "{\"name 1\":\"value 1\",\"name 2\":\"value 2\"}", value ); + + add_c_str( obj, "name 2", "value 2" ); + + check_eq( value.get_obj(), obj ); + + read_cstr( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : \"value 2\",\n" + " \"name 3\" : \"value 3\"\n" + "}", value ); + + add_c_str( obj, "name 3", "value 3" ); + + check_eq( value.get_obj(), obj ); + + check_reading( "{\n" + " \"\" : \"value\",\n" + " \"name\" : \"\"\n" + "}" ); + + check_reading( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : {\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : \"value_4\"\n" + " }\n" + "}" ); + + check_reading( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : {\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : \"value_4\",\n" + " \"name_5\" : {\n" + " \"name_6\" : \"value_6\",\n" + " \"name_7\" : \"value_7\"\n" + " }\n" + " }\n" + "}" ); + + check_reading( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : {\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : {\n" + " \"name_5\" : \"value_5\",\n" + " \"name_6\" : \"value_6\"\n" + " },\n" + " \"name_7\" : \"value_7\"\n" + " }\n" + "}" ); + + check_reading( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : {\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : {\n" + " \"name_5\" : \"value_5\",\n" + " \"name_6\" : \"value_6\"\n" + " },\n" + " \"name_7\" : \"value_7\"\n" + " },\n" + " \"name_8\" : \"value_8\",\n" + " \"name_9\" : {\n" + " \"name_10\" : \"value_10\"\n" + " }\n" + "}" ); + + check_reading( "{\n" + " \"name 1\" : {\n" + " \"name 2\" : {\n" + " \"name 3\" : {\n" + " \"name_4\" : {\n" + " \"name_5\" : \"value\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}" ); + + check_reading( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : true,\n" + " \"name 3\" : false,\n" + " \"name_4\" : \"value_4\",\n" + " \"name_5\" : true\n" + "}" ); + + check_reading( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : null,\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : null\n" + "}" ); + + check_reading( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : 123,\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : -567\n" + "}" ); + + check_reading( "[\n]" ); + + check_reading( "[\n" + " 1\n" + "]" ); + + check_reading( "[\n" + " 1,\n" + " 1.2,\n" + " \"john]\",\n" + " true,\n" + " false,\n" + " null\n" + "]" ); + + check_reading( "[\n" + " 1,\n" + " [\n" + " 2,\n" + " 3\n" + " ]\n" + "]" ); + + check_reading( "[\n" + " 1,\n" + " [\n" + " 2,\n" + " 3\n" + " ],\n" + " [\n" + " 4,\n" + " [\n" + " 5,\n" + " 6,\n" + " 7\n" + " ]\n" + " ]\n" + "]" ); + + check_reading( "[\n" + " {\n" + " \"name\" : \"value\"\n" + " }\n" + "]" ); + + check_reading( "{\n" + " \"name\" : [\n" + " 1\n" + " ]\n" + "}" ); + + check_reading( "[\n" + " {\n" + " \"name 1\" : \"value\",\n" + " \"name 2\" : [\n" + " 1,\n" + " 2,\n" + " 3\n" + " ]\n" + " }\n" + "]" ); + + check_reading( "{\n" + " \"name 1\" : [\n" + " 1,\n" + " {\n" + " \"name 2\" : \"value 2\"\n" + " }\n" + " ]\n" + "}" ); + + check_reading( "[\n" + " {\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : [\n" + " 1,\n" + " 2,\n" + " {\n" + " \"name 3\" : \"value 3\"\n" + " }\n" + " ]\n" + " }\n" + "]" ); + + check_reading( "{\n" + " \"name 1\" : [\n" + " 1,\n" + " {\n" + " \"name 2\" : [\n" + " 1,\n" + " 2,\n" + " 3\n" + " ]\n" + " }\n" + " ]\n" + "}" ); + + check_reading( INT_MIN, INT_MAX ); + check_reading( LLONG_MIN, LLONG_MAX ); + } + + void test_reading_reals() + { + Value_type value; + + const String_type in_s = to_str( "[1.200000000000000,1.234567890123456e+125,-1.234000000000000e-123," + " 1.000000000000000e-123,1234567890.123456,123,]" ); + + basic_istringstream< Char_type > is( in_s ); + + const bool ok = read( is, value ); + + assert_eq( ok, true ); + assert_eq( value.type(), array_type ); + + const Array_type arr = value.get_array(); + + assert_eq( arr.size(), 6u ); + assert_eq( arr[0].get_real(), 1.2, 1e-16 ); + assert_eq( arr[1].get_real(), 1.234567890123456e+125, 1e+110 ); + assert_eq( arr[2].get_real(), -1.234e-123, 1e+108 ); + assert_eq( arr[3].get_real(), 1e-123, 1e+108 ); + assert_eq( arr[4].get_real(), 1234567890.123456, 1e-7 ); + assert_eq( arr[5].get_real(), 123, 1e-13 ); + } + + void test_from_stream( const char* json_str, bool expected_success, + const Error_position& expected_error ) + { + Value_type value; + + String_type in_s( to_str( json_str ) ); + + basic_istringstream< Char_type > is( in_s ); + + const bool ok = read( is, value ); + + assert_eq( ok, expected_success ); + + if( ok ) + { + assert_eq( in_s, write( value ) ); + } + + try + { + basic_istringstream< Char_type > is( in_s ); + + read_or_throw( is, value ); + + assert_eq( expected_success, true ); + + assert_eq( in_s, write( value ) ); + } + catch( const Error_position error ) + { + assert_eq( error, expected_error ); + } + } + + void test_from_stream() + { + test_from_stream( "[1,2]", true, Error_position() ); + test_from_stream( "\n\n foo", false, Error_position( 3, 2,"not a value" ) ); + } + + void test_escape_chars( const char* json_str, const char* c_str ) + { + Value_type value; + + string s( string( "{\"" ) + json_str + "\" : \"" + json_str + "\"} " ); + + read_cstr( s.c_str(), value ); + + const Pair_type& pair( *value.get_obj().begin() ); + + assert_eq( Config_type::get_name ( pair ), to_str( c_str ) ); + assert_eq( Config_type::get_value( pair ), to_str( c_str ) ); + } + + void test_escape_chars() + { + test_escape_chars( "\\t", "\t"); + test_escape_chars( "a\\t", "a\t" ); + test_escape_chars( "\\tb", "\tb" ); + test_escape_chars( "a\\tb", "a\tb" ); + test_escape_chars( "a\\tb", "a\tb" ); + test_escape_chars( "a123\\tb", "a123\tb" ); + test_escape_chars( "\\t\\n\\\\", "\t\n\\" ); + test_escape_chars( "\\/\\r\\b\\f\\\"", "/\r\b\f\"" ); + test_escape_chars( "\\h\\j\\k", "" ); // invalid esc chars + test_escape_chars( "\\x61\\x62\\x63", "abc" ); + test_escape_chars( "a\\x62c", "abc" ); + test_escape_chars( "\\x01\\x02\\x7F", "\x01\x02\x7F" ); // NB x7F is the greatest char spirit will parse + test_escape_chars( "\\u0061\\u0062\\u0063", "abc" ); + } + + void check_is_null( const char* c_str ) + { + assert_eq( read_cstr( c_str ).type(), null_type ); + } + + template< typename T > + void check_value( const char* c_str, const T& expected_value ) + { + const Value_type v( read_cstr( c_str ) ); + + assert_eq( v.template get_value< T >(), expected_value ); + } + + void test_values() + { + check_value( "1", 1 ); + check_value( "+Infinity", std::numeric_limits::infinity() ); + check_value( "Infinity", std::numeric_limits::infinity() ); + check_value( "-Infinity", -std::numeric_limits::infinity() ); + check_value( "0xfe", 0xfe ); + check_value( "1.5", 1.5 ); + check_value( "\"Test\"", to_str( "Test" ) ); + check_value( "true", true ); + check_value( "false", false ); + check_is_null( "null" ); + } + + void check_read_fails( const char* c_str, int line, int column, const string& reason ) + { + Value_type value; + + try + { + read_cstr( c_str, value ); + + assert( false ); + } + catch( const Error_position posn ) + { + assert_eq( posn, Error_position( line, column, reason ) ); + } + } + + void test_error_cases() + { + check_read_fails( "", 1, 1, "not a value" ); + check_read_fails( "foo", 1, 1, "not a value" ); + check_read_fails( " foo", 1, 2, "not a value" ); + check_read_fails( " foo", 1, 3, "not a value" ); + check_read_fails( "\n\n foo", 3, 2, "not a value" ); + check_read_fails( "!!!", 1, 1, "not a value" ); + check_read_fails( "\"bar", 1, 1, "not a value" ); + check_read_fails( "0xreefer", 1, 3, "not a hexadecimal number" ); + check_read_fails( "bar\"", 1, 1, "not a value" ); + check_read_fails( "[1}", 1, 3, "not an array" ); + check_read_fails( "[1,2?", 1, 5, "not an array" ); + check_read_fails( "[1,2}", 1, 5, "not an array" ); + check_read_fails( "[1;2]", 1, 3, "not an array" ); + check_read_fails( "{\"name\":\"value\"]", 1, 16, "not an object" ); + check_read_fails( "{\"name\",\"value\"}", 1, 8, "no colon in pair" ); + check_read_fails( "{\n1:\"value\"}", 2, 1, "not an object" ); + check_read_fails( "{\n name\":\"value\"}", 2, 7, "no colon in pair" ); + check_read_fails( "{\"name\":foo}", 1, 9, "not a value" ); + check_read_fails( "{\"name\":0xfreedom}", 1, 12, "not an object" ); + check_read_fails( "{\"name\":value\"}", 1, 9, "not a value" ); + check_read_fails( "{'name':\"value\"}", 1, 2, "not an object" ); + } + + typedef vector< int > Ints; + + bool test_read_range( Iter_type& first, Iter_type last, Value_type& value ) + { + Iter_type first_ = first; + + const bool ok = read( first, last, value ); + + try + { + Value_type value_; + + read_or_throw( first_, last, value_ ); + + assert_eq( ok, true ); + assert_eq( value, value_ ); + } + catch( ... ) + { + assert_eq( ok, false ); + } + + return ok; + } + + void check_value_sequence( Iter_type first, Iter_type last, const Ints& expected_values, bool all_input_consumed ) + { + Value_type value; + + for( Ints::size_type i = 0; i < expected_values.size(); ++i ) + { + const bool ok = test_read_range( first, last, value ); + + assert_eq( ok, true ); + + const bool is_last( i == expected_values.size() - 1 ); + + assert_eq( first == last, is_last ? all_input_consumed : false ); + } + + const bool ok = test_read_range( first, last, value ); + + assert_eq( ok, false ); + } + + void check_value_sequence( Istream_type& is, const Ints& expected_values, bool all_input_consumed ) + { + Value_type value; + + for( Ints::size_type i = 0; i < expected_values.size(); ++i ) + { + read_or_throw( is, value ); + + assert_eq( value.get_int(), expected_values[i] ); + + const bool is_last( i == expected_values.size() - 1 ); + + assert_eq( is.eof(), is_last ? all_input_consumed : false ); + } + + try + { + read_or_throw( is, value ); + + assert( false ); + } + catch( ... ) + { + } + + assert_eq( is.eof(), true ); + } + + void check_value_sequence( const char* c_str, const Ints& expected_values, bool all_input_consumed ) + { + const String_type s( to_str( c_str ) ); + + check_value_sequence( s.begin(), s.end(), expected_values, all_input_consumed ); + + Istringstream_type is( s ); + + check_value_sequence( is, expected_values, all_input_consumed ); + } + + void check_array( const Value_type& value, typename Array_type::size_type expected_size ) + { + assert_eq( value.type(), array_type ); + + const Array_type& arr = value.get_array(); + + assert_eq( arr.size(), expected_size ); + + for( typename Array_type::size_type i = 0; i < expected_size; ++i ) + { + const Value_type& val = arr[i]; + + assert_eq( val.type(), int_type ); + assert_eq( val.get_int(), int( i + 1 ) ); + } + } + + void check_reading_array( Iter_type& begin, Iter_type end, typename Array_type::size_type expected_size ) + { + Value_type value; + + test_read_range( begin, end, value ); + + check_array( value, expected_size ); + } + + void check_reading_array( Istream_type& is, typename Array_type::size_type expected_size ) + { + Value_type value; + + read( is, value ); + + check_array( value, expected_size ); + } + + void check_reading_arrays( const char* arrays_str ) + { + const String_type str( to_str( arrays_str ) ); + + Iter_type begin = str.begin(); + const Iter_type end = str.end(); + + check_reading_array( begin, end, 0 ); + check_reading_array( begin, end, 1 ); + check_reading_array( begin, end, 2 ); + check_reading_array( begin, end, 3 ); + + Istringstream_type is( str ); + + check_reading_array( is, 0 ); + check_reading_array( is, 1 ); + check_reading_array( is, 2 ); + check_reading_array( is, 3 ); + } + + void test_sequence_of_values() + { + check_value_sequence( "", Ints(), false ); + check_value_sequence( " ", Ints(), false ); + check_value_sequence( " ", Ints(), false ); + check_value_sequence( " 10 ", list_of( 10 ), false ); + check_value_sequence( " 10 11 ", list_of( 10 )( 11 ), false ); + check_value_sequence( " 10 11 12", list_of( 10 )( 11 )( 12 ), true); + check_value_sequence( "10 11 12", list_of( 10 )( 11 )( 12 ), true); + + // + + check_reading_arrays( "[] [ 1 ] [ 1, 2 ] [ 1, 2, 3 ]" ); + // check_reading_arrays( "[][1][1,2][1,2,3]" ); // fails due to multi_pass iterator bug, + // use stream_reader class instead + } + + void test_uint64( const char* value_str, int expected_int, int64_t expected_int64, uint64_t expected_uint64 ) + { + const Value_type v( read_cstr( value_str ) ); + + assert_eq( v.get_int(), expected_int ); + assert_eq( v.get_int64(), expected_int64 ); + assert_eq( v.get_uint64(), expected_uint64 ); + } + + void test_uint64() + { + test_uint64( "0", 0, 0, 0 ); + test_uint64( "1", 1, 1, 1 ); + test_uint64( "-1", -1, -1, ULLONG_MAX ); + test_uint64( "18446744073709551615", -1, -1, ULLONG_MAX ); + } + + void test_types() + { + Value_type value; + + read( to_str( "[ \"foo\", true, false, 1, 12.3, null ]" ), value ); + + assert_eq( value.type(), array_type ); + + const Array_type& a = value.get_array(); + + assert_eq( a[0].get_str(), to_str( "foo" ) ); + assert_eq( a[1].get_bool(), true ); + assert_eq( a[2].get_bool(), false ); + assert_eq( a[3].get_int(), 1 ); + assert_eq( a[3].get_int64(), 1 ); + assert_eq( a[3].get_uint64(), 1u ); + assert_eq( a[3].get_real(), 1.0 ); + assert_eq( a[4].get_real(), 12.3 ); + assert_eq( a[5].is_null(), true ); + } + + void test_comments() + { + Value_type value_1; + + read_cstr( "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : \"value 2 /* not a comment but data */\",\n" + " \"name 3\" : \"value 3 // not a comment but data\"\n" + "}", value_1 ); + + Value_type value_2; + + read_cstr( "{// a comment\n " + " \"name 1\" : /* another comment */ \"value 1\",\n" + " \"name 2\" : \"value 2 /* not a comment but data */\",\n" + " // \"name 2\" : \"value 2\",\n" + " \"name 3\" : \"value 3 // not a comment but data\"\n" + "/* multi\n" + "line\n" + "comment */}", value_2 ); + + assert_eq( value_1, value_2 ); + } + + void run_tests() + { + test_syntax(); + test_reading(); + test_reading_reals(); + test_from_stream(); + test_escape_chars(); + test_values(); + test_error_cases(); + test_sequence_of_values(); + test_uint64(); + test_types(); + test_comments(); + } + }; + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + void test_wide_esc_u() + { + wValue value; + + test_read( L"[\"\\uABCD\"]", value ); + + const wstring s( value.get_array()[0].get_str() ); + + assert_eq( s.length(), static_cast< wstring::size_type >( 1u ) ); + assert_eq( s[0], 0xABCD ); + } +#endif + +#ifdef JSON_SPIRIT_VALUE_ENABLED + void test_extended_ascii( const string& s ) + { + Value value; + + test_read( "[\"" + s + "\"]", value ); + + assert_eq( value.get_array()[0].get_str(), "äöüß" ); + } + + void test_extended_ascii() + { + test_extended_ascii( "\\u00E4\\u00F6\\u00FC\\u00DF" ); + test_extended_ascii( "äöüß" ); + } +#endif +} + +//#include + +void json5_parser::test_reader() +{ +#ifdef JSON_SPIRIT_VALUE_ENABLED + Test_runner< Config >().run_tests(); + test_extended_ascii(); +#endif +#ifdef JSON_SPIRIT_MVALUE_ENABLED + Test_runner< mConfig >().run_tests(); +#endif +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Test_runner< wConfig >().run_tests(); + test_wide_esc_u(); +#endif +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Test_runner< wmConfig >().run_tests(); +#endif + +#ifndef _DEBUG + //ifstream ifs( "test.txt" ); + + //string s; + + //getline( ifs, s ); + + //timer t; + + //for( int i = 0; i < 2000; ++i ) + //{ + // Value value; + + // read( s, value ); + //} + + //cout << t.elapsed() << endl; + +// const string so = write( value ); + + //Object obj; + + //for( int i = 0; i < 100000; ++i ) + //{ + // obj.push_back( Pair( "\x01test\x7F", lexical_cast< string >( i ) ) ); + //} + + //const string s = write( obj ); + + //Value value; + + //timer t; + + //read( s, value ); + + //cout << t.elapsed() << endl; + + //cout << "obj size " << value.get_obj().size(); +#endif +} diff --git a/json_test/json5_parser_reader_test.h b/json_test/json5_parser_reader_test.h index 02542f9..05fe818 100644 --- a/json_test/json5_parser_reader_test.h +++ b/json_test/json5_parser_reader_test.h @@ -1,18 +1,18 @@ -#ifndef JSON_SPIRIT_READER_TEST -#define JSON_SPIRIT_READER_TEST - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -namespace json5_parser -{ - void test_reader(); -} - -#endif +#ifndef JSON_SPIRIT_READER_TEST +#define JSON_SPIRIT_READER_TEST + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace json5_parser +{ + void test_reader(); +} + +#endif diff --git a/json_test/json5_parser_stream_reader_test.cpp b/json_test/json5_parser_stream_reader_test.cpp index 359b9d0..399591b 100644 --- a/json_test/json5_parser_stream_reader_test.cpp +++ b/json_test/json5_parser_stream_reader_test.cpp @@ -1,137 +1,137 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_stream_reader_test.h" -#include "utils_test.h" -#include "json5_parser_stream_reader.h" - -#include -#include - -using namespace json5_parser; -using namespace std; -using namespace boost; -using namespace boost::assign; - -namespace -{ - template< class Config_type > - struct Test_runner - { - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; - typedef typename Config_type::Pair_type Pair_type; - typedef typename String_type::value_type Char_type; - typedef typename String_type::const_iterator Iter_type; - typedef std::basic_istringstream< Char_type > Istringstream_type; - typedef std::basic_istream< Char_type > Istream_type; - - String_type to_str( const char* c_str ) - { - return ::to_str< String_type >( c_str ); - } - - Test_runner() - { - } - - void check_stream_reader( Stream_reader< Istream_type, Value_type >& reader, const vector< int >& expected_result ) - { - Value_type v; - const bool ok = reader.read_next( v ); - assert_eq( ok, true ); - assert_eq( v.type(), array_type ); - assert_eq( v.get_array().size(), expected_result.size() ); - for( vector< int >::size_type i = 0; i < v.get_array().size(); ++i ) - { - assert_eq( v.get_array()[i], expected_result[i] ); - } - } - - void check_stream_read_or_throw( Stream_reader_thrower< Istream_type, Value_type >& reader, const vector< int >& expected_result ) - { - Value_type v; - - try - { - reader.read_next( v ); - assert_eq( v.type(), array_type ); - assert_eq( v.get_array().size(), expected_result.size() ); - for( vector< int >::size_type i = 0; i < v.get_array().size(); ++i ) - { - assert_eq( v.get_array()[i], expected_result[i] ); - } - } - catch( ... ) - { - assert( false ); - } - } - - void test_stream_reader( const char* s ) - { - { - Istringstream_type is( to_str( s ) ); - - Stream_reader< Istream_type, Value_type > reader( is ); - - check_stream_reader( reader, vector< int >() ); - check_stream_reader( reader, list_of( 1 ) ); - check_stream_reader( reader, list_of( 1 )( 2 ) ); - check_stream_reader( reader, list_of( 1 )( 2 )( 3 ) ); - - Value_type v; - const bool ok = reader.read_next( v ); - assert_eq( ok, false ); - } - { - Istringstream_type is( to_str( s ) ); - - Stream_reader_thrower< Istream_type, Value_type > reader( is ); - - check_stream_read_or_throw( reader, vector< int >() ); - check_stream_read_or_throw( reader, list_of( 1 ) ); - check_stream_read_or_throw( reader, list_of( 1 )( 2 ) ); - check_stream_read_or_throw( reader, list_of( 1 )( 2 )( 3 ) ); - - try - { - Value_type v; - reader.read_next( v ); - assert( false ); - } - catch( ... ) - { - } - } - } - - void run_tests() - { - test_stream_reader( "[][1][1,2][1,2,3]" ); - test_stream_reader( "[] [1] [1,2] [1,2,3]" ); - test_stream_reader( " [] [1] [1,2] [1,2,3] " ); - } - }; -} - -void json5_parser::test_stream_reader() -{ -#ifdef JSON_SPIRIT_VALUE_ENABLED - Test_runner< Config >().run_tests(); -#endif -#ifdef JSON_SPIRIT_MVALUE_ENABLED - Test_runner< mConfig >().run_tests(); -#endif - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wConfig >().run_tests(); -#endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wmConfig >().run_tests(); -#endif -} +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_stream_reader_test.h" +#include "utils_test.h" +#include "json5_parser_stream_reader.h" + +#include +#include + +using namespace json5_parser; +using namespace std; +using namespace boost; +using namespace boost::assign; + +namespace +{ + template< class Config_type > + struct Test_runner + { + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + typedef typename Config_type::Pair_type Pair_type; + typedef typename String_type::value_type Char_type; + typedef typename String_type::const_iterator Iter_type; + typedef std::basic_istringstream< Char_type > Istringstream_type; + typedef std::basic_istream< Char_type > Istream_type; + + String_type to_str( const char* c_str ) + { + return ::to_str< String_type >( c_str ); + } + + Test_runner() + { + } + + void check_stream_reader( Stream_reader< Istream_type, Value_type >& reader, const vector< int >& expected_result ) + { + Value_type v; + const bool ok = reader.read_next( v ); + assert_eq( ok, true ); + assert_eq( v.type(), array_type ); + assert_eq( v.get_array().size(), expected_result.size() ); + for( vector< int >::size_type i = 0; i < v.get_array().size(); ++i ) + { + assert_eq( v.get_array()[i], expected_result[i] ); + } + } + + void check_stream_read_or_throw( Stream_reader_thrower< Istream_type, Value_type >& reader, const vector< int >& expected_result ) + { + Value_type v; + + try + { + reader.read_next( v ); + assert_eq( v.type(), array_type ); + assert_eq( v.get_array().size(), expected_result.size() ); + for( vector< int >::size_type i = 0; i < v.get_array().size(); ++i ) + { + assert_eq( v.get_array()[i], expected_result[i] ); + } + } + catch( ... ) + { + assert( false ); + } + } + + void test_stream_reader( const char* s ) + { + { + Istringstream_type is( to_str( s ) ); + + Stream_reader< Istream_type, Value_type > reader( is ); + + check_stream_reader( reader, vector< int >() ); + check_stream_reader( reader, list_of( 1 ) ); + check_stream_reader( reader, list_of( 1 )( 2 ) ); + check_stream_reader( reader, list_of( 1 )( 2 )( 3 ) ); + + Value_type v; + const bool ok = reader.read_next( v ); + assert_eq( ok, false ); + } + { + Istringstream_type is( to_str( s ) ); + + Stream_reader_thrower< Istream_type, Value_type > reader( is ); + + check_stream_read_or_throw( reader, vector< int >() ); + check_stream_read_or_throw( reader, list_of( 1 ) ); + check_stream_read_or_throw( reader, list_of( 1 )( 2 ) ); + check_stream_read_or_throw( reader, list_of( 1 )( 2 )( 3 ) ); + + try + { + Value_type v; + reader.read_next( v ); + assert( false ); + } + catch( ... ) + { + } + } + } + + void run_tests() + { + test_stream_reader( "[][1][1,2][1,2,3]" ); + test_stream_reader( "[] [1] [1,2] [1,2,3]" ); + test_stream_reader( " [] [1] [1,2] [1,2,3] " ); + } + }; +} + +void json5_parser::test_stream_reader() +{ +#ifdef JSON_SPIRIT_VALUE_ENABLED + Test_runner< Config >().run_tests(); +#endif +#ifdef JSON_SPIRIT_MVALUE_ENABLED + Test_runner< mConfig >().run_tests(); +#endif + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Test_runner< wConfig >().run_tests(); +#endif +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Test_runner< wmConfig >().run_tests(); +#endif +} diff --git a/json_test/json5_parser_stream_reader_test.h b/json_test/json5_parser_stream_reader_test.h index 1b9f102..05ccfe6 100644 --- a/json_test/json5_parser_stream_reader_test.h +++ b/json_test/json5_parser_stream_reader_test.h @@ -1,18 +1,18 @@ -#ifndef JSON_SPIRIT_STREAM_READER_TEST -#define JSON_SPIRIT_STREAM_READER_TEST - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -namespace json5_parser -{ - void test_stream_reader(); -} - -#endif +#ifndef JSON_SPIRIT_STREAM_READER_TEST +#define JSON_SPIRIT_STREAM_READER_TEST + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace json5_parser +{ + void test_stream_reader(); +} + +#endif diff --git a/json_test/json5_parser_utils_test.cpp b/json_test/json5_parser_utils_test.cpp index e5ee9c3..4c68711 100644 --- a/json_test/json5_parser_utils_test.cpp +++ b/json_test/json5_parser_utils_test.cpp @@ -1,143 +1,143 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_utils_test.h" -#include "utils_test.h" -#include "json5_parser_utils.h" - -#include - -using namespace json5_parser; -using namespace std; -using namespace boost::assign; - -namespace -{ - template< class Obj_t, class Map_t > - struct Test_runner - { - typedef typename Map_t::key_type String_type; - typedef typename Obj_t::value_type Pair_type; - typedef typename Pair_type::Value_type Value_type; - - String_type to_str( const char* c_str ) - { - return ::to_str< String_type >( c_str ); - } - - void assert_equal( const Obj_t& obj, const Map_t& mp_obj ) - { - typename Obj_t::size_type obj_size = obj.size(); - typename Map_t::size_type map_size = mp_obj.size(); - - assert_eq( obj_size, map_size ); - - for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i ) - { - assert_eq( mp_obj.find( i->name_ )->second, i->value_ ); - } - } - - void check_obj_to_map( const Obj_t& obj ) - { - Map_t mp_obj; - - obj_to_map( obj, mp_obj ); - - assert_equal( obj, mp_obj ); - } - - void check_map_cleared() - { - Map_t mp_obj; - - mp_obj[ to_str( "del" ) ] = to_str( "me" ); - - obj_to_map( Obj_t(), mp_obj ); - - assert_eq( mp_obj.size(), 0u ); - } - - void check_map_to_obj( const Map_t& mp_obj ) - { - Obj_t obj; - - map_to_obj( mp_obj, obj ); - - assert_equal( obj, mp_obj ); - } - - void check_obj_cleared() - { - Obj_t obj; - - obj.push_back( Pair_type( to_str( "del" ), to_str( "me" ) ) ); - - map_to_obj( Map_t(), obj ); - - assert_eq( obj.size(), 0u ); - } - - void test_obj_to_map() - { - check_obj_to_map( Obj_t() ); - check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) ) ); - check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "b" ), 2 ) ) ); - check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "b" ), 2 ) )( Pair_type( to_str( "c" ), 3 ) ) ); - check_map_cleared(); - - check_map_to_obj( Map_t() ); - check_map_to_obj( map_list_of( to_str( "a" ), 1 ) ); - check_map_to_obj( map_list_of( to_str( "a" ), 1 )( to_str( "b" ), 2 ) ); - check_map_to_obj( map_list_of( to_str( "a" ), 1 )( to_str( "b" ), 2 )( to_str( "c" ), 3 ) ); - check_obj_cleared(); - } - - void check_find( const Obj_t& obj, const char* name, const Value_type& expected_result ) - { - const Value_type& result = find_value( obj, to_str( name ) ); - - assert_eq( result, expected_result ); - } - - void test_find() - { - check_find( Obj_t(), "not there", Value_type::null ); - - const Obj_t obj_1 = list_of( Pair_type( to_str( "a" ), 1 ) ); - - check_find( obj_1, "not there", Value_type::null ); - check_find( obj_1, "a", 1 ); - - const Obj_t obj_2 = list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "ab" ), 2 ) ); - - check_find( obj_2, "a", 1 ); - check_find( obj_2, "ab", 2 ); - - const Obj_t obj_3 = list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "ab" ), 2 ) )( Pair_type( to_str( "abc" ), 3 ) ); - - check_find( obj_3, "a", 1 ); - check_find( obj_3, "ab", 2 ); - check_find( obj_3, "abc", 3 ); - } - - void run_tests() - { - test_obj_to_map(); - test_find(); - } - }; -} - -void json5_parser::test_utils() -{ -#ifdef JSON_SPIRIT_VALUE_ENABLED - Test_runner< Object, Mapped_obj >().run_tests(); -#endif - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wObject, wMapped_obj >().run_tests(); -#endif -} +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_utils_test.h" +#include "utils_test.h" +#include "json5_parser_utils.h" + +#include + +using namespace json5_parser; +using namespace std; +using namespace boost::assign; + +namespace +{ + template< class Obj_t, class Map_t > + struct Test_runner + { + typedef typename Map_t::key_type String_type; + typedef typename Obj_t::value_type Pair_type; + typedef typename Pair_type::Value_type Value_type; + + String_type to_str( const char* c_str ) + { + return ::to_str< String_type >( c_str ); + } + + void assert_equal( const Obj_t& obj, const Map_t& mp_obj ) + { + typename Obj_t::size_type obj_size = obj.size(); + typename Map_t::size_type map_size = mp_obj.size(); + + assert_eq( obj_size, map_size ); + + for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i ) + { + assert_eq( mp_obj.find( i->name_ )->second, i->value_ ); + } + } + + void check_obj_to_map( const Obj_t& obj ) + { + Map_t mp_obj; + + obj_to_map( obj, mp_obj ); + + assert_equal( obj, mp_obj ); + } + + void check_map_cleared() + { + Map_t mp_obj; + + mp_obj[ to_str( "del" ) ] = to_str( "me" ); + + obj_to_map( Obj_t(), mp_obj ); + + assert_eq( mp_obj.size(), 0u ); + } + + void check_map_to_obj( const Map_t& mp_obj ) + { + Obj_t obj; + + map_to_obj( mp_obj, obj ); + + assert_equal( obj, mp_obj ); + } + + void check_obj_cleared() + { + Obj_t obj; + + obj.push_back( Pair_type( to_str( "del" ), to_str( "me" ) ) ); + + map_to_obj( Map_t(), obj ); + + assert_eq( obj.size(), 0u ); + } + + void test_obj_to_map() + { + check_obj_to_map( Obj_t() ); + check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) ) ); + check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "b" ), 2 ) ) ); + check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "b" ), 2 ) )( Pair_type( to_str( "c" ), 3 ) ) ); + check_map_cleared(); + + check_map_to_obj( Map_t() ); + check_map_to_obj( map_list_of( to_str( "a" ), 1 ) ); + check_map_to_obj( map_list_of( to_str( "a" ), 1 )( to_str( "b" ), 2 ) ); + check_map_to_obj( map_list_of( to_str( "a" ), 1 )( to_str( "b" ), 2 )( to_str( "c" ), 3 ) ); + check_obj_cleared(); + } + + void check_find( const Obj_t& obj, const char* name, const Value_type& expected_result ) + { + const Value_type& result = find_value( obj, to_str( name ) ); + + assert_eq( result, expected_result ); + } + + void test_find() + { + check_find( Obj_t(), "not there", Value_type::null ); + + const Obj_t obj_1 = list_of( Pair_type( to_str( "a" ), 1 ) ); + + check_find( obj_1, "not there", Value_type::null ); + check_find( obj_1, "a", 1 ); + + const Obj_t obj_2 = list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "ab" ), 2 ) ); + + check_find( obj_2, "a", 1 ); + check_find( obj_2, "ab", 2 ); + + const Obj_t obj_3 = list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "ab" ), 2 ) )( Pair_type( to_str( "abc" ), 3 ) ); + + check_find( obj_3, "a", 1 ); + check_find( obj_3, "ab", 2 ); + check_find( obj_3, "abc", 3 ); + } + + void run_tests() + { + test_obj_to_map(); + test_find(); + } + }; +} + +void json5_parser::test_utils() +{ +#ifdef JSON_SPIRIT_VALUE_ENABLED + Test_runner< Object, Mapped_obj >().run_tests(); +#endif + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Test_runner< wObject, wMapped_obj >().run_tests(); +#endif +} diff --git a/json_test/json5_parser_utils_test.h b/json_test/json5_parser_utils_test.h index 7c80523..0be6067 100644 --- a/json_test/json5_parser_utils_test.h +++ b/json_test/json5_parser_utils_test.h @@ -1,18 +1,18 @@ -#ifndef JSON_SPIRIT_UTILS_TEST -#define JSON_SPIRIT_UTILS_TEST - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -namespace json5_parser -{ - void test_utils(); -} - -#endif +#ifndef JSON_SPIRIT_UTILS_TEST +#define JSON_SPIRIT_UTILS_TEST + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace json5_parser +{ + void test_utils(); +} + +#endif diff --git a/json_test/json5_parser_value_test.cpp b/json_test/json5_parser_value_test.cpp index 63eec79..98dd4c1 100644 --- a/json_test/json5_parser_value_test.cpp +++ b/json_test/json5_parser_value_test.cpp @@ -1,529 +1,529 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_value_test.h" -#include "utils_test.h" -#include "json5_parser_value.h" -#include -#include -#include -#include - -using namespace json5_parser; -using namespace std; -using namespace boost; -using namespace boost::assign; - -namespace -{ -#ifdef JSON_SPIRIT_VALUE_ENABLED - - const int64_t max_int64 = integer_traits< int64_t >::max(); - const uint64_t max_uint64 = integer_traits< uint64_t >::max(); - - void test_obj_value() - { - const Pair p1( "name1", "value1" ); - const Pair p3( "name3", "value3" ); - - Object obj_1; obj_1.push_back( p1 ); - Object obj_2; obj_2.push_back( p1 ); - Object obj_3; obj_3.push_back( p3 ); - - Value v1( obj_1 ); - Value v2( obj_2 ); - Value v3( obj_3 ); - - assert_eq( v1.type(), obj_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); - - assert_eq( v1.get_obj(), obj_1 ); - assert_eq( v3.get_obj(), obj_3 ); - } - - void test_array_value() - { - Array array_1; array_1.push_back( 1 ); array_1.push_back( "2" ); - Array array_2; array_2.push_back( 1 ); array_2.push_back( "2" ); - Array array_3; array_3.push_back( 1 ); array_3.push_back( "X" ); - - Value v1( array_1 ); - Value v2( array_2 ); - Value v3( array_3 ); - - assert_eq( v1.type(), array_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); - - assert_eq( v1.get_array(), array_1 ); - assert_eq( v3.get_array(), array_3 ); - } - - void test_bool_value() - { - Value v1( true ); - Value v2( true ); - Value v3( false ); - - assert_eq( v1.type(), bool_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); - - assert( v1.get_bool() ); - assert( !v3.get_bool() ); - } - - void test_int_value() - { - Value v1( 1 ); - Value v2( 1 ); - Value v3( INT_MAX ); - - assert_eq( v1.type(), int_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); - - unsigned int uint_max = INT_MAX; - - assert_eq( v1.get_int(), 1 ); - assert_eq( v1.get_int64(), 1 ); - assert_eq( v1.get_uint64(), 1u ); - assert_eq( v3.get_int(), INT_MAX ); - assert_eq( v3.get_int64(), INT_MAX ); - assert_eq( v3.get_uint64(), uint_max ); - - Value v4( max_int64 ); - - assert_eq( v4.get_int64(), max_int64 ); - assert_eq( v4.get_uint64(), static_cast< uint64_t >( max_int64 ) ); - - const uint64_t max_int64_plus_1 = max_int64 + uint64_t( 1 ); - - Value v5( max_int64_plus_1 ); - - assert_eq( v5.get_uint64(), max_int64_plus_1 ); - - Value v6( max_uint64 ); - - assert_eq( v6.get_uint64(), max_uint64 ); - - Value v7( 0 ); - - assert_eq( v7.get_int(), 0 ); - assert_eq( v7.get_int64(), 0 ); - assert_eq( v7.get_uint64(), 0u ); - - Value v8( -1 ); - - assert_eq( v8.get_int(), -1 ); - assert_eq( v8.get_int64(), -1 ); - assert_eq( v8.get_uint64(), max_uint64 ); - } - - void test_real_value() - { - Value v1( 1.0 ); - Value v2( 1.0 ); - Value v3( 2.0 ); - - assert_eq( v1.type(), real_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); - - assert_eq( v1.get_real(), 1.0 ); - assert_eq( v3.get_real(), 2.0 ); - } - - void test_null_value() - { - Value v1; - Value v2; - - assert_eq( v1.type(), null_type ); - assert_eq( v1.is_null(), true ); - assert_eq( v1, v2 ); - assert_eq( v1.is_null(), true ); - assert_eq( Value( 1 ).is_null(), false ); - } - - template< typename T > - void test_get_value( const T& t ) - { - assert_eq( Value( t ).get_value< T >(), t ); - } - - void test_get_value() - { - test_get_value( 123 ); - test_get_value( max_int64 ); - test_get_value( 1.23 ); - test_get_value( true ); - test_get_value( false ); - test_get_value( string( "test" ) ); - - Array a; a.push_back( 1 ); a.push_back( "2" ); - - test_get_value( a ); - - Object obj; obj.push_back( Pair( "name1", "value1" ) ); - - test_get_value( obj ); - } - - void assert_array_eq( const Value& v, const Array& a ) - { - assert_eq( v.get_array(), a ); - } - - void assert_obj_eq( const Value& v, const Object& obj ) - { - assert_eq( v.get_obj(), obj ); - } - - template< typename T > - void check_copy( const T& t ) - { - const Value v1( t ); - const Value v2( v1 ); - Value v3; - v3 = v1; - - assert_eq( v1, v2 ); - assert_eq( v1, v3 ); - - assert_eq( v2.get_value< T >(), t ); - assert_eq( v3.get_value< T >(), t ); - - assert_eq( v1.is_uint64(), v2.is_uint64() ); - assert_eq( v1.is_uint64(), v3.is_uint64() ); - } - - void check_copying_null() - { - const Value v1; - const Value v2( v1 ); - Value v3; - v3 = v1; - - assert_eq( v2.type(), null_type ); - assert_eq( v3.type(), null_type ); - } - - void test_copying() - { - { - const Array array_1 = list_of(1)(2); - - Value v1( array_1 ); - const Value v2( v1 ); - - assert_array_eq( v1, array_1 ); - assert_array_eq( v2, array_1 ); - - v1.get_array()[0] = 3; - - assert_array_eq( v1, list_of(3)(2) ); - assert_array_eq( v2, array_1 ); - } - { - const Object obj_1 = list_of( Pair( "a", 1 ) )( Pair( "b", 2 ) ); - - Value v1( obj_1 ); - Value v2; - - v2 = v1; - - assert_obj_eq( v1, obj_1 ); - assert_obj_eq( v2, obj_1 ); - - v1.get_obj()[0] = Pair( "c", 3 ); - - assert_obj_eq( v1, list_of( Pair( "c", 3 ) )( Pair( "b", 2 ) ) ); - assert_obj_eq( v2, obj_1 ); - } - { - check_copy( 1 ); - check_copy( 2.0 ); - check_copy( max_int64 ); - check_copy( max_uint64 ); - check_copy( string("test") ); - check_copy( true ); - check_copy( false ); - const Array array_1 = list_of(1)(2); - check_copy( array_1 ); - const Object obj_1 = list_of( Pair( "a", 1 ) )( Pair( "b", 2 ) ); - check_copy( obj_1 ); - check_copying_null(); - } - } - - void test_obj_map_implemention() - { -#ifdef JSON_SPIRIT_MVALUE_ENABLED - mObject obj; - - obj[ "name 1" ] = 1; - obj[ "name 2" ] = "two"; - - assert_eq( obj.size(), 2u ); - - assert_eq( obj.find( "name 1" )->second.get_int(), 1 ); - assert_eq( obj.find( "name 2" )->second.get_str(), "two" ); -#endif - } - - template< typename Int > - void check_an_int_is_a_real( Int i, bool expected_result ) - { - assert_eq( Value( i ).is_uint64(), expected_result ); - } - - void test_is_uint64() - { - check_an_int_is_a_real( 1, false ); - check_an_int_is_a_real( static_cast< int64_t >( 1 ), false ); - check_an_int_is_a_real( static_cast< uint64_t >( 1 ), true ); - } - - template< typename Int > - void check_an_int_is_a_real( Int i, double expected_result ) - { - assert_eq( Value( i ).get_real(), expected_result ); - } - - void test_an_int_is_a_real() - { - check_an_int_is_a_real( -1, -1.0 ); - check_an_int_is_a_real( 0, 0.0 ); - check_an_int_is_a_real( 1, 1.0 ); - check_an_int_is_a_real( max_int64, 9223372036854775800.0 ); - check_an_int_is_a_real( max_uint64, 18446744073709552000.0 ); - } - - template< typename T > - void check_wrong_type_exceptions( const Value& v, const string& requested_type_name, const string& actual_type_name ) - { - try - { - v.get_value< T >(); - - assert( false ); - } - catch( const runtime_error& e ) - { - ostringstream os; - - os << "get_value< " << requested_type_name << " > called on " << actual_type_name << " Value"; - - assert_eq( e.what(), os.str() ); - } - } - - template< typename T > - void check_wrong_type_exceptions( const string& requested_type_name ) - { - Value v; - - assert_eq( v.type(), null_type ); - - check_wrong_type_exceptions< T >( v, requested_type_name, "null" ); - } - - void test_wrong_type_exceptions() - { - check_wrong_type_exceptions< Object >( "Object" ); - check_wrong_type_exceptions< Array >( "Array" ); - check_wrong_type_exceptions< string >( "string" ); - check_wrong_type_exceptions< bool >( "boolean"); - check_wrong_type_exceptions< boost::int64_t >( "integer" ); - check_wrong_type_exceptions< int >( "integer" ); - check_wrong_type_exceptions< double >( "real" ); - - Value v( "string" ); - - assert_eq( v.type(), str_type ); - - check_wrong_type_exceptions< double >( v, "real", "string" ); - } -#endif - - template< class Config_type > - class Container_constructor_runner - { - public: - - Container_constructor_runner() - { - vector< double > vd = list_of( 1.2 )( 1.3 ); test_container_constructor( vd ); - vector< int > vi = list_of( 1 ); test_container_constructor( vi ); - vi = list_of( 1 )( 2 ); test_container_constructor( vi ); - vi = list_of( 1 )( 2 )( 3 ); test_container_constructor( vi ); - list< double > ld = list_of( 1.2 )( 1.3 ); test_container_constructor( ld ); - list< int > li = list_of( 1 ); test_container_constructor( li ); - li = list_of( 1 )( 2 ); test_container_constructor( li ); - li = list_of( 1 )( 2 )( 3 ); test_container_constructor( li ); - } - - private: - - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; - - template< class Cont > - void test_container_constructor( const Cont& cont ) - { - typedef typename Cont::value_type Cont_value_type; - const Value_type val( cont.begin(), cont.end() ); - const Array_type& arr = val.get_array(); - Cont result; - for( unsigned int i = 0; i < arr.size(); ++i ) - { - result.push_back( arr[i].template get_value< Cont_value_type>() ); - } - assert_eq( result, cont ); - } - }; - - void test_container_constructor() - { -#ifdef JSON_SPIRIT_VALUE_ENABLED - Container_constructor_runner< Config >(); -#endif -#ifdef JSON_SPIRIT_MVALUE_ENABLED - Container_constructor_runner< mConfig >(); -#endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Container_constructor_runner< wConfig >(); -#endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Container_constructor_runner< wmConfig >(); -#endif - } - - template< class Config_type > - class Variant_constructor_runner - { - public: - - Variant_constructor_runner() - { - test_variant_constructor< variant< int, double > >( 1.23 ); - test_variant_constructor< variant< int, double > >( 123 ); - test_variant_constructor< variant< int, double, String_type > >( to_str< String_type >( "foo" ) ); - test_variant_constructor< variant< int, double, String_type, bool > >( true ); - test_variant_constructor< variant< int, double, String_type, bool, boost::int64_t > >( boost::int64_t( 123 ) ); - test_variant_constructor< variant< int, double, String_type, bool, boost::uint64_t > >( boost::uint64_t( 123 ) ); - - { - variant< int, Null > variant = Null(); - const Value_type val( variant ); - assert( val.is_null() ); - } - - vector< double > vd = list_of( 1.2 )( 1.3 ); test_variant_array_constructor< double > ( vd ); - vector< int > vi = list_of( 1 ); test_variant_array_constructor< int >( vi ); - vi = list_of( 1 )( 2 ); test_variant_array_constructor< int >( vi ); - vi = list_of( 1 )( 2 )( 3 ); test_variant_array_constructor< int >( vi ); - list< double > ld = list_of( 1.2 )( 1.3 ); test_variant_array_constructor< double >( ld ); - list< int > li = list_of( 1 ); test_variant_array_constructor< int >( li ); - li = list_of( 1 )( 2 ); test_variant_array_constructor< int >( li ); - li = list_of( 1 )( 2 )( 3 ); test_variant_array_constructor< int >( li ); - } - - private: - - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; - - template< class Variant_t, typename T > - void test_variant_constructor( const T& t ) - { - const Variant_t variant( t ); - const Value_type val( variant ); - assert_eq( val.template get_value< T >(), t ); - } - - template< typename T, typename A, template< typename, typename > class Cont > - void test_variant_array_constructor( const Cont< T, A >& cont ) - { - const variant< int, Cont< T, A > > variant = cont; - const Value_type val( variant ); - const Array_type& arr = val.get_array(); - Cont< T, A > result; - for( unsigned int i = 0; i < arr.size(); ++i ) - { - result.push_back( arr[i].template get_value< T >() ); - } - assert_eq( result, cont ); - } - }; - - void test_variant_constructor() - { -#ifdef JSON_SPIRIT_VALUE_ENABLED - Variant_constructor_runner< Config >(); -#endif -#ifdef JSON_SPIRIT_MVALUE_ENABLED - Variant_constructor_runner< mConfig >(); - -#endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Variant_constructor_runner< wConfig >(); -#endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Variant_constructor_runner< wmConfig >(); -#endif - } -} - -void json5_parser::test_value() -{ -#ifdef JSON_SPIRIT_VALUE_ENABLED - Object obj; - Value value_str ( "value" ); - Value value_obj ( obj ); - Value value_bool( true ); - - Value value_str_2 ( string( "value" ) ); - Value value_obj_2 ( obj ); - Value value_bool_2( false ); - - const char* str( "value" ); - Value value_str_2b ( str ); - - assert_eq( value_str, value_str ); - assert_eq( value_str, value_str_2 ); - assert_eq( value_str, value_str_2b ); - assert_eq( value_obj, value_obj ); - assert_eq( value_obj, value_obj_2 ); - assert_neq( value_str, value_obj ); - assert_neq( value_str, value_bool ); - - Object obj_2; - obj_2.push_back( Pair( "name", value_str ) ); - Value value_str_3( "xxxxx" ); - Value value_obj_3( obj_2 ); - - assert_neq( value_str, value_str_3 ); - assert_neq( value_obj, value_obj_3 ); - - test_obj_value(); - test_array_value(); - test_bool_value(); - test_int_value(); - test_real_value(); - test_null_value(); - test_get_value(); - test_copying(); - test_obj_map_implemention(); - test_is_uint64(); - test_an_int_is_a_real(); - test_wrong_type_exceptions(); -#endif - test_container_constructor(); - test_variant_constructor(); -} +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_value_test.h" +#include "utils_test.h" +#include "json5_parser_value.h" +#include +#include +#include +#include + +using namespace json5_parser; +using namespace std; +using namespace boost; +using namespace boost::assign; + +namespace +{ +#ifdef JSON_SPIRIT_VALUE_ENABLED + + const int64_t max_int64 = integer_traits< int64_t >::max(); + const uint64_t max_uint64 = integer_traits< uint64_t >::max(); + + void test_obj_value() + { + const Pair p1( "name1", "value1" ); + const Pair p3( "name3", "value3" ); + + Object obj_1; obj_1.push_back( p1 ); + Object obj_2; obj_2.push_back( p1 ); + Object obj_3; obj_3.push_back( p3 ); + + Value v1( obj_1 ); + Value v2( obj_2 ); + Value v3( obj_3 ); + + assert_eq( v1.type(), obj_type ); + assert_eq ( v1, v2 ); + assert_neq( v1, v3 ); + + assert_eq( v1.get_obj(), obj_1 ); + assert_eq( v3.get_obj(), obj_3 ); + } + + void test_array_value() + { + Array array_1; array_1.push_back( 1 ); array_1.push_back( "2" ); + Array array_2; array_2.push_back( 1 ); array_2.push_back( "2" ); + Array array_3; array_3.push_back( 1 ); array_3.push_back( "X" ); + + Value v1( array_1 ); + Value v2( array_2 ); + Value v3( array_3 ); + + assert_eq( v1.type(), array_type ); + assert_eq ( v1, v2 ); + assert_neq( v1, v3 ); + + assert_eq( v1.get_array(), array_1 ); + assert_eq( v3.get_array(), array_3 ); + } + + void test_bool_value() + { + Value v1( true ); + Value v2( true ); + Value v3( false ); + + assert_eq( v1.type(), bool_type ); + assert_eq ( v1, v2 ); + assert_neq( v1, v3 ); + + assert( v1.get_bool() ); + assert( !v3.get_bool() ); + } + + void test_int_value() + { + Value v1( 1 ); + Value v2( 1 ); + Value v3( INT_MAX ); + + assert_eq( v1.type(), int_type ); + assert_eq ( v1, v2 ); + assert_neq( v1, v3 ); + + unsigned int uint_max = INT_MAX; + + assert_eq( v1.get_int(), 1 ); + assert_eq( v1.get_int64(), 1 ); + assert_eq( v1.get_uint64(), 1u ); + assert_eq( v3.get_int(), INT_MAX ); + assert_eq( v3.get_int64(), INT_MAX ); + assert_eq( v3.get_uint64(), uint_max ); + + Value v4( max_int64 ); + + assert_eq( v4.get_int64(), max_int64 ); + assert_eq( v4.get_uint64(), static_cast< uint64_t >( max_int64 ) ); + + const uint64_t max_int64_plus_1 = max_int64 + uint64_t( 1 ); + + Value v5( max_int64_plus_1 ); + + assert_eq( v5.get_uint64(), max_int64_plus_1 ); + + Value v6( max_uint64 ); + + assert_eq( v6.get_uint64(), max_uint64 ); + + Value v7( 0 ); + + assert_eq( v7.get_int(), 0 ); + assert_eq( v7.get_int64(), 0 ); + assert_eq( v7.get_uint64(), 0u ); + + Value v8( -1 ); + + assert_eq( v8.get_int(), -1 ); + assert_eq( v8.get_int64(), -1 ); + assert_eq( v8.get_uint64(), max_uint64 ); + } + + void test_real_value() + { + Value v1( 1.0 ); + Value v2( 1.0 ); + Value v3( 2.0 ); + + assert_eq( v1.type(), real_type ); + assert_eq ( v1, v2 ); + assert_neq( v1, v3 ); + + assert_eq( v1.get_real(), 1.0 ); + assert_eq( v3.get_real(), 2.0 ); + } + + void test_null_value() + { + Value v1; + Value v2; + + assert_eq( v1.type(), null_type ); + assert_eq( v1.is_null(), true ); + assert_eq( v1, v2 ); + assert_eq( v1.is_null(), true ); + assert_eq( Value( 1 ).is_null(), false ); + } + + template< typename T > + void test_get_value( const T& t ) + { + assert_eq( Value( t ).get_value< T >(), t ); + } + + void test_get_value() + { + test_get_value( 123 ); + test_get_value( max_int64 ); + test_get_value( 1.23 ); + test_get_value( true ); + test_get_value( false ); + test_get_value( string( "test" ) ); + + Array a; a.push_back( 1 ); a.push_back( "2" ); + + test_get_value( a ); + + Object obj; obj.push_back( Pair( "name1", "value1" ) ); + + test_get_value( obj ); + } + + void assert_array_eq( const Value& v, const Array& a ) + { + assert_eq( v.get_array(), a ); + } + + void assert_obj_eq( const Value& v, const Object& obj ) + { + assert_eq( v.get_obj(), obj ); + } + + template< typename T > + void check_copy( const T& t ) + { + const Value v1( t ); + const Value v2( v1 ); + Value v3; + v3 = v1; + + assert_eq( v1, v2 ); + assert_eq( v1, v3 ); + + assert_eq( v2.get_value< T >(), t ); + assert_eq( v3.get_value< T >(), t ); + + assert_eq( v1.is_uint64(), v2.is_uint64() ); + assert_eq( v1.is_uint64(), v3.is_uint64() ); + } + + void check_copying_null() + { + const Value v1; + const Value v2( v1 ); + Value v3; + v3 = v1; + + assert_eq( v2.type(), null_type ); + assert_eq( v3.type(), null_type ); + } + + void test_copying() + { + { + const Array array_1 = list_of(1)(2); + + Value v1( array_1 ); + const Value v2( v1 ); + + assert_array_eq( v1, array_1 ); + assert_array_eq( v2, array_1 ); + + v1.get_array()[0] = 3; + + assert_array_eq( v1, list_of(3)(2) ); + assert_array_eq( v2, array_1 ); + } + { + const Object obj_1 = list_of( Pair( "a", 1 ) )( Pair( "b", 2 ) ); + + Value v1( obj_1 ); + Value v2; + + v2 = v1; + + assert_obj_eq( v1, obj_1 ); + assert_obj_eq( v2, obj_1 ); + + v1.get_obj()[0] = Pair( "c", 3 ); + + assert_obj_eq( v1, list_of( Pair( "c", 3 ) )( Pair( "b", 2 ) ) ); + assert_obj_eq( v2, obj_1 ); + } + { + check_copy( 1 ); + check_copy( 2.0 ); + check_copy( max_int64 ); + check_copy( max_uint64 ); + check_copy( string("test") ); + check_copy( true ); + check_copy( false ); + const Array array_1 = list_of(1)(2); + check_copy( array_1 ); + const Object obj_1 = list_of( Pair( "a", 1 ) )( Pair( "b", 2 ) ); + check_copy( obj_1 ); + check_copying_null(); + } + } + + void test_obj_map_implemention() + { +#ifdef JSON_SPIRIT_MVALUE_ENABLED + mObject obj; + + obj[ "name 1" ] = 1; + obj[ "name 2" ] = "two"; + + assert_eq( obj.size(), 2u ); + + assert_eq( obj.find( "name 1" )->second.get_int(), 1 ); + assert_eq( obj.find( "name 2" )->second.get_str(), "two" ); +#endif + } + + template< typename Int > + void check_an_int_is_a_real( Int i, bool expected_result ) + { + assert_eq( Value( i ).is_uint64(), expected_result ); + } + + void test_is_uint64() + { + check_an_int_is_a_real( 1, false ); + check_an_int_is_a_real( static_cast< int64_t >( 1 ), false ); + check_an_int_is_a_real( static_cast< uint64_t >( 1 ), true ); + } + + template< typename Int > + void check_an_int_is_a_real( Int i, double expected_result ) + { + assert_eq( Value( i ).get_real(), expected_result ); + } + + void test_an_int_is_a_real() + { + check_an_int_is_a_real( -1, -1.0 ); + check_an_int_is_a_real( 0, 0.0 ); + check_an_int_is_a_real( 1, 1.0 ); + check_an_int_is_a_real( max_int64, 9223372036854775800.0 ); + check_an_int_is_a_real( max_uint64, 18446744073709552000.0 ); + } + + template< typename T > + void check_wrong_type_exceptions( const Value& v, const string& requested_type_name, const string& actual_type_name ) + { + try + { + v.get_value< T >(); + + assert( false ); + } + catch( const runtime_error& e ) + { + ostringstream os; + + os << "get_value< " << requested_type_name << " > called on " << actual_type_name << " Value"; + + assert_eq( e.what(), os.str() ); + } + } + + template< typename T > + void check_wrong_type_exceptions( const string& requested_type_name ) + { + Value v; + + assert_eq( v.type(), null_type ); + + check_wrong_type_exceptions< T >( v, requested_type_name, "null" ); + } + + void test_wrong_type_exceptions() + { + check_wrong_type_exceptions< Object >( "Object" ); + check_wrong_type_exceptions< Array >( "Array" ); + check_wrong_type_exceptions< string >( "string" ); + check_wrong_type_exceptions< bool >( "boolean"); + check_wrong_type_exceptions< boost::int64_t >( "integer" ); + check_wrong_type_exceptions< int >( "integer" ); + check_wrong_type_exceptions< double >( "real" ); + + Value v( "string" ); + + assert_eq( v.type(), str_type ); + + check_wrong_type_exceptions< double >( v, "real", "string" ); + } +#endif + + template< class Config_type > + class Container_constructor_runner + { + public: + + Container_constructor_runner() + { + vector< double > vd = list_of( 1.2 )( 1.3 ); test_container_constructor( vd ); + vector< int > vi = list_of( 1 ); test_container_constructor( vi ); + vi = list_of( 1 )( 2 ); test_container_constructor( vi ); + vi = list_of( 1 )( 2 )( 3 ); test_container_constructor( vi ); + list< double > ld = list_of( 1.2 )( 1.3 ); test_container_constructor( ld ); + list< int > li = list_of( 1 ); test_container_constructor( li ); + li = list_of( 1 )( 2 ); test_container_constructor( li ); + li = list_of( 1 )( 2 )( 3 ); test_container_constructor( li ); + } + + private: + + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + + template< class Cont > + void test_container_constructor( const Cont& cont ) + { + typedef typename Cont::value_type Cont_value_type; + const Value_type val( cont.begin(), cont.end() ); + const Array_type& arr = val.get_array(); + Cont result; + for( unsigned int i = 0; i < arr.size(); ++i ) + { + result.push_back( arr[i].template get_value< Cont_value_type>() ); + } + assert_eq( result, cont ); + } + }; + + void test_container_constructor() + { +#ifdef JSON_SPIRIT_VALUE_ENABLED + Container_constructor_runner< Config >(); +#endif +#ifdef JSON_SPIRIT_MVALUE_ENABLED + Container_constructor_runner< mConfig >(); +#endif +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Container_constructor_runner< wConfig >(); +#endif +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Container_constructor_runner< wmConfig >(); +#endif + } + + template< class Config_type > + class Variant_constructor_runner + { + public: + + Variant_constructor_runner() + { + test_variant_constructor< variant< int, double > >( 1.23 ); + test_variant_constructor< variant< int, double > >( 123 ); + test_variant_constructor< variant< int, double, String_type > >( to_str< String_type >( "foo" ) ); + test_variant_constructor< variant< int, double, String_type, bool > >( true ); + test_variant_constructor< variant< int, double, String_type, bool, boost::int64_t > >( boost::int64_t( 123 ) ); + test_variant_constructor< variant< int, double, String_type, bool, boost::uint64_t > >( boost::uint64_t( 123 ) ); + + { + variant< int, Null > variant = Null(); + const Value_type val( variant ); + assert( val.is_null() ); + } + + vector< double > vd = list_of( 1.2 )( 1.3 ); test_variant_array_constructor< double > ( vd ); + vector< int > vi = list_of( 1 ); test_variant_array_constructor< int >( vi ); + vi = list_of( 1 )( 2 ); test_variant_array_constructor< int >( vi ); + vi = list_of( 1 )( 2 )( 3 ); test_variant_array_constructor< int >( vi ); + list< double > ld = list_of( 1.2 )( 1.3 ); test_variant_array_constructor< double >( ld ); + list< int > li = list_of( 1 ); test_variant_array_constructor< int >( li ); + li = list_of( 1 )( 2 ); test_variant_array_constructor< int >( li ); + li = list_of( 1 )( 2 )( 3 ); test_variant_array_constructor< int >( li ); + } + + private: + + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + + template< class Variant_t, typename T > + void test_variant_constructor( const T& t ) + { + const Variant_t variant( t ); + const Value_type val( variant ); + assert_eq( val.template get_value< T >(), t ); + } + + template< typename T, typename A, template< typename, typename > class Cont > + void test_variant_array_constructor( const Cont< T, A >& cont ) + { + const variant< int, Cont< T, A > > variant = cont; + const Value_type val( variant ); + const Array_type& arr = val.get_array(); + Cont< T, A > result; + for( unsigned int i = 0; i < arr.size(); ++i ) + { + result.push_back( arr[i].template get_value< T >() ); + } + assert_eq( result, cont ); + } + }; + + void test_variant_constructor() + { +#ifdef JSON_SPIRIT_VALUE_ENABLED + Variant_constructor_runner< Config >(); +#endif +#ifdef JSON_SPIRIT_MVALUE_ENABLED + Variant_constructor_runner< mConfig >(); + +#endif +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Variant_constructor_runner< wConfig >(); +#endif +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Variant_constructor_runner< wmConfig >(); +#endif + } +} + +void json5_parser::test_value() +{ +#ifdef JSON_SPIRIT_VALUE_ENABLED + Object obj; + Value value_str ( "value" ); + Value value_obj ( obj ); + Value value_bool( true ); + + Value value_str_2 ( string( "value" ) ); + Value value_obj_2 ( obj ); + Value value_bool_2( false ); + + const char* str( "value" ); + Value value_str_2b ( str ); + + assert_eq( value_str, value_str ); + assert_eq( value_str, value_str_2 ); + assert_eq( value_str, value_str_2b ); + assert_eq( value_obj, value_obj ); + assert_eq( value_obj, value_obj_2 ); + assert_neq( value_str, value_obj ); + assert_neq( value_str, value_bool ); + + Object obj_2; + obj_2.push_back( Pair( "name", value_str ) ); + Value value_str_3( "xxxxx" ); + Value value_obj_3( obj_2 ); + + assert_neq( value_str, value_str_3 ); + assert_neq( value_obj, value_obj_3 ); + + test_obj_value(); + test_array_value(); + test_bool_value(); + test_int_value(); + test_real_value(); + test_null_value(); + test_get_value(); + test_copying(); + test_obj_map_implemention(); + test_is_uint64(); + test_an_int_is_a_real(); + test_wrong_type_exceptions(); +#endif + test_container_constructor(); + test_variant_constructor(); +} diff --git a/json_test/json5_parser_value_test.h b/json_test/json5_parser_value_test.h index a9c1391..c5c4a8f 100644 --- a/json_test/json5_parser_value_test.h +++ b/json_test/json5_parser_value_test.h @@ -1,18 +1,18 @@ -#ifndef JSON_SPIRIT_VALUE_TEST -#define JSON_SPIRIT_VALUE_TEST - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -namespace json5_parser -{ - void test_value(); -} - -#endif +#ifndef JSON_SPIRIT_VALUE_TEST +#define JSON_SPIRIT_VALUE_TEST + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace json5_parser +{ + void test_value(); +} + +#endif diff --git a/json_test/json5_parser_writer_test.cpp b/json_test/json5_parser_writer_test.cpp index 34395a2..c7e3c67 100644 --- a/json_test/json5_parser_writer_test.cpp +++ b/json_test/json5_parser_writer_test.cpp @@ -1,788 +1,788 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_writer_test.h" -#include "utils_test.h" -#include "json5_parser_writer.h" -#include "json5_parser_value.h" - -#include -#include - -using namespace json5_parser; -using namespace std; -using namespace boost; - -namespace -{ - const int64_t max_int64 = integer_traits< int64_t >::max(); - const uint64_t max_uint64 = integer_traits< uint64_t >::max(); - - template< class Config_type > - struct Test_runner - { - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; - typedef typename String_type::value_type Char_type; - typedef typename String_type::const_iterator Iter_type; - typedef std::basic_ostream< Char_type > Ostream_type; - - String_type to_str( const char* c_str ) - { - return ::to_str< String_type >( c_str ); - } - - String_type zero_str() - { -#ifdef WIN32 - return to_str( "0.00000000000000000" ); -#else - return to_str( "0.0000000000000000" ); -#endif - } - - void add_value( Object_type& obj, const char* c_name, const Value_type& value ) - { - Config_type::add( obj, to_str( c_name ), value ); - } - - void add_c_str( Object_type& obj, const char* c_name, const char* c_value ) - { - add_value( obj, c_name, to_str( c_value ) ); - } - - void check_eq( const Value_type& value, const String_type& expected_result ) - { - assert_eq( write( value ), expected_result ); - } - - void check_eq( const Value_type& value, const char* expected_result ) - { - check_eq( value, to_str( expected_result ) ); - } - - void check_eq_pretty( const Value_type& value, const char* expected_result ) - { - assert_eq( write_formatted( value ), to_str( expected_result ) ); - assert_eq( write( value, pretty_print ), to_str( expected_result ) ); - } - - void check_eq_single_line_arrays( const Value_type& value, const char* expected_result ) - { - assert_eq( write( value, single_line_arrays ), to_str( expected_result ) ); - } - - void check_eq( const Value_type& value, const String_type& expected_result , Output_options options ) - { - assert_eq( write( value, options ), expected_result ); - } - - void check_eq( const Value_type& value, const char* expected_result, Output_options options ) - { - check_eq( value, to_str( expected_result ), options ); - } - - void test_empty_obj() - { - check_eq( Object_type(), "{}" ); - check_eq_pretty( Object_type(), "{\n}" ); - } - - void test_obj_with_one_member() - { - Object_type obj; - - add_c_str( obj, "name", "value" ); - - check_eq ( obj, "{\"name\":\"value\"}" ); - check_eq_pretty( obj, "{\n" - " \"name\" : \"value\"\n" - "}" ); - } - - void test_obj_with_two_members() - { - Object_type obj; - - add_c_str( obj, "name_1", "value_1" ); - add_c_str( obj, "name_2", "value_2" ); - - check_eq( obj, "{\"name_1\":\"value_1\",\"name_2\":\"value_2\"}" ); - - check_eq_pretty( obj, "{\n" - " \"name_1\" : \"value_1\",\n" - " \"name_2\" : \"value_2\"\n" - "}" ); - } - - void test_obj_with_three_members() - { - Object_type obj; - - add_c_str( obj, "name_1", "value_1" ); - add_c_str( obj, "name_2", "value_2" ); - add_c_str( obj, "name_3", "value_3" ); - - check_eq( obj, "{\"name_1\":\"value_1\",\"name_2\":\"value_2\",\"name_3\":\"value_3\"}" ); - - check_eq_pretty( obj, "{\n" - " \"name_1\" : \"value_1\",\n" - " \"name_2\" : \"value_2\",\n" - " \"name_3\" : \"value_3\"\n" - "}" ); - } - - void test_obj_with_one_empty_child_obj() - { - Object_type child; - - Object_type root; - - add_value( root, "child", child ); - - check_eq( root, "{\"child\":{}}" ); - - check_eq_pretty( root, "{\n" - " \"child\" : {\n" - " }\n" - "}" ); - } - - void test_obj_with_one_child_obj() - { - Object_type child; - - add_c_str( child, "name_2", "value_2" ); - - Object_type root; - - add_value( root, "child", child ); - add_c_str( root, "name_1", "value_1" ); - - check_eq( root, "{\"child\":{\"name_2\":\"value_2\"},\"name_1\":\"value_1\"}" ); - - check_eq_pretty( root, "{\n" - " \"child\" : {\n" - " \"name_2\" : \"value_2\"\n" - " },\n" - " \"name_1\" : \"value_1\"\n" - "}" ); - } - - void test_obj_with_grandchild_obj() - { - Object_type child_1; add_c_str( child_1, "name_1", "value_1" ); - Object_type child_2; - Object_type child_3; add_c_str( child_3, "name_3", "value_3" ); - - add_value( child_2, "grandchild", child_3 ); - add_c_str( child_2, "name_2", "value_2" ); - - Object_type root; - - add_value( root, "child_1", child_1 ); - add_value( root, "child_2", child_2 ); - add_c_str( root, "name_a", "value_a" ); - add_c_str( root, "name_b", "value_b" ); - - check_eq( root, "{\"child_1\":{\"name_1\":\"value_1\"}," - "\"child_2\":{\"grandchild\":{\"name_3\":\"value_3\"},\"name_2\":\"value_2\"}," - "\"name_a\":\"value_a\"," - "\"name_b\":\"value_b\"}" ); - - check_eq_pretty( root, "{\n" - " \"child_1\" : {\n" - " \"name_1\" : \"value_1\"\n" - " },\n" - " \"child_2\" : {\n" - " \"grandchild\" : {\n" - " \"name_3\" : \"value_3\"\n" - " },\n" - " \"name_2\" : \"value_2\"\n" - " },\n" - " \"name_a\" : \"value_a\",\n" - " \"name_b\" : \"value_b\"\n" - "}" ); - } - - void test_objs_with_bool_pairs() - { - Object_type obj; - - add_value( obj, "name_1", true ); - add_value( obj, "name_2", false ); - add_value( obj, "name_3", true ); - - check_eq( obj, "{\"name_1\":true,\"name_2\":false,\"name_3\":true}" ); - } - - void test_objs_with_int_pairs() - { - Object_type obj; - - add_value( obj, "name_1", 11 ); - add_value( obj, "name_2", INT_MAX ); - add_value( obj, "name_3", max_int64 ); - - ostringstream os; - - os << "{\"name_1\":11,\"name_2\":" << INT_MAX << ",\"name_3\":" << max_int64 << "}"; - - check_eq( obj, os.str().c_str() ); - } - - void test_objs_with_real_pairs() - { - Object_type obj; - - add_value( obj, "name_1", 0.0 ); - add_value( obj, "name_2", 1.234567890123456789e-108 ); - add_value( obj, "name_3", -1234567890.123456789 ); - add_value( obj, "name_4", -1.2e-126 ); - - check_eq( obj, to_str( "{\"name_1\":0," - "\"name_2\":1.2345678901234567e-108," - "\"name_3\":-1234567890.1234567," - "\"name_4\":-1.2e-126}" ) ); - } - - void test_objs_with_null_pairs() - { - Object_type obj; - - add_value( obj, "name_1", Value_type::null ); - add_value( obj, "name_2", Value_type::null ); - add_value( obj, "name_3", Value_type::null ); - - check_eq( obj, "{\"name_1\":null,\"name_2\":null,\"name_3\":null}" ); - } - - void test_empty_array() - { - check_eq( Array_type(), "[]" ); - check_eq_pretty( Array_type(), "[\n" - "]" ); - check_eq_single_line_arrays( Array_type(), "[ ]" ); - } - - void test_array_with_one_member() - { - Array_type arr; - - arr.push_back( to_str( "value" ) ); - - check_eq ( arr, "[\"value\"]" ); - check_eq_pretty( arr, "[\n" - " \"value\"\n" - "]" ); - check_eq_single_line_arrays( arr, "[ \"value\" ]" ); - } - - void test_array_with_two_members() - { - Array_type arr; - - arr.push_back( to_str( "value_1" ) ); - arr.push_back( 1 ); - - check_eq ( arr, "[\"value_1\",1]" ); - check_eq_pretty( arr, "[\n" - " \"value_1\",\n" - " 1\n" - "]" ); - check_eq_single_line_arrays( arr, "[ \"value_1\", 1 ]" ); - } - - void test_array_with_n_members() - { - Array_type arr; - - arr.push_back( to_str( "value_1" ) ); - arr.push_back( 123 ); - arr.push_back( 123.456 ); - arr.push_back( true ); - arr.push_back( false ); - arr.push_back( Value_type() ); - - check_eq ( arr, "[\"value_1\",123,123.456,true,false,null]" ); - check_eq_pretty( arr, "[\n" - " \"value_1\",\n" - " 123,\n" - " 123.456,\n" - " true,\n" - " false,\n" - " null\n" - "]" ); - check_eq_single_line_arrays( arr, "[ \"value_1\", 123, 123.456, true, false, null ]" ); - } - - void test_array_with_one_empty_child_array() - { - Array_type arr; - - arr.push_back( Array_type() ); - - check_eq ( arr, "[[]]" ); - check_eq_pretty( arr, "[\n" - " [\n" - " ]\n" - "]" ); - check_eq_single_line_arrays( arr, "[\n" - " [ ]\n" - "]" ); - } - - void test_array_with_one_child_array() - { - Array_type child; - - child.push_back( 2 ); - - Array_type root; - - root.push_back( 1 ); - root.push_back( child ); - - check_eq ( root, "[1,[2]]" ); - check_eq_pretty( root, "[\n" - " 1,\n" - " [\n" - " 2\n" - " ]\n" - "]" ); - check_eq_single_line_arrays( root, "[\n" - " 1,\n" - " [ 2 ]\n" - "]" ); - } - - void test_array_with_grandchild_array() - { - Array_type child_1; child_1.push_back( 11 ); - Array_type child_2; child_2.push_back( 22 ); - Array_type child_3; child_3.push_back( 33 ); - - child_2.push_back( child_3 ); - - Array_type root; - - root.push_back( 1); - root.push_back( child_1 ); - root.push_back( child_2 ); - root.push_back( 2 ); - - check_eq ( root, "[1,[11],[22,[33]],2]" ); - check_eq_pretty( root, "[\n" - " 1,\n" - " [\n" - " 11\n" - " ],\n" - " [\n" - " 22,\n" - " [\n" - " 33\n" - " ]\n" - " ],\n" - " 2\n" - "]" ); - check_eq_single_line_arrays( root, "[\n" - " 1,\n" - " [ 11 ],\n" - " [\n" - " 22,\n" - " [ 33 ]\n" - " ],\n" - " 2\n" - "]" ); - } - - void test_array_and_objs() - { - Array_type a; - - a.push_back( 11 ); - - Object_type obj; - - add_value( obj, "a", 1 ); - - a.push_back( obj ); - - check_eq ( a, "[11,{\"a\":1}]" ); - check_eq_pretty( a, "[\n" - " 11,\n" - " {\n" - " \"a\" : 1\n" - " }\n" - "]" ); - check_eq_single_line_arrays( a, "[\n" - " 11,\n" - " {\n" - " \"a\" : 1\n" - " }\n" - "]" ); - - add_value( obj, "b", 2 ); - - a.push_back( 22 ); - a.push_back( 33 ); - a.push_back( obj ); - - check_eq ( a, "[11,{\"a\":1},22,33,{\"a\":1,\"b\":2}]" ); - check_eq_pretty( a, "[\n" - " 11,\n" - " {\n" - " \"a\" : 1\n" - " },\n" - " 22,\n" - " 33,\n" - " {\n" - " \"a\" : 1,\n" - " \"b\" : 2\n" - " }\n" - "]" ); - check_eq_single_line_arrays( a, "[\n" - " 11,\n" - " {\n" - " \"a\" : 1\n" - " },\n" - " 22,\n" - " 33,\n" - " {\n" - " \"a\" : 1,\n" - " \"b\" : 2\n" - " }\n" - "]" ); - } - - void test_obj_and_arrays() - { - Object_type obj; - - add_value( obj, "a", 1 ); - - Array_type a; - - a.push_back( 11 ); - a.push_back( 12 ); - - add_value( obj, "b", a ); - - check_eq ( obj, "{\"a\":1,\"b\":[11,12]}" ); - check_eq_pretty( obj, "{\n" - " \"a\" : 1,\n" - " \"b\" : [\n" - " 11,\n" - " 12\n" - " ]\n" - "}" ); - check_eq_single_line_arrays( obj, "{\n" - " \"a\" : 1,\n" - " \"b\" : [ 11, 12 ]\n" - "}" ); - - a.push_back( obj ); - - add_value( obj, "c", a ); - - check_eq ( obj, "{\"a\":1,\"b\":[11,12],\"c\":[11,12,{\"a\":1,\"b\":[11,12]}]}" ); - check_eq_pretty( obj, "{\n" - " \"a\" : 1,\n" - " \"b\" : [\n" - " 11,\n" - " 12\n" - " ],\n" - " \"c\" : [\n" - " 11,\n" - " 12,\n" - " {\n" - " \"a\" : 1,\n" - " \"b\" : [\n" - " 11,\n" - " 12\n" - " ]\n" - " }\n" - " ]\n" - "}" ); - check_eq_single_line_arrays( obj, "{\n" - " \"a\" : 1,\n" - " \"b\" : [ 11, 12 ],\n" - " \"c\" : [\n" - " 11,\n" - " 12,\n" - " {\n" - " \"a\" : 1,\n" - " \"b\" : [ 11, 12 ]\n" - " }\n" - " ]\n" - "}" ); - } - - void test_escape_char( const char* esc_str_in, const char* esc_str_out, Output_options options = none ) - { - Object_type obj; - - const string name_str( string( esc_str_in ) + "name" ); - - add_value( obj, name_str.c_str(), to_str( "value" ) + to_str( esc_str_in ) ); - - const string out_str( string( "{\"" ) + esc_str_out + "name\":\"value" + esc_str_out + "\"}" ); - - check_eq( obj, out_str.c_str(), options ); - } - - void test_escape_chars() - { - test_escape_char( "\r", "\\r" ); - test_escape_char( "\n", "\\n" ); - test_escape_char( "\t", "\\t" ); - test_escape_char( "\f", "\\f" ); - test_escape_char( "\b", "\\b" ); - test_escape_char( "\"", "\\\"" ); - test_escape_char( "\\", "\\\\" ); - test_escape_char( "\x01", "\\u0001" ); - test_escape_char( "\x12", "\\u0012" ); - test_escape_char( "\x7F", "\\u007F" ); - } - - void test_disabling_nonprintable_esc_chars() - { - test_escape_char( "\t", "\\t", raw_utf8 ); - test_escape_char( "\x01", "\x01", raw_utf8 ); - test_escape_char( "\x01\x12", "\x01\x12", raw_utf8 ); - } - - void test_to_stream() - { - basic_ostringstream< Char_type > os; - - Array_type arr; - - arr.push_back( 111 ); - arr.push_back( 222 ); - - os << hex; // the code should handle this, i.e. output decimal - - write( arr, os ); - - assert_eq( os.str(), to_str( "[111,222]" ) ); - } - - void test_values() - { - check_eq( 123, "123" ); - check_eq( 1.234, "1.234" ); - check_eq( to_str( "abc" ), "\"abc\"" ); - check_eq( false, "false" ); - check_eq( Value_type::null, "null" ); - } - - void test_uint64() - { - check_eq( Value_type( 0 ), "0" ); - check_eq( Value_type( int64_t( 0 ) ), "0" ); - check_eq( Value_type( uint64_t( 0 ) ), "0" ); - - check_eq( Value_type( 1 ), "1" ); - check_eq( Value_type( int64_t( 1 ) ), "1" ); - check_eq( Value_type( uint64_t( 1 ) ), "1" ); - - check_eq( Value_type( -1 ), "-1" ); - check_eq( Value_type( int64_t( -1 ) ), "-1" ); - - check_eq( Value_type( max_int64 ), "9223372036854775807" ); - check_eq( Value_type( uint64_t( max_int64 ) ), "9223372036854775807" ); - - check_eq( Value_type( max_uint64 ), "18446744073709551615" ); - } - - void test_ios_state_saved() - { - basic_ostringstream< Char_type > os; - - os << 0.123456789; - - Array_type arr; - - arr.push_back( 0.123456789 ); - - write( arr, os ); - - os << 0.123456789; - - assert_eq( os.str(), to_str( "0.123457" - "[0.123456789]" - "0.123457" ) ); - } - - void check_remove_trailing_zeros( const double value, const String_type& expected_str_with, const String_type& expected_str_without ) - { - check_eq( value, expected_str_with, none ); - check_eq( value, expected_str_without, remove_trailing_zeros ); - } - - void check_remove_trailing_zeros( const double value, const char* expected_str_with, const char* expected_str_without ) - { - check_remove_trailing_zeros( value, to_str( expected_str_with ), to_str( expected_str_without ) ); - } - - void test_remove_trailing_zeros() - { -#ifdef WIN32 - const String_type exp = to_str( "099" ); -#else - const String_type exp = to_str( "99" ); -#endif - check_remove_trailing_zeros( 0.0, "0", "0" ); - check_remove_trailing_zeros( 1.2, "1.2", "1.2" ); - check_remove_trailing_zeros( 0.123456789, "0.123456789", "0.123456789" ); - check_remove_trailing_zeros( 1.2e-99, to_str( "1.2e-" ) + exp, to_str( "1.2e-" ) + exp ); - check_remove_trailing_zeros( 1.23456789e99, to_str( "1.2345678900000001e+" ) + exp, to_str( "1.23456789e+" ) + exp ); - } - - void check_precision_of_doubles( unsigned int precision, const char* expected_result_1, const char* expected_result_2 = 0 ) - { - Value_type val = 0.1234567890123456789; - assert_eq( write( val, none, precision ), to_str( expected_result_1 ) ); - if( !expected_result_2 ) - { - expected_result_2 = expected_result_1; - } - assert_eq( write( val, remove_trailing_zeros, precision ), to_str( expected_result_2 ) ); - } - - void check_precision_of_doubles( const char* expected_result_1, const char* expected_result_2 ) - { - Value_type val = 0.1234567890123456789; - assert_eq( write( val, none ), to_str( expected_result_1 ) ); - assert_eq( write( val, remove_trailing_zeros ), to_str( expected_result_2 ) ); - } - - void test_precision_of_doubles() - { - // default is 17, or 16 for remove_trailing_zeros flag - check_precision_of_doubles( "0.12345678901234568", "0.1234567890123457" ); - check_precision_of_doubles( 0, "0.12345678901234568", "0.1234567890123457" ); - - // specified override is used with or without remove_trailing_zeros flag - check_precision_of_doubles( 9, "0.123456789" ); - check_precision_of_doubles( 6, "0.123457" ); - check_precision_of_doubles( 1, "0.1" ); - } - - void test_multiple_options() - { - Value value; - write(value, always_escape_nonascii | pretty_print ); - } - - void run_tests() - { - test_empty_obj(); - test_obj_with_one_member(); - test_obj_with_two_members(); - test_obj_with_three_members(); - test_obj_with_one_empty_child_obj(); - test_obj_with_one_child_obj(); - test_obj_with_grandchild_obj(); - test_objs_with_bool_pairs(); - test_objs_with_int_pairs(); - test_objs_with_real_pairs(); - test_objs_with_null_pairs(); - test_empty_array(); - test_array_with_one_member(); - test_array_with_two_members(); - test_array_with_n_members(); - test_array_with_one_empty_child_array(); - test_array_with_one_child_array(); - test_array_with_grandchild_array(); - test_array_and_objs(); - test_obj_and_arrays(); - test_escape_chars(); - test_disabling_nonprintable_esc_chars(); - test_to_stream(); - test_values(); - test_uint64(); - test_ios_state_saved(); - test_remove_trailing_zeros(); - test_precision_of_doubles(); - test_multiple_options(); - } - }; - -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void test_always_esc_nonascii() - { - if( iswprint( L'\x05DE' ) ) - { - const wstring s( L"\x05DE\x05E9\x05EA\x05DE\x05E9" ); - - wArray arr( 1, s ); - - const wstring foo = arr[0].get_str(); - - const wstring json_raw = write( arr ); - - assert_eq( json_raw, L"[\"" + s + L"\"]" ); - - const wstring json_escaped = write( arr, always_escape_nonascii ); - - assert_eq( json_escaped, L"[\"\\u05DE\\u05E9\\u05EA\\u05DE\\u05E9\"]" ); - } - } - - void test_wide_esc_u( wchar_t c, const wstring& result) - { - const wstring s( 1, c ); - - wArray arr( 1, s ); - - assert_eq( write( arr ), L"[\"\\u" + result + L"\"]" ); - } - - void test_wide_esc_u() - { - test_wide_esc_u( 0xABCD, L"ABCD" ); - test_wide_esc_u( 0xFFFF, L"FFFF" ); - } -#endif - - bool is_printable( char c ) - { - const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c ); - - return iswprint( unsigned_c ) != 0; - } - -#ifdef JSON_SPIRIT_VALUE_ENABLED - void test_extended_ascii() - { - const string expeced_result( is_printable( '\xE4' ) ? "[\"\xE4\xF6\xFC\xDF\"]" : "[\"\\u00E4\\u00F6\\u00FC\\u00DF\"]" ); - - assert_eq( write( Array( 1, "\xE4\xF6\xFC\xDF" ) ), expeced_result ); - } -#endif -} - -void json5_parser::test_writer() -{ -#ifdef JSON_SPIRIT_VALUE_ENABLED - Test_runner< Config >().run_tests(); - test_extended_ascii(); -#endif -#ifdef JSON_SPIRIT_MVALUE_ENABLED - Test_runner< mConfig >().run_tests(); -#endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wConfig >().run_tests(); - test_wide_esc_u(); - test_always_esc_nonascii(); -#endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wmConfig >().run_tests(); -#endif -} +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_writer_test.h" +#include "utils_test.h" +#include "json5_parser_writer.h" +#include "json5_parser_value.h" + +#include +#include + +using namespace json5_parser; +using namespace std; +using namespace boost; + +namespace +{ + const int64_t max_int64 = integer_traits< int64_t >::max(); + const uint64_t max_uint64 = integer_traits< uint64_t >::max(); + + template< class Config_type > + struct Test_runner + { + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + typedef typename String_type::value_type Char_type; + typedef typename String_type::const_iterator Iter_type; + typedef std::basic_ostream< Char_type > Ostream_type; + + String_type to_str( const char* c_str ) + { + return ::to_str< String_type >( c_str ); + } + + String_type zero_str() + { +#ifdef WIN32 + return to_str( "0.00000000000000000" ); +#else + return to_str( "0.0000000000000000" ); +#endif + } + + void add_value( Object_type& obj, const char* c_name, const Value_type& value ) + { + Config_type::add( obj, to_str( c_name ), value ); + } + + void add_c_str( Object_type& obj, const char* c_name, const char* c_value ) + { + add_value( obj, c_name, to_str( c_value ) ); + } + + void check_eq( const Value_type& value, const String_type& expected_result ) + { + assert_eq( write( value ), expected_result ); + } + + void check_eq( const Value_type& value, const char* expected_result ) + { + check_eq( value, to_str( expected_result ) ); + } + + void check_eq_pretty( const Value_type& value, const char* expected_result ) + { + assert_eq( write_formatted( value ), to_str( expected_result ) ); + assert_eq( write( value, pretty_print ), to_str( expected_result ) ); + } + + void check_eq_single_line_arrays( const Value_type& value, const char* expected_result ) + { + assert_eq( write( value, single_line_arrays ), to_str( expected_result ) ); + } + + void check_eq( const Value_type& value, const String_type& expected_result , Output_options options ) + { + assert_eq( write( value, options ), expected_result ); + } + + void check_eq( const Value_type& value, const char* expected_result, Output_options options ) + { + check_eq( value, to_str( expected_result ), options ); + } + + void test_empty_obj() + { + check_eq( Object_type(), "{}" ); + check_eq_pretty( Object_type(), "{\n}" ); + } + + void test_obj_with_one_member() + { + Object_type obj; + + add_c_str( obj, "name", "value" ); + + check_eq ( obj, "{\"name\":\"value\"}" ); + check_eq_pretty( obj, "{\n" + " \"name\" : \"value\"\n" + "}" ); + } + + void test_obj_with_two_members() + { + Object_type obj; + + add_c_str( obj, "name_1", "value_1" ); + add_c_str( obj, "name_2", "value_2" ); + + check_eq( obj, "{\"name_1\":\"value_1\",\"name_2\":\"value_2\"}" ); + + check_eq_pretty( obj, "{\n" + " \"name_1\" : \"value_1\",\n" + " \"name_2\" : \"value_2\"\n" + "}" ); + } + + void test_obj_with_three_members() + { + Object_type obj; + + add_c_str( obj, "name_1", "value_1" ); + add_c_str( obj, "name_2", "value_2" ); + add_c_str( obj, "name_3", "value_3" ); + + check_eq( obj, "{\"name_1\":\"value_1\",\"name_2\":\"value_2\",\"name_3\":\"value_3\"}" ); + + check_eq_pretty( obj, "{\n" + " \"name_1\" : \"value_1\",\n" + " \"name_2\" : \"value_2\",\n" + " \"name_3\" : \"value_3\"\n" + "}" ); + } + + void test_obj_with_one_empty_child_obj() + { + Object_type child; + + Object_type root; + + add_value( root, "child", child ); + + check_eq( root, "{\"child\":{}}" ); + + check_eq_pretty( root, "{\n" + " \"child\" : {\n" + " }\n" + "}" ); + } + + void test_obj_with_one_child_obj() + { + Object_type child; + + add_c_str( child, "name_2", "value_2" ); + + Object_type root; + + add_value( root, "child", child ); + add_c_str( root, "name_1", "value_1" ); + + check_eq( root, "{\"child\":{\"name_2\":\"value_2\"},\"name_1\":\"value_1\"}" ); + + check_eq_pretty( root, "{\n" + " \"child\" : {\n" + " \"name_2\" : \"value_2\"\n" + " },\n" + " \"name_1\" : \"value_1\"\n" + "}" ); + } + + void test_obj_with_grandchild_obj() + { + Object_type child_1; add_c_str( child_1, "name_1", "value_1" ); + Object_type child_2; + Object_type child_3; add_c_str( child_3, "name_3", "value_3" ); + + add_value( child_2, "grandchild", child_3 ); + add_c_str( child_2, "name_2", "value_2" ); + + Object_type root; + + add_value( root, "child_1", child_1 ); + add_value( root, "child_2", child_2 ); + add_c_str( root, "name_a", "value_a" ); + add_c_str( root, "name_b", "value_b" ); + + check_eq( root, "{\"child_1\":{\"name_1\":\"value_1\"}," + "\"child_2\":{\"grandchild\":{\"name_3\":\"value_3\"},\"name_2\":\"value_2\"}," + "\"name_a\":\"value_a\"," + "\"name_b\":\"value_b\"}" ); + + check_eq_pretty( root, "{\n" + " \"child_1\" : {\n" + " \"name_1\" : \"value_1\"\n" + " },\n" + " \"child_2\" : {\n" + " \"grandchild\" : {\n" + " \"name_3\" : \"value_3\"\n" + " },\n" + " \"name_2\" : \"value_2\"\n" + " },\n" + " \"name_a\" : \"value_a\",\n" + " \"name_b\" : \"value_b\"\n" + "}" ); + } + + void test_objs_with_bool_pairs() + { + Object_type obj; + + add_value( obj, "name_1", true ); + add_value( obj, "name_2", false ); + add_value( obj, "name_3", true ); + + check_eq( obj, "{\"name_1\":true,\"name_2\":false,\"name_3\":true}" ); + } + + void test_objs_with_int_pairs() + { + Object_type obj; + + add_value( obj, "name_1", 11 ); + add_value( obj, "name_2", INT_MAX ); + add_value( obj, "name_3", max_int64 ); + + ostringstream os; + + os << "{\"name_1\":11,\"name_2\":" << INT_MAX << ",\"name_3\":" << max_int64 << "}"; + + check_eq( obj, os.str().c_str() ); + } + + void test_objs_with_real_pairs() + { + Object_type obj; + + add_value( obj, "name_1", 0.0 ); + add_value( obj, "name_2", 1.234567890123456789e-108 ); + add_value( obj, "name_3", -1234567890.123456789 ); + add_value( obj, "name_4", -1.2e-126 ); + + check_eq( obj, to_str( "{\"name_1\":0," + "\"name_2\":1.2345678901234567e-108," + "\"name_3\":-1234567890.1234567," + "\"name_4\":-1.2e-126}" ) ); + } + + void test_objs_with_null_pairs() + { + Object_type obj; + + add_value( obj, "name_1", Value_type::null ); + add_value( obj, "name_2", Value_type::null ); + add_value( obj, "name_3", Value_type::null ); + + check_eq( obj, "{\"name_1\":null,\"name_2\":null,\"name_3\":null}" ); + } + + void test_empty_array() + { + check_eq( Array_type(), "[]" ); + check_eq_pretty( Array_type(), "[\n" + "]" ); + check_eq_single_line_arrays( Array_type(), "[ ]" ); + } + + void test_array_with_one_member() + { + Array_type arr; + + arr.push_back( to_str( "value" ) ); + + check_eq ( arr, "[\"value\"]" ); + check_eq_pretty( arr, "[\n" + " \"value\"\n" + "]" ); + check_eq_single_line_arrays( arr, "[ \"value\" ]" ); + } + + void test_array_with_two_members() + { + Array_type arr; + + arr.push_back( to_str( "value_1" ) ); + arr.push_back( 1 ); + + check_eq ( arr, "[\"value_1\",1]" ); + check_eq_pretty( arr, "[\n" + " \"value_1\",\n" + " 1\n" + "]" ); + check_eq_single_line_arrays( arr, "[ \"value_1\", 1 ]" ); + } + + void test_array_with_n_members() + { + Array_type arr; + + arr.push_back( to_str( "value_1" ) ); + arr.push_back( 123 ); + arr.push_back( 123.456 ); + arr.push_back( true ); + arr.push_back( false ); + arr.push_back( Value_type() ); + + check_eq ( arr, "[\"value_1\",123,123.456,true,false,null]" ); + check_eq_pretty( arr, "[\n" + " \"value_1\",\n" + " 123,\n" + " 123.456,\n" + " true,\n" + " false,\n" + " null\n" + "]" ); + check_eq_single_line_arrays( arr, "[ \"value_1\", 123, 123.456, true, false, null ]" ); + } + + void test_array_with_one_empty_child_array() + { + Array_type arr; + + arr.push_back( Array_type() ); + + check_eq ( arr, "[[]]" ); + check_eq_pretty( arr, "[\n" + " [\n" + " ]\n" + "]" ); + check_eq_single_line_arrays( arr, "[\n" + " [ ]\n" + "]" ); + } + + void test_array_with_one_child_array() + { + Array_type child; + + child.push_back( 2 ); + + Array_type root; + + root.push_back( 1 ); + root.push_back( child ); + + check_eq ( root, "[1,[2]]" ); + check_eq_pretty( root, "[\n" + " 1,\n" + " [\n" + " 2\n" + " ]\n" + "]" ); + check_eq_single_line_arrays( root, "[\n" + " 1,\n" + " [ 2 ]\n" + "]" ); + } + + void test_array_with_grandchild_array() + { + Array_type child_1; child_1.push_back( 11 ); + Array_type child_2; child_2.push_back( 22 ); + Array_type child_3; child_3.push_back( 33 ); + + child_2.push_back( child_3 ); + + Array_type root; + + root.push_back( 1); + root.push_back( child_1 ); + root.push_back( child_2 ); + root.push_back( 2 ); + + check_eq ( root, "[1,[11],[22,[33]],2]" ); + check_eq_pretty( root, "[\n" + " 1,\n" + " [\n" + " 11\n" + " ],\n" + " [\n" + " 22,\n" + " [\n" + " 33\n" + " ]\n" + " ],\n" + " 2\n" + "]" ); + check_eq_single_line_arrays( root, "[\n" + " 1,\n" + " [ 11 ],\n" + " [\n" + " 22,\n" + " [ 33 ]\n" + " ],\n" + " 2\n" + "]" ); + } + + void test_array_and_objs() + { + Array_type a; + + a.push_back( 11 ); + + Object_type obj; + + add_value( obj, "a", 1 ); + + a.push_back( obj ); + + check_eq ( a, "[11,{\"a\":1}]" ); + check_eq_pretty( a, "[\n" + " 11,\n" + " {\n" + " \"a\" : 1\n" + " }\n" + "]" ); + check_eq_single_line_arrays( a, "[\n" + " 11,\n" + " {\n" + " \"a\" : 1\n" + " }\n" + "]" ); + + add_value( obj, "b", 2 ); + + a.push_back( 22 ); + a.push_back( 33 ); + a.push_back( obj ); + + check_eq ( a, "[11,{\"a\":1},22,33,{\"a\":1,\"b\":2}]" ); + check_eq_pretty( a, "[\n" + " 11,\n" + " {\n" + " \"a\" : 1\n" + " },\n" + " 22,\n" + " 33,\n" + " {\n" + " \"a\" : 1,\n" + " \"b\" : 2\n" + " }\n" + "]" ); + check_eq_single_line_arrays( a, "[\n" + " 11,\n" + " {\n" + " \"a\" : 1\n" + " },\n" + " 22,\n" + " 33,\n" + " {\n" + " \"a\" : 1,\n" + " \"b\" : 2\n" + " }\n" + "]" ); + } + + void test_obj_and_arrays() + { + Object_type obj; + + add_value( obj, "a", 1 ); + + Array_type a; + + a.push_back( 11 ); + a.push_back( 12 ); + + add_value( obj, "b", a ); + + check_eq ( obj, "{\"a\":1,\"b\":[11,12]}" ); + check_eq_pretty( obj, "{\n" + " \"a\" : 1,\n" + " \"b\" : [\n" + " 11,\n" + " 12\n" + " ]\n" + "}" ); + check_eq_single_line_arrays( obj, "{\n" + " \"a\" : 1,\n" + " \"b\" : [ 11, 12 ]\n" + "}" ); + + a.push_back( obj ); + + add_value( obj, "c", a ); + + check_eq ( obj, "{\"a\":1,\"b\":[11,12],\"c\":[11,12,{\"a\":1,\"b\":[11,12]}]}" ); + check_eq_pretty( obj, "{\n" + " \"a\" : 1,\n" + " \"b\" : [\n" + " 11,\n" + " 12\n" + " ],\n" + " \"c\" : [\n" + " 11,\n" + " 12,\n" + " {\n" + " \"a\" : 1,\n" + " \"b\" : [\n" + " 11,\n" + " 12\n" + " ]\n" + " }\n" + " ]\n" + "}" ); + check_eq_single_line_arrays( obj, "{\n" + " \"a\" : 1,\n" + " \"b\" : [ 11, 12 ],\n" + " \"c\" : [\n" + " 11,\n" + " 12,\n" + " {\n" + " \"a\" : 1,\n" + " \"b\" : [ 11, 12 ]\n" + " }\n" + " ]\n" + "}" ); + } + + void test_escape_char( const char* esc_str_in, const char* esc_str_out, Output_options options = none ) + { + Object_type obj; + + const string name_str( string( esc_str_in ) + "name" ); + + add_value( obj, name_str.c_str(), to_str( "value" ) + to_str( esc_str_in ) ); + + const string out_str( string( "{\"" ) + esc_str_out + "name\":\"value" + esc_str_out + "\"}" ); + + check_eq( obj, out_str.c_str(), options ); + } + + void test_escape_chars() + { + test_escape_char( "\r", "\\r" ); + test_escape_char( "\n", "\\n" ); + test_escape_char( "\t", "\\t" ); + test_escape_char( "\f", "\\f" ); + test_escape_char( "\b", "\\b" ); + test_escape_char( "\"", "\\\"" ); + test_escape_char( "\\", "\\\\" ); + test_escape_char( "\x01", "\\u0001" ); + test_escape_char( "\x12", "\\u0012" ); + test_escape_char( "\x7F", "\\u007F" ); + } + + void test_disabling_nonprintable_esc_chars() + { + test_escape_char( "\t", "\\t", raw_utf8 ); + test_escape_char( "\x01", "\x01", raw_utf8 ); + test_escape_char( "\x01\x12", "\x01\x12", raw_utf8 ); + } + + void test_to_stream() + { + basic_ostringstream< Char_type > os; + + Array_type arr; + + arr.push_back( 111 ); + arr.push_back( 222 ); + + os << hex; // the code should handle this, i.e. output decimal + + write( arr, os ); + + assert_eq( os.str(), to_str( "[111,222]" ) ); + } + + void test_values() + { + check_eq( 123, "123" ); + check_eq( 1.234, "1.234" ); + check_eq( to_str( "abc" ), "\"abc\"" ); + check_eq( false, "false" ); + check_eq( Value_type::null, "null" ); + } + + void test_uint64() + { + check_eq( Value_type( 0 ), "0" ); + check_eq( Value_type( int64_t( 0 ) ), "0" ); + check_eq( Value_type( uint64_t( 0 ) ), "0" ); + + check_eq( Value_type( 1 ), "1" ); + check_eq( Value_type( int64_t( 1 ) ), "1" ); + check_eq( Value_type( uint64_t( 1 ) ), "1" ); + + check_eq( Value_type( -1 ), "-1" ); + check_eq( Value_type( int64_t( -1 ) ), "-1" ); + + check_eq( Value_type( max_int64 ), "9223372036854775807" ); + check_eq( Value_type( uint64_t( max_int64 ) ), "9223372036854775807" ); + + check_eq( Value_type( max_uint64 ), "18446744073709551615" ); + } + + void test_ios_state_saved() + { + basic_ostringstream< Char_type > os; + + os << 0.123456789; + + Array_type arr; + + arr.push_back( 0.123456789 ); + + write( arr, os ); + + os << 0.123456789; + + assert_eq( os.str(), to_str( "0.123457" + "[0.123456789]" + "0.123457" ) ); + } + + void check_remove_trailing_zeros( const double value, const String_type& expected_str_with, const String_type& expected_str_without ) + { + check_eq( value, expected_str_with, none ); + check_eq( value, expected_str_without, remove_trailing_zeros ); + } + + void check_remove_trailing_zeros( const double value, const char* expected_str_with, const char* expected_str_without ) + { + check_remove_trailing_zeros( value, to_str( expected_str_with ), to_str( expected_str_without ) ); + } + + void test_remove_trailing_zeros() + { +#ifdef WIN32 + const String_type exp = to_str( "099" ); +#else + const String_type exp = to_str( "99" ); +#endif + check_remove_trailing_zeros( 0.0, "0", "0" ); + check_remove_trailing_zeros( 1.2, "1.2", "1.2" ); + check_remove_trailing_zeros( 0.123456789, "0.123456789", "0.123456789" ); + check_remove_trailing_zeros( 1.2e-99, to_str( "1.2e-" ) + exp, to_str( "1.2e-" ) + exp ); + check_remove_trailing_zeros( 1.23456789e99, to_str( "1.2345678900000001e+" ) + exp, to_str( "1.23456789e+" ) + exp ); + } + + void check_precision_of_doubles( unsigned int precision, const char* expected_result_1, const char* expected_result_2 = 0 ) + { + Value_type val = 0.1234567890123456789; + assert_eq( write( val, none, precision ), to_str( expected_result_1 ) ); + if( !expected_result_2 ) + { + expected_result_2 = expected_result_1; + } + assert_eq( write( val, remove_trailing_zeros, precision ), to_str( expected_result_2 ) ); + } + + void check_precision_of_doubles( const char* expected_result_1, const char* expected_result_2 ) + { + Value_type val = 0.1234567890123456789; + assert_eq( write( val, none ), to_str( expected_result_1 ) ); + assert_eq( write( val, remove_trailing_zeros ), to_str( expected_result_2 ) ); + } + + void test_precision_of_doubles() + { + // default is 17, or 16 for remove_trailing_zeros flag + check_precision_of_doubles( "0.12345678901234568", "0.1234567890123457" ); + check_precision_of_doubles( 0, "0.12345678901234568", "0.1234567890123457" ); + + // specified override is used with or without remove_trailing_zeros flag + check_precision_of_doubles( 9, "0.123456789" ); + check_precision_of_doubles( 6, "0.123457" ); + check_precision_of_doubles( 1, "0.1" ); + } + + void test_multiple_options() + { + Value value; + write(value, always_escape_nonascii | pretty_print ); + } + + void run_tests() + { + test_empty_obj(); + test_obj_with_one_member(); + test_obj_with_two_members(); + test_obj_with_three_members(); + test_obj_with_one_empty_child_obj(); + test_obj_with_one_child_obj(); + test_obj_with_grandchild_obj(); + test_objs_with_bool_pairs(); + test_objs_with_int_pairs(); + test_objs_with_real_pairs(); + test_objs_with_null_pairs(); + test_empty_array(); + test_array_with_one_member(); + test_array_with_two_members(); + test_array_with_n_members(); + test_array_with_one_empty_child_array(); + test_array_with_one_child_array(); + test_array_with_grandchild_array(); + test_array_and_objs(); + test_obj_and_arrays(); + test_escape_chars(); + test_disabling_nonprintable_esc_chars(); + test_to_stream(); + test_values(); + test_uint64(); + test_ios_state_saved(); + test_remove_trailing_zeros(); + test_precision_of_doubles(); + test_multiple_options(); + } + }; + +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + void test_always_esc_nonascii() + { + if( iswprint( L'\x05DE' ) ) + { + const wstring s( L"\x05DE\x05E9\x05EA\x05DE\x05E9" ); + + wArray arr( 1, s ); + + const wstring foo = arr[0].get_str(); + + const wstring json_raw = write( arr ); + + assert_eq( json_raw, L"[\"" + s + L"\"]" ); + + const wstring json_escaped = write( arr, always_escape_nonascii ); + + assert_eq( json_escaped, L"[\"\\u05DE\\u05E9\\u05EA\\u05DE\\u05E9\"]" ); + } + } + + void test_wide_esc_u( wchar_t c, const wstring& result) + { + const wstring s( 1, c ); + + wArray arr( 1, s ); + + assert_eq( write( arr ), L"[\"\\u" + result + L"\"]" ); + } + + void test_wide_esc_u() + { + test_wide_esc_u( 0xABCD, L"ABCD" ); + test_wide_esc_u( 0xFFFF, L"FFFF" ); + } +#endif + + bool is_printable( char c ) + { + const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c ); + + return iswprint( unsigned_c ) != 0; + } + +#ifdef JSON_SPIRIT_VALUE_ENABLED + void test_extended_ascii() + { + const string expeced_result( is_printable( '\xE4' ) ? "[\"\xE4\xF6\xFC\xDF\"]" : "[\"\\u00E4\\u00F6\\u00FC\\u00DF\"]" ); + + assert_eq( write( Array( 1, "\xE4\xF6\xFC\xDF" ) ), expeced_result ); + } +#endif +} + +void json5_parser::test_writer() +{ +#ifdef JSON_SPIRIT_VALUE_ENABLED + Test_runner< Config >().run_tests(); + test_extended_ascii(); +#endif +#ifdef JSON_SPIRIT_MVALUE_ENABLED + Test_runner< mConfig >().run_tests(); +#endif +#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Test_runner< wConfig >().run_tests(); + test_wide_esc_u(); + test_always_esc_nonascii(); +#endif +#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) + Test_runner< wmConfig >().run_tests(); +#endif +} diff --git a/json_test/json5_parser_writer_test.h b/json_test/json5_parser_writer_test.h index 3c9bb77..a6eaf77 100644 --- a/json_test/json5_parser_writer_test.h +++ b/json_test/json5_parser_writer_test.h @@ -1,18 +1,18 @@ -#ifndef JSON_SPIRIT_WRITER_TEST -#define JSON_SPIRIT_WRITER_TEST - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -namespace json5_parser -{ - void test_writer(); -} - -#endif +#ifndef JSON_SPIRIT_WRITER_TEST +#define JSON_SPIRIT_WRITER_TEST + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace json5_parser +{ + void test_writer(); +} + +#endif diff --git a/json_test/json_test.cpp b/json_test/json_test.cpp index 6d63fbe..6cf579b 100644 --- a/json_test/json_test.cpp +++ b/json_test/json_test.cpp @@ -1,29 +1,29 @@ -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "json5_parser_value_test.h" -#include "json5_parser_writer_test.h" -#include "json5_parser_reader_test.h" -#include "json5_parser_stream_reader_test.h" -#include "json5_parser_utils_test.h" - -#include -#include - -using namespace std; -using namespace json5_parser; - -int main() -{ - test_value(); - test_writer(); - test_reader(); - test_stream_reader(); - test_utils(); - - cout << "all tests passed" << endl << endl; - return 0; -} - +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "json5_parser_value_test.h" +#include "json5_parser_writer_test.h" +#include "json5_parser_reader_test.h" +#include "json5_parser_stream_reader_test.h" +#include "json5_parser_utils_test.h" + +#include +#include + +using namespace std; +using namespace json5_parser; + +int main() +{ + test_value(); + test_writer(); + test_reader(); + test_stream_reader(); + test_utils(); + + cout << "all tests passed" << endl << endl; + return 0; +} + diff --git a/json_test/utils_test.cpp b/json_test/utils_test.cpp index 73cac15..a6f3e30 100644 --- a/json_test/utils_test.cpp +++ b/json_test/utils_test.cpp @@ -1,15 +1,15 @@ -// Copyright John W. Wilkinson 2011 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#include "utils_test.h" - -void assert_eq( const double d1, const double d2, const double abs_error ) -{ - const double err = fabs( d1 - d2 ); - - if( err <= abs_error ) return; - - assert( false ); -} +// Copyright John W. Wilkinson 2011 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#include "utils_test.h" + +void assert_eq( const double d1, const double d2, const double abs_error ) +{ + const double err = fabs( d1 - d2 ); + + if( err <= abs_error ) return; + + assert( false ); +} diff --git a/json_test/utils_test.h b/json_test/utils_test.h index 9f65731..fd9fa53 100644 --- a/json_test/utils_test.h +++ b/json_test/utils_test.h @@ -1,36 +1,36 @@ -#ifndef JSON_SPIRIT_TEST_UTILS -#define JSON_SPIRIT_TEST_UTILS - -// Copyright John W. Wilkinson 2007 - 2014 -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.08 - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -#include -#include - -// these functions allow you to inspect the values that caused a test to fail - -template< class T1, class T2 > -void assert_eq( const T1& t1, const T2& t2 ) -{ - if( t1 == t2 ) return; - - assert( false ); -} - -template< class T1, class T2 > -void assert_neq( const T1& t1, const T2& t2 ) -{ - if( !(t1 == t2) ) return; - - assert( false ); -} - -void assert_eq( const double d1, const double d2, const double abs_error ); - -#endif +#ifndef JSON_SPIRIT_TEST_UTILS +#define JSON_SPIRIT_TEST_UTILS + +// Copyright John W. Wilkinson 2007 - 2014 +// Distributed under the MIT License, see accompanying file LICENSE.txt + +// json spirit version 4.08 + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +// these functions allow you to inspect the values that caused a test to fail + +template< class T1, class T2 > +void assert_eq( const T1& t1, const T2& t2 ) +{ + if( t1 == t2 ) return; + + assert( false ); +} + +template< class T1, class T2 > +void assert_neq( const T1& t1, const T2& t2 ) +{ + if( !(t1 == t2) ) return; + + assert( false ); +} + +void assert_eq( const double d1, const double d2, const double abs_error ); + +#endif From 98338b2f3cdc89abe0dfc38835b42e416e08648b Mon Sep 17 00:00:00 2001 From: Judith Silverman Date: Tue, 7 Apr 2020 12:19:55 -0700 Subject: [PATCH 2/3] Reformat source files with clang --- json5_parser/json5_parser.h | 6 +- json5_parser/json5_parser_error_position.h | 64 +- json5_parser/json5_parser_reader.cpp | 220 ++- json5_parser/json5_parser_reader.h | 71 +- json5_parser/json5_parser_reader_template.h | 1055 ++++++------ json5_parser/json5_parser_stream_reader.h | 96 +- json5_parser/json5_parser_utils.h | 61 +- json5_parser/json5_parser_value.h | 892 +++++----- json5_parser/json5_parser_writer.cpp | 154 +- json5_parser/json5_parser_writer.h | 73 +- json5_parser/json5_parser_writer_options.h | 43 +- json5_parser/json5_parser_writer_template.h | 484 +++--- json_demo/json_demo.cpp | 122 +- .../json_headers_only_demo.cpp | 127 +- json_map_demo/json_map_demo.cpp | 112 +- json_test/json5_parser_reader_test.cpp | 1451 ++++++++--------- json_test/json5_parser_reader_test.h | 7 +- json_test/json5_parser_stream_reader_test.cpp | 179 +- json_test/json5_parser_stream_reader_test.h | 7 +- json_test/json5_parser_utils_test.cpp | 182 +-- json_test/json5_parser_utils_test.h | 7 +- json_test/json5_parser_value_test.cpp | 756 +++++---- json_test/json5_parser_value_test.h | 7 +- json_test/json5_parser_writer_test.cpp | 1287 ++++++++------- json_test/json5_parser_writer_test.h | 7 +- json_test/json_test.cpp | 12 +- json_test/utils_test.cpp | 9 +- json_test/utils_test.h | 22 +- 28 files changed, 3588 insertions(+), 3925 deletions(-) diff --git a/json5_parser/json5_parser.h b/json5_parser/json5_parser.h index fc592da..2ba50c2 100644 --- a/json5_parser/json5_parser.h +++ b/json5_parser/json5_parser.h @@ -7,12 +7,12 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -#include "json5_parser_value.h" #include "json5_parser_reader.h" -#include "json5_parser_writer.h" #include "json5_parser_utils.h" +#include "json5_parser_value.h" +#include "json5_parser_writer.h" #endif diff --git a/json5_parser/json5_parser_error_position.h b/json5_parser/json5_parser_error_position.h index 20c1967..749de77 100644 --- a/json5_parser/json5_parser_error_position.h +++ b/json5_parser/json5_parser_error_position.h @@ -7,48 +7,36 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif #include -namespace json5_parser -{ - // An Error_position exception is thrown by the "read_or_throw" functions below on finding an error. - // Note the "read_or_throw" functions are around 3 times slower than the standard functions "read" - // functions that return a bool. - // - struct Error_position - { - Error_position(); - Error_position( unsigned int line, unsigned int column, const std::string& reason ); - bool operator==( const Error_position& lhs ) const; - unsigned int line_; - unsigned int column_; - std::string reason_; - }; - - inline Error_position::Error_position() - : line_( 0 ) - , column_( 0 ) - { - } - - inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason ) - : line_( line ) - , column_( column ) - , reason_( reason ) - { - } - - inline bool Error_position::operator==( const Error_position& lhs ) const - { - if( this == &lhs ) return true; - - return ( reason_ == lhs.reason_ ) && - ( line_ == lhs.line_ ) && - ( column_ == lhs.column_ ); - } +namespace json5_parser { +// An Error_position exception is thrown by the "read_or_throw" functions below on +// finding an error. Note the "read_or_throw" functions are around 3 times slower than +// the standard functions "read" functions that return a bool. +// +struct Error_position { + Error_position(); + Error_position(unsigned int line, unsigned int column, const std::string& reason); + bool operator==(const Error_position& lhs) const; + unsigned int line_; + unsigned int column_; + std::string reason_; +}; + +inline Error_position::Error_position() : line_(0), column_(0) {} + +inline Error_position::Error_position(unsigned int line, unsigned int column, + const std::string& reason) + : line_(line), column_(column), reason_(reason) {} + +inline bool Error_position::operator==(const Error_position& lhs) const { + if (this == &lhs) return true; + + return (reason_ == lhs.reason_) && (line_ == lhs.line_) && (column_ == lhs.column_); } +} // namespace json5_parser #endif diff --git a/json5_parser/json5_parser_reader.cpp b/json5_parser/json5_parser_reader.cpp index c30b667..20d6e48 100644 --- a/json5_parser/json5_parser_reader.cpp +++ b/json5_parser/json5_parser_reader.cpp @@ -9,129 +9,113 @@ using namespace json5_parser; #ifdef JSON_SPIRIT_VALUE_ENABLED - bool json5_parser::read( const std::string& s, Value& value ) - { - return read_string( s, value ); - } - - void json5_parser::read_or_throw( const std::string& s, Value& value ) - { - read_string_or_throw( s, value ); - } - - bool json5_parser::read( std::istream& is, Value& value ) - { - return read_stream( is, value ); - } - - void json5_parser::read_or_throw( std::istream& is, Value& value ) - { - read_stream_or_throw( is, value ); - } - - bool json5_parser::read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ) - { - return read_range( begin, end, value ); - } - - void json5_parser::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ) - { - begin = read_range_or_throw( begin, end, value ); - } +bool json5_parser::read(const std::string& s, Value& value) { + return read_string(s, value); +} + +void json5_parser::read_or_throw(const std::string& s, Value& value) { + read_string_or_throw(s, value); +} + +bool json5_parser::read(std::istream& is, Value& value) { + return read_stream(is, value); +} + +void json5_parser::read_or_throw(std::istream& is, Value& value) { + read_stream_or_throw(is, value); +} + +bool json5_parser::read(std::string::const_iterator& begin, + std::string::const_iterator end, Value& value) { + return read_range(begin, end, value); +} + +void json5_parser::read_or_throw(std::string::const_iterator& begin, + std::string::const_iterator end, Value& value) { + begin = read_range_or_throw(begin, end, value); +} #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - bool json5_parser::read( const std::wstring& s, wValue& value ) - { - return read_string( s, value ); - } - - void json5_parser::read_or_throw( const std::wstring& s, wValue& value ) - { - read_string_or_throw( s, value ); - } - - bool json5_parser::read( std::wistream& is, wValue& value ) - { - return read_stream( is, value ); - } - - void json5_parser::read_or_throw( std::wistream& is, wValue& value ) - { - read_stream_or_throw( is, value ); - } - - bool json5_parser::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ) - { - return read_range( begin, end, value ); - } - - void json5_parser::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ) - { - begin = read_range_or_throw( begin, end, value ); - } +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +bool json5_parser::read(const std::wstring& s, wValue& value) { + return read_string(s, value); +} + +void json5_parser::read_or_throw(const std::wstring& s, wValue& value) { + read_string_or_throw(s, value); +} + +bool json5_parser::read(std::wistream& is, wValue& value) { + return read_stream(is, value); +} + +void json5_parser::read_or_throw(std::wistream& is, wValue& value) { + read_stream_or_throw(is, value); +} + +bool json5_parser::read(std::wstring::const_iterator& begin, + std::wstring::const_iterator end, wValue& value) { + return read_range(begin, end, value); +} + +void json5_parser::read_or_throw(std::wstring::const_iterator& begin, + std::wstring::const_iterator end, wValue& value) { + begin = read_range_or_throw(begin, end, value); +} #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - bool json5_parser::read( const std::string& s, mValue& value ) - { - return read_string( s, value ); - } - - void json5_parser::read_or_throw( const std::string& s, mValue& value ) - { - read_string_or_throw( s, value ); - } - - bool json5_parser::read( std::istream& is, mValue& value ) - { - return read_stream( is, value ); - } - - void json5_parser::read_or_throw( std::istream& is, mValue& value ) - { - read_stream_or_throw( is, value ); - } - - bool json5_parser::read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ) - { - return read_range( begin, end, value ); - } - - void json5_parser::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ) - { - begin = read_range_or_throw( begin, end, value ); - } +bool json5_parser::read(const std::string& s, mValue& value) { + return read_string(s, value); +} + +void json5_parser::read_or_throw(const std::string& s, mValue& value) { + read_string_or_throw(s, value); +} + +bool json5_parser::read(std::istream& is, mValue& value) { + return read_stream(is, value); +} + +void json5_parser::read_or_throw(std::istream& is, mValue& value) { + read_stream_or_throw(is, value); +} + +bool json5_parser::read(std::string::const_iterator& begin, + std::string::const_iterator end, mValue& value) { + return read_range(begin, end, value); +} + +void json5_parser::read_or_throw(std::string::const_iterator& begin, + std::string::const_iterator end, mValue& value) { + begin = read_range_or_throw(begin, end, value); +} #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - bool json5_parser::read( const std::wstring& s, wmValue& value ) - { - return read_string( s, value ); - } - - void json5_parser::read_or_throw( const std::wstring& s, wmValue& value ) - { - read_string_or_throw( s, value ); - } - - bool json5_parser::read( std::wistream& is, wmValue& value ) - { - return read_stream( is, value ); - } - - void json5_parser::read_or_throw( std::wistream& is, wmValue& value ) - { - read_stream_or_throw( is, value ); - } - - bool json5_parser::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ) - { - return read_range( begin, end, value ); - } - - void json5_parser::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ) - { - begin = read_range_or_throw( begin, end, value ); - } +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +bool json5_parser::read(const std::wstring& s, wmValue& value) { + return read_string(s, value); +} + +void json5_parser::read_or_throw(const std::wstring& s, wmValue& value) { + read_string_or_throw(s, value); +} + +bool json5_parser::read(std::wistream& is, wmValue& value) { + return read_stream(is, value); +} + +void json5_parser::read_or_throw(std::wistream& is, wmValue& value) { + read_stream_or_throw(is, value); +} + +bool json5_parser::read(std::wstring::const_iterator& begin, + std::wstring::const_iterator end, wmValue& value) { + return read_range(begin, end, value); +} + +void json5_parser::read_or_throw(std::wstring::const_iterator& begin, + std::wstring::const_iterator end, wmValue& value) { + begin = read_range_or_throw(begin, end, value); +} #endif diff --git a/json5_parser/json5_parser_reader.h b/json5_parser/json5_parser_reader.h index 152b73f..c183140 100644 --- a/json5_parser/json5_parser_reader.h +++ b/json5_parser/json5_parser_reader.h @@ -7,55 +7,62 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -#include "json5_parser_value.h" -#include "json5_parser_error_position.h" #include +#include "json5_parser_error_position.h" +#include "json5_parser_value.h" -namespace json5_parser -{ - // functions to reads a JSON values +namespace json5_parser { +// functions to reads a JSON values #ifdef JSON_SPIRIT_VALUE_ENABLED - bool read( const std::string& s, Value& value ); - bool read( std::istream& is, Value& value ); - bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); +bool read(const std::string& s, Value& value); +bool read(std::istream& is, Value& value); +bool read(std::string::const_iterator& begin, std::string::const_iterator end, + Value& value); - void read_or_throw( const std::string& s, Value& value ); - void read_or_throw( std::istream& is, Value& value ); - void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); +void read_or_throw(const std::string& s, Value& value); +void read_or_throw(std::istream& is, Value& value); +void read_or_throw(std::string::const_iterator& begin, std::string::const_iterator end, + Value& value); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - bool read( const std::wstring& s, wValue& value ); - bool read( std::wistream& is, wValue& value ); - bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +bool read(const std::wstring& s, wValue& value); +bool read(std::wistream& is, wValue& value); +bool read(std::wstring::const_iterator& begin, std::wstring::const_iterator end, + wValue& value); - void read_or_throw( const std::wstring& s, wValue& value ); - void read_or_throw( std::wistream& is, wValue& value ); - void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); +void read_or_throw(const std::wstring& s, wValue& value); +void read_or_throw(std::wistream& is, wValue& value); +void read_or_throw(std::wstring::const_iterator& begin, + std::wstring::const_iterator end, wValue& value); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - bool read( const std::string& s, mValue& value ); - bool read( std::istream& is, mValue& value ); - bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); +bool read(const std::string& s, mValue& value); +bool read(std::istream& is, mValue& value); +bool read(std::string::const_iterator& begin, std::string::const_iterator end, + mValue& value); - void read_or_throw( const std::string& s, mValue& value ); - void read_or_throw( std::istream& is, mValue& value ); - void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); +void read_or_throw(const std::string& s, mValue& value); +void read_or_throw(std::istream& is, mValue& value); +void read_or_throw(std::string::const_iterator& begin, std::string::const_iterator end, + mValue& value); #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - bool read( const std::wstring& s, wmValue& value ); - bool read( std::wistream& is, wmValue& value ); - bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +bool read(const std::wstring& s, wmValue& value); +bool read(std::wistream& is, wmValue& value); +bool read(std::wstring::const_iterator& begin, std::wstring::const_iterator end, + wmValue& value); - void read_or_throw( const std::wstring& s, wmValue& value ); - void read_or_throw( std::wistream& is, wmValue& value ); - void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); +void read_or_throw(const std::wstring& s, wmValue& value); +void read_or_throw(std::wistream& is, wmValue& value); +void read_or_throw(std::wstring::const_iterator& begin, + std::wstring::const_iterator end, wmValue& value); #endif } diff --git a/json5_parser/json5_parser_reader_template.h b/json5_parser/json5_parser_reader_template.h index d62867e..2ddf9ed 100644 --- a/json5_parser/json5_parser_reader_template.h +++ b/json5_parser/json5_parser_reader_template.h @@ -7,695 +7,614 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -#include "json5_parser_value.h" #include "json5_parser_error_position.h" +#include "json5_parser_value.h" -#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread +#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to + // boost.thread #include #include #include #if BOOST_VERSION >= 103800 - #include - #include - #include - #include - #include - #define spirit_namespace boost::spirit::classic +#include +#include +#include +#include +#include +#define spirit_namespace boost::spirit::classic #else - #include - #include - #include - #include - #include - #define spirit_namespace boost::spirit +#include +#include +#include +#include +#include +#define spirit_namespace boost::spirit #endif -namespace json5_parser -{ - const spirit_namespace::int_parser < boost::int64_t > int64_p = spirit_namespace::int_parser < boost::int64_t >(); - const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >(); +namespace json5_parser { +const spirit_namespace::int_parser int64_p = + spirit_namespace::int_parser(); +const spirit_namespace::uint_parser uint64_p = + spirit_namespace::uint_parser(); - template< class Iter_type > - bool is_eq( Iter_type first, Iter_type last, const char* c_str ) - { - for( Iter_type i = first; i != last; ++i, ++c_str ) - { - if( *c_str == 0 ) return false; - - if( *i != *c_str ) return false; - } +template +bool is_eq(Iter_type first, Iter_type last, const char* c_str) { + for (Iter_type i = first; i != last; ++i, ++c_str) { + if (*c_str == 0) return false; - return true; + if (*i != *c_str) return false; } - template< class Char_type > - Char_type hex_to_num( const Char_type c ) - { - if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0'; - if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10; - if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10; - return 0; - } + return true; +} - template< class Char_type, class Iter_type > - Char_type hex_str_to_char( Iter_type& begin ) - { - const Char_type c1( *( ++begin ) ); - const Char_type c2( *( ++begin ) ); - - return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 ); - } - - template< class Char_type, class Iter_type > - Char_type unicode_str_to_char( Iter_type& begin ) - { - const Char_type c1( *( ++begin ) ); - const Char_type c2( *( ++begin ) ); - const Char_type c3( *( ++begin ) ); - const Char_type c4( *( ++begin ) ); - - return ( hex_to_num( c1 ) << 12 ) + - ( hex_to_num( c2 ) << 8 ) + - ( hex_to_num( c3 ) << 4 ) + - hex_to_num( c4 ); - } +template +Char_type hex_to_num(const Char_type c) { + if ((c >= '0') && (c <= '9')) return c - '0'; + if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; + if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; + return 0; +} + +template +Char_type hex_str_to_char(Iter_type& begin) { + const Char_type c1(*(++begin)); + const Char_type c2(*(++begin)); + + return (hex_to_num(c1) << 4) + hex_to_num(c2); +} - template< class String_type > - void append_esc_char_and_incr_iter( String_type& s, - typename String_type::const_iterator& begin, - typename String_type::const_iterator end ) - { - typedef typename String_type::value_type Char_type; - - const Char_type c2( *begin ); - - switch( c2 ) - { - case 't': s += '\t'; break; - case 'b': s += '\b'; break; - case 'f': s += '\f'; break; - case 'n': s += '\n'; break; - case 'r': s += '\r'; break; - case '\\': s += '\\'; break; - case '/': s += '/'; break; - case '"': s += '"'; break; - case 'x': +template +Char_type unicode_str_to_char(Iter_type& begin) { + const Char_type c1(*(++begin)); + const Char_type c2(*(++begin)); + const Char_type c3(*(++begin)); + const Char_type c4(*(++begin)); + + return (hex_to_num(c1) << 12) + (hex_to_num(c2) << 8) + (hex_to_num(c3) << 4) + + hex_to_num(c4); +} + +template +void append_esc_char_and_incr_iter(String_type& s, + typename String_type::const_iterator& begin, + typename String_type::const_iterator end) { + typedef typename String_type::value_type Char_type; + + const Char_type c2(*begin); + + switch (c2) { + case 't': + s += '\t'; + break; + case 'b': + s += '\b'; + break; + case 'f': + s += '\f'; + break; + case 'n': + s += '\n'; + break; + case 'r': + s += '\r'; + break; + case '\\': + s += '\\'; + break; + case '/': + s += '/'; + break; + case '"': + s += '"'; + break; + case 'x': { + if (end - begin >= 3) // expecting "xHH..." { - if( end - begin >= 3 ) // expecting "xHH..." - { - s += hex_str_to_char< Char_type >( begin ); - } - break; + s += hex_str_to_char(begin); } - case 'u': + break; + } + case 'u': { + if (end - begin >= 5) // expecting "uHHHH..." { - if( end - begin >= 5 ) // expecting "uHHHH..." - { - s += unicode_str_to_char< Char_type >( begin ); - } - break; + s += unicode_str_to_char(begin); } - case '\n': break; // skip escaped newlines + break; } + case '\n': + break; // skip escaped newlines } +} - template< class String_type > - String_type substitute_esc_chars( typename String_type::const_iterator begin, - typename String_type::const_iterator end ) - { - typedef typename String_type::const_iterator Iter_type; +template +String_type substitute_esc_chars(typename String_type::const_iterator begin, + typename String_type::const_iterator end) { + typedef typename String_type::const_iterator Iter_type; - if( end - begin < 2 ) return String_type( begin, end ); + if (end - begin < 2) return String_type(begin, end); - String_type result; - - result.reserve( end - begin ); + String_type result; - const Iter_type end_minus_1( end - 1 ); + result.reserve(end - begin); - Iter_type substr_start = begin; - Iter_type i = begin; + const Iter_type end_minus_1(end - 1); - for( ; i < end_minus_1; ++i ) - { - if( *i == '\\' ) - { - result.append( substr_start, i ); + Iter_type substr_start = begin; + Iter_type i = begin; - ++i; // skip the '\' - - append_esc_char_and_incr_iter( result, i, end ); + for (; i < end_minus_1; ++i) { + if (*i == '\\') { + result.append(substr_start, i); - substr_start = i + 1; - } - } + ++i; // skip the '\' - result.append( substr_start, end ); + append_esc_char_and_incr_iter(result, i, end); - return result; + substr_start = i + 1; + } } - template< class String_type > - String_type get_str_( typename String_type::const_iterator begin, - typename String_type::const_iterator end ) - { - assert( end - begin >= 2 ); - - typedef typename String_type::const_iterator Iter_type; - - Iter_type str_without_quotes( ++begin ); - Iter_type end_without_quotes( --end ); + result.append(substr_start, end); - return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes ); - } + return result; +} - inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end ) - { - return get_str_< std::string >( begin, end ); - } +template +String_type get_str_(typename String_type::const_iterator begin, + typename String_type::const_iterator end) { + assert(end - begin >= 2); - inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end ) - { - return get_str_< std::wstring >( begin, end ); - } - - template< class String_type, class Iter_type > - String_type get_str( Iter_type begin, Iter_type end ) - { - const String_type tmp( begin, end ); // convert multipass iterators to string iterators + typedef typename String_type::const_iterator Iter_type; - return get_str( tmp.begin(), tmp.end() ); - } + Iter_type str_without_quotes(++begin); + Iter_type end_without_quotes(--end); - // this class's methods get called by the spirit parse resulting - // in the creation of a JSON object or array - // - // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator - // - template< class Value_type, class Iter_type > - class Semantic_actions - { - public: + return substitute_esc_chars(str_without_quotes, end_without_quotes); +} - typedef typename Value_type::Config_type Config_type; - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename String_type::value_type Char_type; +inline std::string get_str(std::string::const_iterator begin, + std::string::const_iterator end) { + return get_str_(begin, end); +} - Semantic_actions( Value_type& value ) - : value_( value ) - , current_p_( 0 ) - { - } +inline std::wstring get_str(std::wstring::const_iterator begin, + std::wstring::const_iterator end) { + return get_str_(begin, end); +} - void begin_obj( Char_type c ) - { - assert( c == '{' ); +template +String_type get_str(Iter_type begin, Iter_type end) { + const String_type tmp(begin, + end); // convert multipass iterators to string iterators - begin_compound< Object_type >(); - } + return get_str(tmp.begin(), tmp.end()); +} - void end_obj( Char_type c ) - { - assert( c == '}' ); +// this class's methods get called by the spirit parse resulting +// in the creation of a JSON object or array +// +// NB Iter_type could be a std::string iterator, wstring iterator, a position iterator +// or a multipass iterator +// +template +class Semantic_actions { +public: + typedef typename Value_type::Config_type Config_type; + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename String_type::value_type Char_type; + + Semantic_actions(Value_type& value) : value_(value), current_p_(0) {} + + void begin_obj(Char_type c) { + assert(c == '{'); + + begin_compound(); + } - end_compound(); - } + void end_obj(Char_type c) { + assert(c == '}'); - void begin_array( Char_type c ) - { - assert( c == '[' ); - - begin_compound< Array_type >(); - } + end_compound(); + } - void end_array( Char_type c ) - { - assert( c == ']' ); + void begin_array(Char_type c) { + assert(c == '['); - end_compound(); - } + begin_compound(); + } - void new_name( Iter_type begin, Iter_type end ) - { - assert( current_p_->type() == obj_type ); + void end_array(Char_type c) { + assert(c == ']'); - name_ = get_str< String_type >( begin, end ); - } + end_compound(); + } - void new_identifier( Iter_type begin, Iter_type end ) - { - assert( current_p_->type() == obj_type ); + void new_name(Iter_type begin, Iter_type end) { + assert(current_p_->type() == obj_type); - String_type result; - result.append(begin,end); - name_ = result; - } + name_ = get_str(begin, end); + } - void new_str( Iter_type begin, Iter_type end ) - { - add_to_current( get_str< String_type >( begin, end ) ); - } + void new_identifier(Iter_type begin, Iter_type end) { + assert(current_p_->type() == obj_type); - void new_true( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "true" ) ); + String_type result; + result.append(begin, end); + name_ = result; + } - add_to_current( true ); - } + void new_str(Iter_type begin, Iter_type end) { + add_to_current(get_str(begin, end)); + } - void new_false( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "false" ) ); + void new_true(Iter_type begin, Iter_type end) { + assert(is_eq(begin, end, "true")); - add_to_current( false ); - } + add_to_current(true); + } - void new_null( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "null" ) ); + void new_false(Iter_type begin, Iter_type end) { + assert(is_eq(begin, end, "false")); - add_to_current( Value_type() ); - } + add_to_current(false); + } - void new_int( boost::int64_t i ) - { - add_to_current( i ); - } + void new_null(Iter_type begin, Iter_type end) { + assert(is_eq(begin, end, "null")); - void new_uint64( boost::uint64_t ui ) - { - add_to_current( ui ); - } + add_to_current(Value_type()); + } - void new_real( double d ) - { - add_to_current( d ); - } + void new_int(boost::int64_t i) { add_to_current(i); } - void new_infinity( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "Infinity" ) ); + void new_uint64(boost::uint64_t ui) { add_to_current(ui); } - add_to_current( std::numeric_limits::infinity() ); - } + void new_real(double d) { add_to_current(d); } - void new_minus_infinity( Iter_type begin, Iter_type end ) - { - assert( is_eq( begin, end, "-Infinity" ) ); + void new_infinity(Iter_type begin, Iter_type end) { + assert(is_eq(begin, end, "Infinity")); - add_to_current( -std::numeric_limits::infinity() ); - } + add_to_current(std::numeric_limits::infinity()); + } - private: + void new_minus_infinity(Iter_type begin, Iter_type end) { + assert(is_eq(begin, end, "-Infinity")); - Semantic_actions& operator=( const Semantic_actions& ); - // to prevent "assignment operator could not be generated" warning + add_to_current(-std::numeric_limits::infinity()); + } - Value_type* add_first( const Value_type& value ) - { - assert( current_p_ == 0 ); +private: + Semantic_actions& operator=(const Semantic_actions&); + // to prevent "assignment operator could not be generated" warning - value_ = value; - current_p_ = &value_; - return current_p_; - } + Value_type* add_first(const Value_type& value) { + assert(current_p_ == 0); - template< class Array_or_obj > - void begin_compound() - { - if( current_p_ == 0 ) - { - add_first( Array_or_obj() ); - } - else - { - stack_.push_back( current_p_ ); + value_ = value; + current_p_ = &value_; + return current_p_; + } - Array_or_obj new_array_or_obj; // avoid copy by building new array or object in place + template + void begin_compound() { + if (current_p_ == 0) { + add_first(Array_or_obj()); + } else { + stack_.push_back(current_p_); - current_p_ = add_to_current( new_array_or_obj ); - } - } + Array_or_obj new_array_or_obj; // avoid copy by building new array or + // object in place - void end_compound() - { - if( current_p_ != &value_ ) - { - current_p_ = stack_.back(); - - stack_.pop_back(); - } + current_p_ = add_to_current(new_array_or_obj); } + } - Value_type* add_to_current( const Value_type& value ) - { - if( current_p_ == 0 ) - { - return add_first( value ); - } - else if( current_p_->type() == array_type ) - { - current_p_->get_array().push_back( value ); - - return ¤t_p_->get_array().back(); - } - - assert( current_p_->type() == obj_type ); + void end_compound() { + if (current_p_ != &value_) { + current_p_ = stack_.back(); - return &Config_type::add( current_p_->get_obj(), name_, value ); + stack_.pop_back(); } + } - Value_type& value_; // this is the object or array that is being created - Value_type* current_p_; // the child object or array that is currently being constructed - - std::vector< Value_type* > stack_; // previous child objects and arrays + Value_type* add_to_current(const Value_type& value) { + if (current_p_ == 0) { + return add_first(value); + } else if (current_p_->type() == array_type) { + current_p_->get_array().push_back(value); - String_type name_; // of current name/value pair - }; + return ¤t_p_->get_array().back(); + } - template< typename Iter_type > - void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason ) - { - throw Error_position( i.get_position().line, i.get_position().column, reason ); - } + assert(current_p_->type() == obj_type); - template< typename Iter_type > - void throw_error( Iter_type , const std::string& reason ) - { - throw reason; + return &Config_type::add(current_p_->get_obj(), name_, value); } - // the spirit grammer - // - template< class Value_type, class Iter_type > - class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > > - { - public: - - typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t; + Value_type& value_; // this is the object or array that is being created + Value_type* current_p_; // the child object or array that is currently being + // constructed - Json_grammer( Semantic_actions_t& semantic_actions ) - : actions_( semantic_actions ) - { - } + std::vector stack_; // previous child objects and arrays - static void throw_not_value( Iter_type begin, Iter_type ) - { - throw_error( begin, "not a value" ); - } + String_type name_; // of current name/value pair +}; - static void throw_not_hex( Iter_type begin, Iter_type ) - { - throw_error( begin, "not a hexadecimal number" ); - } - - static void throw_not_array( Iter_type begin, Iter_type ) - { - throw_error( begin, "not an array" ); - } +template +void throw_error(spirit_namespace::position_iterator i, + const std::string& reason) { + throw Error_position(i.get_position().line, i.get_position().column, reason); +} - static void throw_not_object( Iter_type begin, Iter_type ) - { - throw_error( begin, "not an object" ); - } +template +void throw_error(Iter_type, const std::string& reason) { + throw reason; +} - static void throw_not_pair( Iter_type begin, Iter_type ) - { - throw_error( begin, "not a pair" ); - } +// the spirit grammer +// +template +class Json_grammer + : public spirit_namespace::grammar > { +public: + typedef Semantic_actions Semantic_actions_t; - static void throw_not_colon( Iter_type begin, Iter_type ) - { - throw_error( begin, "no colon in pair" ); - } + Json_grammer(Semantic_actions_t& semantic_actions) : actions_(semantic_actions) {} - static void throw_not_string( Iter_type begin, Iter_type ) - { - throw_error( begin, "not a string" ); - } + static void throw_not_value(Iter_type begin, Iter_type) { + throw_error(begin, "not a value"); + } - template< typename ScannerT > - class definition - { - public: + static void throw_not_hex(Iter_type begin, Iter_type) { + throw_error(begin, "not a hexadecimal number"); + } - definition( const Json_grammer& self ) - { - using namespace spirit_namespace; - - typedef typename Value_type::String_type::value_type Char_type; - - // first we convert the semantic action class methods to functors with the - // parameter signature expected by spirit - - typedef boost::function< void( Char_type ) > Char_action; - typedef boost::function< void( Iter_type, Iter_type ) > Str_action; - typedef boost::function< void( double ) > Real_action; - typedef boost::function< void( boost::int64_t ) > Int_action; - typedef boost::function< void( boost::uint64_t ) > Uint64_action; - - Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) ); - Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) ); - Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) ); - Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) ); - Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) ); - Str_action new_identifier( boost::bind( &Semantic_actions_t::new_identifier, &self.actions_, _1, _2 ) ); - Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) ); - Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) ); - Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) ); - Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) ); - Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) ); - Str_action new_infinity ( boost::bind( &Semantic_actions_t::new_infinity, &self.actions_, _1, _2 ) ); - Str_action new_minus_infinity ( boost::bind( &Semantic_actions_t::new_minus_infinity, &self.actions_, _1, _2 ) ); - Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) ); - Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) ); - - // actual grammer - - json_ - = value_ | eps_p[ &throw_not_value ] - ; - - value_ - = single_quoted_string_[ new_str ] - | double_quoted_string_[ new_str ] - | number_ - | object_ - | array_ - | str_p( "true" ) [ new_true ] - | str_p( "false" )[ new_false ] - | str_p( "null" ) [ new_null ] - | (!ch_p('+') >> str_p( "Infinity" ) [ new_infinity ]) - | str_p( "-Infinity" ) [ new_minus_infinity ] - ; - - object_ - = ch_p('{')[ begin_obj ] - >> !members_ - >> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] ) - ; - - members_ - = pair_ >> *( ',' >> pair_ ) >> !ch_p(',') - ; - - pair_ - = (double_quoted_string_[ new_name ] | identifier_[ new_identifier ]) - >> ( ':' | eps_p[ &throw_not_colon ] ) - >> ( value_ | eps_p[ &throw_not_value ] ) - ; - - array_ - = ch_p('[')[ begin_array ] - >> !elements_ - >> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] ) - ; - - elements_ - = value_ >> *( ',' >> value_ ) >> !ch_p(',') - ; - - double_quoted_string_ - = lexeme_d // this causes white space and what would appear to be comments inside a string to be retained - [ - confix_p - ( - '"', - *lex_escape_ch_p, - '"' - ) - ] - ; - - single_quoted_string_ - = lexeme_d // this causes white space and what would appear to be comments inside a string to be retained - [ - confix_p - ( - '\'', - *lex_escape_ch_p, - '\'' - ) - ] - ; - - identifier_ - = (alpha_p | ch_p('_') | ch_p('$')) >> *(alnum_p | ch_p('_') | ch_p('$')); - - number_ - = ( str_p("0x") >> (hex_p[ new_int ] | eps_p[ &throw_not_hex ] ) ) - | strict_real_p[ new_real ] - | int64_p [ new_int ] - | uint64_p [ new_uint64 ] - ; - } + static void throw_not_array(Iter_type begin, Iter_type) { + throw_error(begin, "not an array"); + } - spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, single_quoted_string_, double_quoted_string_, number_, identifier_; + static void throw_not_object(Iter_type begin, Iter_type) { + throw_error(begin, "not an object"); + } - const spirit_namespace::rule< ScannerT >& start() const { return json_; } - }; + static void throw_not_pair(Iter_type begin, Iter_type) { + throw_error(begin, "not a pair"); + } - private: + static void throw_not_colon(Iter_type begin, Iter_type) { + throw_error(begin, "no colon in pair"); + } - Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning + static void throw_not_string(Iter_type begin, Iter_type) { + throw_error(begin, "not a string"); + } - Semantic_actions_t& actions_; + template + class definition { + public: + definition(const Json_grammer& self) { + using namespace spirit_namespace; + + typedef typename Value_type::String_type::value_type Char_type; + + // first we convert the semantic action class methods to functors with the + // parameter signature expected by spirit + + typedef boost::function Char_action; + typedef boost::function Str_action; + typedef boost::function Real_action; + typedef boost::function Int_action; + typedef boost::function Uint64_action; + + Char_action begin_obj( + boost::bind(&Semantic_actions_t::begin_obj, &self.actions_, _1)); + Char_action end_obj( + boost::bind(&Semantic_actions_t::end_obj, &self.actions_, _1)); + Char_action begin_array( + boost::bind(&Semantic_actions_t::begin_array, &self.actions_, _1)); + Char_action end_array( + boost::bind(&Semantic_actions_t::end_array, &self.actions_, _1)); + Str_action new_name( + boost::bind(&Semantic_actions_t::new_name, &self.actions_, _1, _2)); + Str_action new_identifier(boost::bind(&Semantic_actions_t::new_identifier, + &self.actions_, _1, _2)); + Str_action new_str( + boost::bind(&Semantic_actions_t::new_str, &self.actions_, _1, _2)); + Str_action new_true( + boost::bind(&Semantic_actions_t::new_true, &self.actions_, _1, _2)); + Str_action new_false(boost::bind(&Semantic_actions_t::new_false, + &self.actions_, _1, _2)); + Str_action new_null( + boost::bind(&Semantic_actions_t::new_null, &self.actions_, _1, _2)); + Real_action new_real( + boost::bind(&Semantic_actions_t::new_real, &self.actions_, _1)); + Str_action new_infinity(boost::bind(&Semantic_actions_t::new_infinity, + &self.actions_, _1, _2)); + Str_action new_minus_infinity(boost::bind( + &Semantic_actions_t::new_minus_infinity, &self.actions_, _1, _2)); + Int_action new_int( + boost::bind(&Semantic_actions_t::new_int, &self.actions_, _1)); + Uint64_action new_uint64( + boost::bind(&Semantic_actions_t::new_uint64, &self.actions_, _1)); + + // actual grammer + + json_ = value_ | eps_p[&throw_not_value]; + + value_ = single_quoted_string_[new_str] | double_quoted_string_[new_str] | + number_ | object_ | array_ | str_p("true")[new_true] | + str_p("false")[new_false] | str_p("null")[new_null] | + (!ch_p('+') >> str_p("Infinity")[new_infinity]) | + str_p("-Infinity")[new_minus_infinity]; + + object_ = ch_p('{')[begin_obj] >> !members_ >> + (ch_p('}')[end_obj] | eps_p[&throw_not_object]); + + members_ = pair_ >> *(',' >> pair_) >> !ch_p(','); + + pair_ = (double_quoted_string_[new_name] | identifier_[new_identifier]) >> + (':' | eps_p[&throw_not_colon]) >> + (value_ | eps_p[&throw_not_value]); + + array_ = ch_p('[')[begin_array] >> !elements_ >> + (ch_p(']')[end_array] | eps_p[&throw_not_array]); + + elements_ = value_ >> *(',' >> value_) >> !ch_p(','); + + double_quoted_string_ = + lexeme_d // this causes white space and what would appear to be + // comments inside a string to be retained + [confix_p('"', *lex_escape_ch_p, '"')]; + + single_quoted_string_ = + lexeme_d // this causes white space and what would appear to be + // comments inside a string to be retained + [confix_p('\'', *lex_escape_ch_p, '\'')]; + + identifier_ = (alpha_p | ch_p('_') | ch_p('$')) >> + *(alnum_p | ch_p('_') | ch_p('$')); + + number_ = (str_p("0x") >> (hex_p[new_int] | eps_p[&throw_not_hex])) | + strict_real_p[new_real] | int64_p[new_int] | uint64_p[new_uint64]; + } + + spirit_namespace::rule json_, object_, members_, pair_, array_, + elements_, value_, single_quoted_string_, double_quoted_string_, + number_, identifier_; + + const spirit_namespace::rule& start() const { return json_; } }; - template< class Iter_type, class Value_type > - void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) - { - typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t; +private: + Json_grammer& operator=(const Json_grammer&); // to prevent "assignment operator + // could not be generated" warning - const Posn_iter_t posn_begin( begin, end ); - const Posn_iter_t posn_end( end, end ); - - read_range_or_throw( posn_begin, posn_end, value ); - } + Semantic_actions_t& actions_; +}; - template< class Istream_type > - struct Multi_pass_iters - { - typedef typename Istream_type::char_type Char_type; - typedef std::istream_iterator< Char_type, Char_type > istream_iter; - typedef spirit_namespace::multi_pass< istream_iter > Mp_iter; +template +void add_posn_iter_and_read_range_or_throw(Iter_type begin, Iter_type end, + Value_type& value) { + typedef spirit_namespace::position_iterator Posn_iter_t; - Multi_pass_iters( Istream_type& is ) - { - is.unsetf( std::ios::skipws ); + const Posn_iter_t posn_begin(begin, end); + const Posn_iter_t posn_end(end, end); - begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) ); - end_ = spirit_namespace::make_multi_pass( istream_iter() ); - } + read_range_or_throw(posn_begin, posn_end, value); +} - Mp_iter begin_; - Mp_iter end_; - }; +template +struct Multi_pass_iters { + typedef typename Istream_type::char_type Char_type; + typedef std::istream_iterator istream_iter; + typedef spirit_namespace::multi_pass Mp_iter; - // reads a JSON Value from a pair of input iterators throwing an exception on invalid input, e.g. - // - // string::const_iterator start = str.begin(); - // const string::const_iterator next = read_range_or_throw( str.begin(), str.end(), value ); - // - // The iterator 'next' will point to the character past the - // last one read. - // - template< class Iter_type, class Value_type > - Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) - { - Semantic_actions< Value_type, Iter_type > semantic_actions( value ); - - const spirit_namespace::parse_info< Iter_type > info = - spirit_namespace::parse( begin, end, - Json_grammer< Value_type, Iter_type >( semantic_actions ), - spirit_namespace::space_p | - spirit_namespace::comment_p("//") | - spirit_namespace::comment_p("/*", "*/") ); - - if( !info.hit ) - { - assert( false ); // in theory exception should already have been thrown - throw_error( info.stop, "error" ); - } + Multi_pass_iters(Istream_type& is) { + is.unsetf(std::ios::skipws); - return info.stop; + begin_ = spirit_namespace::make_multi_pass(istream_iter(is)); + end_ = spirit_namespace::make_multi_pass(istream_iter()); } - // reads a JSON Value from a pair of input iterators, e.g. - // - // string::const_iterator start = str.begin(); - // const bool success = read_string( start, str.end(), value ); - // - // The iterator 'start' will point to the character past the - // last one read. - // - template< class Iter_type, class Value_type > - bool read_range( Iter_type& begin, Iter_type end, Value_type& value ) - { - try - { - begin = read_range_or_throw( begin, end, value ); - - return true; - } - catch( ... ) - { - return false; - } + Mp_iter begin_; + Mp_iter end_; +}; + +// reads a JSON Value from a pair of input iterators throwing an exception on invalid +// input, e.g. +// +// string::const_iterator start = str.begin(); +// const string::const_iterator next = read_range_or_throw( str.begin(), str.end(), +// value ); +// +// The iterator 'next' will point to the character past the +// last one read. +// +template +Iter_type read_range_or_throw(Iter_type begin, Iter_type end, Value_type& value) { + Semantic_actions semantic_actions(value); + + const spirit_namespace::parse_info info = spirit_namespace::parse( + begin, end, Json_grammer(semantic_actions), + spirit_namespace::space_p | spirit_namespace::comment_p("//") | + spirit_namespace::comment_p("/*", "*/")); + + if (!info.hit) { + assert(false); // in theory exception should already have been thrown + throw_error(info.stop, "error"); } - // reads a JSON Value from a string, e.g. - // - // const bool success = read_string( str, value ); - // - template< class String_type, class Value_type > - bool read_string( const String_type& s, Value_type& value ) - { - typename String_type::const_iterator begin = s.begin(); + return info.stop; +} - return read_range( begin, s.end(), value ); - } +// reads a JSON Value from a pair of input iterators, e.g. +// +// string::const_iterator start = str.begin(); +// const bool success = read_string( start, str.end(), value ); +// +// The iterator 'start' will point to the character past the +// last one read. +// +template +bool read_range(Iter_type& begin, Iter_type end, Value_type& value) { + try { + begin = read_range_or_throw(begin, end, value); - // reads a JSON Value from a string throwing an exception on invalid input, e.g. - // - // read_string_or_throw( is, value ); - // - template< class String_type, class Value_type > - void read_string_or_throw( const String_type& s, Value_type& value ) - { - add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value ); + return true; + } catch (...) { + return false; } +} - // reads a JSON Value from a stream, e.g. - // - // const bool success = read_stream( is, value ); - // - template< class Istream_type, class Value_type > - bool read_stream( Istream_type& is, Value_type& value ) - { - Multi_pass_iters< Istream_type > mp_iters( is ); +// reads a JSON Value from a string, e.g. +// +// const bool success = read_string( str, value ); +// +template +bool read_string(const String_type& s, Value_type& value) { + typename String_type::const_iterator begin = s.begin(); - return read_range( mp_iters.begin_, mp_iters.end_, value ); - } + return read_range(begin, s.end(), value); +} + +// reads a JSON Value from a string throwing an exception on invalid input, e.g. +// +// read_string_or_throw( is, value ); +// +template +void read_string_or_throw(const String_type& s, Value_type& value) { + add_posn_iter_and_read_range_or_throw(s.begin(), s.end(), value); +} - // reads a JSON Value from a stream throwing an exception on invalid input, e.g. - // - // read_stream_or_throw( is, value ); - // - template< class Istream_type, class Value_type > - void read_stream_or_throw( Istream_type& is, Value_type& value ) - { - const Multi_pass_iters< Istream_type > mp_iters( is ); +// reads a JSON Value from a stream, e.g. +// +// const bool success = read_stream( is, value ); +// +template +bool read_stream(Istream_type& is, Value_type& value) { + Multi_pass_iters mp_iters(is); - add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value ); - } + return read_range(mp_iters.begin_, mp_iters.end_, value); +} + +// reads a JSON Value from a stream throwing an exception on invalid input, e.g. +// +// read_stream_or_throw( is, value ); +// +template +void read_stream_or_throw(Istream_type& is, Value_type& value) { + const Multi_pass_iters mp_iters(is); + + add_posn_iter_and_read_range_or_throw(mp_iters.begin_, mp_iters.end_, value); } +} // namespace json5_parser #endif diff --git a/json5_parser/json5_parser_stream_reader.h b/json5_parser/json5_parser_stream_reader.h index 1e08e5c..d14022e 100644 --- a/json5_parser/json5_parser_stream_reader.h +++ b/json5_parser/json5_parser_stream_reader.h @@ -7,64 +7,50 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif #include "json5_parser_reader_template.h" -namespace json5_parser -{ - // these classes allows you to read multiple top level contiguous values from a stream, - // the normal stream read functions have a bug that prevent multiple top level values - // from being read unless they are separated by spaces - - template< class Istream_type, class Value_type > - class Stream_reader - { - public: - - Stream_reader( Istream_type& is ) - : iters_( is ) - { - } - - bool read_next( Value_type& value ) - { - return read_range( iters_.begin_, iters_.end_, value ); - } - - private: - - typedef Multi_pass_iters< Istream_type > Mp_iters; - - Mp_iters iters_; - }; - - template< class Istream_type, class Value_type > - class Stream_reader_thrower - { - public: - - Stream_reader_thrower( Istream_type& is ) - : iters_( is ) - , posn_begin_( iters_.begin_, iters_.end_ ) - , posn_end_( iters_.end_, iters_.end_ ) - { - } - - void read_next( Value_type& value ) - { - posn_begin_ = read_range_or_throw( posn_begin_, posn_end_, value ); - } - - private: - - typedef Multi_pass_iters< Istream_type > Mp_iters; - typedef spirit_namespace::position_iterator< typename Mp_iters::Mp_iter > Posn_iter_t; - - Mp_iters iters_; - Posn_iter_t posn_begin_, posn_end_; - }; -} +namespace json5_parser { +// these classes allows you to read multiple top level contiguous values from a stream, +// the normal stream read functions have a bug that prevent multiple top level values +// from being read unless they are separated by spaces + +template +class Stream_reader { +public: + Stream_reader(Istream_type& is) : iters_(is) {} + + bool read_next(Value_type& value) { + return read_range(iters_.begin_, iters_.end_, value); + } + +private: + typedef Multi_pass_iters Mp_iters; + + Mp_iters iters_; +}; + +template +class Stream_reader_thrower { +public: + Stream_reader_thrower(Istream_type& is) + : iters_(is), + posn_begin_(iters_.begin_, iters_.end_), + posn_end_(iters_.end_, iters_.end_) {} + + void read_next(Value_type& value) { + posn_begin_ = read_range_or_throw(posn_begin_, posn_end_, value); + } + +private: + typedef Multi_pass_iters Mp_iters; + typedef spirit_namespace::position_iterator Posn_iter_t; + + Mp_iters iters_; + Posn_iter_t posn_begin_, posn_end_; +}; +} // namespace json5_parser #endif diff --git a/json5_parser/json5_parser_utils.h b/json5_parser/json5_parser_utils.h index 0f57c7c..331dd22 100644 --- a/json5_parser/json5_parser_utils.h +++ b/json5_parser/json5_parser_utils.h @@ -7,57 +7,50 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -#include "json5_parser_value.h" #include +#include "json5_parser_value.h" -namespace json5_parser -{ - template< class Obj_t, class Map_t > - void obj_to_map( const Obj_t& obj, Map_t& mp_obj ) - { - mp_obj.clear(); +namespace json5_parser { +template +void obj_to_map(const Obj_t& obj, Map_t& mp_obj) { + mp_obj.clear(); - for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i ) - { - mp_obj[ i->name_ ] = i->value_; - } + for (typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i) { + mp_obj[i->name_] = i->value_; } +} - template< class Obj_t, class Map_t > - void map_to_obj( const Map_t& mp_obj, Obj_t& obj ) - { - obj.clear(); +template +void map_to_obj(const Map_t& mp_obj, Obj_t& obj) { + obj.clear(); - for( typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i ) - { - obj.push_back( typename Obj_t::value_type( i->first, i->second ) ); - } + for (typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i) { + obj.push_back(typename Obj_t::value_type(i->first, i->second)); } +} #ifdef JSON_SPIRIT_VALUE_ENABLED - typedef std::map< std::string, Value > Mapped_obj; +typedef std::map Mapped_obj; #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - typedef std::map< std::wstring, wValue > wMapped_obj; +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +typedef std::map wMapped_obj; #endif - template< class Object_type, class String_type > - const typename Object_type::value_type::Value_type& find_value( const Object_type& obj, const String_type& name ) - { - for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i ) - { - if( i->name_ == name ) - { - return i->value_; - } +template +const typename Object_type::value_type::Value_type& find_value( + const Object_type& obj, const String_type& name) { + for (typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i) { + if (i->name_ == name) { + return i->value_; } - - return Object_type::value_type::Value_type::null; } + + return Object_type::value_type::Value_type::null; } +} // namespace json5_parser #endif diff --git a/json5_parser/json5_parser_value.h b/json5_parser/json5_parser_value.h index 06b11e6..6fe4e32 100644 --- a/json5_parser/json5_parser_value.h +++ b/json5_parser/json5_parser_value.h @@ -7,599 +7,517 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -#include -#include -#include +#include +#include +#include +#include #include +#include #include #include -#include -#include -#include -#include +#include +#include -// comment out the value types you don't need to reduce build times and intermediate file sizes +// comment out the value types you don't need to reduce build times and intermediate +// file sizes #define JSON_SPIRIT_VALUE_ENABLED #define JSON_SPIRIT_WVALUE_ENABLED #define JSON_SPIRIT_MVALUE_ENABLED #define JSON_SPIRIT_WMVALUE_ENABLED -namespace json5_parser -{ - enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type }; - - static inline std::string value_type_to_string( Value_type vtype ); - - struct Null{}; - - template< class Config > // Config determines whether the value uses std::string or std::wstring and - // whether JSON Objects are represented as vectors or maps - class Value_impl - { +namespace json5_parser { +enum Value_type { + obj_type, + array_type, + str_type, + bool_type, + int_type, + real_type, + null_type +}; + +static inline std::string value_type_to_string(Value_type vtype); + +struct Null {}; + +template // Config determines whether the value uses std::string or + // std::wstring and whether JSON Objects are represented as + // vectors or maps + class Value_impl { +public: + typedef Config Config_type; + typedef typename Config::String_type String_type; + typedef typename Config::Object_type Object; + typedef typename Config::Array_type Array; + typedef typename String_type::const_pointer Const_str_ptr; // eg const char* + + Value_impl(); // creates null value + Value_impl(Const_str_ptr value); + Value_impl(const String_type& value); + Value_impl(const Object& value); + Value_impl(const Array& value); + Value_impl(bool value); + Value_impl(int value); + Value_impl(boost::int64_t value); + Value_impl(boost::uint64_t value); + Value_impl(double value); + + template + Value_impl( + Iter first, + Iter last); // constructor from containers, e.g. std::vector or std::list + + template + Value_impl(const boost::variant& + variant); // constructor for compatible variant types + + Value_impl(const Value_impl& other); + + bool operator==(const Value_impl& lhs) const; + + Value_impl& operator=(const Value_impl& lhs); + + Value_type type() const; + + bool is_uint64() const; + bool is_null() const; + + const String_type& get_str() const; + const Object& get_obj() const; + const Array& get_array() const; + bool get_bool() const; + int get_int() const; + boost::int64_t get_int64() const; + boost::uint64_t get_uint64() const; + double get_real() const; + + Object& get_obj(); + Array& get_array(); + + template + T get_value() const; // example usage: int i = value.get_value< int >(); + // or double d = value.get_value< double >(); + + static const Value_impl null; + +private: + void check_type(const Value_type vtype) const; + + typedef boost::variant, + boost::recursive_wrapper, String_type, bool, + boost::int64_t, double, Null, boost::uint64_t> + Variant; + + Variant v_; + + class Variant_converter_visitor : public boost::static_visitor { public: + template class Cont> + Variant operator()(const Cont& cont) const { + return Array(cont.begin(), cont.end()); + } + + Variant operator()(int i) const { return static_cast(i); } - typedef Config Config_type; - typedef typename Config::String_type String_type; - typedef typename Config::Object_type Object; - typedef typename Config::Array_type Array; - typedef typename String_type::const_pointer Const_str_ptr; // eg const char* - - Value_impl(); // creates null value - Value_impl( Const_str_ptr value ); - Value_impl( const String_type& value ); - Value_impl( const Object& value ); - Value_impl( const Array& value ); - Value_impl( bool value ); - Value_impl( int value ); - Value_impl( boost::int64_t value ); - Value_impl( boost::uint64_t value ); - Value_impl( double value ); - - template< class Iter > - Value_impl( Iter first, Iter last ); // constructor from containers, e.g. std::vector or std::list - - template< BOOST_VARIANT_ENUM_PARAMS( typename T ) > - Value_impl( const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& variant ); // constructor for compatible variant types - - Value_impl( const Value_impl& other ); - - bool operator==( const Value_impl& lhs ) const; - - Value_impl& operator=( const Value_impl& lhs ); - - Value_type type() const; - - bool is_uint64() const; - bool is_null() const; - - const String_type& get_str() const; - const Object& get_obj() const; - const Array& get_array() const; - bool get_bool() const; - int get_int() const; - boost::int64_t get_int64() const; - boost::uint64_t get_uint64() const; - double get_real() const; - - Object& get_obj(); - Array& get_array(); - - template< typename T > T get_value() const; // example usage: int i = value.get_value< int >(); - // or double d = value.get_value< double >(); - - static const Value_impl null; - - private: - - void check_type( const Value_type vtype ) const; - - typedef boost::variant< boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, - String_type, bool, boost::int64_t, double, Null, boost::uint64_t > Variant; - - Variant v_; - - class Variant_converter_visitor : public boost::static_visitor< Variant > - { - public: - - template< typename T, typename A, template< typename, typename > class Cont > - Variant operator()( const Cont< T, A >& cont ) const - { - return Array( cont.begin(), cont.end() ); - } - - Variant operator()( int i ) const - { - return static_cast< boost::int64_t >( i ); - } - - template - Variant operator()( const T& t ) const - { - return t; - } - }; + template + Variant operator()(const T& t) const { + return t; + } }; +}; - // vector objects +// vector objects - template< class Config > - struct Pair_impl - { - typedef typename Config::String_type String_type; - typedef typename Config::Value_type Value_type; +template +struct Pair_impl { + typedef typename Config::String_type String_type; + typedef typename Config::Value_type Value_type; - Pair_impl() - { - } + Pair_impl() {} - Pair_impl( const String_type& name, const Value_type& value ); + Pair_impl(const String_type& name, const Value_type& value); - bool operator==( const Pair_impl& lhs ) const; + bool operator==(const Pair_impl& lhs) const; - String_type name_; - Value_type value_; - }; + String_type name_; + Value_type value_; +}; -#if defined( JSON_SPIRIT_VALUE_ENABLED ) || defined( JSON_SPIRIT_WVALUE_ENABLED ) - template< class String > - struct Config_vector - { - typedef String String_type; - typedef Value_impl< Config_vector > Value_type; - typedef Pair_impl < Config_vector > Pair_type; - typedef std::vector< Value_type > Array_type; - typedef std::vector< Pair_type > Object_type; - - static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value ) - { - obj.push_back( Pair_type( name , value ) ); - - return obj.back().value_; - } - - static const String_type& get_name( const Pair_type& pair ) - { - return pair.name_; - } - - static const Value_type& get_value( const Pair_type& pair ) - { - return pair.value_; - } - }; +#if defined(JSON_SPIRIT_VALUE_ENABLED) || defined(JSON_SPIRIT_WVALUE_ENABLED) +template +struct Config_vector { + typedef String String_type; + typedef Value_impl Value_type; + typedef Pair_impl Pair_type; + typedef std::vector Array_type; + typedef std::vector Object_type; + + static Value_type& add(Object_type& obj, const String_type& name, + const Value_type& value) { + obj.push_back(Pair_type(name, value)); + + return obj.back().value_; + } + + static const String_type& get_name(const Pair_type& pair) { return pair.name_; } + + static const Value_type& get_value(const Pair_type& pair) { return pair.value_; } +}; #endif - // typedefs for ASCII +// typedefs for ASCII #ifdef JSON_SPIRIT_VALUE_ENABLED - typedef Config_vector< std::string > Config; +typedef Config_vector Config; - typedef Config::Value_type Value; - typedef Config::Pair_type Pair; - typedef Config::Object_type Object; - typedef Config::Array_type Array; +typedef Config::Value_type Value; +typedef Config::Pair_type Pair; +typedef Config::Object_type Object; +typedef Config::Array_type Array; #endif - // typedefs for Unicode +// typedefs for Unicode -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - typedef Config_vector< std::wstring > wConfig; +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +typedef Config_vector wConfig; - typedef wConfig::Value_type wValue; - typedef wConfig::Pair_type wPair; - typedef wConfig::Object_type wObject; - typedef wConfig::Array_type wArray; +typedef wConfig::Value_type wValue; +typedef wConfig::Pair_type wPair; +typedef wConfig::Object_type wObject; +typedef wConfig::Array_type wArray; #endif - // map objects - -#if defined( JSON_SPIRIT_MVALUE_ENABLED ) || defined( JSON_SPIRIT_WMVALUE_ENABLED ) - template< class String > - struct Config_map - { - typedef String String_type; - typedef Value_impl< Config_map > Value_type; - typedef std::vector< Value_type > Array_type; - typedef std::map< String_type, Value_type > Object_type; - typedef std::pair< const String_type, Value_type > Pair_type; - - static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value ) - { - return obj[ name ] = value; - } - - static const String_type& get_name( const Pair_type& pair ) - { - return pair.first; - } - - static const Value_type& get_value( const Pair_type& pair ) - { - return pair.second; - } - }; +// map objects + +#if defined(JSON_SPIRIT_MVALUE_ENABLED) || defined(JSON_SPIRIT_WMVALUE_ENABLED) +template +struct Config_map { + typedef String String_type; + typedef Value_impl Value_type; + typedef std::vector Array_type; + typedef std::map Object_type; + typedef std::pair Pair_type; + + static Value_type& add(Object_type& obj, const String_type& name, + const Value_type& value) { + return obj[name] = value; + } + + static const String_type& get_name(const Pair_type& pair) { return pair.first; } + + static const Value_type& get_value(const Pair_type& pair) { return pair.second; } +}; #endif - // typedefs for ASCII +// typedefs for ASCII #ifdef JSON_SPIRIT_MVALUE_ENABLED - typedef Config_map< std::string > mConfig; +typedef Config_map mConfig; - typedef mConfig::Value_type mValue; - typedef mConfig::Object_type mObject; - typedef mConfig::Array_type mArray; +typedef mConfig::Value_type mValue; +typedef mConfig::Object_type mObject; +typedef mConfig::Array_type mArray; #endif - // typedefs for Unicode +// typedefs for Unicode -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - typedef Config_map< std::wstring > wmConfig; +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +typedef Config_map wmConfig; - typedef wmConfig::Value_type wmValue; - typedef wmConfig::Object_type wmObject; - typedef wmConfig::Array_type wmArray; +typedef wmConfig::Value_type wmValue; +typedef wmConfig::Object_type wmObject; +typedef wmConfig::Array_type wmArray; #endif - /////////////////////////////////////////////////////////////////////////////////////////////// - // - // implementation +/////////////////////////////////////////////////////////////////////////////////////////////// +// +// implementation - inline bool operator==( const Null&, const Null& ) - { - return true; - } +inline bool operator==(const Null&, const Null&) { return true; } - template< class Config > - const Value_impl< Config > Value_impl< Config >::null; +template +const Value_impl Value_impl::null; - template< class Config > - Value_impl< Config >::Value_impl() - : v_( Null() ) - { - } +template +Value_impl::Value_impl() : v_(Null()) {} - template< class Config > - Value_impl< Config >::Value_impl( const Const_str_ptr value ) - : v_( String_type( value ) ) - { - } +template +Value_impl::Value_impl(const Const_str_ptr value) : v_(String_type(value)) {} - template< class Config > - Value_impl< Config >::Value_impl( const String_type& value ) - : v_( value ) - { - } +template +Value_impl::Value_impl(const String_type& value) : v_(value) {} - template< class Config > - Value_impl< Config >::Value_impl( const Object& value ) - : v_( value ) - { - } +template +Value_impl::Value_impl(const Object& value) : v_(value) {} - template< class Config > - Value_impl< Config >::Value_impl( const Array& value ) - : v_( value ) - { - } +template +Value_impl::Value_impl(const Array& value) : v_(value) {} - template< class Config > - Value_impl< Config >::Value_impl( bool value ) - : v_( value ) - { - } +template +Value_impl::Value_impl(bool value) : v_(value) {} - template< class Config > - Value_impl< Config >::Value_impl( int value ) - : v_( static_cast< boost::int64_t >( value ) ) - { - } +template +Value_impl::Value_impl(int value) : v_(static_cast(value)) {} - template< class Config > - Value_impl< Config >::Value_impl( boost::int64_t value ) - : v_( value ) - { - } +template +Value_impl::Value_impl(boost::int64_t value) : v_(value) {} - template< class Config > - Value_impl< Config >::Value_impl( boost::uint64_t value ) - : v_( value ) - { - } +template +Value_impl::Value_impl(boost::uint64_t value) : v_(value) {} - template< class Config > - Value_impl< Config >::Value_impl( double value ) - : v_( value ) - { - } +template +Value_impl::Value_impl(double value) : v_(value) {} - template< class Config > - Value_impl< Config >::Value_impl( const Value_impl< Config >& other ) - : v_( other.v_ ) - { - } +template +Value_impl::Value_impl(const Value_impl& other) : v_(other.v_) {} - template< class Config > - template< class Iter > - Value_impl< Config >::Value_impl( Iter first, Iter last ) - : v_( Array( first, last ) ) - { - } +template +template +Value_impl::Value_impl(Iter first, Iter last) : v_(Array(first, last)) {} - template< class Config > - template< BOOST_VARIANT_ENUM_PARAMS( typename T ) > - Value_impl< Config >::Value_impl( const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& variant ) - : v_( boost::apply_visitor( Variant_converter_visitor(), variant) ) - { - } +template +template +Value_impl::Value_impl( + const boost::variant& variant) + : v_(boost::apply_visitor(Variant_converter_visitor(), variant)) {} - template< class Config > - Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs ) - { - Value_impl tmp( lhs ); +template +Value_impl& Value_impl::operator=(const Value_impl& lhs) { + Value_impl tmp(lhs); - std::swap( v_, tmp.v_ ); + std::swap(v_, tmp.v_); - return *this; - } + return *this; +} - template< class Config > - bool Value_impl< Config >::operator==( const Value_impl& lhs ) const - { - if( this == &lhs ) return true; +template +bool Value_impl::operator==(const Value_impl& lhs) const { + if (this == &lhs) return true; - if( type() != lhs.type() ) return false; + if (type() != lhs.type()) return false; - return v_ == lhs.v_; + return v_ == lhs.v_; +} + +template +Value_type Value_impl::type() const { + if (is_uint64()) { + return int_type; } - template< class Config > - Value_type Value_impl< Config >::type() const - { - if( is_uint64() ) - { - return int_type; - } + return static_cast(v_.which()); +} - return static_cast< Value_type >( v_.which() ); - } +template +bool Value_impl::is_uint64() const { + return v_.which() == null_type + 1; +} - template< class Config > - bool Value_impl< Config >::is_uint64() const - { - return v_.which() == null_type + 1; - } +template +bool Value_impl::is_null() const { + return type() == null_type; +} - template< class Config > - bool Value_impl< Config >::is_null() const - { - return type() == null_type; +template +void Value_impl::check_type(const Value_type vtype) const { + if (type() != vtype) { + std::ostringstream os; + + os << "get_value< " << value_type_to_string(vtype) << " > called on " + << value_type_to_string(type()) << " Value"; + + throw std::runtime_error(os.str()); } +} - template< class Config > - void Value_impl< Config >::check_type( const Value_type vtype ) const - { - if( type() != vtype ) - { - std::ostringstream os; +template +const typename Config::String_type& Value_impl::get_str() const { + check_type(str_type); - os << "get_value< " << value_type_to_string( vtype ) << " > called on " << value_type_to_string( type() ) << " Value"; + return *boost::get(&v_); +} - throw std::runtime_error( os.str() ); - } - } +template +const typename Value_impl::Object& Value_impl::get_obj() const { + check_type(obj_type); - template< class Config > - const typename Config::String_type& Value_impl< Config >::get_str() const - { - check_type( str_type ); + return *boost::get(&v_); +} - return *boost::get< String_type >( &v_ ); - } +template +const typename Value_impl::Array& Value_impl::get_array() const { + check_type(array_type); - template< class Config > - const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const - { - check_type( obj_type ); + return *boost::get(&v_); +} - return *boost::get< Object >( &v_ ); - } - - template< class Config > - const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const - { - check_type( array_type ); +template +bool Value_impl::get_bool() const { + check_type(bool_type); - return *boost::get< Array >( &v_ ); - } - - template< class Config > - bool Value_impl< Config >::get_bool() const - { - check_type( bool_type ); + return boost::get(v_); +} - return boost::get< bool >( v_ ); - } - - template< class Config > - int Value_impl< Config >::get_int() const - { - check_type( int_type ); +template +int Value_impl::get_int() const { + check_type(int_type); - return static_cast< int >( get_int64() ); - } - - template< class Config > - boost::int64_t Value_impl< Config >::get_int64() const - { - check_type( int_type ); - - if( is_uint64() ) - { - return static_cast< boost::int64_t >( get_uint64() ); - } + return static_cast(get_int64()); +} - return boost::get< boost::int64_t >( v_ ); - } - - template< class Config > - boost::uint64_t Value_impl< Config >::get_uint64() const - { - check_type( int_type ); - - if( !is_uint64() ) - { - return static_cast< boost::uint64_t >( get_int64() ); - } +template +boost::int64_t Value_impl::get_int64() const { + check_type(int_type); - return boost::get< boost::uint64_t >( v_ ); + if (is_uint64()) { + return static_cast(get_uint64()); } - template< class Config > - double Value_impl< Config >::get_real() const - { - if( type() == int_type ) - { - return is_uint64() ? static_cast< double >( get_uint64() ) - : static_cast< double >( get_int64() ); - } + return boost::get(v_); +} - check_type( real_type ); +template +boost::uint64_t Value_impl::get_uint64() const { + check_type(int_type); - return boost::get< double >( v_ ); + if (!is_uint64()) { + return static_cast(get_int64()); } - template< class Config > - typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() - { - check_type( obj_type ); + return boost::get(v_); +} - return *boost::get< Object >( &v_ ); +template +double Value_impl::get_real() const { + if (type() == int_type) { + return is_uint64() ? static_cast(get_uint64()) + : static_cast(get_int64()); } - template< class Config > - typename Value_impl< Config >::Array& Value_impl< Config >::get_array() - { - check_type( array_type ); + check_type(real_type); - return *boost::get< Array >( &v_ ); - } + return boost::get(v_); +} - template< class Config > - Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value ) - : name_( name ) - , value_( value ) - { - } +template +typename Value_impl::Object& Value_impl::get_obj() { + check_type(obj_type); - template< class Config > - bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const - { - if( this == &lhs ) return true; + return *boost::get(&v_); +} - return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ ); - } +template +typename Value_impl::Array& Value_impl::get_array() { + check_type(array_type); - // converts a C string, ie. 8 bit char array, to a string object - // - template < class String_type > - String_type to_str( const char* c_str ) - { - String_type result; + return *boost::get(&v_); +} - for( const char* p = c_str; *p != 0; ++p ) - { - result += *p; - } +template +Pair_impl::Pair_impl(const String_type& name, const Value_type& value) + : name_(name), value_(value) {} - return result; - } +template +bool Pair_impl::operator==(const Pair_impl& lhs) const { + if (this == &lhs) return true; - // + return (name_ == lhs.name_) && (value_ == lhs.value_); +} - namespace internal_ - { - template< typename T > - struct Type_to_type - { - }; +// converts a C string, ie. 8 bit char array, to a string object +// +template +String_type to_str(const char* c_str) { + String_type result; - template< class Value > - int get_value( const Value& value, Type_to_type< int > ) - { - return value.get_int(); - } - - template< class Value > - boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > ) - { - return value.get_int64(); - } - - template< class Value > - boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > ) - { - return value.get_uint64(); - } - - template< class Value > - double get_value( const Value& value, Type_to_type< double > ) - { - return value.get_real(); - } - - template< class Value > - typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > ) - { - return value.get_str(); - } - - template< class Value > - typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > ) - { - return value.get_array(); - } - - template< class Value > - typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > ) - { - return value.get_obj(); - } - - template< class Value > - bool get_value( const Value& value, Type_to_type< bool > ) - { - return value.get_bool(); - } + for (const char* p = c_str; *p != 0; ++p) { + result += *p; } - template< class Config > - template< typename T > - T Value_impl< Config >::get_value() const - { - return internal_::get_value( *this, internal_::Type_to_type< T >() ); - } + return result; +} - static std::string value_type_to_string( const Value_type vtype ) - { - switch( vtype ) - { - case obj_type: return "Object"; - case array_type: return "Array"; - case str_type: return "string"; - case bool_type: return "boolean"; - case int_type: return "integer"; - case real_type: return "real"; - case null_type: return "null"; - } +// - assert( false ); +namespace internal_ { +template +struct Type_to_type {}; - return "unknown type"; - } +template +int get_value(const Value& value, Type_to_type) { + return value.get_int(); +} + +template +boost::int64_t get_value(const Value& value, Type_to_type) { + return value.get_int64(); +} + +template +boost::uint64_t get_value(const Value& value, Type_to_type) { + return value.get_uint64(); +} + +template +double get_value(const Value& value, Type_to_type) { + return value.get_real(); +} + +template +typename Value::String_type get_value(const Value& value, + Type_to_type) { + return value.get_str(); +} + +template +typename Value::Array get_value(const Value& value, + Type_to_type) { + return value.get_array(); +} + +template +typename Value::Object get_value(const Value& value, + Type_to_type) { + return value.get_obj(); +} + +template +bool get_value(const Value& value, Type_to_type) { + return value.get_bool(); +} +} // namespace internal_ + +template +template +T Value_impl::get_value() const { + return internal_::get_value(*this, internal_::Type_to_type()); +} + +static std::string value_type_to_string(const Value_type vtype) { + switch (vtype) { + case obj_type: + return "Object"; + case array_type: + return "Array"; + case str_type: + return "string"; + case bool_type: + return "boolean"; + case int_type: + return "integer"; + case real_type: + return "real"; + case null_type: + return "null"; + } + + assert(false); + + return "unknown type"; } +} // namespace json5_parser #endif diff --git a/json5_parser/json5_parser_writer.cpp b/json5_parser/json5_parser_writer.cpp index 7e44c76..88d2061 100644 --- a/json5_parser/json5_parser_writer.cpp +++ b/json5_parser/json5_parser_writer.cpp @@ -9,88 +9,88 @@ using namespace json5_parser; #ifdef JSON_SPIRIT_VALUE_ENABLED - void json5_parser::write( const Value& value, std::ostream& os, int options, unsigned int precision_of_doubles ) - { - write_stream( value, os, options, precision_of_doubles ); - } - std::string json5_parser::write( const Value& value, int options, unsigned int precision_of_doubles ) - { - return write_string( value, options, precision_of_doubles ); - } - - void json5_parser::write_formatted( const Value& value, std::ostream& os, unsigned int precision_of_doubles ) - { - write_stream( value, os, pretty_print, precision_of_doubles ); - } - - std::string json5_parser::write_formatted( const Value& value, unsigned int precision_of_doubles ) - { - return write_string( value, pretty_print, precision_of_doubles ); - } +void json5_parser::write(const Value& value, std::ostream& os, int options, + unsigned int precision_of_doubles) { + write_stream(value, os, options, precision_of_doubles); +} +std::string json5_parser::write(const Value& value, int options, + unsigned int precision_of_doubles) { + return write_string(value, options, precision_of_doubles); +} + +void json5_parser::write_formatted(const Value& value, std::ostream& os, + unsigned int precision_of_doubles) { + write_stream(value, os, pretty_print, precision_of_doubles); +} + +std::string json5_parser::write_formatted(const Value& value, + unsigned int precision_of_doubles) { + return write_string(value, pretty_print, precision_of_doubles); +} #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - void json5_parser::write( const mValue& value, std::ostream& os, int options, unsigned int precision_of_doubles ) - { - write_stream( value, os, options, precision_of_doubles ); - } - - std::string json5_parser::write( const mValue& value, int options, unsigned int precision_of_doubles ) - { - return write_string( value, options, precision_of_doubles ); - } - - void json5_parser::write_formatted( const mValue& value, std::ostream& os, unsigned int precision_of_doubles ) - { - write_stream( value, os, pretty_print, precision_of_doubles ); - } - - std::string json5_parser::write_formatted( const mValue& value, unsigned int precision_of_doubles ) - { - return write_string( value, pretty_print, precision_of_doubles ); - } +void json5_parser::write(const mValue& value, std::ostream& os, int options, + unsigned int precision_of_doubles) { + write_stream(value, os, options, precision_of_doubles); +} + +std::string json5_parser::write(const mValue& value, int options, + unsigned int precision_of_doubles) { + return write_string(value, options, precision_of_doubles); +} + +void json5_parser::write_formatted(const mValue& value, std::ostream& os, + unsigned int precision_of_doubles) { + write_stream(value, os, pretty_print, precision_of_doubles); +} + +std::string json5_parser::write_formatted(const mValue& value, + unsigned int precision_of_doubles) { + return write_string(value, pretty_print, precision_of_doubles); +} #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void json5_parser::write( const wValue& value, std::wostream& os, int options, unsigned int precision_of_doubles ) - { - write_stream( value, os, options, precision_of_doubles ); - } - - std::wstring json5_parser::write( const wValue& value, int options, unsigned int precision_of_doubles ) - { - return write_string( value, options, precision_of_doubles ); - } - - void json5_parser::write_formatted( const wValue& value, std::wostream& os, unsigned int precision_of_doubles ) - { - write_stream( value, os, pretty_print, precision_of_doubles ); - } - - std::wstring json5_parser::write_formatted( const wValue& value, unsigned int precision_of_doubles ) - { - return write_string( value, pretty_print, precision_of_doubles ); - } +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +void json5_parser::write(const wValue& value, std::wostream& os, int options, + unsigned int precision_of_doubles) { + write_stream(value, os, options, precision_of_doubles); +} + +std::wstring json5_parser::write(const wValue& value, int options, + unsigned int precision_of_doubles) { + return write_string(value, options, precision_of_doubles); +} + +void json5_parser::write_formatted(const wValue& value, std::wostream& os, + unsigned int precision_of_doubles) { + write_stream(value, os, pretty_print, precision_of_doubles); +} + +std::wstring json5_parser::write_formatted(const wValue& value, + unsigned int precision_of_doubles) { + return write_string(value, pretty_print, precision_of_doubles); +} #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void json5_parser::write_formatted( const wmValue& value, std::wostream& os, unsigned int precision_of_doubles ) - { - write_stream( value, os, pretty_print, precision_of_doubles ); - } - - std::wstring json5_parser::write_formatted( const wmValue& value, unsigned int precision_of_doubles ) - { - return write_string( value, pretty_print, precision_of_doubles ); - } - - void json5_parser::write( const wmValue& value, std::wostream& os, int options, unsigned int precision_of_doubles ) - { - write_stream( value, os, options, precision_of_doubles ); - } - - std::wstring json5_parser::write( const wmValue& value, int options, unsigned int precision_of_doubles ) - { - return write_string( value, options, precision_of_doubles ); - } +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +void json5_parser::write_formatted(const wmValue& value, std::wostream& os, + unsigned int precision_of_doubles) { + write_stream(value, os, pretty_print, precision_of_doubles); +} + +std::wstring json5_parser::write_formatted(const wmValue& value, + unsigned int precision_of_doubles) { + return write_string(value, pretty_print, precision_of_doubles); +} + +void json5_parser::write(const wmValue& value, std::wostream& os, int options, + unsigned int precision_of_doubles) { + write_stream(value, os, options, precision_of_doubles); +} + +std::wstring json5_parser::write(const wmValue& value, int options, + unsigned int precision_of_doubles) { + return write_string(value, options, precision_of_doubles); +} #endif diff --git a/json5_parser/json5_parser_writer.h b/json5_parser/json5_parser_writer.h index ead34af..66afedb 100644 --- a/json5_parser/json5_parser_writer.h +++ b/json5_parser/json5_parser_writer.h @@ -7,58 +7,71 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif +#include #include "json5_parser_value.h" #include "json5_parser_writer_options.h" -#include -namespace json5_parser -{ - // these functions to convert JSON Values to text - // note the precision used outputing doubles defaults to 17, - // unless the remove_trailing_zeros option is given in which case the default is 16 +namespace json5_parser { +// these functions to convert JSON Values to text +// note the precision used outputing doubles defaults to 17, +// unless the remove_trailing_zeros option is given in which case the default is 16 #ifdef JSON_SPIRIT_VALUE_ENABLED - void write( const Value& value, std::ostream& os, int options = none, unsigned int precision_of_doubles = 0 ); - std::string write( const Value& value, int options = none, unsigned int precision_of_doubles = 0 ); +void write(const Value& value, std::ostream& os, int options = none, + unsigned int precision_of_doubles = 0); +std::string write(const Value& value, int options = none, + unsigned int precision_of_doubles = 0); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - void write( const mValue& value, std::ostream& os, int options = none, unsigned int precision_of_doubles = 0 ); - std::string write( const mValue& value, int options = none, unsigned int precision_of_doubles = 0 ); +void write(const mValue& value, std::ostream& os, int options = none, + unsigned int precision_of_doubles = 0); +std::string write(const mValue& value, int options = none, + unsigned int precision_of_doubles = 0); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void write( const wValue& value, std::wostream& os, int options = none, unsigned int precision_of_doubles = 0 ); - std::wstring write( const wValue& value, int options = none, unsigned int precision_of_doubles = 0 ); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +void write(const wValue& value, std::wostream& os, int options = none, + unsigned int precision_of_doubles = 0); +std::wstring write(const wValue& value, int options = none, + unsigned int precision_of_doubles = 0); #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void write( const wmValue& value, std::wostream& os, int options = none, unsigned int precision_of_doubles = 0 ); - std::wstring write( const wmValue& value, int options = none, unsigned int precision_of_doubles = 0 ); +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +void write(const wmValue& value, std::wostream& os, int options = none, + unsigned int precision_of_doubles = 0); +std::wstring write(const wmValue& value, int options = none, + unsigned int precision_of_doubles = 0); #endif - // these "formatted" versions of the "write" functions are the equivalent of the above functions - // with option "pretty_print" - +// these "formatted" versions of the "write" functions are the equivalent of the above +// functions with option "pretty_print" + #ifdef JSON_SPIRIT_VALUE_ENABLED - void write_formatted( const Value& value, std::ostream& os, unsigned int precision_of_doubles = 0 ); - std::string write_formatted( const Value& value, unsigned int precision_of_doubles = 0 ); +void write_formatted(const Value& value, std::ostream& os, + unsigned int precision_of_doubles = 0); +std::string write_formatted(const Value& value, unsigned int precision_of_doubles = 0); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - void write_formatted( const mValue& value, std::ostream& os, unsigned int precision_of_doubles = 0 ); - std::string write_formatted( const mValue& value, unsigned int precision_of_doubles = 0 ); +void write_formatted(const mValue& value, std::ostream& os, + unsigned int precision_of_doubles = 0); +std::string write_formatted(const mValue& value, unsigned int precision_of_doubles = 0); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void write_formatted( const wValue& value, std::wostream& os, unsigned int precision_of_doubles = 0 ); - std::wstring write_formatted( const wValue& value, unsigned int precision_of_doubles = 0 ); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +void write_formatted(const wValue& value, std::wostream& os, + unsigned int precision_of_doubles = 0); +std::wstring write_formatted(const wValue& value, + unsigned int precision_of_doubles = 0); #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void write_formatted( const wmValue& value, std::wostream& os, unsigned int precision_of_doubles = 0 ); - std::wstring write_formatted( const wmValue& value, unsigned int precision_of_doubles = 0 ); +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +void write_formatted(const wmValue& value, std::wostream& os, + unsigned int precision_of_doubles = 0); +std::wstring write_formatted(const wmValue& value, + unsigned int precision_of_doubles = 0); #endif } diff --git a/json5_parser/json5_parser_writer_options.h b/json5_parser/json5_parser_writer_options.h index e84a330..f858ae2 100644 --- a/json5_parser/json5_parser_writer_options.h +++ b/json5_parser/json5_parser_writer_options.h @@ -7,29 +7,30 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -namespace json5_parser -{ - enum Output_options{ none = 0, // default options - - pretty_print = 0x01, // Add whitespace to format the output nicely. - - raw_utf8 = 0x02, // This prevents non-printable characters from being escapted using "\uNNNN" notation. - // Note, this is an extension to the JSON standard. It disables the escaping of - // non-printable characters allowing UTF-8 sequences held in 8 bit char strings - // to pass through unaltered. - - remove_trailing_zeros = 0x04, - // no longer used kept for backwards compatibility - single_line_arrays = 0x08, - // pretty printing except that arrays printed on single lines unless they contain - // composite elements, i.e. objects or arrays - always_escape_nonascii = 0x10, - // all unicode wide characters are escaped, i.e. outputed as "\uXXXX", even if they are - // printable under the current locale, ascii printable chars are not escaped - }; +namespace json5_parser { +enum Output_options { + none = 0, // default options + + pretty_print = 0x01, // Add whitespace to format the output nicely. + + raw_utf8 = 0x02, // This prevents non-printable characters from being escapted + // using "\uNNNN" notation. Note, this is an extension to the JSON + // standard. It disables the escaping of non-printable characters + // allowing UTF-8 sequences held in 8 bit char strings to pass + // through unaltered. + + remove_trailing_zeros = 0x04, + // no longer used kept for backwards compatibility + single_line_arrays = 0x08, + // pretty printing except that arrays printed on single lines unless they contain + // composite elements, i.e. objects or arrays + always_escape_nonascii = 0x10, + // all unicode wide characters are escaped, i.e. outputed as "\uXXXX", even if they + // are printable under the current locale, ascii printable chars are not escaped +}; } #endif diff --git a/json5_parser/json5_parser_writer_template.h b/json5_parser/json5_parser_writer_template.h index 342400b..23aada9 100644 --- a/json5_parser/json5_parser_writer_template.h +++ b/json5_parser/json5_parser_writer_template.h @@ -7,319 +7,309 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif #include "json5_parser_value.h" #include "json5_parser_writer_options.h" +#include #include -#include #include -#include +#include -namespace json5_parser -{ - inline char to_hex_char( unsigned int c ) - { - assert( c <= 0xF ); +namespace json5_parser { +inline char to_hex_char(unsigned int c) { + assert(c <= 0xF); - const char ch = static_cast< char >( c ); + const char ch = static_cast(c); - if( ch < 10 ) return '0' + ch; + if (ch < 10) return '0' + ch; - return 'A' - 10 + ch; - } + return 'A' - 10 + ch; +} + +template +String_type non_printable_to_string(unsigned int c) { + String_type result(6, '\\'); - template< class String_type > - String_type non_printable_to_string( unsigned int c ) - { - String_type result( 6, '\\' ); + result[1] = 'u'; - result[1] = 'u'; + result[5] = to_hex_char(c & 0x000F); + c >>= 4; + result[4] = to_hex_char(c & 0x000F); + c >>= 4; + result[3] = to_hex_char(c & 0x000F); + c >>= 4; + result[2] = to_hex_char(c & 0x000F); - result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4; - result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4; - result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4; - result[ 2 ] = to_hex_char( c & 0x000F ); + return result; +} - return result; +template +bool add_esc_char(Char_type c, String_type& s) { + switch (c) { + case '"': + s += to_str("\\\""); + return true; + case '\\': + s += to_str("\\\\"); + return true; + case '\b': + s += to_str("\\b"); + return true; + case '\f': + s += to_str("\\f"); + return true; + case '\n': + s += to_str("\\n"); + return true; + case '\r': + s += to_str("\\r"); + return true; + case '\t': + s += to_str("\\t"); + return true; } - template< typename Char_type, class String_type > - bool add_esc_char( Char_type c, String_type& s ) - { - switch( c ) - { - case '"': s += to_str< String_type >( "\\\"" ); return true; - case '\\': s += to_str< String_type >( "\\\\" ); return true; - case '\b': s += to_str< String_type >( "\\b" ); return true; - case '\f': s += to_str< String_type >( "\\f" ); return true; - case '\n': s += to_str< String_type >( "\\n" ); return true; - case '\r': s += to_str< String_type >( "\\r" ); return true; - case '\t': s += to_str< String_type >( "\\t" ); return true; - } + return false; +} - return false; - } +template +String_type add_esc_chars(const String_type& s, bool raw_utf8, bool esc_nonascii) { + typedef typename String_type::const_iterator Iter_type; + typedef typename String_type::value_type Char_type; - template< class String_type > - String_type add_esc_chars( const String_type& s, bool raw_utf8, bool esc_nonascii ) - { - typedef typename String_type::const_iterator Iter_type; - typedef typename String_type::value_type Char_type; + String_type result; - String_type result; + const Iter_type end(s.end()); - const Iter_type end( s.end() ); + for (Iter_type i = s.begin(); i != end; ++i) { + const Char_type c(*i); - for( Iter_type i = s.begin(); i != end; ++i ) - { - const Char_type c( *i ); + if (add_esc_char(c, result)) continue; - if( add_esc_char( c, result ) ) continue; + if (raw_utf8) { + result += c; + } else { + const wint_t unsigned_c((c >= 0) ? c : 256 + c); - if( raw_utf8 ) - { + if (!esc_nonascii && iswprint(unsigned_c)) { result += c; - } - else - { - const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c ); - - if( !esc_nonascii && iswprint( unsigned_c ) ) - { - result += c; - } - else - { - result += non_printable_to_string< String_type >( unsigned_c ); - } + } else { + result += non_printable_to_string(unsigned_c); } } - - return result; } - // this class generates the JSON text, - // it keeps track of the indentation level etc. - // - template< class Value_type, class Ostream_type > - class Generator - { - typedef typename Value_type::Config_type Config_type; - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename String_type::value_type Char_type; - typedef typename Object_type::value_type Obj_member_type; - - public: - - Generator( const Value_type& value, Ostream_type& os, int options, unsigned int precision_of_doubles ) - : os_( os ) - , indentation_level_( 0 ) - , pretty_( ( options & pretty_print ) != 0 || ( options & single_line_arrays ) != 0 ) - , raw_utf8_( ( options & raw_utf8 ) != 0 ) - , esc_nonascii_( ( options & always_escape_nonascii ) != 0 ) - , single_line_arrays_( ( options & single_line_arrays ) != 0 ) - , ios_saver_( os ) - { - if( precision_of_doubles > 0 ) - { - precision_of_doubles_ = precision_of_doubles; - } - else - { - precision_of_doubles_ = ( options & remove_trailing_zeros ) != 0 ? 16 : 17; - } + return result; +} - output( value ); +// this class generates the JSON text, +// it keeps track of the indentation level etc. +// +template +class Generator { + typedef typename Value_type::Config_type Config_type; + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename String_type::value_type Char_type; + typedef typename Object_type::value_type Obj_member_type; + +public: + Generator(const Value_type& value, Ostream_type& os, int options, + unsigned int precision_of_doubles) + : os_(os), + indentation_level_(0), + pretty_((options & pretty_print) != 0 || + (options & single_line_arrays) != 0), + raw_utf8_((options & raw_utf8) != 0), + esc_nonascii_((options & always_escape_nonascii) != 0), + single_line_arrays_((options & single_line_arrays) != 0), + ios_saver_(os) { + if (precision_of_doubles > 0) { + precision_of_doubles_ = precision_of_doubles; + } else { + precision_of_doubles_ = (options & remove_trailing_zeros) != 0 ? 16 : 17; } - private: - - void output( const Value_type& value ) - { - switch( value.type() ) - { - case obj_type: output( value.get_obj() ); break; - case array_type: output( value.get_array() ); break; - case str_type: output( value.get_str() ); break; - case bool_type: output( value.get_bool() ); break; - case real_type: output( value.get_real() ); break; - case int_type: output_int( value ); break; - case null_type: os_ << "null"; break; - default: assert( false ); - } - } + output(value); + } - void output( const Object_type& obj ) - { - output_array_or_obj( obj, '{', '}' ); +private: + void output(const Value_type& value) { + switch (value.type()) { + case obj_type: + output(value.get_obj()); + break; + case array_type: + output(value.get_array()); + break; + case str_type: + output(value.get_str()); + break; + case bool_type: + output(value.get_bool()); + break; + case real_type: + output(value.get_real()); + break; + case int_type: + output_int(value); + break; + case null_type: + os_ << "null"; + break; + default: + assert(false); } + } - void output( const Obj_member_type& member ) - { - output( Config_type::get_name( member ) ); space(); - os_ << ':'; space(); - output( Config_type::get_value( member ) ); - } + void output(const Object_type& obj) { output_array_or_obj(obj, '{', '}'); } - void output_int( const Value_type& value ) - { - if( value.is_uint64() ) - { - os_ << value.get_uint64(); - } - else - { - os_ << value.get_int64(); - } - } + void output(const Obj_member_type& member) { + output(Config_type::get_name(member)); + space(); + os_ << ':'; + space(); + output(Config_type::get_value(member)); + } - void output( const String_type& s ) - { - os_ << '"' << add_esc_chars( s, raw_utf8_, esc_nonascii_ ) << '"'; + void output_int(const Value_type& value) { + if (value.is_uint64()) { + os_ << value.get_uint64(); + } else { + os_ << value.get_int64(); } + } - void output( bool b ) - { - os_ << to_str< String_type >( b ? "true" : "false" ); - } + void output(const String_type& s) { + os_ << '"' << add_esc_chars(s, raw_utf8_, esc_nonascii_) << '"'; + } - void output( double d ) - { - os_ << std::setprecision( precision_of_doubles_ ) << d; - } + void output(bool b) { os_ << to_str(b ? "true" : "false"); } - static bool contains_composite_elements( const Array_type& arr ) - { - for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i ) - { - const Value_type& val = *i; - - if( val.type() == obj_type || - val.type() == array_type ) - { - return true; - } - } + void output(double d) { os_ << std::setprecision(precision_of_doubles_) << d; } + + static bool contains_composite_elements(const Array_type& arr) { + for (typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i) { + const Value_type& val = *i; - return false; + if (val.type() == obj_type || val.type() == array_type) { + return true; + } } - template< class Iter > - void output_composite_item( Iter i, Iter last ) - { - output( *i ); + return false; + } + + template + void output_composite_item(Iter i, Iter last) { + output(*i); - if( ++i != last ) - { - os_ << ','; - } + if (++i != last) { + os_ << ','; } + } - void output( const Array_type& arr ) - { - if( single_line_arrays_ && !contains_composite_elements( arr ) ) - { - os_ << '['; space(); - - for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i ) - { - output_composite_item( i, arr.end() ); + void output(const Array_type& arr) { + if (single_line_arrays_ && !contains_composite_elements(arr)) { + os_ << '['; + space(); - space(); - } + for (typename Array_type::const_iterator i = arr.begin(); i != arr.end(); + ++i) { + output_composite_item(i, arr.end()); - os_ << ']'; - } - else - { - output_array_or_obj( arr, '[', ']' ); + space(); } + + os_ << ']'; + } else { + output_array_or_obj(arr, '[', ']'); } + } - template< class T > - void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char ) - { - os_ << start_char; new_line(); + template + void output_array_or_obj(const T& t, Char_type start_char, Char_type end_char) { + os_ << start_char; + new_line(); - ++indentation_level_; - - for( typename T::const_iterator i = t.begin(); i != t.end(); ++i ) - { - indent(); + ++indentation_level_; - output_composite_item( i, t.end() ); + for (typename T::const_iterator i = t.begin(); i != t.end(); ++i) { + indent(); - new_line(); - } + output_composite_item(i, t.end()); - --indentation_level_; - - indent(); os_ << end_char; - } - - void indent() - { - if( !pretty_ ) return; - - for( int i = 0; i < indentation_level_; ++i ) - { - os_ << " "; - } + new_line(); } - void space() - { - if( pretty_ ) os_ << ' '; - } + --indentation_level_; + + indent(); + os_ << end_char; + } + + void indent() { + if (!pretty_) return; - void new_line() - { - if( pretty_ ) os_ << '\n'; + for (int i = 0; i < indentation_level_; ++i) { + os_ << " "; } + } + + void space() { + if (pretty_) os_ << ' '; + } - Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning - - Ostream_type& os_; - int indentation_level_; - bool pretty_; - bool raw_utf8_; - bool esc_nonascii_; - bool single_line_arrays_; - int precision_of_doubles_; - boost::io::basic_ios_all_saver< Char_type > ios_saver_; // so that ostream state is reset after control is returned to the caller - }; - - // writes JSON Value to a stream, e.g. - // - // write_stream( value, os, pretty_print ); - // - template< class Value_type, class Ostream_type > - void write_stream( const Value_type& value, Ostream_type& os, int options = none, unsigned int precision_of_doubles = 0 ) - { - os << std::dec; - Generator< Value_type, Ostream_type >( value, os, options, precision_of_doubles ); + void new_line() { + if (pretty_) os_ << '\n'; } - // writes JSON Value to a stream, e.g. - // - // const string json_str = write( value, pretty_print ); - // - template< class Value_type > - typename Value_type::String_type write_string( const Value_type& value, int options = none, unsigned int precision_of_doubles = 0 ) - { - typedef typename Value_type::String_type::value_type Char_type; + Generator& operator=(const Generator&); // to prevent "assignment operator could + // not be generated" warning + + Ostream_type& os_; + int indentation_level_; + bool pretty_; + bool raw_utf8_; + bool esc_nonascii_; + bool single_line_arrays_; + int precision_of_doubles_; + boost::io::basic_ios_all_saver ios_saver_; // so that ostream state is + // reset after control is + // returned to the caller +}; + +// writes JSON Value to a stream, e.g. +// +// write_stream( value, os, pretty_print ); +// +template +void write_stream(const Value_type& value, Ostream_type& os, int options = none, + unsigned int precision_of_doubles = 0) { + os << std::dec; + Generator(value, os, options, precision_of_doubles); +} - std::basic_ostringstream< Char_type > os; +// writes JSON Value to a stream, e.g. +// +// const string json_str = write( value, pretty_print ); +// +template +typename Value_type::String_type write_string(const Value_type& value, + int options = none, + unsigned int precision_of_doubles = 0) { + typedef typename Value_type::String_type::value_type Char_type; - write_stream( value, os, options, precision_of_doubles ); + std::basic_ostringstream os; - return os.str(); - } + write_stream(value, os, options, precision_of_doubles); + + return os.str(); } +} // namespace json5_parser #endif diff --git a/json_demo/json_demo.cpp b/json_demo/json_demo.cpp index 75941eb..7f8415d 100644 --- a/json_demo/json_demo.cpp +++ b/json_demo/json_demo.cpp @@ -6,19 +6,18 @@ // This demo shows you how to read and write JSON objects and arrays. // In this demo objects are stored as a vector of name/value pairs. -#include "json5_parser.h" #include #include +#include "json5_parser.h" #ifndef JSON_SPIRIT_VALUE_ENABLED -#error Please define JSON_SPIRIT_VALUE_ENABLED for the Value type to be enabled +#error Please define JSON_SPIRIT_VALUE_ENABLED for the Value type to be enabled #endif using namespace std; using namespace json5_parser; -struct Address -{ +struct Address { int house_number_; string road_; string town_; @@ -26,124 +25,101 @@ struct Address string country_; }; -bool operator==( const Address& a1, const Address& a2 ) -{ - return ( a1.house_number_ == a2.house_number_ ) && - ( a1.road_ == a2.road_ ) && - ( a1.town_ == a2.town_ ) && - ( a1.county_ == a2.county_ ) && - ( a1.country_ == a2.country_ ); +bool operator==(const Address& a1, const Address& a2) { + return (a1.house_number_ == a2.house_number_) && (a1.road_ == a2.road_) && + (a1.town_ == a2.town_) && (a1.county_ == a2.county_) && + (a1.country_ == a2.country_); } -void write_address( Array& a, const Address& addr ) -{ +void write_address(Array& a, const Address& addr) { Object addr_obj; - addr_obj.push_back( Pair( "house_number", addr.house_number_ ) ); - addr_obj.push_back( Pair( "road", addr.road_ ) ); - addr_obj.push_back( Pair( "town", addr.town_ ) ); - addr_obj.push_back( Pair( "county", addr.county_ ) ); - addr_obj.push_back( Pair( "country", addr.country_ ) ); + addr_obj.push_back(Pair("house_number", addr.house_number_)); + addr_obj.push_back(Pair("road", addr.road_)); + addr_obj.push_back(Pair("town", addr.town_)); + addr_obj.push_back(Pair("county", addr.county_)); + addr_obj.push_back(Pair("country", addr.country_)); - a.push_back( addr_obj ); + a.push_back(addr_obj); } -Address read_address( const Object& obj ) -{ +Address read_address(const Object& obj) { Address addr; - for( Object::size_type i = 0; i != obj.size(); ++i ) - { + for (Object::size_type i = 0; i != obj.size(); ++i) { const Pair& pair = obj[i]; - const string& name = pair.name_; - const Value& value = pair.value_; + const string& name = pair.name_; + const Value& value = pair.value_; - if( name == "house_number" ) - { + if (name == "house_number") { addr.house_number_ = value.get_int(); - } - else if( name == "road" ) - { + } else if (name == "road") { addr.road_ = value.get_str(); - } - else if( name == "town" ) - { + } else if (name == "town") { addr.town_ = value.get_str(); - } - else if( name == "county" ) - { + } else if (name == "county") { addr.county_ = value.get_str(); - } - else if( name == "country" ) - { + } else if (name == "country") { addr.country_ = value.get_str(); - } - else - { - assert( false ); + } else { + assert(false); } } return addr; } -void write_addrs( const char* file_name, const Address addrs[] ) -{ +void write_addrs(const char* file_name, const Address addrs[]) { Array addr_array; - for( int i = 0; i < 5; ++i ) - { - write_address( addr_array, addrs[i] ); + for (int i = 0; i < 5; ++i) { + write_address(addr_array, addrs[i]); } - ofstream os( file_name ); + ofstream os(file_name); - write_formatted( addr_array, os ); + write_formatted(addr_array, os); os.close(); } -vector< Address > read_addrs( const char* file_name ) -{ - ifstream is( file_name ); +vector
read_addrs(const char* file_name) { + ifstream is(file_name); Value value; - read( is, value ); + read(is, value); const Array& addr_array = value.get_array(); - vector< Address > addrs; + vector
addrs; - for( unsigned int i = 0; i < addr_array.size(); ++i ) - { - addrs.push_back( read_address( addr_array[i].get_obj() ) ); + for (unsigned int i = 0; i < addr_array.size(); ++i) { + addrs.push_back(read_address(addr_array[i].get_obj())); } return addrs; } -int main() -{ - const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, - { 1, "West Street", "Hull", "Yorkshire", "England" }, - { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, - { 45, "North Road", "Paignton", "Devon", "England" }, - { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; +int main() { + const Address addrs[5] = {{42, "East Street", "Newtown", "Essex", "England"}, + {1, "West Street", "Hull", "Yorkshire", "England"}, + {12, "South Road", "Aberystwyth", "Dyfed", "Wales"}, + {45, "North Road", "Paignton", "Devon", "England"}, + {78, "Upper Street", "Ware", "Hertfordshire", "England"}}; - const char* file_name( "demo.txt" ); + const char* file_name("demo.txt"); - write_addrs( file_name, addrs ); + write_addrs(file_name, addrs); - vector< Address > new_addrs = read_addrs( file_name ); + vector
new_addrs = read_addrs(file_name); - assert( new_addrs.size() == 5 ); + assert(new_addrs.size() == 5); - for( int i = 0; i < 5; ++i ) - { - assert( new_addrs[i] == addrs[i] ); + for (int i = 0; i < 5; ++i) { + assert(new_addrs[i] == addrs[i]); } - return 0; + return 0; } diff --git a/json_headers_only_demo/json_headers_only_demo.cpp b/json_headers_only_demo/json_headers_only_demo.cpp index a8896d6..0730c96 100644 --- a/json_headers_only_demo/json_headers_only_demo.cpp +++ b/json_headers_only_demo/json_headers_only_demo.cpp @@ -3,24 +3,23 @@ // json spirit version 4.08 -// This demo shows you how to read and write JSON objects and arrays +// This demo shows you how to read and write JSON objects and arrays // using header files only, i.e. not linking to the JSON Spirit object library. // In this demo objects are stored as a vector of name/value pairs. -#include "json5_parser_reader_template.h" -#include "json5_parser_writer_template.h" #include #include +#include "json5_parser_reader_template.h" +#include "json5_parser_writer_template.h" #ifndef JSON_SPIRIT_VALUE_ENABLED -#error Please define JSON_SPIRIT_VALUE_ENABLED for the Value type to be enabled +#error Please define JSON_SPIRIT_VALUE_ENABLED for the Value type to be enabled #endif using namespace std; using namespace json5_parser; -struct Address -{ +struct Address { int house_number_; string road_; string town_; @@ -28,124 +27,102 @@ struct Address string country_; }; -bool operator==( const Address& a1, const Address& a2 ) -{ - return ( a1.house_number_ == a2.house_number_ ) && - ( a1.road_ == a2.road_ ) && - ( a1.town_ == a2.town_ ) && - ( a1.county_ == a2.county_ ) && - ( a1.country_ == a2.country_ ); +bool operator==(const Address& a1, const Address& a2) { + return (a1.house_number_ == a2.house_number_) && (a1.road_ == a2.road_) && + (a1.town_ == a2.town_) && (a1.county_ == a2.county_) && + (a1.country_ == a2.country_); } -void write_address( Array& a, const Address& addr ) -{ +void write_address(Array& a, const Address& addr) { Object addr_obj; - addr_obj.push_back( Pair( "house_number", addr.house_number_ ) ); - addr_obj.push_back( Pair( "road", addr.road_ ) ); - addr_obj.push_back( Pair( "town", addr.town_ ) ); - addr_obj.push_back( Pair( "county", addr.county_ ) ); - addr_obj.push_back( Pair( "country", addr.country_ ) ); + addr_obj.push_back(Pair("house_number", addr.house_number_)); + addr_obj.push_back(Pair("road", addr.road_)); + addr_obj.push_back(Pair("town", addr.town_)); + addr_obj.push_back(Pair("county", addr.county_)); + addr_obj.push_back(Pair("country", addr.country_)); - a.push_back( addr_obj ); + a.push_back(addr_obj); } -Address read_address( const Object& obj ) -{ +Address read_address(const Object& obj) { Address addr; - for( Object::size_type i = 0; i != obj.size(); ++i ) - { + for (Object::size_type i = 0; i != obj.size(); ++i) { const Pair& pair = obj[i]; - const string& name = pair.name_; - const Value& value = pair.value_; + const string& name = pair.name_; + const Value& value = pair.value_; - if( name == "house_number" ) - { + if (name == "house_number") { addr.house_number_ = value.get_int(); - } - else if( name == "road" ) - { + } else if (name == "road") { addr.road_ = value.get_str(); - } - else if( name == "town" ) - { + } else if (name == "town") { addr.town_ = value.get_str(); - } - else if( name == "county" ) - { + } else if (name == "county") { addr.county_ = value.get_str(); - } - else if( name == "country" ) - { + } else if (name == "country") { addr.country_ = value.get_str(); - } - else - { - assert( false ); + } else { + assert(false); } } return addr; } -void write_addrs( const char* file_name, const Address addrs[] ) -{ +void write_addrs(const char* file_name, const Address addrs[]) { Array addr_array; - for( int i = 0; i < 5; ++i ) - { - write_address( addr_array, addrs[i] ); + for (int i = 0; i < 5; ++i) { + write_address(addr_array, addrs[i]); } - ofstream os( file_name ); + ofstream os(file_name); - write_stream( Value( addr_array ), os, pretty_print ); // NB need to convert Array to a Value + write_stream(Value(addr_array), os, + pretty_print); // NB need to convert Array to a Value os.close(); } -vector< Address > read_addrs( const char* file_name ) -{ - ifstream is( file_name ); +vector
read_addrs(const char* file_name) { + ifstream is(file_name); Value value; - read_stream( is, value ); + read_stream(is, value); const Array& addr_array = value.get_array(); - vector< Address > addrs; + vector
addrs; - for( unsigned int i = 0; i < addr_array.size(); ++i ) - { - addrs.push_back( read_address( addr_array[i].get_obj() ) ); + for (unsigned int i = 0; i < addr_array.size(); ++i) { + addrs.push_back(read_address(addr_array[i].get_obj())); } return addrs; } -int main() -{ - const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, - { 1, "West Street", "Hull", "Yorkshire", "England" }, - { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, - { 45, "North Road", "Paignton", "Devon", "England" }, - { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; +int main() { + const Address addrs[5] = {{42, "East Street", "Newtown", "Essex", "England"}, + {1, "West Street", "Hull", "Yorkshire", "England"}, + {12, "South Road", "Aberystwyth", "Dyfed", "Wales"}, + {45, "North Road", "Paignton", "Devon", "England"}, + {78, "Upper Street", "Ware", "Hertfordshire", "England"}}; - const char* file_name( "demo.txt" ); + const char* file_name("demo.txt"); - write_addrs( file_name, addrs ); + write_addrs(file_name, addrs); - vector< Address > new_addrs = read_addrs( file_name ); + vector
new_addrs = read_addrs(file_name); - assert( new_addrs.size() == 5 ); + assert(new_addrs.size() == 5); - for( int i = 0; i < 5; ++i ) - { - assert( new_addrs[i] == addrs[i] ); + for (int i = 0; i < 5; ++i) { + assert(new_addrs[i] == addrs[i]); } - return 0; + return 0; } diff --git a/json_map_demo/json_map_demo.cpp b/json_map_demo/json_map_demo.cpp index e9c428c..34cab7b 100644 --- a/json_map_demo/json_map_demo.cpp +++ b/json_map_demo/json_map_demo.cpp @@ -6,19 +6,18 @@ // This demo shows you how to read and write JSON objects and arrays. // In this demo objects are stored as a map of names to values. -#include "json5_parser.h" #include #include +#include "json5_parser.h" #ifndef JSON_SPIRIT_MVALUE_ENABLED -#error Please define JSON_SPIRIT_MVALUE_ENABLED for the mValue type to be enabled +#error Please define JSON_SPIRIT_MVALUE_ENABLED for the mValue type to be enabled #endif using namespace std; using namespace json5_parser; -struct Address -{ +struct Address { int house_number_; string road_; string town_; @@ -26,108 +25,95 @@ struct Address string country_; }; -bool operator==( const Address& a1, const Address& a2 ) -{ - return ( a1.house_number_ == a2.house_number_ ) && - ( a1.road_ == a2.road_ ) && - ( a1.town_ == a2.town_ ) && - ( a1.county_ == a2.county_ ) && - ( a1.country_ == a2.country_ ); +bool operator==(const Address& a1, const Address& a2) { + return (a1.house_number_ == a2.house_number_) && (a1.road_ == a2.road_) && + (a1.town_ == a2.town_) && (a1.county_ == a2.county_) && + (a1.country_ == a2.country_); } -void write_address( mArray& a, const Address& addr ) -{ +void write_address(mArray& a, const Address& addr) { mObject addr_obj; - addr_obj[ "house_number" ] = addr.house_number_; - addr_obj[ "road" ] = addr.road_; - addr_obj[ "town" ] = addr.town_; - addr_obj[ "county" ] = addr.county_; - addr_obj[ "country" ] = addr.country_; + addr_obj["house_number"] = addr.house_number_; + addr_obj["road"] = addr.road_; + addr_obj["town"] = addr.town_; + addr_obj["county"] = addr.county_; + addr_obj["country"] = addr.country_; - a.push_back( addr_obj ); + a.push_back(addr_obj); } -const mValue& find_value( const mObject& obj, const string& name ) -{ - mObject::const_iterator i = obj.find( name ); +const mValue& find_value(const mObject& obj, const string& name) { + mObject::const_iterator i = obj.find(name); - assert( i != obj.end() ); - assert( i->first == name ); + assert(i != obj.end()); + assert(i->first == name); return i->second; } -Address read_address( const mObject& obj ) -{ +Address read_address(const mObject& obj) { Address addr; - addr.house_number_ = find_value( obj, "house_number" ).get_int(); - addr.road_ = find_value( obj, "road" ).get_str(); - addr.town_ = find_value( obj, "town" ).get_str(); - addr.county_ = find_value( obj, "county" ).get_str(); - addr.country_ = find_value( obj, "country" ).get_str(); + addr.house_number_ = find_value(obj, "house_number").get_int(); + addr.road_ = find_value(obj, "road").get_str(); + addr.town_ = find_value(obj, "town").get_str(); + addr.county_ = find_value(obj, "county").get_str(); + addr.country_ = find_value(obj, "country").get_str(); return addr; } -void write_addrs( const char* file_name, const Address addrs[] ) -{ +void write_addrs(const char* file_name, const Address addrs[]) { mArray addr_array; - for( int i = 0; i < 5; ++i ) - { - write_address( addr_array, addrs[i] ); + for (int i = 0; i < 5; ++i) { + write_address(addr_array, addrs[i]); } - ofstream os( file_name ); + ofstream os(file_name); - write_formatted( addr_array, os ); + write_formatted(addr_array, os); os.close(); } -vector< Address > read_addrs( const char* file_name ) -{ - ifstream is( file_name ); +vector
read_addrs(const char* file_name) { + ifstream is(file_name); mValue value; - read( is, value ); + read(is, value); const mArray& addr_array = value.get_array(); - vector< Address > addrs; + vector
addrs; - for( vector< Address >::size_type i = 0; i < addr_array.size(); ++i ) - { - addrs.push_back( read_address( addr_array[i].get_obj() ) ); + for (vector
::size_type i = 0; i < addr_array.size(); ++i) { + addrs.push_back(read_address(addr_array[i].get_obj())); } return addrs; } -int main() -{ - const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" }, - { 1, "West Street", "Hull", "Yorkshire", "England" }, - { 12, "South Road", "Aberystwyth", "Dyfed", "Wales" }, - { 45, "North Road", "Paignton", "Devon", "England" }, - { 78, "Upper Street", "Ware", "Hertfordshire", "England" } }; +int main() { + const Address addrs[5] = {{42, "East Street", "Newtown", "Essex", "England"}, + {1, "West Street", "Hull", "Yorkshire", "England"}, + {12, "South Road", "Aberystwyth", "Dyfed", "Wales"}, + {45, "North Road", "Paignton", "Devon", "England"}, + {78, "Upper Street", "Ware", "Hertfordshire", "England"}}; - const char* file_name( "demo.txt" ); + const char* file_name("demo.txt"); - write_addrs( file_name, addrs ); + write_addrs(file_name, addrs); - vector< Address > new_addrs = read_addrs( file_name ); + vector
new_addrs = read_addrs(file_name); - assert( new_addrs.size() == 5 ); + assert(new_addrs.size() == 5); - for( int i = 0; i < 5; ++i ) - { - assert( new_addrs[i] == addrs[i] ); + for (int i = 0; i < 5; ++i) { + assert(new_addrs[i] == addrs[i]); } - return 0; -} -; \ No newline at end of file + return 0; +}; \ No newline at end of file diff --git a/json_test/json5_parser_reader_test.cpp b/json_test/json5_parser_reader_test.cpp index eab6445..05257ac 100644 --- a/json_test/json5_parser_reader_test.cpp +++ b/json_test/json5_parser_reader_test.cpp @@ -4,922 +4,901 @@ // json spirit version 4.08 #include "json5_parser_reader_test.h" -#include "utils_test.h" #include "json5_parser_reader.h" -#include "json5_parser_value.h" -#include "json5_parser_writer.h" +#include "json5_parser_value.h" +#include "json5_parser_writer.h" +#include "utils_test.h" #include -#include #include -#include #include +#include +#include using namespace json5_parser; using namespace std; using namespace boost; using namespace boost::assign; -namespace -{ - template< class String_type, class Value_type > - void test_read( const String_type& s, Value_type& value ) - { - // performs both types of read and checks they produce the same value +namespace { +template +void test_read(const String_type& s, Value_type& value) { + // performs both types of read and checks they produce the same value - read( s, value ); + read(s, value); - Value_type value_2; + Value_type value_2; - read_or_throw( s, value_2 ); + read_or_throw(s, value_2); - assert_eq( value, value_2 ); - } + assert_eq(value, value_2); +} - template< class Config_type > - struct Test_runner - { - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; - typedef typename Config_type::Pair_type Pair_type; - typedef typename String_type::value_type Char_type; - typedef typename String_type::const_iterator Iter_type; - typedef std::basic_istringstream< Char_type > Istringstream_type; - typedef std::basic_istream< Char_type > Istream_type; +template +struct Test_runner { + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + typedef typename Config_type::Pair_type Pair_type; + typedef typename String_type::value_type Char_type; + typedef typename String_type::const_iterator Iter_type; + typedef std::basic_istringstream Istringstream_type; + typedef std::basic_istream Istream_type; - String_type to_str( const char* c_str ) - { - return ::to_str< String_type >( c_str ); - } + String_type to_str(const char* c_str) { return ::to_str(c_str); } - Test_runner() - { - } + Test_runner() {} - void check_eq( const Object_type& obj_1, const Object_type& obj_2 ) - { - const typename Object_type::size_type size( obj_1.size() ); + void check_eq(const Object_type& obj_1, const Object_type& obj_2) { + const typename Object_type::size_type size(obj_1.size()); - assert_eq( size, obj_2.size() ); + assert_eq(size, obj_2.size()); - typename Object_type::const_iterator i1 = obj_1.begin(); - typename Object_type::const_iterator i2 = obj_2.begin(); + typename Object_type::const_iterator i1 = obj_1.begin(); + typename Object_type::const_iterator i2 = obj_2.begin(); - for( ; i1 != obj_1.end(); ++i1, ++i2 ) - { - assert_eq( *i1, *i2 ); - } + for (; i1 != obj_1.end(); ++i1, ++i2) { + assert_eq(*i1, *i2); } + } - void add_value( Object_type& obj, const char* c_name, const Value_type& value ) - { - Config_type::add( obj, to_str( c_name ), value ); - } + void add_value(Object_type& obj, const char* c_name, const Value_type& value) { + Config_type::add(obj, to_str(c_name), value); + } - void add_c_str( Object_type& obj, const char* c_name, const char* c_value ) - { - add_value( obj, c_name, to_str( c_value ) ); - } + void add_c_str(Object_type& obj, const char* c_name, const char* c_value) { + add_value(obj, c_name, to_str(c_value)); + } - void test_syntax( const char* c_str, bool expected_success = true ) - { - const String_type str = to_str( c_str ); + void test_syntax(const char* c_str, bool expected_success = true) { + const String_type str = to_str(c_str); - Value_type value; + Value_type value; - const bool ok = read( str, value ); + const bool ok = read(str, value); - assert_eq( ok, expected_success ); + assert_eq(ok, expected_success); - try - { - read_or_throw( str, value ); + try { + read_or_throw(str, value); - assert( expected_success ); - } - catch( ... ) - { - assert( !expected_success ); - } + assert(expected_success); + } catch (...) { + assert(!expected_success); } + } - template< typename Int > - void test_syntax( Int min_int, Int max_int ) - { - ostringstream os; + template + void test_syntax(Int min_int, Int max_int) { + ostringstream os; - os << "[" << min_int << "," << max_int << "]"; + os << "[" << min_int << "," << max_int << "]"; - test_syntax( os.str().c_str() ); - } + test_syntax(os.str().c_str()); + } - void test_syntax() - { - test_syntax( "{}" ); - test_syntax( "{ }" ); - test_syntax( "{ } " ); - test_syntax( "{ } " ); - test_syntax( "{\"\":\"\"}" ); - test_syntax( "{\"test\":\"123\"}" ); - test_syntax( "{\"test\" : \"123\"}" ); - test_syntax( "{\"testing testing testing\":\"123\"}" ); - test_syntax( "{\"\":\"abc\"}" ); - test_syntax( "{\"abc\":\"\"}" ); - test_syntax( "{\"\":\"\"}" ); - test_syntax( "{\"test\":true}" ); - test_syntax( "{\"test\":false}" ); - test_syntax( "{\"test\":null}" ); - test_syntax( "{\"test1\":\"123\",\"test2\":\"456\"}" ); - test_syntax( "{\"test1\":\"123\",\"test2\":\"456\",\"test3\":\"789\"}" ); - test_syntax( "{\"test1\":{\"test2\":\"123\",\"test3\":\"456\"}}" ); - test_syntax( "{\"test1\":{\"test2\":{\"test3\":\"456\"}}}" ); - test_syntax( "{\"test1\":[\"a\",\"bb\",\"cc\"]}" ); - test_syntax( "{\"test1\":[true,false,null]}" ); - test_syntax( "{\"test1\":[true,\"abc\",{\"a\":\"b\"},{\"d\":false},null]}" ); - test_syntax( "{\"test1\":[1,2,-3]}" ); - test_syntax( "{\"test1\":[1.1,2e4,-1.234e-34]}" ); - test_syntax( "{\n" - "\t\"test1\":\n" - "\t\t{\n" - "\t\t\t\"test2\":\"123\",\n" - "\t\t\t\"test3\":\"456\"\n" - "\t\t}\n" - "}\n" ); - test_syntax( "[]" ); - test_syntax( "[ ]" ); - test_syntax( "[1,2,3]" ); - test_syntax( "[ 1, -2, 3]" ); - test_syntax( "[ 1.2, -2e6, -3e-6 ]" ); - test_syntax( "[ 1.2, \"str\", -3e-6, { \"field\" : \"data\" } ]" ); - - test_syntax( INT_MIN, INT_MAX ); - test_syntax( LLONG_MIN, LLONG_MAX ); - test_syntax( "[1 2 3]", false ); - test_syntax( "[1,\n2,\n3,]"); - test_syntax( "[0xfreedom]",false); - test_syntax( "[0xreefer]",false); - } + void test_syntax() { + test_syntax("{}"); + test_syntax("{ }"); + test_syntax("{ } "); + test_syntax("{ } "); + test_syntax("{\"\":\"\"}"); + test_syntax("{\"test\":\"123\"}"); + test_syntax("{\"test\" : \"123\"}"); + test_syntax("{\"testing testing testing\":\"123\"}"); + test_syntax("{\"\":\"abc\"}"); + test_syntax("{\"abc\":\"\"}"); + test_syntax("{\"\":\"\"}"); + test_syntax("{\"test\":true}"); + test_syntax("{\"test\":false}"); + test_syntax("{\"test\":null}"); + test_syntax("{\"test1\":\"123\",\"test2\":\"456\"}"); + test_syntax("{\"test1\":\"123\",\"test2\":\"456\",\"test3\":\"789\"}"); + test_syntax("{\"test1\":{\"test2\":\"123\",\"test3\":\"456\"}}"); + test_syntax("{\"test1\":{\"test2\":{\"test3\":\"456\"}}}"); + test_syntax("{\"test1\":[\"a\",\"bb\",\"cc\"]}"); + test_syntax("{\"test1\":[true,false,null]}"); + test_syntax("{\"test1\":[true,\"abc\",{\"a\":\"b\"},{\"d\":false},null]}"); + test_syntax("{\"test1\":[1,2,-3]}"); + test_syntax("{\"test1\":[1.1,2e4,-1.234e-34]}"); + test_syntax( + "{\n" + "\t\"test1\":\n" + "\t\t{\n" + "\t\t\t\"test2\":\"123\",\n" + "\t\t\t\"test3\":\"456\"\n" + "\t\t}\n" + "}\n"); + test_syntax("[]"); + test_syntax("[ ]"); + test_syntax("[1,2,3]"); + test_syntax("[ 1, -2, 3]"); + test_syntax("[ 1.2, -2e6, -3e-6 ]"); + test_syntax("[ 1.2, \"str\", -3e-6, { \"field\" : \"data\" } ]"); + + test_syntax(INT_MIN, INT_MAX); + test_syntax(LLONG_MIN, LLONG_MAX); + test_syntax("[1 2 3]", false); + test_syntax("[1,\n2,\n3,]"); + test_syntax("[0xfreedom]", false); + test_syntax("[0xreefer]", false); + } - Value_type read_cstr( const char* c_str ) - { - Value_type value; + Value_type read_cstr(const char* c_str) { + Value_type value; - test_read( to_str( c_str ), value ); + test_read(to_str(c_str), value); - return value; - } + return value; + } - void read_cstr( const char* c_str, Value_type& value ) - { - test_read( to_str( c_str ), value ); - } + void read_cstr(const char* c_str, Value_type& value) { + test_read(to_str(c_str), value); + } - void check_reading( const char* c_str ) - { - Value_type value; + void check_reading(const char* c_str) { + Value_type value; - String_type in_s( to_str( c_str ) ); + String_type in_s(to_str(c_str)); - test_read( in_s, value ); + test_read(in_s, value); - const String_type result = write_formatted( value ); + const String_type result = write_formatted(value); - assert_eq( in_s, result ); - } + assert_eq(in_s, result); + } - template< typename Int > - void check_reading( Int min_int, Int max_int ) - { - ostringstream os; + template + void check_reading(Int min_int, Int max_int) { + ostringstream os; - os << "[\n" - " " << min_int << ",\n" - " " << max_int << "\n" - "]"; + os << "[\n" + " " + << min_int + << ",\n" + " " + << max_int + << "\n" + "]"; - check_reading( os.str().c_str() ); - } + check_reading(os.str().c_str()); + } + + void test_reading() { + check_reading("{\n}"); - void test_reading() { - check_reading( "{\n}" ); + Object_type obj; + Value_type value; - { - Object_type obj; - Value_type value; + read_cstr( + "{\n" + " name1 : 'value \\\n1',\n" + "}", + value); + + add_c_str(obj, "name1", "value 1"); + + check_eq(value.get_obj(), obj); + } + + Object_type obj; + Value_type value; + + read_cstr( + "{\n" + " \"name 1\" : \"value 1\"\n" + "}", + value); + + add_c_str(obj, "name 1", "value 1"); + + check_eq(value.get_obj(), obj); + + read_cstr("{\"name 1\":\"value 1\",\"name 2\":\"value 2\"}", value); + + add_c_str(obj, "name 2", "value 2"); + + check_eq(value.get_obj(), obj); + + read_cstr( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : \"value 2\",\n" + " \"name 3\" : \"value 3\"\n" + "}", + value); + + add_c_str(obj, "name 3", "value 3"); + + check_eq(value.get_obj(), obj); + + check_reading( + "{\n" + " \"\" : \"value\",\n" + " \"name\" : \"\"\n" + "}"); + + check_reading( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : {\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : \"value_4\"\n" + " }\n" + "}"); + + check_reading( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : {\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : \"value_4\",\n" + " \"name_5\" : {\n" + " \"name_6\" : \"value_6\",\n" + " \"name_7\" : \"value_7\"\n" + " }\n" + " }\n" + "}"); + + check_reading( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : {\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : {\n" + " \"name_5\" : \"value_5\",\n" + " \"name_6\" : \"value_6\"\n" + " },\n" + " \"name_7\" : \"value_7\"\n" + " }\n" + "}"); + + check_reading( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : {\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : {\n" + " \"name_5\" : \"value_5\",\n" + " \"name_6\" : \"value_6\"\n" + " },\n" + " \"name_7\" : \"value_7\"\n" + " },\n" + " \"name_8\" : \"value_8\",\n" + " \"name_9\" : {\n" + " \"name_10\" : \"value_10\"\n" + " }\n" + "}"); + + check_reading( + "{\n" + " \"name 1\" : {\n" + " \"name 2\" : {\n" + " \"name 3\" : {\n" + " \"name_4\" : {\n" + " \"name_5\" : \"value\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"); + + check_reading( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : true,\n" + " \"name 3\" : false,\n" + " \"name_4\" : \"value_4\",\n" + " \"name_5\" : true\n" + "}"); + + check_reading( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : null,\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : null\n" + "}"); + + check_reading( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : 123,\n" + " \"name 3\" : \"value 3\",\n" + " \"name_4\" : -567\n" + "}"); + + check_reading("[\n]"); + + check_reading( + "[\n" + " 1\n" + "]"); + + check_reading( + "[\n" + " 1,\n" + " 1.2,\n" + " \"john]\",\n" + " true,\n" + " false,\n" + " null\n" + "]"); + + check_reading( + "[\n" + " 1,\n" + " [\n" + " 2,\n" + " 3\n" + " ]\n" + "]"); + + check_reading( + "[\n" + " 1,\n" + " [\n" + " 2,\n" + " 3\n" + " ],\n" + " [\n" + " 4,\n" + " [\n" + " 5,\n" + " 6,\n" + " 7\n" + " ]\n" + " ]\n" + "]"); + + check_reading( + "[\n" + " {\n" + " \"name\" : \"value\"\n" + " }\n" + "]"); + + check_reading( + "{\n" + " \"name\" : [\n" + " 1\n" + " ]\n" + "}"); + + check_reading( + "[\n" + " {\n" + " \"name 1\" : \"value\",\n" + " \"name 2\" : [\n" + " 1,\n" + " 2,\n" + " 3\n" + " ]\n" + " }\n" + "]"); + + check_reading( + "{\n" + " \"name 1\" : [\n" + " 1,\n" + " {\n" + " \"name 2\" : \"value 2\"\n" + " }\n" + " ]\n" + "}"); + + check_reading( + "[\n" + " {\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : [\n" + " 1,\n" + " 2,\n" + " {\n" + " \"name 3\" : \"value 3\"\n" + " }\n" + " ]\n" + " }\n" + "]"); + + check_reading( + "{\n" + " \"name 1\" : [\n" + " 1,\n" + " {\n" + " \"name 2\" : [\n" + " 1,\n" + " 2,\n" + " 3\n" + " ]\n" + " }\n" + " ]\n" + "}"); + + check_reading(INT_MIN, INT_MAX); + check_reading(LLONG_MIN, LLONG_MAX); + } - read_cstr( "{\n" - " name1 : 'value \\\n1',\n" - "}", value ); + void test_reading_reals() { + Value_type value; - add_c_str( obj, "name1", "value 1" ); + const String_type in_s = to_str( + "[1.200000000000000,1.234567890123456e+125,-1.234000000000000e-123," + " 1.000000000000000e-123,1234567890.123456,123,]"); - check_eq( value.get_obj(), obj ); - } + basic_istringstream is(in_s); - Object_type obj; - Value_type value; + const bool ok = read(is, value); - read_cstr( "{\n" - " \"name 1\" : \"value 1\"\n" - "}", value ); - - add_c_str( obj, "name 1", "value 1" ); - - check_eq( value.get_obj(), obj ); - - read_cstr( "{\"name 1\":\"value 1\",\"name 2\":\"value 2\"}", value ); - - add_c_str( obj, "name 2", "value 2" ); - - check_eq( value.get_obj(), obj ); - - read_cstr( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : \"value 2\",\n" - " \"name 3\" : \"value 3\"\n" - "}", value ); - - add_c_str( obj, "name 3", "value 3" ); - - check_eq( value.get_obj(), obj ); - - check_reading( "{\n" - " \"\" : \"value\",\n" - " \"name\" : \"\"\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : {\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : \"value_4\"\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : {\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : \"value_4\",\n" - " \"name_5\" : {\n" - " \"name_6\" : \"value_6\",\n" - " \"name_7\" : \"value_7\"\n" - " }\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : {\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : {\n" - " \"name_5\" : \"value_5\",\n" - " \"name_6\" : \"value_6\"\n" - " },\n" - " \"name_7\" : \"value_7\"\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : {\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : {\n" - " \"name_5\" : \"value_5\",\n" - " \"name_6\" : \"value_6\"\n" - " },\n" - " \"name_7\" : \"value_7\"\n" - " },\n" - " \"name_8\" : \"value_8\",\n" - " \"name_9\" : {\n" - " \"name_10\" : \"value_10\"\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : {\n" - " \"name 2\" : {\n" - " \"name 3\" : {\n" - " \"name_4\" : {\n" - " \"name_5\" : \"value\"\n" - " }\n" - " }\n" - " }\n" - " }\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : true,\n" - " \"name 3\" : false,\n" - " \"name_4\" : \"value_4\",\n" - " \"name_5\" : true\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : null,\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : null\n" - "}" ); - - check_reading( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : 123,\n" - " \"name 3\" : \"value 3\",\n" - " \"name_4\" : -567\n" - "}" ); - - check_reading( "[\n]" ); - - check_reading( "[\n" - " 1\n" - "]" ); - - check_reading( "[\n" - " 1,\n" - " 1.2,\n" - " \"john]\",\n" - " true,\n" - " false,\n" - " null\n" - "]" ); - - check_reading( "[\n" - " 1,\n" - " [\n" - " 2,\n" - " 3\n" - " ]\n" - "]" ); - - check_reading( "[\n" - " 1,\n" - " [\n" - " 2,\n" - " 3\n" - " ],\n" - " [\n" - " 4,\n" - " [\n" - " 5,\n" - " 6,\n" - " 7\n" - " ]\n" - " ]\n" - "]" ); - - check_reading( "[\n" - " {\n" - " \"name\" : \"value\"\n" - " }\n" - "]" ); - - check_reading( "{\n" - " \"name\" : [\n" - " 1\n" - " ]\n" - "}" ); - - check_reading( "[\n" - " {\n" - " \"name 1\" : \"value\",\n" - " \"name 2\" : [\n" - " 1,\n" - " 2,\n" - " 3\n" - " ]\n" - " }\n" - "]" ); - - check_reading( "{\n" - " \"name 1\" : [\n" - " 1,\n" - " {\n" - " \"name 2\" : \"value 2\"\n" - " }\n" - " ]\n" - "}" ); - - check_reading( "[\n" - " {\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : [\n" - " 1,\n" - " 2,\n" - " {\n" - " \"name 3\" : \"value 3\"\n" - " }\n" - " ]\n" - " }\n" - "]" ); - - check_reading( "{\n" - " \"name 1\" : [\n" - " 1,\n" - " {\n" - " \"name 2\" : [\n" - " 1,\n" - " 2,\n" - " 3\n" - " ]\n" - " }\n" - " ]\n" - "}" ); - - check_reading( INT_MIN, INT_MAX ); - check_reading( LLONG_MIN, LLONG_MAX ); - } + assert_eq(ok, true); + assert_eq(value.type(), array_type); - void test_reading_reals() - { - Value_type value; + const Array_type arr = value.get_array(); + + assert_eq(arr.size(), 6u); + assert_eq(arr[0].get_real(), 1.2, 1e-16); + assert_eq(arr[1].get_real(), 1.234567890123456e+125, 1e+110); + assert_eq(arr[2].get_real(), -1.234e-123, 1e+108); + assert_eq(arr[3].get_real(), 1e-123, 1e+108); + assert_eq(arr[4].get_real(), 1234567890.123456, 1e-7); + assert_eq(arr[5].get_real(), 123, 1e-13); + } - const String_type in_s = to_str( "[1.200000000000000,1.234567890123456e+125,-1.234000000000000e-123," - " 1.000000000000000e-123,1234567890.123456,123,]" ); + void test_from_stream(const char* json_str, bool expected_success, + const Error_position& expected_error) { + Value_type value; - basic_istringstream< Char_type > is( in_s ); + String_type in_s(to_str(json_str)); - const bool ok = read( is, value ); + basic_istringstream is(in_s); - assert_eq( ok, true ); - assert_eq( value.type(), array_type ); + const bool ok = read(is, value); - const Array_type arr = value.get_array(); + assert_eq(ok, expected_success); - assert_eq( arr.size(), 6u ); - assert_eq( arr[0].get_real(), 1.2, 1e-16 ); - assert_eq( arr[1].get_real(), 1.234567890123456e+125, 1e+110 ); - assert_eq( arr[2].get_real(), -1.234e-123, 1e+108 ); - assert_eq( arr[3].get_real(), 1e-123, 1e+108 ); - assert_eq( arr[4].get_real(), 1234567890.123456, 1e-7 ); - assert_eq( arr[5].get_real(), 123, 1e-13 ); + if (ok) { + assert_eq(in_s, write(value)); } - void test_from_stream( const char* json_str, bool expected_success, - const Error_position& expected_error ) - { - Value_type value; + try { + basic_istringstream is(in_s); - String_type in_s( to_str( json_str ) ); + read_or_throw(is, value); - basic_istringstream< Char_type > is( in_s ); + assert_eq(expected_success, true); - const bool ok = read( is, value ); + assert_eq(in_s, write(value)); + } catch (const Error_position error) { + assert_eq(error, expected_error); + } + } - assert_eq( ok, expected_success ); + void test_from_stream() { + test_from_stream("[1,2]", true, Error_position()); + test_from_stream("\n\n foo", false, Error_position(3, 2, "not a value")); + } - if( ok ) - { - assert_eq( in_s, write( value ) ); - } + void test_escape_chars(const char* json_str, const char* c_str) { + Value_type value; - try - { - basic_istringstream< Char_type > is( in_s ); + string s(string("{\"") + json_str + "\" : \"" + json_str + "\"} "); - read_or_throw( is, value ); + read_cstr(s.c_str(), value); - assert_eq( expected_success, true ); + const Pair_type& pair(*value.get_obj().begin()); - assert_eq( in_s, write( value ) ); - } - catch( const Error_position error ) - { - assert_eq( error, expected_error ); - } - } + assert_eq(Config_type::get_name(pair), to_str(c_str)); + assert_eq(Config_type::get_value(pair), to_str(c_str)); + } - void test_from_stream() - { - test_from_stream( "[1,2]", true, Error_position() ); - test_from_stream( "\n\n foo", false, Error_position( 3, 2,"not a value" ) ); - } + void test_escape_chars() { + test_escape_chars("\\t", "\t"); + test_escape_chars("a\\t", "a\t"); + test_escape_chars("\\tb", "\tb"); + test_escape_chars("a\\tb", "a\tb"); + test_escape_chars("a\\tb", "a\tb"); + test_escape_chars("a123\\tb", "a123\tb"); + test_escape_chars("\\t\\n\\\\", "\t\n\\"); + test_escape_chars("\\/\\r\\b\\f\\\"", "/\r\b\f\""); + test_escape_chars("\\h\\j\\k", ""); // invalid esc chars + test_escape_chars("\\x61\\x62\\x63", "abc"); + test_escape_chars("a\\x62c", "abc"); + test_escape_chars( + "\\x01\\x02\\x7F", + "\x01\x02\x7F"); // NB x7F is the greatest char spirit will parse + test_escape_chars("\\u0061\\u0062\\u0063", "abc"); + } - void test_escape_chars( const char* json_str, const char* c_str ) - { - Value_type value; + void check_is_null(const char* c_str) { + assert_eq(read_cstr(c_str).type(), null_type); + } - string s( string( "{\"" ) + json_str + "\" : \"" + json_str + "\"} " ); + template + void check_value(const char* c_str, const T& expected_value) { + const Value_type v(read_cstr(c_str)); - read_cstr( s.c_str(), value ); + assert_eq(v.template get_value(), expected_value); + } - const Pair_type& pair( *value.get_obj().begin() ); + void test_values() { + check_value("1", 1); + check_value("+Infinity", std::numeric_limits::infinity()); + check_value("Infinity", std::numeric_limits::infinity()); + check_value("-Infinity", -std::numeric_limits::infinity()); + check_value("0xfe", 0xfe); + check_value("1.5", 1.5); + check_value("\"Test\"", to_str("Test")); + check_value("true", true); + check_value("false", false); + check_is_null("null"); + } - assert_eq( Config_type::get_name ( pair ), to_str( c_str ) ); - assert_eq( Config_type::get_value( pair ), to_str( c_str ) ); - } + void check_read_fails(const char* c_str, int line, int column, + const string& reason) { + Value_type value; - void test_escape_chars() - { - test_escape_chars( "\\t", "\t"); - test_escape_chars( "a\\t", "a\t" ); - test_escape_chars( "\\tb", "\tb" ); - test_escape_chars( "a\\tb", "a\tb" ); - test_escape_chars( "a\\tb", "a\tb" ); - test_escape_chars( "a123\\tb", "a123\tb" ); - test_escape_chars( "\\t\\n\\\\", "\t\n\\" ); - test_escape_chars( "\\/\\r\\b\\f\\\"", "/\r\b\f\"" ); - test_escape_chars( "\\h\\j\\k", "" ); // invalid esc chars - test_escape_chars( "\\x61\\x62\\x63", "abc" ); - test_escape_chars( "a\\x62c", "abc" ); - test_escape_chars( "\\x01\\x02\\x7F", "\x01\x02\x7F" ); // NB x7F is the greatest char spirit will parse - test_escape_chars( "\\u0061\\u0062\\u0063", "abc" ); - } + try { + read_cstr(c_str, value); - void check_is_null( const char* c_str ) - { - assert_eq( read_cstr( c_str ).type(), null_type ); + assert(false); + } catch (const Error_position posn) { + assert_eq(posn, Error_position(line, column, reason)); } + } - template< typename T > - void check_value( const char* c_str, const T& expected_value ) - { - const Value_type v( read_cstr( c_str ) ); - - assert_eq( v.template get_value< T >(), expected_value ); - } + void test_error_cases() { + check_read_fails("", 1, 1, "not a value"); + check_read_fails("foo", 1, 1, "not a value"); + check_read_fails(" foo", 1, 2, "not a value"); + check_read_fails(" foo", 1, 3, "not a value"); + check_read_fails("\n\n foo", 3, 2, "not a value"); + check_read_fails("!!!", 1, 1, "not a value"); + check_read_fails("\"bar", 1, 1, "not a value"); + check_read_fails("0xreefer", 1, 3, "not a hexadecimal number"); + check_read_fails("bar\"", 1, 1, "not a value"); + check_read_fails("[1}", 1, 3, "not an array"); + check_read_fails("[1,2?", 1, 5, "not an array"); + check_read_fails("[1,2}", 1, 5, "not an array"); + check_read_fails("[1;2]", 1, 3, "not an array"); + check_read_fails("{\"name\":\"value\"]", 1, 16, "not an object"); + check_read_fails("{\"name\",\"value\"}", 1, 8, "no colon in pair"); + check_read_fails("{\n1:\"value\"}", 2, 1, "not an object"); + check_read_fails("{\n name\":\"value\"}", 2, 7, "no colon in pair"); + check_read_fails("{\"name\":foo}", 1, 9, "not a value"); + check_read_fails("{\"name\":0xfreedom}", 1, 12, "not an object"); + check_read_fails("{\"name\":value\"}", 1, 9, "not a value"); + check_read_fails("{'name':\"value\"}", 1, 2, "not an object"); + } - void test_values() - { - check_value( "1", 1 ); - check_value( "+Infinity", std::numeric_limits::infinity() ); - check_value( "Infinity", std::numeric_limits::infinity() ); - check_value( "-Infinity", -std::numeric_limits::infinity() ); - check_value( "0xfe", 0xfe ); - check_value( "1.5", 1.5 ); - check_value( "\"Test\"", to_str( "Test" ) ); - check_value( "true", true ); - check_value( "false", false ); - check_is_null( "null" ); - } + typedef vector Ints; - void check_read_fails( const char* c_str, int line, int column, const string& reason ) - { - Value_type value; + bool test_read_range(Iter_type& first, Iter_type last, Value_type& value) { + Iter_type first_ = first; - try - { - read_cstr( c_str, value ); + const bool ok = read(first, last, value); - assert( false ); - } - catch( const Error_position posn ) - { - assert_eq( posn, Error_position( line, column, reason ) ); - } - } + try { + Value_type value_; - void test_error_cases() - { - check_read_fails( "", 1, 1, "not a value" ); - check_read_fails( "foo", 1, 1, "not a value" ); - check_read_fails( " foo", 1, 2, "not a value" ); - check_read_fails( " foo", 1, 3, "not a value" ); - check_read_fails( "\n\n foo", 3, 2, "not a value" ); - check_read_fails( "!!!", 1, 1, "not a value" ); - check_read_fails( "\"bar", 1, 1, "not a value" ); - check_read_fails( "0xreefer", 1, 3, "not a hexadecimal number" ); - check_read_fails( "bar\"", 1, 1, "not a value" ); - check_read_fails( "[1}", 1, 3, "not an array" ); - check_read_fails( "[1,2?", 1, 5, "not an array" ); - check_read_fails( "[1,2}", 1, 5, "not an array" ); - check_read_fails( "[1;2]", 1, 3, "not an array" ); - check_read_fails( "{\"name\":\"value\"]", 1, 16, "not an object" ); - check_read_fails( "{\"name\",\"value\"}", 1, 8, "no colon in pair" ); - check_read_fails( "{\n1:\"value\"}", 2, 1, "not an object" ); - check_read_fails( "{\n name\":\"value\"}", 2, 7, "no colon in pair" ); - check_read_fails( "{\"name\":foo}", 1, 9, "not a value" ); - check_read_fails( "{\"name\":0xfreedom}", 1, 12, "not an object" ); - check_read_fails( "{\"name\":value\"}", 1, 9, "not a value" ); - check_read_fails( "{'name':\"value\"}", 1, 2, "not an object" ); - } + read_or_throw(first_, last, value_); - typedef vector< int > Ints; + assert_eq(ok, true); + assert_eq(value, value_); + } catch (...) { + assert_eq(ok, false); + } - bool test_read_range( Iter_type& first, Iter_type last, Value_type& value ) - { - Iter_type first_ = first; + return ok; + } - const bool ok = read( first, last, value ); + void check_value_sequence(Iter_type first, Iter_type last, + const Ints& expected_values, bool all_input_consumed) { + Value_type value; - try - { - Value_type value_; + for (Ints::size_type i = 0; i < expected_values.size(); ++i) { + const bool ok = test_read_range(first, last, value); - read_or_throw( first_, last, value_ ); + assert_eq(ok, true); - assert_eq( ok, true ); - assert_eq( value, value_ ); - } - catch( ... ) - { - assert_eq( ok, false ); - } + const bool is_last(i == expected_values.size() - 1); - return ok; + assert_eq(first == last, is_last ? all_input_consumed : false); } - void check_value_sequence( Iter_type first, Iter_type last, const Ints& expected_values, bool all_input_consumed ) - { - Value_type value; - - for( Ints::size_type i = 0; i < expected_values.size(); ++i ) - { - const bool ok = test_read_range( first, last, value ); + const bool ok = test_read_range(first, last, value); + + assert_eq(ok, false); + } - assert_eq( ok, true ); + void check_value_sequence(Istream_type& is, const Ints& expected_values, + bool all_input_consumed) { + Value_type value; - const bool is_last( i == expected_values.size() - 1 ); + for (Ints::size_type i = 0; i < expected_values.size(); ++i) { + read_or_throw(is, value); - assert_eq( first == last, is_last ? all_input_consumed : false ); - } - - const bool ok = test_read_range( first, last, value ); + assert_eq(value.get_int(), expected_values[i]); - assert_eq( ok, false ); - } + const bool is_last(i == expected_values.size() - 1); - void check_value_sequence( Istream_type& is, const Ints& expected_values, bool all_input_consumed ) - { - Value_type value; - - for( Ints::size_type i = 0; i < expected_values.size(); ++i ) - { - read_or_throw( is, value ); - - assert_eq( value.get_int(), expected_values[i] ); - - const bool is_last( i == expected_values.size() - 1 ); - - assert_eq( is.eof(), is_last ? all_input_consumed : false ); - } - - try - { - read_or_throw( is, value ); - - assert( false ); - } - catch( ... ) - { - } - - assert_eq( is.eof(), true ); + assert_eq(is.eof(), is_last ? all_input_consumed : false); } - void check_value_sequence( const char* c_str, const Ints& expected_values, bool all_input_consumed ) - { - const String_type s( to_str( c_str ) ); + try { + read_or_throw(is, value); - check_value_sequence( s.begin(), s.end(), expected_values, all_input_consumed ); + assert(false); + } catch (...) { + } - Istringstream_type is( s ); + assert_eq(is.eof(), true); + } - check_value_sequence( is, expected_values, all_input_consumed ); - } + void check_value_sequence(const char* c_str, const Ints& expected_values, + bool all_input_consumed) { + const String_type s(to_str(c_str)); - void check_array( const Value_type& value, typename Array_type::size_type expected_size ) - { - assert_eq( value.type(), array_type ); + check_value_sequence(s.begin(), s.end(), expected_values, all_input_consumed); - const Array_type& arr = value.get_array(); + Istringstream_type is(s); - assert_eq( arr.size(), expected_size ); + check_value_sequence(is, expected_values, all_input_consumed); + } - for( typename Array_type::size_type i = 0; i < expected_size; ++i ) - { - const Value_type& val = arr[i]; + void check_array(const Value_type& value, + typename Array_type::size_type expected_size) { + assert_eq(value.type(), array_type); - assert_eq( val.type(), int_type ); - assert_eq( val.get_int(), int( i + 1 ) ); - } - } + const Array_type& arr = value.get_array(); - void check_reading_array( Iter_type& begin, Iter_type end, typename Array_type::size_type expected_size ) - { - Value_type value; + assert_eq(arr.size(), expected_size); - test_read_range( begin, end, value ); + for (typename Array_type::size_type i = 0; i < expected_size; ++i) { + const Value_type& val = arr[i]; - check_array( value, expected_size ); + assert_eq(val.type(), int_type); + assert_eq(val.get_int(), int(i + 1)); } + } - void check_reading_array( Istream_type& is, typename Array_type::size_type expected_size ) - { - Value_type value; + void check_reading_array(Iter_type& begin, Iter_type end, + typename Array_type::size_type expected_size) { + Value_type value; - read( is, value ); + test_read_range(begin, end, value); - check_array( value, expected_size ); - } + check_array(value, expected_size); + } - void check_reading_arrays( const char* arrays_str ) - { - const String_type str( to_str( arrays_str ) ); + void check_reading_array(Istream_type& is, + typename Array_type::size_type expected_size) { + Value_type value; - Iter_type begin = str.begin(); - const Iter_type end = str.end(); + read(is, value); - check_reading_array( begin, end, 0 ); - check_reading_array( begin, end, 1 ); - check_reading_array( begin, end, 2 ); - check_reading_array( begin, end, 3 ); + check_array(value, expected_size); + } - Istringstream_type is( str ); + void check_reading_arrays(const char* arrays_str) { + const String_type str(to_str(arrays_str)); - check_reading_array( is, 0 ); - check_reading_array( is, 1 ); - check_reading_array( is, 2 ); - check_reading_array( is, 3 ); - } + Iter_type begin = str.begin(); + const Iter_type end = str.end(); - void test_sequence_of_values() - { - check_value_sequence( "", Ints(), false ); - check_value_sequence( " ", Ints(), false ); - check_value_sequence( " ", Ints(), false ); - check_value_sequence( " 10 ", list_of( 10 ), false ); - check_value_sequence( " 10 11 ", list_of( 10 )( 11 ), false ); - check_value_sequence( " 10 11 12", list_of( 10 )( 11 )( 12 ), true); - check_value_sequence( "10 11 12", list_of( 10 )( 11 )( 12 ), true); - - // - - check_reading_arrays( "[] [ 1 ] [ 1, 2 ] [ 1, 2, 3 ]" ); - // check_reading_arrays( "[][1][1,2][1,2,3]" ); // fails due to multi_pass iterator bug, - // use stream_reader class instead - } + check_reading_array(begin, end, 0); + check_reading_array(begin, end, 1); + check_reading_array(begin, end, 2); + check_reading_array(begin, end, 3); - void test_uint64( const char* value_str, int expected_int, int64_t expected_int64, uint64_t expected_uint64 ) - { - const Value_type v( read_cstr( value_str ) ); - - assert_eq( v.get_int(), expected_int ); - assert_eq( v.get_int64(), expected_int64 ); - assert_eq( v.get_uint64(), expected_uint64 ); - } - - void test_uint64() - { - test_uint64( "0", 0, 0, 0 ); - test_uint64( "1", 1, 1, 1 ); - test_uint64( "-1", -1, -1, ULLONG_MAX ); - test_uint64( "18446744073709551615", -1, -1, ULLONG_MAX ); - } + Istringstream_type is(str); - void test_types() - { - Value_type value; + check_reading_array(is, 0); + check_reading_array(is, 1); + check_reading_array(is, 2); + check_reading_array(is, 3); + } - read( to_str( "[ \"foo\", true, false, 1, 12.3, null ]" ), value ); + void test_sequence_of_values() { + check_value_sequence("", Ints(), false); + check_value_sequence(" ", Ints(), false); + check_value_sequence(" ", Ints(), false); + check_value_sequence(" 10 ", list_of(10), false); + check_value_sequence(" 10 11 ", list_of(10)(11), false); + check_value_sequence(" 10 11 12", list_of(10)(11)(12), true); + check_value_sequence("10 11 12", list_of(10)(11)(12), true); + + // + + check_reading_arrays("[] [ 1 ] [ 1, 2 ] [ 1, 2, 3 ]"); + // check_reading_arrays( "[][1][1,2][1,2,3]" ); // fails due to + // multi_pass iterator bug, + // use stream_reader class instead + } - assert_eq( value.type(), array_type ); + void test_uint64(const char* value_str, int expected_int, int64_t expected_int64, + uint64_t expected_uint64) { + const Value_type v(read_cstr(value_str)); - const Array_type& a = value.get_array(); + assert_eq(v.get_int(), expected_int); + assert_eq(v.get_int64(), expected_int64); + assert_eq(v.get_uint64(), expected_uint64); + } - assert_eq( a[0].get_str(), to_str( "foo" ) ); - assert_eq( a[1].get_bool(), true ); - assert_eq( a[2].get_bool(), false ); - assert_eq( a[3].get_int(), 1 ); - assert_eq( a[3].get_int64(), 1 ); - assert_eq( a[3].get_uint64(), 1u ); - assert_eq( a[3].get_real(), 1.0 ); - assert_eq( a[4].get_real(), 12.3 ); - assert_eq( a[5].is_null(), true ); - } - - void test_comments() - { - Value_type value_1; - - read_cstr( "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : \"value 2 /* not a comment but data */\",\n" - " \"name 3\" : \"value 3 // not a comment but data\"\n" - "}", value_1 ); - - Value_type value_2; - - read_cstr( "{// a comment\n " - " \"name 1\" : /* another comment */ \"value 1\",\n" - " \"name 2\" : \"value 2 /* not a comment but data */\",\n" - " // \"name 2\" : \"value 2\",\n" - " \"name 3\" : \"value 3 // not a comment but data\"\n" - "/* multi\n" - "line\n" - "comment */}", value_2 ); - - assert_eq( value_1, value_2 ); - } - - void run_tests() - { - test_syntax(); - test_reading(); - test_reading_reals(); - test_from_stream(); - test_escape_chars(); - test_values(); - test_error_cases(); - test_sequence_of_values(); - test_uint64(); - test_types(); - test_comments(); - } - }; + void test_uint64() { + test_uint64("0", 0, 0, 0); + test_uint64("1", 1, 1, 1); + test_uint64("-1", -1, -1, ULLONG_MAX); + test_uint64("18446744073709551615", -1, -1, ULLONG_MAX); + } + + void test_types() { + Value_type value; -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void test_wide_esc_u() - { - wValue value; + read(to_str("[ \"foo\", true, false, 1, 12.3, null ]"), value); - test_read( L"[\"\\uABCD\"]", value ); + assert_eq(value.type(), array_type); - const wstring s( value.get_array()[0].get_str() ); + const Array_type& a = value.get_array(); - assert_eq( s.length(), static_cast< wstring::size_type >( 1u ) ); - assert_eq( s[0], 0xABCD ); + assert_eq(a[0].get_str(), to_str("foo")); + assert_eq(a[1].get_bool(), true); + assert_eq(a[2].get_bool(), false); + assert_eq(a[3].get_int(), 1); + assert_eq(a[3].get_int64(), 1); + assert_eq(a[3].get_uint64(), 1u); + assert_eq(a[3].get_real(), 1.0); + assert_eq(a[4].get_real(), 12.3); + assert_eq(a[5].is_null(), true); } -#endif -#ifdef JSON_SPIRIT_VALUE_ENABLED - void test_extended_ascii( const string& s ) - { - Value value; + void test_comments() { + Value_type value_1; - test_read( "[\"" + s + "\"]", value ); + read_cstr( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : \"value 2 /* not a comment but data */\",\n" + " \"name 3\" : \"value 3 // not a comment but data\"\n" + "}", + value_1); - assert_eq( value.get_array()[0].get_str(), "äöüß" ); + Value_type value_2; + + read_cstr( + "{// a comment\n " + " \"name 1\" : /* another comment */ \"value 1\",\n" + " \"name 2\" : \"value 2 /* not a comment but data */\",\n" + " // \"name 2\" : \"value 2\",\n" + " \"name 3\" : \"value 3 // not a comment but data\"\n" + "/* multi\n" + "line\n" + "comment */}", + value_2); + + assert_eq(value_1, value_2); } - void test_extended_ascii() - { - test_extended_ascii( "\\u00E4\\u00F6\\u00FC\\u00DF" ); - test_extended_ascii( "äöüß" ); + void run_tests() { + test_syntax(); + test_reading(); + test_reading_reals(); + test_from_stream(); + test_escape_chars(); + test_values(); + test_error_cases(); + test_sequence_of_values(); + test_uint64(); + test_types(); + test_comments(); } +}; + +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +void test_wide_esc_u() { + wValue value; + + test_read(L"[\"\\uABCD\"]", value); + + const wstring s(value.get_array()[0].get_str()); + + assert_eq(s.length(), static_cast(1u)); + assert_eq(s[0], 0xABCD); +} #endif + +#ifdef JSON_SPIRIT_VALUE_ENABLED +void test_extended_ascii(const string& s) { + Value value; + + test_read("[\"" + s + "\"]", value); + + assert_eq(value.get_array()[0].get_str(), "äöüß"); +} + +void test_extended_ascii() { + test_extended_ascii("\\u00E4\\u00F6\\u00FC\\u00DF"); + test_extended_ascii("äöüß"); } +#endif +} // namespace //#include -void json5_parser::test_reader() -{ +void json5_parser::test_reader() { #ifdef JSON_SPIRIT_VALUE_ENABLED - Test_runner< Config >().run_tests(); + Test_runner().run_tests(); test_extended_ascii(); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - Test_runner< mConfig >().run_tests(); + Test_runner().run_tests(); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wConfig >().run_tests(); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Test_runner().run_tests(); test_wide_esc_u(); #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wmConfig >().run_tests(); +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Test_runner().run_tests(); #endif #ifndef _DEBUG - //ifstream ifs( "test.txt" ); + // ifstream ifs( "test.txt" ); - //string s; + // string s; - //getline( ifs, s ); + // getline( ifs, s ); - //timer t; + // timer t; - //for( int i = 0; i < 2000; ++i ) + // for( int i = 0; i < 2000; ++i ) //{ // Value value; // read( s, value ); //} - //cout << t.elapsed() << endl; + // cout << t.elapsed() << endl; // const string so = write( value ); - //Object obj; + // Object obj; - //for( int i = 0; i < 100000; ++i ) + // for( int i = 0; i < 100000; ++i ) //{ // obj.push_back( Pair( "\x01test\x7F", lexical_cast< string >( i ) ) ); //} - //const string s = write( obj ); + // const string s = write( obj ); - //Value value; + // Value value; - //timer t; + // timer t; - //read( s, value ); + // read( s, value ); - //cout << t.elapsed() << endl; + // cout << t.elapsed() << endl; - //cout << "obj size " << value.get_obj().size(); + // cout << "obj size " << value.get_obj().size(); #endif } diff --git a/json_test/json5_parser_reader_test.h b/json_test/json5_parser_reader_test.h index 05fe818..2896798 100644 --- a/json_test/json5_parser_reader_test.h +++ b/json_test/json5_parser_reader_test.h @@ -7,12 +7,11 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -namespace json5_parser -{ - void test_reader(); +namespace json5_parser { +void test_reader(); } #endif diff --git a/json_test/json5_parser_stream_reader_test.cpp b/json_test/json5_parser_stream_reader_test.cpp index 399591b..9638980 100644 --- a/json_test/json5_parser_stream_reader_test.cpp +++ b/json_test/json5_parser_stream_reader_test.cpp @@ -4,134 +4,117 @@ // json spirit version 4.08 #include "json5_parser_stream_reader_test.h" -#include "utils_test.h" #include "json5_parser_stream_reader.h" +#include "utils_test.h" -#include #include +#include using namespace json5_parser; using namespace std; using namespace boost; using namespace boost::assign; -namespace -{ - template< class Config_type > - struct Test_runner - { - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; - typedef typename Config_type::Pair_type Pair_type; - typedef typename String_type::value_type Char_type; - typedef typename String_type::const_iterator Iter_type; - typedef std::basic_istringstream< Char_type > Istringstream_type; - typedef std::basic_istream< Char_type > Istream_type; - - String_type to_str( const char* c_str ) - { - return ::to_str< String_type >( c_str ); +namespace { +template +struct Test_runner { + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + typedef typename Config_type::Pair_type Pair_type; + typedef typename String_type::value_type Char_type; + typedef typename String_type::const_iterator Iter_type; + typedef std::basic_istringstream Istringstream_type; + typedef std::basic_istream Istream_type; + + String_type to_str(const char* c_str) { return ::to_str(c_str); } + + Test_runner() {} + + void check_stream_reader(Stream_reader& reader, + const vector& expected_result) { + Value_type v; + const bool ok = reader.read_next(v); + assert_eq(ok, true); + assert_eq(v.type(), array_type); + assert_eq(v.get_array().size(), expected_result.size()); + for (vector::size_type i = 0; i < v.get_array().size(); ++i) { + assert_eq(v.get_array()[i], expected_result[i]); } - - Test_runner() - { - } - - void check_stream_reader( Stream_reader< Istream_type, Value_type >& reader, const vector< int >& expected_result ) - { - Value_type v; - const bool ok = reader.read_next( v ); - assert_eq( ok, true ); - assert_eq( v.type(), array_type ); - assert_eq( v.get_array().size(), expected_result.size() ); - for( vector< int >::size_type i = 0; i < v.get_array().size(); ++i ) - { - assert_eq( v.get_array()[i], expected_result[i] ); + } + + void check_stream_read_or_throw( + Stream_reader_thrower& reader, + const vector& expected_result) { + Value_type v; + + try { + reader.read_next(v); + assert_eq(v.type(), array_type); + assert_eq(v.get_array().size(), expected_result.size()); + for (vector::size_type i = 0; i < v.get_array().size(); ++i) { + assert_eq(v.get_array()[i], expected_result[i]); } + } catch (...) { + assert(false); } + } - void check_stream_read_or_throw( Stream_reader_thrower< Istream_type, Value_type >& reader, const vector< int >& expected_result ) + void test_stream_reader(const char* s) { { - Value_type v; + Istringstream_type is(to_str(s)); - try - { - reader.read_next( v ); - assert_eq( v.type(), array_type ); - assert_eq( v.get_array().size(), expected_result.size() ); - for( vector< int >::size_type i = 0; i < v.get_array().size(); ++i ) - { - assert_eq( v.get_array()[i], expected_result[i] ); - } - } - catch( ... ) - { - assert( false ); - } - } + Stream_reader reader(is); + + check_stream_reader(reader, vector()); + check_stream_reader(reader, list_of(1)); + check_stream_reader(reader, list_of(1)(2)); + check_stream_reader(reader, list_of(1)(2)(3)); - void test_stream_reader( const char* s ) + Value_type v; + const bool ok = reader.read_next(v); + assert_eq(ok, false); + } { - { - Istringstream_type is( to_str( s ) ); + Istringstream_type is(to_str(s)); - Stream_reader< Istream_type, Value_type > reader( is ); + Stream_reader_thrower reader(is); - check_stream_reader( reader, vector< int >() ); - check_stream_reader( reader, list_of( 1 ) ); - check_stream_reader( reader, list_of( 1 )( 2 ) ); - check_stream_reader( reader, list_of( 1 )( 2 )( 3 ) ); + check_stream_read_or_throw(reader, vector()); + check_stream_read_or_throw(reader, list_of(1)); + check_stream_read_or_throw(reader, list_of(1)(2)); + check_stream_read_or_throw(reader, list_of(1)(2)(3)); + try { Value_type v; - const bool ok = reader.read_next( v ); - assert_eq( ok, false ); - } - { - Istringstream_type is( to_str( s ) ); - - Stream_reader_thrower< Istream_type, Value_type > reader( is ); - - check_stream_read_or_throw( reader, vector< int >() ); - check_stream_read_or_throw( reader, list_of( 1 ) ); - check_stream_read_or_throw( reader, list_of( 1 )( 2 ) ); - check_stream_read_or_throw( reader, list_of( 1 )( 2 )( 3 ) ); - - try - { - Value_type v; - reader.read_next( v ); - assert( false ); - } - catch( ... ) - { - } + reader.read_next(v); + assert(false); + } catch (...) { } } + } - void run_tests() - { - test_stream_reader( "[][1][1,2][1,2,3]" ); - test_stream_reader( "[] [1] [1,2] [1,2,3]" ); - test_stream_reader( " [] [1] [1,2] [1,2,3] " ); - } - }; -} + void run_tests() { + test_stream_reader("[][1][1,2][1,2,3]"); + test_stream_reader("[] [1] [1,2] [1,2,3]"); + test_stream_reader(" [] [1] [1,2] [1,2,3] "); + } +}; +} // namespace -void json5_parser::test_stream_reader() -{ +void json5_parser::test_stream_reader() { #ifdef JSON_SPIRIT_VALUE_ENABLED - Test_runner< Config >().run_tests(); + Test_runner().run_tests(); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - Test_runner< mConfig >().run_tests(); + Test_runner().run_tests(); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wConfig >().run_tests(); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Test_runner().run_tests(); #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wmConfig >().run_tests(); +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Test_runner().run_tests(); #endif } diff --git a/json_test/json5_parser_stream_reader_test.h b/json_test/json5_parser_stream_reader_test.h index 05ccfe6..495db4c 100644 --- a/json_test/json5_parser_stream_reader_test.h +++ b/json_test/json5_parser_stream_reader_test.h @@ -7,12 +7,11 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -namespace json5_parser -{ - void test_stream_reader(); +namespace json5_parser { +void test_stream_reader(); } #endif diff --git a/json_test/json5_parser_utils_test.cpp b/json_test/json5_parser_utils_test.cpp index 4c68711..bf62b4b 100644 --- a/json_test/json5_parser_utils_test.cpp +++ b/json_test/json5_parser_utils_test.cpp @@ -4,8 +4,8 @@ // json spirit version 4.08 #include "json5_parser_utils_test.h" -#include "utils_test.h" #include "json5_parser_utils.h" +#include "utils_test.h" #include @@ -13,131 +13,119 @@ using namespace json5_parser; using namespace std; using namespace boost::assign; -namespace -{ - template< class Obj_t, class Map_t > - struct Test_runner - { - typedef typename Map_t::key_type String_type; - typedef typename Obj_t::value_type Pair_type; - typedef typename Pair_type::Value_type Value_type; - - String_type to_str( const char* c_str ) - { - return ::to_str< String_type >( c_str ); - } - - void assert_equal( const Obj_t& obj, const Map_t& mp_obj ) - { - typename Obj_t::size_type obj_size = obj.size(); - typename Map_t::size_type map_size = mp_obj.size(); - - assert_eq( obj_size, map_size ); - - for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i ) - { - assert_eq( mp_obj.find( i->name_ )->second, i->value_ ); - } - } +namespace { +template +struct Test_runner { + typedef typename Map_t::key_type String_type; + typedef typename Obj_t::value_type Pair_type; + typedef typename Pair_type::Value_type Value_type; + + String_type to_str(const char* c_str) { return ::to_str(c_str); } - void check_obj_to_map( const Obj_t& obj ) - { - Map_t mp_obj; + void assert_equal(const Obj_t& obj, const Map_t& mp_obj) { + typename Obj_t::size_type obj_size = obj.size(); + typename Map_t::size_type map_size = mp_obj.size(); - obj_to_map( obj, mp_obj ); + assert_eq(obj_size, map_size); - assert_equal( obj, mp_obj ); + for (typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i) { + assert_eq(mp_obj.find(i->name_)->second, i->value_); } + } - void check_map_cleared() - { - Map_t mp_obj; + void check_obj_to_map(const Obj_t& obj) { + Map_t mp_obj; - mp_obj[ to_str( "del" ) ] = to_str( "me" ); + obj_to_map(obj, mp_obj); - obj_to_map( Obj_t(), mp_obj ); + assert_equal(obj, mp_obj); + } - assert_eq( mp_obj.size(), 0u ); - } + void check_map_cleared() { + Map_t mp_obj; - void check_map_to_obj( const Map_t& mp_obj ) - { - Obj_t obj; + mp_obj[to_str("del")] = to_str("me"); - map_to_obj( mp_obj, obj ); + obj_to_map(Obj_t(), mp_obj); - assert_equal( obj, mp_obj ); - } + assert_eq(mp_obj.size(), 0u); + } - void check_obj_cleared() - { - Obj_t obj; + void check_map_to_obj(const Map_t& mp_obj) { + Obj_t obj; - obj.push_back( Pair_type( to_str( "del" ), to_str( "me" ) ) ); + map_to_obj(mp_obj, obj); - map_to_obj( Map_t(), obj ); + assert_equal(obj, mp_obj); + } - assert_eq( obj.size(), 0u ); - } + void check_obj_cleared() { + Obj_t obj; - void test_obj_to_map() - { - check_obj_to_map( Obj_t() ); - check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) ) ); - check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "b" ), 2 ) ) ); - check_obj_to_map( list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "b" ), 2 ) )( Pair_type( to_str( "c" ), 3 ) ) ); - check_map_cleared(); - - check_map_to_obj( Map_t() ); - check_map_to_obj( map_list_of( to_str( "a" ), 1 ) ); - check_map_to_obj( map_list_of( to_str( "a" ), 1 )( to_str( "b" ), 2 ) ); - check_map_to_obj( map_list_of( to_str( "a" ), 1 )( to_str( "b" ), 2 )( to_str( "c" ), 3 ) ); - check_obj_cleared(); - } + obj.push_back(Pair_type(to_str("del"), to_str("me"))); - void check_find( const Obj_t& obj, const char* name, const Value_type& expected_result ) - { - const Value_type& result = find_value( obj, to_str( name ) ); + map_to_obj(Map_t(), obj); - assert_eq( result, expected_result ); - } + assert_eq(obj.size(), 0u); + } - void test_find() - { - check_find( Obj_t(), "not there", Value_type::null ); + void test_obj_to_map() { + check_obj_to_map(Obj_t()); + check_obj_to_map(list_of(Pair_type(to_str("a"), 1))); + check_obj_to_map(list_of(Pair_type(to_str("a"), 1))(Pair_type(to_str("b"), 2))); + check_obj_to_map(list_of(Pair_type(to_str("a"), 1))(Pair_type(to_str("b"), 2))( + Pair_type(to_str("c"), 3))); + check_map_cleared(); - const Obj_t obj_1 = list_of( Pair_type( to_str( "a" ), 1 ) ); + check_map_to_obj(Map_t()); + check_map_to_obj(map_list_of(to_str("a"), 1)); + check_map_to_obj(map_list_of(to_str("a"), 1)(to_str("b"), 2)); + check_map_to_obj(map_list_of(to_str("a"), 1)(to_str("b"), 2)(to_str("c"), 3)); + check_obj_cleared(); + } - check_find( obj_1, "not there", Value_type::null ); - check_find( obj_1, "a", 1 ); + void check_find(const Obj_t& obj, const char* name, + const Value_type& expected_result) { + const Value_type& result = find_value(obj, to_str(name)); - const Obj_t obj_2 = list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "ab" ), 2 ) ); + assert_eq(result, expected_result); + } - check_find( obj_2, "a", 1 ); - check_find( obj_2, "ab", 2 ); + void test_find() { + check_find(Obj_t(), "not there", Value_type::null); - const Obj_t obj_3 = list_of( Pair_type( to_str( "a" ), 1 ) )( Pair_type( to_str( "ab" ), 2 ) )( Pair_type( to_str( "abc" ), 3 ) ); + const Obj_t obj_1 = list_of(Pair_type(to_str("a"), 1)); - check_find( obj_3, "a", 1 ); - check_find( obj_3, "ab", 2 ); - check_find( obj_3, "abc", 3 ); - } + check_find(obj_1, "not there", Value_type::null); + check_find(obj_1, "a", 1); - void run_tests() - { - test_obj_to_map(); - test_find(); - } - }; -} + const Obj_t obj_2 = + list_of(Pair_type(to_str("a"), 1))(Pair_type(to_str("ab"), 2)); + + check_find(obj_2, "a", 1); + check_find(obj_2, "ab", 2); + + const Obj_t obj_3 = list_of(Pair_type(to_str("a"), 1))( + Pair_type(to_str("ab"), 2))(Pair_type(to_str("abc"), 3)); + + check_find(obj_3, "a", 1); + check_find(obj_3, "ab", 2); + check_find(obj_3, "abc", 3); + } + + void run_tests() { + test_obj_to_map(); + test_find(); + } +}; +} // namespace -void json5_parser::test_utils() -{ +void json5_parser::test_utils() { #ifdef JSON_SPIRIT_VALUE_ENABLED - Test_runner< Object, Mapped_obj >().run_tests(); + Test_runner().run_tests(); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wObject, wMapped_obj >().run_tests(); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Test_runner().run_tests(); #endif } diff --git a/json_test/json5_parser_utils_test.h b/json_test/json5_parser_utils_test.h index 0be6067..fb07418 100644 --- a/json_test/json5_parser_utils_test.h +++ b/json_test/json5_parser_utils_test.h @@ -7,12 +7,11 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -namespace json5_parser -{ - void test_utils(); +namespace json5_parser { +void test_utils(); } #endif diff --git a/json_test/json5_parser_value_test.cpp b/json_test/json5_parser_value_test.cpp index 98dd4c1..554721b 100644 --- a/json_test/json5_parser_value_test.cpp +++ b/json_test/json5_parser_value_test.cpp @@ -4,512 +4,502 @@ // json spirit version 4.08 #include "json5_parser_value_test.h" -#include "utils_test.h" -#include "json5_parser_value.h" #include -#include #include #include +#include +#include "json5_parser_value.h" +#include "utils_test.h" using namespace json5_parser; using namespace std; using namespace boost; using namespace boost::assign; -namespace -{ +namespace { #ifdef JSON_SPIRIT_VALUE_ENABLED - const int64_t max_int64 = integer_traits< int64_t >::max(); - const uint64_t max_uint64 = integer_traits< uint64_t >::max(); +const int64_t max_int64 = integer_traits::max(); +const uint64_t max_uint64 = integer_traits::max(); - void test_obj_value() - { - const Pair p1( "name1", "value1" ); - const Pair p3( "name3", "value3" ); +void test_obj_value() { + const Pair p1("name1", "value1"); + const Pair p3("name3", "value3"); - Object obj_1; obj_1.push_back( p1 ); - Object obj_2; obj_2.push_back( p1 ); - Object obj_3; obj_3.push_back( p3 ); + Object obj_1; + obj_1.push_back(p1); + Object obj_2; + obj_2.push_back(p1); + Object obj_3; + obj_3.push_back(p3); - Value v1( obj_1 ); - Value v2( obj_2 ); - Value v3( obj_3 ); + Value v1(obj_1); + Value v2(obj_2); + Value v3(obj_3); - assert_eq( v1.type(), obj_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); + assert_eq(v1.type(), obj_type); + assert_eq(v1, v2); + assert_neq(v1, v3); - assert_eq( v1.get_obj(), obj_1 ); - assert_eq( v3.get_obj(), obj_3 ); - } + assert_eq(v1.get_obj(), obj_1); + assert_eq(v3.get_obj(), obj_3); +} - void test_array_value() - { - Array array_1; array_1.push_back( 1 ); array_1.push_back( "2" ); - Array array_2; array_2.push_back( 1 ); array_2.push_back( "2" ); - Array array_3; array_3.push_back( 1 ); array_3.push_back( "X" ); +void test_array_value() { + Array array_1; + array_1.push_back(1); + array_1.push_back("2"); + Array array_2; + array_2.push_back(1); + array_2.push_back("2"); + Array array_3; + array_3.push_back(1); + array_3.push_back("X"); + + Value v1(array_1); + Value v2(array_2); + Value v3(array_3); + + assert_eq(v1.type(), array_type); + assert_eq(v1, v2); + assert_neq(v1, v3); + + assert_eq(v1.get_array(), array_1); + assert_eq(v3.get_array(), array_3); +} - Value v1( array_1 ); - Value v2( array_2 ); - Value v3( array_3 ); +void test_bool_value() { + Value v1(true); + Value v2(true); + Value v3(false); - assert_eq( v1.type(), array_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); + assert_eq(v1.type(), bool_type); + assert_eq(v1, v2); + assert_neq(v1, v3); - assert_eq( v1.get_array(), array_1 ); - assert_eq( v3.get_array(), array_3 ); - } + assert(v1.get_bool()); + assert(!v3.get_bool()); +} - void test_bool_value() - { - Value v1( true ); - Value v2( true ); - Value v3( false ); +void test_int_value() { + Value v1(1); + Value v2(1); + Value v3(INT_MAX); - assert_eq( v1.type(), bool_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); + assert_eq(v1.type(), int_type); + assert_eq(v1, v2); + assert_neq(v1, v3); - assert( v1.get_bool() ); - assert( !v3.get_bool() ); - } + unsigned int uint_max = INT_MAX; - void test_int_value() - { - Value v1( 1 ); - Value v2( 1 ); - Value v3( INT_MAX ); + assert_eq(v1.get_int(), 1); + assert_eq(v1.get_int64(), 1); + assert_eq(v1.get_uint64(), 1u); + assert_eq(v3.get_int(), INT_MAX); + assert_eq(v3.get_int64(), INT_MAX); + assert_eq(v3.get_uint64(), uint_max); - assert_eq( v1.type(), int_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); + Value v4(max_int64); - unsigned int uint_max = INT_MAX; - - assert_eq( v1.get_int(), 1 ); - assert_eq( v1.get_int64(), 1 ); - assert_eq( v1.get_uint64(), 1u ); - assert_eq( v3.get_int(), INT_MAX ); - assert_eq( v3.get_int64(), INT_MAX ); - assert_eq( v3.get_uint64(), uint_max ); + assert_eq(v4.get_int64(), max_int64); + assert_eq(v4.get_uint64(), static_cast(max_int64)); - Value v4( max_int64 ); + const uint64_t max_int64_plus_1 = max_int64 + uint64_t(1); - assert_eq( v4.get_int64(), max_int64 ); - assert_eq( v4.get_uint64(), static_cast< uint64_t >( max_int64 ) ); + Value v5(max_int64_plus_1); - const uint64_t max_int64_plus_1 = max_int64 + uint64_t( 1 ); + assert_eq(v5.get_uint64(), max_int64_plus_1); - Value v5( max_int64_plus_1 ); + Value v6(max_uint64); - assert_eq( v5.get_uint64(), max_int64_plus_1 ); + assert_eq(v6.get_uint64(), max_uint64); - Value v6( max_uint64 ); + Value v7(0); - assert_eq( v6.get_uint64(), max_uint64 ); + assert_eq(v7.get_int(), 0); + assert_eq(v7.get_int64(), 0); + assert_eq(v7.get_uint64(), 0u); - Value v7( 0 ); + Value v8(-1); - assert_eq( v7.get_int(), 0 ); - assert_eq( v7.get_int64(), 0 ); - assert_eq( v7.get_uint64(), 0u ); + assert_eq(v8.get_int(), -1); + assert_eq(v8.get_int64(), -1); + assert_eq(v8.get_uint64(), max_uint64); +} - Value v8( -1 ); +void test_real_value() { + Value v1(1.0); + Value v2(1.0); + Value v3(2.0); - assert_eq( v8.get_int(), -1 ); - assert_eq( v8.get_int64(), -1 ); - assert_eq( v8.get_uint64(), max_uint64 ); - } + assert_eq(v1.type(), real_type); + assert_eq(v1, v2); + assert_neq(v1, v3); - void test_real_value() - { - Value v1( 1.0 ); - Value v2( 1.0 ); - Value v3( 2.0 ); + assert_eq(v1.get_real(), 1.0); + assert_eq(v3.get_real(), 2.0); +} - assert_eq( v1.type(), real_type ); - assert_eq ( v1, v2 ); - assert_neq( v1, v3 ); +void test_null_value() { + Value v1; + Value v2; - assert_eq( v1.get_real(), 1.0 ); - assert_eq( v3.get_real(), 2.0 ); - } + assert_eq(v1.type(), null_type); + assert_eq(v1.is_null(), true); + assert_eq(v1, v2); + assert_eq(v1.is_null(), true); + assert_eq(Value(1).is_null(), false); +} - void test_null_value() - { - Value v1; - Value v2; +template +void test_get_value(const T& t) { + assert_eq(Value(t).get_value(), t); +} - assert_eq( v1.type(), null_type ); - assert_eq( v1.is_null(), true ); - assert_eq( v1, v2 ); - assert_eq( v1.is_null(), true ); - assert_eq( Value( 1 ).is_null(), false ); - } +void test_get_value() { + test_get_value(123); + test_get_value(max_int64); + test_get_value(1.23); + test_get_value(true); + test_get_value(false); + test_get_value(string("test")); - template< typename T > - void test_get_value( const T& t ) - { - assert_eq( Value( t ).get_value< T >(), t ); - } + Array a; + a.push_back(1); + a.push_back("2"); - void test_get_value() - { - test_get_value( 123 ); - test_get_value( max_int64 ); - test_get_value( 1.23 ); - test_get_value( true ); - test_get_value( false ); - test_get_value( string( "test" ) ); + test_get_value(a); - Array a; a.push_back( 1 ); a.push_back( "2" ); + Object obj; + obj.push_back(Pair("name1", "value1")); - test_get_value( a ); + test_get_value(obj); +} - Object obj; obj.push_back( Pair( "name1", "value1" ) ); +void assert_array_eq(const Value& v, const Array& a) { assert_eq(v.get_array(), a); } - test_get_value( obj ); - } +void assert_obj_eq(const Value& v, const Object& obj) { assert_eq(v.get_obj(), obj); } - void assert_array_eq( const Value& v, const Array& a ) - { - assert_eq( v.get_array(), a ); - } +template +void check_copy(const T& t) { + const Value v1(t); + const Value v2(v1); + Value v3; + v3 = v1; - void assert_obj_eq( const Value& v, const Object& obj ) - { - assert_eq( v.get_obj(), obj ); - } + assert_eq(v1, v2); + assert_eq(v1, v3); - template< typename T > - void check_copy( const T& t ) - { - const Value v1( t ); - const Value v2( v1 ); - Value v3; - v3 = v1; - - assert_eq( v1, v2 ); - assert_eq( v1, v3 ); - - assert_eq( v2.get_value< T >(), t ); - assert_eq( v3.get_value< T >(), t ); - - assert_eq( v1.is_uint64(), v2.is_uint64() ); - assert_eq( v1.is_uint64(), v3.is_uint64() ); - } + assert_eq(v2.get_value(), t); + assert_eq(v3.get_value(), t); - void check_copying_null() - { - const Value v1; - const Value v2( v1 ); - Value v3; - v3 = v1; - - assert_eq( v2.type(), null_type ); - assert_eq( v3.type(), null_type ); - } + assert_eq(v1.is_uint64(), v2.is_uint64()); + assert_eq(v1.is_uint64(), v3.is_uint64()); +} + +void check_copying_null() { + const Value v1; + const Value v2(v1); + Value v3; + v3 = v1; + + assert_eq(v2.type(), null_type); + assert_eq(v3.type(), null_type); +} - void test_copying() +void test_copying() { { - { - const Array array_1 = list_of(1)(2); + const Array array_1 = list_of(1)(2); - Value v1( array_1 ); - const Value v2( v1 ); + Value v1(array_1); + const Value v2(v1); - assert_array_eq( v1, array_1 ); - assert_array_eq( v2, array_1 ); + assert_array_eq(v1, array_1); + assert_array_eq(v2, array_1); - v1.get_array()[0] = 3; + v1.get_array()[0] = 3; - assert_array_eq( v1, list_of(3)(2) ); - assert_array_eq( v2, array_1 ); - } - { - const Object obj_1 = list_of( Pair( "a", 1 ) )( Pair( "b", 2 ) ); + assert_array_eq(v1, list_of(3)(2)); + assert_array_eq(v2, array_1); + } + { + const Object obj_1 = list_of(Pair("a", 1))(Pair("b", 2)); - Value v1( obj_1 ); - Value v2; - - v2 = v1; + Value v1(obj_1); + Value v2; - assert_obj_eq( v1, obj_1 ); - assert_obj_eq( v2, obj_1 ); + v2 = v1; - v1.get_obj()[0] = Pair( "c", 3 ); + assert_obj_eq(v1, obj_1); + assert_obj_eq(v2, obj_1); - assert_obj_eq( v1, list_of( Pair( "c", 3 ) )( Pair( "b", 2 ) ) ); - assert_obj_eq( v2, obj_1 ); - } - { - check_copy( 1 ); - check_copy( 2.0 ); - check_copy( max_int64 ); - check_copy( max_uint64 ); - check_copy( string("test") ); - check_copy( true ); - check_copy( false ); - const Array array_1 = list_of(1)(2); - check_copy( array_1 ); - const Object obj_1 = list_of( Pair( "a", 1 ) )( Pair( "b", 2 ) ); - check_copy( obj_1 ); - check_copying_null(); - } - } + v1.get_obj()[0] = Pair("c", 3); - void test_obj_map_implemention() + assert_obj_eq(v1, list_of(Pair("c", 3))(Pair("b", 2))); + assert_obj_eq(v2, obj_1); + } { + check_copy(1); + check_copy(2.0); + check_copy(max_int64); + check_copy(max_uint64); + check_copy(string("test")); + check_copy(true); + check_copy(false); + const Array array_1 = list_of(1)(2); + check_copy(array_1); + const Object obj_1 = list_of(Pair("a", 1))(Pair("b", 2)); + check_copy(obj_1); + check_copying_null(); + } +} + +void test_obj_map_implemention() { #ifdef JSON_SPIRIT_MVALUE_ENABLED - mObject obj; + mObject obj; - obj[ "name 1" ] = 1; - obj[ "name 2" ] = "two"; + obj["name 1"] = 1; + obj["name 2"] = "two"; - assert_eq( obj.size(), 2u ); + assert_eq(obj.size(), 2u); - assert_eq( obj.find( "name 1" )->second.get_int(), 1 ); - assert_eq( obj.find( "name 2" )->second.get_str(), "two" ); + assert_eq(obj.find("name 1")->second.get_int(), 1); + assert_eq(obj.find("name 2")->second.get_str(), "two"); #endif - } +} - template< typename Int > - void check_an_int_is_a_real( Int i, bool expected_result ) - { - assert_eq( Value( i ).is_uint64(), expected_result ); - } +template +void check_an_int_is_a_real(Int i, bool expected_result) { + assert_eq(Value(i).is_uint64(), expected_result); +} - void test_is_uint64() - { - check_an_int_is_a_real( 1, false ); - check_an_int_is_a_real( static_cast< int64_t >( 1 ), false ); - check_an_int_is_a_real( static_cast< uint64_t >( 1 ), true ); - } +void test_is_uint64() { + check_an_int_is_a_real(1, false); + check_an_int_is_a_real(static_cast(1), false); + check_an_int_is_a_real(static_cast(1), true); +} - template< typename Int > - void check_an_int_is_a_real( Int i, double expected_result ) - { - assert_eq( Value( i ).get_real(), expected_result ); - } +template +void check_an_int_is_a_real(Int i, double expected_result) { + assert_eq(Value(i).get_real(), expected_result); +} - void test_an_int_is_a_real() - { - check_an_int_is_a_real( -1, -1.0 ); - check_an_int_is_a_real( 0, 0.0 ); - check_an_int_is_a_real( 1, 1.0 ); - check_an_int_is_a_real( max_int64, 9223372036854775800.0 ); - check_an_int_is_a_real( max_uint64, 18446744073709552000.0 ); - } +void test_an_int_is_a_real() { + check_an_int_is_a_real(-1, -1.0); + check_an_int_is_a_real(0, 0.0); + check_an_int_is_a_real(1, 1.0); + check_an_int_is_a_real(max_int64, 9223372036854775800.0); + check_an_int_is_a_real(max_uint64, 18446744073709552000.0); +} - template< typename T > - void check_wrong_type_exceptions( const Value& v, const string& requested_type_name, const string& actual_type_name ) - { - try - { - v.get_value< T >(); +template +void check_wrong_type_exceptions(const Value& v, const string& requested_type_name, + const string& actual_type_name) { + try { + v.get_value(); - assert( false ); - } - catch( const runtime_error& e ) - { - ostringstream os; + assert(false); + } catch (const runtime_error& e) { + ostringstream os; - os << "get_value< " << requested_type_name << " > called on " << actual_type_name << " Value"; + os << "get_value< " << requested_type_name << " > called on " + << actual_type_name << " Value"; - assert_eq( e.what(), os.str() ); - } + assert_eq(e.what(), os.str()); } +} - template< typename T > - void check_wrong_type_exceptions( const string& requested_type_name ) - { - Value v; +template +void check_wrong_type_exceptions(const string& requested_type_name) { + Value v; - assert_eq( v.type(), null_type ); + assert_eq(v.type(), null_type); - check_wrong_type_exceptions< T >( v, requested_type_name, "null" ); - } + check_wrong_type_exceptions(v, requested_type_name, "null"); +} - void test_wrong_type_exceptions() - { - check_wrong_type_exceptions< Object >( "Object" ); - check_wrong_type_exceptions< Array >( "Array" ); - check_wrong_type_exceptions< string >( "string" ); - check_wrong_type_exceptions< bool >( "boolean"); - check_wrong_type_exceptions< boost::int64_t >( "integer" ); - check_wrong_type_exceptions< int >( "integer" ); - check_wrong_type_exceptions< double >( "real" ); +void test_wrong_type_exceptions() { + check_wrong_type_exceptions("Object"); + check_wrong_type_exceptions("Array"); + check_wrong_type_exceptions("string"); + check_wrong_type_exceptions("boolean"); + check_wrong_type_exceptions("integer"); + check_wrong_type_exceptions("integer"); + check_wrong_type_exceptions("real"); - Value v( "string" ); + Value v("string"); - assert_eq( v.type(), str_type ); + assert_eq(v.type(), str_type); - check_wrong_type_exceptions< double >( v, "real", "string" ); - } + check_wrong_type_exceptions(v, "real", "string"); +} #endif - template< class Config_type > - class Container_constructor_runner - { - public: - - Container_constructor_runner() - { - vector< double > vd = list_of( 1.2 )( 1.3 ); test_container_constructor( vd ); - vector< int > vi = list_of( 1 ); test_container_constructor( vi ); - vi = list_of( 1 )( 2 ); test_container_constructor( vi ); - vi = list_of( 1 )( 2 )( 3 ); test_container_constructor( vi ); - list< double > ld = list_of( 1.2 )( 1.3 ); test_container_constructor( ld ); - list< int > li = list_of( 1 ); test_container_constructor( li ); - li = list_of( 1 )( 2 ); test_container_constructor( li ); - li = list_of( 1 )( 2 )( 3 ); test_container_constructor( li ); - } - - private: - - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; +template +class Container_constructor_runner { +public: + Container_constructor_runner() { + vector vd = list_of(1.2)(1.3); + test_container_constructor(vd); + vector vi = list_of(1); + test_container_constructor(vi); + vi = list_of(1)(2); + test_container_constructor(vi); + vi = list_of(1)(2)(3); + test_container_constructor(vi); + list ld = list_of(1.2)(1.3); + test_container_constructor(ld); + list li = list_of(1); + test_container_constructor(li); + li = list_of(1)(2); + test_container_constructor(li); + li = list_of(1)(2)(3); + test_container_constructor(li); + } - template< class Cont > - void test_container_constructor( const Cont& cont ) - { - typedef typename Cont::value_type Cont_value_type; - const Value_type val( cont.begin(), cont.end() ); - const Array_type& arr = val.get_array(); - Cont result; - for( unsigned int i = 0; i < arr.size(); ++i ) - { - result.push_back( arr[i].template get_value< Cont_value_type>() ); - } - assert_eq( result, cont ); +private: + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + + template + void test_container_constructor(const Cont& cont) { + typedef typename Cont::value_type Cont_value_type; + const Value_type val(cont.begin(), cont.end()); + const Array_type& arr = val.get_array(); + Cont result; + for (unsigned int i = 0; i < arr.size(); ++i) { + result.push_back(arr[i].template get_value()); } - }; + assert_eq(result, cont); + } +}; - void test_container_constructor() - { +void test_container_constructor() { #ifdef JSON_SPIRIT_VALUE_ENABLED - Container_constructor_runner< Config >(); + Container_constructor_runner(); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - Container_constructor_runner< mConfig >(); + Container_constructor_runner(); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Container_constructor_runner< wConfig >(); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Container_constructor_runner(); #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Container_constructor_runner< wmConfig >(); +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Container_constructor_runner(); #endif - } +} - template< class Config_type > - class Variant_constructor_runner - { - public: +template +class Variant_constructor_runner { +public: + Variant_constructor_runner() { + test_variant_constructor >(1.23); + test_variant_constructor >(123); + test_variant_constructor >( + to_str("foo")); + test_variant_constructor >(true); + test_variant_constructor< + variant >( + boost::int64_t(123)); + test_variant_constructor< + variant >( + boost::uint64_t(123)); - Variant_constructor_runner() { - test_variant_constructor< variant< int, double > >( 1.23 ); - test_variant_constructor< variant< int, double > >( 123 ); - test_variant_constructor< variant< int, double, String_type > >( to_str< String_type >( "foo" ) ); - test_variant_constructor< variant< int, double, String_type, bool > >( true ); - test_variant_constructor< variant< int, double, String_type, bool, boost::int64_t > >( boost::int64_t( 123 ) ); - test_variant_constructor< variant< int, double, String_type, bool, boost::uint64_t > >( boost::uint64_t( 123 ) ); - - { - variant< int, Null > variant = Null(); - const Value_type val( variant ); - assert( val.is_null() ); - } - - vector< double > vd = list_of( 1.2 )( 1.3 ); test_variant_array_constructor< double > ( vd ); - vector< int > vi = list_of( 1 ); test_variant_array_constructor< int >( vi ); - vi = list_of( 1 )( 2 ); test_variant_array_constructor< int >( vi ); - vi = list_of( 1 )( 2 )( 3 ); test_variant_array_constructor< int >( vi ); - list< double > ld = list_of( 1.2 )( 1.3 ); test_variant_array_constructor< double >( ld ); - list< int > li = list_of( 1 ); test_variant_array_constructor< int >( li ); - li = list_of( 1 )( 2 ); test_variant_array_constructor< int >( li ); - li = list_of( 1 )( 2 )( 3 ); test_variant_array_constructor< int >( li ); + variant variant = Null(); + const Value_type val(variant); + assert(val.is_null()); } - private: + vector vd = list_of(1.2)(1.3); + test_variant_array_constructor(vd); + vector vi = list_of(1); + test_variant_array_constructor(vi); + vi = list_of(1)(2); + test_variant_array_constructor(vi); + vi = list_of(1)(2)(3); + test_variant_array_constructor(vi); + list ld = list_of(1.2)(1.3); + test_variant_array_constructor(ld); + list li = list_of(1); + test_variant_array_constructor(li); + li = list_of(1)(2); + test_variant_array_constructor(li); + li = list_of(1)(2)(3); + test_variant_array_constructor(li); + } - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; +private: + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; - template< class Variant_t, typename T > - void test_variant_constructor( const T& t ) - { - const Variant_t variant( t ); - const Value_type val( variant ); - assert_eq( val.template get_value< T >(), t ); - } + template + void test_variant_constructor(const T& t) { + const Variant_t variant(t); + const Value_type val(variant); + assert_eq(val.template get_value(), t); + } - template< typename T, typename A, template< typename, typename > class Cont > - void test_variant_array_constructor( const Cont< T, A >& cont ) - { - const variant< int, Cont< T, A > > variant = cont; - const Value_type val( variant ); - const Array_type& arr = val.get_array(); - Cont< T, A > result; - for( unsigned int i = 0; i < arr.size(); ++i ) - { - result.push_back( arr[i].template get_value< T >() ); - } - assert_eq( result, cont ); + template class Cont> + void test_variant_array_constructor(const Cont& cont) { + const variant > variant = cont; + const Value_type val(variant); + const Array_type& arr = val.get_array(); + Cont result; + for (unsigned int i = 0; i < arr.size(); ++i) { + result.push_back(arr[i].template get_value()); } - }; + assert_eq(result, cont); + } +}; - void test_variant_constructor() - { +void test_variant_constructor() { #ifdef JSON_SPIRIT_VALUE_ENABLED - Variant_constructor_runner< Config >(); + Variant_constructor_runner(); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - Variant_constructor_runner< mConfig >(); + Variant_constructor_runner(); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Variant_constructor_runner< wConfig >(); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Variant_constructor_runner(); #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Variant_constructor_runner< wmConfig >(); +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Variant_constructor_runner(); #endif - } +} } -void json5_parser::test_value() -{ +void json5_parser::test_value() { #ifdef JSON_SPIRIT_VALUE_ENABLED Object obj; - Value value_str ( "value" ); - Value value_obj ( obj ); - Value value_bool( true ); + Value value_str("value"); + Value value_obj(obj); + Value value_bool(true); - Value value_str_2 ( string( "value" ) ); - Value value_obj_2 ( obj ); - Value value_bool_2( false ); + Value value_str_2(string("value")); + Value value_obj_2(obj); + Value value_bool_2(false); - const char* str( "value" ); - Value value_str_2b ( str ); + const char* str("value"); + Value value_str_2b(str); - assert_eq( value_str, value_str ); - assert_eq( value_str, value_str_2 ); - assert_eq( value_str, value_str_2b ); - assert_eq( value_obj, value_obj ); - assert_eq( value_obj, value_obj_2 ); - assert_neq( value_str, value_obj ); - assert_neq( value_str, value_bool ); + assert_eq(value_str, value_str); + assert_eq(value_str, value_str_2); + assert_eq(value_str, value_str_2b); + assert_eq(value_obj, value_obj); + assert_eq(value_obj, value_obj_2); + assert_neq(value_str, value_obj); + assert_neq(value_str, value_bool); Object obj_2; - obj_2.push_back( Pair( "name", value_str ) ); - Value value_str_3( "xxxxx" ); - Value value_obj_3( obj_2 ); + obj_2.push_back(Pair("name", value_str)); + Value value_str_3("xxxxx"); + Value value_obj_3(obj_2); - assert_neq( value_str, value_str_3 ); - assert_neq( value_obj, value_obj_3 ); + assert_neq(value_str, value_str_3); + assert_neq(value_obj, value_obj_3); test_obj_value(); test_array_value(); diff --git a/json_test/json5_parser_value_test.h b/json_test/json5_parser_value_test.h index c5c4a8f..3751d7d 100644 --- a/json_test/json5_parser_value_test.h +++ b/json_test/json5_parser_value_test.h @@ -7,12 +7,11 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -namespace json5_parser -{ - void test_value(); +namespace json5_parser { +void test_value(); } #endif diff --git a/json_test/json5_parser_writer_test.cpp b/json_test/json5_parser_writer_test.cpp index c7e3c67..46f7fb7 100644 --- a/json_test/json5_parser_writer_test.cpp +++ b/json_test/json5_parser_writer_test.cpp @@ -4,785 +4,780 @@ // json spirit version 4.08 #include "json5_parser_writer_test.h" -#include "utils_test.h" +#include "json5_parser_value.h" #include "json5_parser_writer.h" -#include "json5_parser_value.h" +#include "utils_test.h" -#include #include +#include using namespace json5_parser; using namespace std; using namespace boost; -namespace -{ - const int64_t max_int64 = integer_traits< int64_t >::max(); - const uint64_t max_uint64 = integer_traits< uint64_t >::max(); - - template< class Config_type > - struct Test_runner - { - typedef typename Config_type::String_type String_type; - typedef typename Config_type::Object_type Object_type; - typedef typename Config_type::Array_type Array_type; - typedef typename Config_type::Value_type Value_type; - typedef typename String_type::value_type Char_type; - typedef typename String_type::const_iterator Iter_type; - typedef std::basic_ostream< Char_type > Ostream_type; - - String_type to_str( const char* c_str ) - { - return ::to_str< String_type >( c_str ); - } - - String_type zero_str() - { +namespace { +const int64_t max_int64 = integer_traits::max(); +const uint64_t max_uint64 = integer_traits::max(); + +template +struct Test_runner { + typedef typename Config_type::String_type String_type; + typedef typename Config_type::Object_type Object_type; + typedef typename Config_type::Array_type Array_type; + typedef typename Config_type::Value_type Value_type; + typedef typename String_type::value_type Char_type; + typedef typename String_type::const_iterator Iter_type; + typedef std::basic_ostream Ostream_type; + + String_type to_str(const char* c_str) { return ::to_str(c_str); } + + String_type zero_str() { #ifdef WIN32 - return to_str( "0.00000000000000000" ); + return to_str("0.00000000000000000"); #else - return to_str( "0.0000000000000000" ); + return to_str("0.0000000000000000"); #endif - } + } - void add_value( Object_type& obj, const char* c_name, const Value_type& value ) - { - Config_type::add( obj, to_str( c_name ), value ); - } + void add_value(Object_type& obj, const char* c_name, const Value_type& value) { + Config_type::add(obj, to_str(c_name), value); + } - void add_c_str( Object_type& obj, const char* c_name, const char* c_value ) - { - add_value( obj, c_name, to_str( c_value ) ); - } + void add_c_str(Object_type& obj, const char* c_name, const char* c_value) { + add_value(obj, c_name, to_str(c_value)); + } - void check_eq( const Value_type& value, const String_type& expected_result ) - { - assert_eq( write( value ), expected_result ); - } + void check_eq(const Value_type& value, const String_type& expected_result) { + assert_eq(write(value), expected_result); + } - void check_eq( const Value_type& value, const char* expected_result ) - { - check_eq( value, to_str( expected_result ) ); - } + void check_eq(const Value_type& value, const char* expected_result) { + check_eq(value, to_str(expected_result)); + } - void check_eq_pretty( const Value_type& value, const char* expected_result ) - { - assert_eq( write_formatted( value ), to_str( expected_result ) ); - assert_eq( write( value, pretty_print ), to_str( expected_result ) ); - } + void check_eq_pretty(const Value_type& value, const char* expected_result) { + assert_eq(write_formatted(value), to_str(expected_result)); + assert_eq(write(value, pretty_print), to_str(expected_result)); + } - void check_eq_single_line_arrays( const Value_type& value, const char* expected_result ) - { - assert_eq( write( value, single_line_arrays ), to_str( expected_result ) ); - } + void check_eq_single_line_arrays(const Value_type& value, + const char* expected_result) { + assert_eq(write(value, single_line_arrays), to_str(expected_result)); + } - void check_eq( const Value_type& value, const String_type& expected_result , Output_options options ) - { - assert_eq( write( value, options ), expected_result ); - } + void check_eq(const Value_type& value, const String_type& expected_result, + Output_options options) { + assert_eq(write(value, options), expected_result); + } - void check_eq( const Value_type& value, const char* expected_result, Output_options options ) - { - check_eq( value, to_str( expected_result ), options ); - } + void check_eq(const Value_type& value, const char* expected_result, + Output_options options) { + check_eq(value, to_str(expected_result), options); + } - void test_empty_obj() - { - check_eq( Object_type(), "{}" ); - check_eq_pretty( Object_type(), "{\n}" ); - } + void test_empty_obj() { + check_eq(Object_type(), "{}"); + check_eq_pretty(Object_type(), "{\n}"); + } - void test_obj_with_one_member() - { - Object_type obj; + void test_obj_with_one_member() { + Object_type obj; - add_c_str( obj, "name", "value" ); + add_c_str(obj, "name", "value"); - check_eq ( obj, "{\"name\":\"value\"}" ); - check_eq_pretty( obj, "{\n" - " \"name\" : \"value\"\n" - "}" ); - } + check_eq(obj, "{\"name\":\"value\"}"); + check_eq_pretty(obj, + "{\n" + " \"name\" : \"value\"\n" + "}"); + } - void test_obj_with_two_members() - { - Object_type obj; + void test_obj_with_two_members() { + Object_type obj; - add_c_str( obj, "name_1", "value_1" ); - add_c_str( obj, "name_2", "value_2" ); + add_c_str(obj, "name_1", "value_1"); + add_c_str(obj, "name_2", "value_2"); - check_eq( obj, "{\"name_1\":\"value_1\",\"name_2\":\"value_2\"}" ); + check_eq(obj, "{\"name_1\":\"value_1\",\"name_2\":\"value_2\"}"); - check_eq_pretty( obj, "{\n" - " \"name_1\" : \"value_1\",\n" - " \"name_2\" : \"value_2\"\n" - "}" ); - } + check_eq_pretty(obj, + "{\n" + " \"name_1\" : \"value_1\",\n" + " \"name_2\" : \"value_2\"\n" + "}"); + } - void test_obj_with_three_members() - { - Object_type obj; + void test_obj_with_three_members() { + Object_type obj; - add_c_str( obj, "name_1", "value_1" ); - add_c_str( obj, "name_2", "value_2" ); - add_c_str( obj, "name_3", "value_3" ); + add_c_str(obj, "name_1", "value_1"); + add_c_str(obj, "name_2", "value_2"); + add_c_str(obj, "name_3", "value_3"); - check_eq( obj, "{\"name_1\":\"value_1\",\"name_2\":\"value_2\",\"name_3\":\"value_3\"}" ); + check_eq(obj, + "{\"name_1\":\"value_1\",\"name_2\":\"value_2\",\"name_3\":\"value_" + "3\"}"); - check_eq_pretty( obj, "{\n" - " \"name_1\" : \"value_1\",\n" - " \"name_2\" : \"value_2\",\n" - " \"name_3\" : \"value_3\"\n" - "}" ); - } + check_eq_pretty(obj, + "{\n" + " \"name_1\" : \"value_1\",\n" + " \"name_2\" : \"value_2\",\n" + " \"name_3\" : \"value_3\"\n" + "}"); + } - void test_obj_with_one_empty_child_obj() - { - Object_type child; + void test_obj_with_one_empty_child_obj() { + Object_type child; - Object_type root; + Object_type root; - add_value( root, "child", child ); + add_value(root, "child", child); - check_eq( root, "{\"child\":{}}" ); + check_eq(root, "{\"child\":{}}"); - check_eq_pretty( root, "{\n" - " \"child\" : {\n" - " }\n" - "}" ); - } + check_eq_pretty(root, + "{\n" + " \"child\" : {\n" + " }\n" + "}"); + } - void test_obj_with_one_child_obj() - { - Object_type child; + void test_obj_with_one_child_obj() { + Object_type child; - add_c_str( child, "name_2", "value_2" ); + add_c_str(child, "name_2", "value_2"); - Object_type root; + Object_type root; - add_value( root, "child", child ); - add_c_str( root, "name_1", "value_1" ); + add_value(root, "child", child); + add_c_str(root, "name_1", "value_1"); - check_eq( root, "{\"child\":{\"name_2\":\"value_2\"},\"name_1\":\"value_1\"}" ); + check_eq(root, "{\"child\":{\"name_2\":\"value_2\"},\"name_1\":\"value_1\"}"); - check_eq_pretty( root, "{\n" - " \"child\" : {\n" - " \"name_2\" : \"value_2\"\n" - " },\n" - " \"name_1\" : \"value_1\"\n" - "}" ); - } + check_eq_pretty(root, + "{\n" + " \"child\" : {\n" + " \"name_2\" : \"value_2\"\n" + " },\n" + " \"name_1\" : \"value_1\"\n" + "}"); + } - void test_obj_with_grandchild_obj() - { - Object_type child_1; add_c_str( child_1, "name_1", "value_1" ); - Object_type child_2; - Object_type child_3; add_c_str( child_3, "name_3", "value_3" ); - - add_value( child_2, "grandchild", child_3 ); - add_c_str( child_2, "name_2", "value_2" ); - - Object_type root; - - add_value( root, "child_1", child_1 ); - add_value( root, "child_2", child_2 ); - add_c_str( root, "name_a", "value_a" ); - add_c_str( root, "name_b", "value_b" ); - - check_eq( root, "{\"child_1\":{\"name_1\":\"value_1\"}," - "\"child_2\":{\"grandchild\":{\"name_3\":\"value_3\"},\"name_2\":\"value_2\"}," - "\"name_a\":\"value_a\"," - "\"name_b\":\"value_b\"}" ); - - check_eq_pretty( root, "{\n" - " \"child_1\" : {\n" - " \"name_1\" : \"value_1\"\n" - " },\n" - " \"child_2\" : {\n" - " \"grandchild\" : {\n" - " \"name_3\" : \"value_3\"\n" - " },\n" - " \"name_2\" : \"value_2\"\n" - " },\n" - " \"name_a\" : \"value_a\",\n" - " \"name_b\" : \"value_b\"\n" - "}" ); - } + void test_obj_with_grandchild_obj() { + Object_type child_1; + add_c_str(child_1, "name_1", "value_1"); + Object_type child_2; + Object_type child_3; + add_c_str(child_3, "name_3", "value_3"); + + add_value(child_2, "grandchild", child_3); + add_c_str(child_2, "name_2", "value_2"); + + Object_type root; + + add_value(root, "child_1", child_1); + add_value(root, "child_2", child_2); + add_c_str(root, "name_a", "value_a"); + add_c_str(root, "name_b", "value_b"); + + check_eq(root, + "{\"child_1\":{\"name_1\":\"value_1\"}," + "\"child_2\":{\"grandchild\":{\"name_3\":\"value_3\"},\"name_2\":" + "\"value_2\"}," + "\"name_a\":\"value_a\"," + "\"name_b\":\"value_b\"}"); + + check_eq_pretty(root, + "{\n" + " \"child_1\" : {\n" + " \"name_1\" : \"value_1\"\n" + " },\n" + " \"child_2\" : {\n" + " \"grandchild\" : {\n" + " \"name_3\" : \"value_3\"\n" + " },\n" + " \"name_2\" : \"value_2\"\n" + " },\n" + " \"name_a\" : \"value_a\",\n" + " \"name_b\" : \"value_b\"\n" + "}"); + } - void test_objs_with_bool_pairs() - { - Object_type obj; + void test_objs_with_bool_pairs() { + Object_type obj; - add_value( obj, "name_1", true ); - add_value( obj, "name_2", false ); - add_value( obj, "name_3", true ); - - check_eq( obj, "{\"name_1\":true,\"name_2\":false,\"name_3\":true}" ); - } + add_value(obj, "name_1", true); + add_value(obj, "name_2", false); + add_value(obj, "name_3", true); - void test_objs_with_int_pairs() - { - Object_type obj; + check_eq(obj, "{\"name_1\":true,\"name_2\":false,\"name_3\":true}"); + } - add_value( obj, "name_1", 11 ); - add_value( obj, "name_2", INT_MAX ); - add_value( obj, "name_3", max_int64 ); + void test_objs_with_int_pairs() { + Object_type obj; - ostringstream os; + add_value(obj, "name_1", 11); + add_value(obj, "name_2", INT_MAX); + add_value(obj, "name_3", max_int64); - os << "{\"name_1\":11,\"name_2\":" << INT_MAX << ",\"name_3\":" << max_int64 << "}"; - - check_eq( obj, os.str().c_str() ); - } + ostringstream os; - void test_objs_with_real_pairs() - { - Object_type obj; - - add_value( obj, "name_1", 0.0 ); - add_value( obj, "name_2", 1.234567890123456789e-108 ); - add_value( obj, "name_3", -1234567890.123456789 ); - add_value( obj, "name_4", -1.2e-126 ); - - check_eq( obj, to_str( "{\"name_1\":0," - "\"name_2\":1.2345678901234567e-108," - "\"name_3\":-1234567890.1234567," - "\"name_4\":-1.2e-126}" ) ); - } - - void test_objs_with_null_pairs() - { - Object_type obj; - - add_value( obj, "name_1", Value_type::null ); - add_value( obj, "name_2", Value_type::null ); - add_value( obj, "name_3", Value_type::null ); - - check_eq( obj, "{\"name_1\":null,\"name_2\":null,\"name_3\":null}" ); - } + os << "{\"name_1\":11,\"name_2\":" << INT_MAX << ",\"name_3\":" << max_int64 + << "}"; - void test_empty_array() - { - check_eq( Array_type(), "[]" ); - check_eq_pretty( Array_type(), "[\n" - "]" ); - check_eq_single_line_arrays( Array_type(), "[ ]" ); - } + check_eq(obj, os.str().c_str()); + } - void test_array_with_one_member() - { - Array_type arr; + void test_objs_with_real_pairs() { + Object_type obj; - arr.push_back( to_str( "value" ) ); + add_value(obj, "name_1", 0.0); + add_value(obj, "name_2", 1.234567890123456789e-108); + add_value(obj, "name_3", -1234567890.123456789); + add_value(obj, "name_4", -1.2e-126); - check_eq ( arr, "[\"value\"]" ); - check_eq_pretty( arr, "[\n" - " \"value\"\n" - "]" ); - check_eq_single_line_arrays( arr, "[ \"value\" ]" ); - } + check_eq(obj, to_str("{\"name_1\":0," + "\"name_2\":1.2345678901234567e-108," + "\"name_3\":-1234567890.1234567," + "\"name_4\":-1.2e-126}")); + } - void test_array_with_two_members() - { - Array_type arr; + void test_objs_with_null_pairs() { + Object_type obj; - arr.push_back( to_str( "value_1" ) ); - arr.push_back( 1 ); + add_value(obj, "name_1", Value_type::null); + add_value(obj, "name_2", Value_type::null); + add_value(obj, "name_3", Value_type::null); - check_eq ( arr, "[\"value_1\",1]" ); - check_eq_pretty( arr, "[\n" - " \"value_1\",\n" - " 1\n" - "]" ); - check_eq_single_line_arrays( arr, "[ \"value_1\", 1 ]" ); - } + check_eq(obj, "{\"name_1\":null,\"name_2\":null,\"name_3\":null}"); + } - void test_array_with_n_members() - { - Array_type arr; - - arr.push_back( to_str( "value_1" ) ); - arr.push_back( 123 ); - arr.push_back( 123.456 ); - arr.push_back( true ); - arr.push_back( false ); - arr.push_back( Value_type() ); - - check_eq ( arr, "[\"value_1\",123,123.456,true,false,null]" ); - check_eq_pretty( arr, "[\n" - " \"value_1\",\n" - " 123,\n" - " 123.456,\n" - " true,\n" - " false,\n" - " null\n" - "]" ); - check_eq_single_line_arrays( arr, "[ \"value_1\", 123, 123.456, true, false, null ]" ); - } + void test_empty_array() { + check_eq(Array_type(), "[]"); + check_eq_pretty(Array_type(), + "[\n" + "]"); + check_eq_single_line_arrays(Array_type(), "[ ]"); + } - void test_array_with_one_empty_child_array() - { - Array_type arr; + void test_array_with_one_member() { + Array_type arr; - arr.push_back( Array_type() ); + arr.push_back(to_str("value")); - check_eq ( arr, "[[]]" ); - check_eq_pretty( arr, "[\n" - " [\n" - " ]\n" - "]" ); - check_eq_single_line_arrays( arr, "[\n" - " [ ]\n" - "]" ); - } + check_eq(arr, "[\"value\"]"); + check_eq_pretty(arr, + "[\n" + " \"value\"\n" + "]"); + check_eq_single_line_arrays(arr, "[ \"value\" ]"); + } - void test_array_with_one_child_array() - { - Array_type child; + void test_array_with_two_members() { + Array_type arr; - child.push_back( 2 ); + arr.push_back(to_str("value_1")); + arr.push_back(1); - Array_type root; + check_eq(arr, "[\"value_1\",1]"); + check_eq_pretty(arr, + "[\n" + " \"value_1\",\n" + " 1\n" + "]"); + check_eq_single_line_arrays(arr, "[ \"value_1\", 1 ]"); + } - root.push_back( 1 ); - root.push_back( child ); + void test_array_with_n_members() { + Array_type arr; + + arr.push_back(to_str("value_1")); + arr.push_back(123); + arr.push_back(123.456); + arr.push_back(true); + arr.push_back(false); + arr.push_back(Value_type()); + + check_eq(arr, "[\"value_1\",123,123.456,true,false,null]"); + check_eq_pretty(arr, + "[\n" + " \"value_1\",\n" + " 123,\n" + " 123.456,\n" + " true,\n" + " false,\n" + " null\n" + "]"); + check_eq_single_line_arrays(arr, + "[ \"value_1\", 123, 123.456, true, false, null ]"); + } - check_eq ( root, "[1,[2]]" ); - check_eq_pretty( root, "[\n" - " 1,\n" - " [\n" - " 2\n" - " ]\n" - "]" ); - check_eq_single_line_arrays( root, "[\n" - " 1,\n" - " [ 2 ]\n" - "]" ); - } + void test_array_with_one_empty_child_array() { + Array_type arr; + + arr.push_back(Array_type()); + + check_eq(arr, "[[]]"); + check_eq_pretty(arr, + "[\n" + " [\n" + " ]\n" + "]"); + check_eq_single_line_arrays(arr, + "[\n" + " [ ]\n" + "]"); + } - void test_array_with_grandchild_array() - { - Array_type child_1; child_1.push_back( 11 ); - Array_type child_2; child_2.push_back( 22 ); - Array_type child_3; child_3.push_back( 33 ); - - child_2.push_back( child_3 ); - - Array_type root; - - root.push_back( 1); - root.push_back( child_1 ); - root.push_back( child_2 ); - root.push_back( 2 ); - - check_eq ( root, "[1,[11],[22,[33]],2]" ); - check_eq_pretty( root, "[\n" - " 1,\n" - " [\n" - " 11\n" - " ],\n" - " [\n" - " 22,\n" - " [\n" - " 33\n" - " ]\n" - " ],\n" - " 2\n" - "]" ); - check_eq_single_line_arrays( root, "[\n" - " 1,\n" - " [ 11 ],\n" - " [\n" - " 22,\n" - " [ 33 ]\n" - " ],\n" - " 2\n" - "]" ); - } + void test_array_with_one_child_array() { + Array_type child; + + child.push_back(2); + + Array_type root; + + root.push_back(1); + root.push_back(child); + + check_eq(root, "[1,[2]]"); + check_eq_pretty(root, + "[\n" + " 1,\n" + " [\n" + " 2\n" + " ]\n" + "]"); + check_eq_single_line_arrays(root, + "[\n" + " 1,\n" + " [ 2 ]\n" + "]"); + } - void test_array_and_objs() - { - Array_type a; - - a.push_back( 11 ); - - Object_type obj; - - add_value( obj, "a", 1 ); - - a.push_back( obj ); - - check_eq ( a, "[11,{\"a\":1}]" ); - check_eq_pretty( a, "[\n" - " 11,\n" - " {\n" - " \"a\" : 1\n" - " }\n" - "]" ); - check_eq_single_line_arrays( a, "[\n" - " 11,\n" - " {\n" - " \"a\" : 1\n" - " }\n" - "]" ); - - add_value( obj, "b", 2 ); - - a.push_back( 22 ); - a.push_back( 33 ); - a.push_back( obj ); - - check_eq ( a, "[11,{\"a\":1},22,33,{\"a\":1,\"b\":2}]" ); - check_eq_pretty( a, "[\n" - " 11,\n" - " {\n" - " \"a\" : 1\n" - " },\n" - " 22,\n" - " 33,\n" - " {\n" - " \"a\" : 1,\n" - " \"b\" : 2\n" - " }\n" - "]" ); - check_eq_single_line_arrays( a, "[\n" - " 11,\n" - " {\n" - " \"a\" : 1\n" - " },\n" - " 22,\n" - " 33,\n" - " {\n" - " \"a\" : 1,\n" - " \"b\" : 2\n" - " }\n" - "]" ); - } + void test_array_with_grandchild_array() { + Array_type child_1; + child_1.push_back(11); + Array_type child_2; + child_2.push_back(22); + Array_type child_3; + child_3.push_back(33); + + child_2.push_back(child_3); + + Array_type root; + + root.push_back(1); + root.push_back(child_1); + root.push_back(child_2); + root.push_back(2); + + check_eq(root, "[1,[11],[22,[33]],2]"); + check_eq_pretty(root, + "[\n" + " 1,\n" + " [\n" + " 11\n" + " ],\n" + " [\n" + " 22,\n" + " [\n" + " 33\n" + " ]\n" + " ],\n" + " 2\n" + "]"); + check_eq_single_line_arrays(root, + "[\n" + " 1,\n" + " [ 11 ],\n" + " [\n" + " 22,\n" + " [ 33 ]\n" + " ],\n" + " 2\n" + "]"); + } - void test_obj_and_arrays() - { - Object_type obj; - - add_value( obj, "a", 1 ); - - Array_type a; - - a.push_back( 11 ); - a.push_back( 12 ); - - add_value( obj, "b", a ); - - check_eq ( obj, "{\"a\":1,\"b\":[11,12]}" ); - check_eq_pretty( obj, "{\n" - " \"a\" : 1,\n" - " \"b\" : [\n" - " 11,\n" - " 12\n" - " ]\n" - "}" ); - check_eq_single_line_arrays( obj, "{\n" - " \"a\" : 1,\n" - " \"b\" : [ 11, 12 ]\n" - "}" ); - - a.push_back( obj ); - - add_value( obj, "c", a ); - - check_eq ( obj, "{\"a\":1,\"b\":[11,12],\"c\":[11,12,{\"a\":1,\"b\":[11,12]}]}" ); - check_eq_pretty( obj, "{\n" - " \"a\" : 1,\n" - " \"b\" : [\n" - " 11,\n" - " 12\n" - " ],\n" - " \"c\" : [\n" - " 11,\n" - " 12,\n" - " {\n" - " \"a\" : 1,\n" - " \"b\" : [\n" - " 11,\n" - " 12\n" - " ]\n" - " }\n" - " ]\n" - "}" ); - check_eq_single_line_arrays( obj, "{\n" - " \"a\" : 1,\n" - " \"b\" : [ 11, 12 ],\n" - " \"c\" : [\n" - " 11,\n" - " 12,\n" - " {\n" - " \"a\" : 1,\n" - " \"b\" : [ 11, 12 ]\n" - " }\n" - " ]\n" - "}" ); - } + void test_array_and_objs() { + Array_type a; + + a.push_back(11); + + Object_type obj; + + add_value(obj, "a", 1); + + a.push_back(obj); + + check_eq(a, "[11,{\"a\":1}]"); + check_eq_pretty(a, + "[\n" + " 11,\n" + " {\n" + " \"a\" : 1\n" + " }\n" + "]"); + check_eq_single_line_arrays(a, + "[\n" + " 11,\n" + " {\n" + " \"a\" : 1\n" + " }\n" + "]"); + + add_value(obj, "b", 2); + + a.push_back(22); + a.push_back(33); + a.push_back(obj); + + check_eq(a, "[11,{\"a\":1},22,33,{\"a\":1,\"b\":2}]"); + check_eq_pretty(a, + "[\n" + " 11,\n" + " {\n" + " \"a\" : 1\n" + " },\n" + " 22,\n" + " 33,\n" + " {\n" + " \"a\" : 1,\n" + " \"b\" : 2\n" + " }\n" + "]"); + check_eq_single_line_arrays(a, + "[\n" + " 11,\n" + " {\n" + " \"a\" : 1\n" + " },\n" + " 22,\n" + " 33,\n" + " {\n" + " \"a\" : 1,\n" + " \"b\" : 2\n" + " }\n" + "]"); + } - void test_escape_char( const char* esc_str_in, const char* esc_str_out, Output_options options = none ) - { - Object_type obj; + void test_obj_and_arrays() { + Object_type obj; + + add_value(obj, "a", 1); + + Array_type a; + + a.push_back(11); + a.push_back(12); + + add_value(obj, "b", a); + + check_eq(obj, "{\"a\":1,\"b\":[11,12]}"); + check_eq_pretty(obj, + "{\n" + " \"a\" : 1,\n" + " \"b\" : [\n" + " 11,\n" + " 12\n" + " ]\n" + "}"); + check_eq_single_line_arrays(obj, + "{\n" + " \"a\" : 1,\n" + " \"b\" : [ 11, 12 ]\n" + "}"); + + a.push_back(obj); + + add_value(obj, "c", a); + + check_eq(obj, "{\"a\":1,\"b\":[11,12],\"c\":[11,12,{\"a\":1,\"b\":[11,12]}]}"); + check_eq_pretty(obj, + "{\n" + " \"a\" : 1,\n" + " \"b\" : [\n" + " 11,\n" + " 12\n" + " ],\n" + " \"c\" : [\n" + " 11,\n" + " 12,\n" + " {\n" + " \"a\" : 1,\n" + " \"b\" : [\n" + " 11,\n" + " 12\n" + " ]\n" + " }\n" + " ]\n" + "}"); + check_eq_single_line_arrays(obj, + "{\n" + " \"a\" : 1,\n" + " \"b\" : [ 11, 12 ],\n" + " \"c\" : [\n" + " 11,\n" + " 12,\n" + " {\n" + " \"a\" : 1,\n" + " \"b\" : [ 11, 12 ]\n" + " }\n" + " ]\n" + "}"); + } - const string name_str( string( esc_str_in ) + "name" ); + void test_escape_char(const char* esc_str_in, const char* esc_str_out, + Output_options options = none) { + Object_type obj; - add_value( obj, name_str.c_str(), to_str( "value" ) + to_str( esc_str_in ) ); + const string name_str(string(esc_str_in) + "name"); - const string out_str( string( "{\"" ) + esc_str_out + "name\":\"value" + esc_str_out + "\"}" ); + add_value(obj, name_str.c_str(), to_str("value") + to_str(esc_str_in)); - check_eq( obj, out_str.c_str(), options ); - } + const string out_str(string("{\"") + esc_str_out + "name\":\"value" + + esc_str_out + "\"}"); - void test_escape_chars() - { - test_escape_char( "\r", "\\r" ); - test_escape_char( "\n", "\\n" ); - test_escape_char( "\t", "\\t" ); - test_escape_char( "\f", "\\f" ); - test_escape_char( "\b", "\\b" ); - test_escape_char( "\"", "\\\"" ); - test_escape_char( "\\", "\\\\" ); - test_escape_char( "\x01", "\\u0001" ); - test_escape_char( "\x12", "\\u0012" ); - test_escape_char( "\x7F", "\\u007F" ); - } + check_eq(obj, out_str.c_str(), options); + } - void test_disabling_nonprintable_esc_chars() - { - test_escape_char( "\t", "\\t", raw_utf8 ); - test_escape_char( "\x01", "\x01", raw_utf8 ); - test_escape_char( "\x01\x12", "\x01\x12", raw_utf8 ); - } + void test_escape_chars() { + test_escape_char("\r", "\\r"); + test_escape_char("\n", "\\n"); + test_escape_char("\t", "\\t"); + test_escape_char("\f", "\\f"); + test_escape_char("\b", "\\b"); + test_escape_char("\"", "\\\""); + test_escape_char("\\", "\\\\"); + test_escape_char("\x01", "\\u0001"); + test_escape_char("\x12", "\\u0012"); + test_escape_char("\x7F", "\\u007F"); + } - void test_to_stream() - { - basic_ostringstream< Char_type > os; + void test_disabling_nonprintable_esc_chars() { + test_escape_char("\t", "\\t", raw_utf8); + test_escape_char("\x01", "\x01", raw_utf8); + test_escape_char("\x01\x12", "\x01\x12", raw_utf8); + } - Array_type arr; + void test_to_stream() { + basic_ostringstream os; - arr.push_back( 111 ); - arr.push_back( 222 ); + Array_type arr; - os << hex; // the code should handle this, i.e. output decimal + arr.push_back(111); + arr.push_back(222); - write( arr, os ); + os << hex; // the code should handle this, i.e. output decimal - assert_eq( os.str(), to_str( "[111,222]" ) ); - } + write(arr, os); - void test_values() - { - check_eq( 123, "123" ); - check_eq( 1.234, "1.234" ); - check_eq( to_str( "abc" ), "\"abc\"" ); - check_eq( false, "false" ); - check_eq( Value_type::null, "null" ); - } + assert_eq(os.str(), to_str("[111,222]")); + } - void test_uint64() - { - check_eq( Value_type( 0 ), "0" ); - check_eq( Value_type( int64_t( 0 ) ), "0" ); - check_eq( Value_type( uint64_t( 0 ) ), "0" ); + void test_values() { + check_eq(123, "123"); + check_eq(1.234, "1.234"); + check_eq(to_str("abc"), "\"abc\""); + check_eq(false, "false"); + check_eq(Value_type::null, "null"); + } - check_eq( Value_type( 1 ), "1" ); - check_eq( Value_type( int64_t( 1 ) ), "1" ); - check_eq( Value_type( uint64_t( 1 ) ), "1" ); + void test_uint64() { + check_eq(Value_type(0), "0"); + check_eq(Value_type(int64_t(0)), "0"); + check_eq(Value_type(uint64_t(0)), "0"); - check_eq( Value_type( -1 ), "-1" ); - check_eq( Value_type( int64_t( -1 ) ), "-1" ); + check_eq(Value_type(1), "1"); + check_eq(Value_type(int64_t(1)), "1"); + check_eq(Value_type(uint64_t(1)), "1"); - check_eq( Value_type( max_int64 ), "9223372036854775807" ); - check_eq( Value_type( uint64_t( max_int64 ) ), "9223372036854775807" ); + check_eq(Value_type(-1), "-1"); + check_eq(Value_type(int64_t(-1)), "-1"); - check_eq( Value_type( max_uint64 ), "18446744073709551615" ); - } + check_eq(Value_type(max_int64), "9223372036854775807"); + check_eq(Value_type(uint64_t(max_int64)), "9223372036854775807"); - void test_ios_state_saved() - { - basic_ostringstream< Char_type > os; + check_eq(Value_type(max_uint64), "18446744073709551615"); + } - os << 0.123456789; + void test_ios_state_saved() { + basic_ostringstream os; - Array_type arr; + os << 0.123456789; - arr.push_back( 0.123456789 ); + Array_type arr; - write( arr, os ); + arr.push_back(0.123456789); - os << 0.123456789; + write(arr, os); - assert_eq( os.str(), to_str( "0.123457" - "[0.123456789]" - "0.123457" ) ); - } + os << 0.123456789; - void check_remove_trailing_zeros( const double value, const String_type& expected_str_with, const String_type& expected_str_without ) - { - check_eq( value, expected_str_with, none ); - check_eq( value, expected_str_without, remove_trailing_zeros ); - } + assert_eq(os.str(), to_str("0.123457" + "[0.123456789]" + "0.123457")); + } - void check_remove_trailing_zeros( const double value, const char* expected_str_with, const char* expected_str_without ) - { - check_remove_trailing_zeros( value, to_str( expected_str_with ), to_str( expected_str_without ) ); - } + void check_remove_trailing_zeros(const double value, + const String_type& expected_str_with, + const String_type& expected_str_without) { + check_eq(value, expected_str_with, none); + check_eq(value, expected_str_without, remove_trailing_zeros); + } + + void check_remove_trailing_zeros(const double value, const char* expected_str_with, + const char* expected_str_without) { + check_remove_trailing_zeros(value, to_str(expected_str_with), + to_str(expected_str_without)); + } - void test_remove_trailing_zeros() - { + void test_remove_trailing_zeros() { #ifdef WIN32 - const String_type exp = to_str( "099" ); + const String_type exp = to_str("099"); #else - const String_type exp = to_str( "99" ); + const String_type exp = to_str("99"); #endif - check_remove_trailing_zeros( 0.0, "0", "0" ); - check_remove_trailing_zeros( 1.2, "1.2", "1.2" ); - check_remove_trailing_zeros( 0.123456789, "0.123456789", "0.123456789" ); - check_remove_trailing_zeros( 1.2e-99, to_str( "1.2e-" ) + exp, to_str( "1.2e-" ) + exp ); - check_remove_trailing_zeros( 1.23456789e99, to_str( "1.2345678900000001e+" ) + exp, to_str( "1.23456789e+" ) + exp ); - } + check_remove_trailing_zeros(0.0, "0", "0"); + check_remove_trailing_zeros(1.2, "1.2", "1.2"); + check_remove_trailing_zeros(0.123456789, "0.123456789", "0.123456789"); + check_remove_trailing_zeros(1.2e-99, to_str("1.2e-") + exp, + to_str("1.2e-") + exp); + check_remove_trailing_zeros(1.23456789e99, to_str("1.2345678900000001e+") + exp, + to_str("1.23456789e+") + exp); + } - void check_precision_of_doubles( unsigned int precision, const char* expected_result_1, const char* expected_result_2 = 0 ) - { - Value_type val = 0.1234567890123456789; - assert_eq( write( val, none, precision ), to_str( expected_result_1 ) ); - if( !expected_result_2 ) - { - expected_result_2 = expected_result_1; - } - assert_eq( write( val, remove_trailing_zeros, precision ), to_str( expected_result_2 ) ); + void check_precision_of_doubles(unsigned int precision, + const char* expected_result_1, + const char* expected_result_2 = 0) { + Value_type val = 0.1234567890123456789; + assert_eq(write(val, none, precision), to_str(expected_result_1)); + if (!expected_result_2) { + expected_result_2 = expected_result_1; } + assert_eq(write(val, remove_trailing_zeros, precision), + to_str(expected_result_2)); + } - void check_precision_of_doubles( const char* expected_result_1, const char* expected_result_2 ) - { - Value_type val = 0.1234567890123456789; - assert_eq( write( val, none ), to_str( expected_result_1 ) ); - assert_eq( write( val, remove_trailing_zeros ), to_str( expected_result_2 ) ); - } + void check_precision_of_doubles(const char* expected_result_1, + const char* expected_result_2) { + Value_type val = 0.1234567890123456789; + assert_eq(write(val, none), to_str(expected_result_1)); + assert_eq(write(val, remove_trailing_zeros), to_str(expected_result_2)); + } - void test_precision_of_doubles() - { - // default is 17, or 16 for remove_trailing_zeros flag - check_precision_of_doubles( "0.12345678901234568", "0.1234567890123457" ); - check_precision_of_doubles( 0, "0.12345678901234568", "0.1234567890123457" ); - - // specified override is used with or without remove_trailing_zeros flag - check_precision_of_doubles( 9, "0.123456789" ); - check_precision_of_doubles( 6, "0.123457" ); - check_precision_of_doubles( 1, "0.1" ); - } - - void test_multiple_options() - { - Value value; - write(value, always_escape_nonascii | pretty_print ); - } + void test_precision_of_doubles() { + // default is 17, or 16 for remove_trailing_zeros flag + check_precision_of_doubles("0.12345678901234568", "0.1234567890123457"); + check_precision_of_doubles(0, "0.12345678901234568", "0.1234567890123457"); - void run_tests() - { - test_empty_obj(); - test_obj_with_one_member(); - test_obj_with_two_members(); - test_obj_with_three_members(); - test_obj_with_one_empty_child_obj(); - test_obj_with_one_child_obj(); - test_obj_with_grandchild_obj(); - test_objs_with_bool_pairs(); - test_objs_with_int_pairs(); - test_objs_with_real_pairs(); - test_objs_with_null_pairs(); - test_empty_array(); - test_array_with_one_member(); - test_array_with_two_members(); - test_array_with_n_members(); - test_array_with_one_empty_child_array(); - test_array_with_one_child_array(); - test_array_with_grandchild_array(); - test_array_and_objs(); - test_obj_and_arrays(); - test_escape_chars(); - test_disabling_nonprintable_esc_chars(); - test_to_stream(); - test_values(); - test_uint64(); - test_ios_state_saved(); - test_remove_trailing_zeros(); - test_precision_of_doubles(); - test_multiple_options(); - } - }; + // specified override is used with or without remove_trailing_zeros flag + check_precision_of_doubles(9, "0.123456789"); + check_precision_of_doubles(6, "0.123457"); + check_precision_of_doubles(1, "0.1"); + } + + void test_multiple_options() { + Value value; + write(value, always_escape_nonascii | pretty_print); + } -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - void test_always_esc_nonascii() - { - if( iswprint( L'\x05DE' ) ) - { - const wstring s( L"\x05DE\x05E9\x05EA\x05DE\x05E9" ); + void run_tests() { + test_empty_obj(); + test_obj_with_one_member(); + test_obj_with_two_members(); + test_obj_with_three_members(); + test_obj_with_one_empty_child_obj(); + test_obj_with_one_child_obj(); + test_obj_with_grandchild_obj(); + test_objs_with_bool_pairs(); + test_objs_with_int_pairs(); + test_objs_with_real_pairs(); + test_objs_with_null_pairs(); + test_empty_array(); + test_array_with_one_member(); + test_array_with_two_members(); + test_array_with_n_members(); + test_array_with_one_empty_child_array(); + test_array_with_one_child_array(); + test_array_with_grandchild_array(); + test_array_and_objs(); + test_obj_and_arrays(); + test_escape_chars(); + test_disabling_nonprintable_esc_chars(); + test_to_stream(); + test_values(); + test_uint64(); + test_ios_state_saved(); + test_remove_trailing_zeros(); + test_precision_of_doubles(); + test_multiple_options(); + } +}; - wArray arr( 1, s ); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) +void test_always_esc_nonascii() { + if (iswprint(L'\x05DE')) { + const wstring s(L"\x05DE\x05E9\x05EA\x05DE\x05E9"); - const wstring foo = arr[0].get_str(); + wArray arr(1, s); - const wstring json_raw = write( arr ); + const wstring foo = arr[0].get_str(); - assert_eq( json_raw, L"[\"" + s + L"\"]" ); + const wstring json_raw = write(arr); - const wstring json_escaped = write( arr, always_escape_nonascii ); + assert_eq(json_raw, L"[\"" + s + L"\"]"); - assert_eq( json_escaped, L"[\"\\u05DE\\u05E9\\u05EA\\u05DE\\u05E9\"]" ); - } + const wstring json_escaped = write(arr, always_escape_nonascii); + + assert_eq(json_escaped, L"[\"\\u05DE\\u05E9\\u05EA\\u05DE\\u05E9\"]"); } +} - void test_wide_esc_u( wchar_t c, const wstring& result) - { - const wstring s( 1, c ); +void test_wide_esc_u(wchar_t c, const wstring& result) { + const wstring s(1, c); - wArray arr( 1, s ); + wArray arr(1, s); - assert_eq( write( arr ), L"[\"\\u" + result + L"\"]" ); - } + assert_eq(write(arr), L"[\"\\u" + result + L"\"]"); +} - void test_wide_esc_u() - { - test_wide_esc_u( 0xABCD, L"ABCD" ); - test_wide_esc_u( 0xFFFF, L"FFFF" ); - } +void test_wide_esc_u() { + test_wide_esc_u(0xABCD, L"ABCD"); + test_wide_esc_u(0xFFFF, L"FFFF"); +} #endif - bool is_printable( char c ) - { - const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c ); +bool is_printable(char c) { + const wint_t unsigned_c((c >= 0) ? c : 256 + c); - return iswprint( unsigned_c ) != 0; - } + return iswprint(unsigned_c) != 0; +} #ifdef JSON_SPIRIT_VALUE_ENABLED - void test_extended_ascii() - { - const string expeced_result( is_printable( '\xE4' ) ? "[\"\xE4\xF6\xFC\xDF\"]" : "[\"\\u00E4\\u00F6\\u00FC\\u00DF\"]" ); +void test_extended_ascii() { + const string expeced_result(is_printable('\xE4') + ? "[\"\xE4\xF6\xFC\xDF\"]" + : "[\"\\u00E4\\u00F6\\u00FC\\u00DF\"]"); - assert_eq( write( Array( 1, "\xE4\xF6\xFC\xDF" ) ), expeced_result ); - } -#endif + assert_eq(write(Array(1, "\xE4\xF6\xFC\xDF")), expeced_result); } +#endif +} // namespace -void json5_parser::test_writer() -{ +void json5_parser::test_writer() { #ifdef JSON_SPIRIT_VALUE_ENABLED - Test_runner< Config >().run_tests(); + Test_runner().run_tests(); test_extended_ascii(); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED - Test_runner< mConfig >().run_tests(); + Test_runner().run_tests(); #endif -#if defined( JSON_SPIRIT_WVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wConfig >().run_tests(); +#if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Test_runner().run_tests(); test_wide_esc_u(); test_always_esc_nonascii(); #endif -#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING ) - Test_runner< wmConfig >().run_tests(); +#if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + Test_runner().run_tests(); #endif } diff --git a/json_test/json5_parser_writer_test.h b/json_test/json5_parser_writer_test.h index a6eaf77..b1caf5c 100644 --- a/json_test/json5_parser_writer_test.h +++ b/json_test/json5_parser_writer_test.h @@ -7,12 +7,11 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif -namespace json5_parser -{ - void test_writer(); +namespace json5_parser { +void test_writer(); } #endif diff --git a/json_test/json_test.cpp b/json_test/json_test.cpp index 6cf579b..bc7bad4 100644 --- a/json_test/json_test.cpp +++ b/json_test/json_test.cpp @@ -3,20 +3,19 @@ // json spirit version 4.08 -#include "json5_parser_value_test.h" -#include "json5_parser_writer_test.h" #include "json5_parser_reader_test.h" #include "json5_parser_stream_reader_test.h" #include "json5_parser_utils_test.h" +#include "json5_parser_value_test.h" +#include "json5_parser_writer_test.h" -#include #include +#include using namespace std; using namespace json5_parser; -int main() -{ +int main() { test_value(); test_writer(); test_reader(); @@ -24,6 +23,5 @@ int main() test_utils(); cout << "all tests passed" << endl << endl; - return 0; + return 0; } - diff --git a/json_test/utils_test.cpp b/json_test/utils_test.cpp index a6f3e30..3ddc599 100644 --- a/json_test/utils_test.cpp +++ b/json_test/utils_test.cpp @@ -5,11 +5,10 @@ #include "utils_test.h" -void assert_eq( const double d1, const double d2, const double abs_error ) -{ - const double err = fabs( d1 - d2 ); +void assert_eq(const double d1, const double d2, const double abs_error) { + const double err = fabs(d1 - d2); - if( err <= abs_error ) return; + if (err <= abs_error) return; - assert( false ); + assert(false); } diff --git a/json_test/utils_test.h b/json_test/utils_test.h index fd9fa53..e2364c0 100644 --- a/json_test/utils_test.h +++ b/json_test/utils_test.h @@ -7,7 +7,7 @@ // json spirit version 4.08 #if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once +#pragma once #endif #include @@ -15,22 +15,20 @@ // these functions allow you to inspect the values that caused a test to fail -template< class T1, class T2 > -void assert_eq( const T1& t1, const T2& t2 ) -{ - if( t1 == t2 ) return; +template +void assert_eq(const T1& t1, const T2& t2) { + if (t1 == t2) return; - assert( false ); + assert(false); } -template< class T1, class T2 > -void assert_neq( const T1& t1, const T2& t2 ) -{ - if( !(t1 == t2) ) return; +template +void assert_neq(const T1& t1, const T2& t2) { + if (!(t1 == t2)) return; - assert( false ); + assert(false); } -void assert_eq( const double d1, const double d2, const double abs_error ); +void assert_eq(const double d1, const double d2, const double abs_error); #endif From baf3bddc6a2d7f8b4fdb489d9483ccfaf7ec15a0 Mon Sep 17 00:00:00 2001 From: Judith Silverman Date: Sun, 12 Apr 2020 12:17:31 -0700 Subject: [PATCH 3/3] Port to Debian 10 The port was complicated by changes to boost::spirit which I was unable to pinpoint. json5_parser_reader_template.h: new_identifier() now trims trailing whitespace no longer trimmed by boost::spirit parser. json5_parser_reader_test.cpp: test_reading(): reformatted and added test case. check_reading_arrays(): added "unget()" to accommodate change to boost::spirit. json5_parser_value_test.cpp: tweaked to accommodate change to boost::assign::list_of(). json_demo.cpp, json_map_demo.cpp, json_headers_only_demo.cpp: Added "sleep()" call intended to prevent unreproducible "read" failures. Added print statements to test source files. wscript: Replaced "-Ofast" with "-O3". --- json5_parser/json5_parser_reader.h | 2 +- json5_parser/json5_parser_reader_template.h | 25 +++--- json5_parser/json5_parser_value.h | 2 +- json5_parser/json5_parser_writer.h | 2 +- json_demo/json_demo.cpp | 3 + .../json_headers_only_demo.cpp | 6 +- json_map_demo/json_map_demo.cpp | 6 +- json_test/json5_parser_reader_test.cpp | 89 +++++++++++++------ json_test/json5_parser_value_test.cpp | 48 ++++++---- json_test/json_test.cpp | 7 +- wscript | 2 +- 11 files changed, 129 insertions(+), 63 deletions(-) diff --git a/json5_parser/json5_parser_reader.h b/json5_parser/json5_parser_reader.h index c183140..b41ad9d 100644 --- a/json5_parser/json5_parser_reader.h +++ b/json5_parser/json5_parser_reader.h @@ -64,6 +64,6 @@ void read_or_throw(std::wistream& is, wmValue& value); void read_or_throw(std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value); #endif -} +} // namespace json5_parser #endif diff --git a/json5_parser/json5_parser_reader_template.h b/json5_parser/json5_parser_reader_template.h index 2ddf9ed..be9950e 100644 --- a/json5_parser/json5_parser_reader_template.h +++ b/json5_parser/json5_parser_reader_template.h @@ -10,6 +10,9 @@ #pragma once #endif +#include +#include + #include "json5_parser_error_position.h" #include "json5_parser_value.h" @@ -248,7 +251,7 @@ class Semantic_actions { String_type result; result.append(begin, end); - name_ = result; + name_ = boost::algorithm::trim_right_copy(result); } void new_str(Iter_type begin, Iter_type end) { @@ -359,15 +362,15 @@ void throw_error(Iter_type, const std::string& reason) { throw reason; } -// the spirit grammer +// the spirit grammar // template -class Json_grammer - : public spirit_namespace::grammar > { +class Json_grammar + : public spirit_namespace::grammar > { public: typedef Semantic_actions Semantic_actions_t; - Json_grammer(Semantic_actions_t& semantic_actions) : actions_(semantic_actions) {} + Json_grammar(Semantic_actions_t& semantic_actions) : actions_(semantic_actions) {} static void throw_not_value(Iter_type begin, Iter_type) { throw_error(begin, "not a value"); @@ -400,7 +403,7 @@ class Json_grammer template class definition { public: - definition(const Json_grammer& self) { + definition(const Json_grammar& self) { using namespace spirit_namespace; typedef typename Value_type::String_type::value_type Char_type; @@ -445,7 +448,7 @@ class Json_grammer Uint64_action new_uint64( boost::bind(&Semantic_actions_t::new_uint64, &self.actions_, _1)); - // actual grammer + // actual grammar json_ = value_ | eps_p[&throw_not_value]; @@ -472,12 +475,12 @@ class Json_grammer double_quoted_string_ = lexeme_d // this causes white space and what would appear to be // comments inside a string to be retained - [confix_p('"', *lex_escape_ch_p, '"')]; + [confix_p('"', *lex_escape_ch_p, '"')]; single_quoted_string_ = lexeme_d // this causes white space and what would appear to be // comments inside a string to be retained - [confix_p('\'', *lex_escape_ch_p, '\'')]; + [confix_p('\'', *lex_escape_ch_p, '\'')]; identifier_ = (alpha_p | ch_p('_') | ch_p('$')) >> *(alnum_p | ch_p('_') | ch_p('$')); @@ -494,7 +497,7 @@ class Json_grammer }; private: - Json_grammer& operator=(const Json_grammer&); // to prevent "assignment operator + Json_grammar& operator=(const Json_grammar&); // to prevent "assignment operator // could not be generated" warning Semantic_actions_t& actions_; @@ -543,7 +546,7 @@ Iter_type read_range_or_throw(Iter_type begin, Iter_type end, Value_type& value) Semantic_actions semantic_actions(value); const spirit_namespace::parse_info info = spirit_namespace::parse( - begin, end, Json_grammer(semantic_actions), + begin, end, Json_grammar(semantic_actions), spirit_namespace::space_p | spirit_namespace::comment_p("//") | spirit_namespace::comment_p("/*", "*/")); diff --git a/json5_parser/json5_parser_value.h b/json5_parser/json5_parser_value.h index 6fe4e32..ecb8bd2 100644 --- a/json5_parser/json5_parser_value.h +++ b/json5_parser/json5_parser_value.h @@ -46,7 +46,7 @@ struct Null {}; template // Config determines whether the value uses std::string or // std::wstring and whether JSON Objects are represented as // vectors or maps - class Value_impl { +class Value_impl { public: typedef Config Config_type; typedef typename Config::String_type String_type; diff --git a/json5_parser/json5_parser_writer.h b/json5_parser/json5_parser_writer.h index 66afedb..8850067 100644 --- a/json5_parser/json5_parser_writer.h +++ b/json5_parser/json5_parser_writer.h @@ -73,6 +73,6 @@ void write_formatted(const wmValue& value, std::wostream& os, std::wstring write_formatted(const wmValue& value, unsigned int precision_of_doubles = 0); #endif -} +} // namespace json5_parser #endif diff --git a/json_demo/json_demo.cpp b/json_demo/json_demo.cpp index 7f8415d..14fcc36 100644 --- a/json_demo/json_demo.cpp +++ b/json_demo/json_demo.cpp @@ -8,6 +8,7 @@ #include #include + #include "json5_parser.h" #ifndef JSON_SPIRIT_VALUE_ENABLED @@ -103,6 +104,7 @@ vector
read_addrs(const char* file_name) { } int main() { + const Address addrs[5] = {{42, "East Street", "Newtown", "Essex", "England"}, {1, "West Street", "Hull", "Yorkshire", "England"}, {12, "South Road", "Aberystwyth", "Dyfed", "Wales"}, @@ -121,5 +123,6 @@ int main() { assert(new_addrs[i] == addrs[i]); } + std::cout << "json_demo tests all passed" << std::endl; return 0; } diff --git a/json_headers_only_demo/json_headers_only_demo.cpp b/json_headers_only_demo/json_headers_only_demo.cpp index 0730c96..4ea4379 100644 --- a/json_headers_only_demo/json_headers_only_demo.cpp +++ b/json_headers_only_demo/json_headers_only_demo.cpp @@ -9,6 +9,7 @@ #include #include + #include "json5_parser_reader_template.h" #include "json5_parser_writer_template.h" @@ -112,7 +113,9 @@ int main() { {45, "North Road", "Paignton", "Devon", "England"}, {78, "Upper Street", "Ware", "Hertfordshire", "England"}}; - const char* file_name("demo.txt"); + + // Changed from "demo.txt" because tests were failing. NSF weirdness? + const char* file_name("/tmp/json5_demo.txt"); write_addrs(file_name, addrs); @@ -124,5 +127,6 @@ int main() { assert(new_addrs[i] == addrs[i]); } + std::cout << "json_headers_only_demo tests all passed" << std::endl; return 0; } diff --git a/json_map_demo/json_map_demo.cpp b/json_map_demo/json_map_demo.cpp index 34cab7b..3210e02 100644 --- a/json_map_demo/json_map_demo.cpp +++ b/json_map_demo/json_map_demo.cpp @@ -8,6 +8,7 @@ #include #include + #include "json5_parser.h" #ifndef JSON_SPIRIT_MVALUE_ENABLED @@ -103,7 +104,7 @@ int main() { {45, "North Road", "Paignton", "Devon", "England"}, {78, "Upper Street", "Ware", "Hertfordshire", "England"}}; - const char* file_name("demo.txt"); + const char* file_name("map_demo.txt"); write_addrs(file_name, addrs); @@ -115,5 +116,6 @@ int main() { assert(new_addrs[i] == addrs[i]); } + std::cout << "json_map_demo tests all passed" << std::endl; return 0; -}; \ No newline at end of file +}; diff --git a/json_test/json5_parser_reader_test.cpp b/json_test/json5_parser_reader_test.cpp index 05257ac..8fbe9f0 100644 --- a/json_test/json5_parser_reader_test.cpp +++ b/json_test/json5_parser_reader_test.cpp @@ -203,36 +203,52 @@ struct Test_runner { check_eq(value.get_obj(), obj); } - Object_type obj; - Value_type value; + { + Object_type obj; + Value_type value; - read_cstr( - "{\n" - " \"name 1\" : \"value 1\"\n" - "}", - value); + read_cstr( + "{\n" + " \"name 1\" : \"value 1\"\n" + "}", + value); - add_c_str(obj, "name 1", "value 1"); + add_c_str(obj, "name 1", "value 1"); - check_eq(value.get_obj(), obj); + check_eq(value.get_obj(), obj); - read_cstr("{\"name 1\":\"value 1\",\"name 2\":\"value 2\"}", value); + read_cstr("{\"name 1\":\"value 1\",\"name 2\":\"value 2\"}", value); - add_c_str(obj, "name 2", "value 2"); + add_c_str(obj, "name 2", "value 2"); - check_eq(value.get_obj(), obj); + check_eq(value.get_obj(), obj); - read_cstr( - "{\n" - " \"name 1\" : \"value 1\",\n" - " \"name 2\" : \"value 2\",\n" - " \"name 3\" : \"value 3\"\n" - "}", - value); + read_cstr( + "{\n" + " \"name 1\" : \"value 1\",\n" + " \"name 2\" : \"value 2\",\n" + " \"name 3\" : \"value 3\"\n" + "}", + value); + + add_c_str(obj, "name 3", "value 3"); + + check_eq(value.get_obj(), obj); + } + + { + Object_type obj; + Value_type value; - add_c_str(obj, "name 3", "value 3"); + read_cstr( + "{\n" + " name 1 : \"value 1\"\n" + "}", + value); - check_eq(value.get_obj(), obj); + add_c_str(obj, "name 1", "value 1"); + check_eq(value.get_obj(), obj); + } check_reading( "{\n" @@ -715,8 +731,11 @@ struct Test_runner { Istringstream_type is(str); check_reading_array(is, 0); + is.unget(); check_reading_array(is, 1); + is.unget(); check_reading_array(is, 2); + is.unget(); check_reading_array(is, 3); } @@ -729,12 +748,9 @@ struct Test_runner { check_value_sequence(" 10 11 12", list_of(10)(11)(12), true); check_value_sequence("10 11 12", list_of(10)(11)(12), true); - // - + // Note: check_reading_arrays() expects exactly this list of arrays. check_reading_arrays("[] [ 1 ] [ 1, 2 ] [ 1, 2, 3 ]"); - // check_reading_arrays( "[][1][1,2][1,2,3]" ); // fails due to - // multi_pass iterator bug, - // use stream_reader class instead + check_reading_arrays("[][1][1,2][1,2,3]"); } void test_uint64(const char* value_str, int expected_int, int64_t expected_int64, @@ -801,16 +817,27 @@ struct Test_runner { } void run_tests() { + std::cout << " before test_syntax()" << std::endl; test_syntax(); + std::cout << " before test_reading()" << std::endl; test_reading(); + std::cout << " before test_reading_reals()" << std::endl; test_reading_reals(); + std::cout << " before test_from_stream()" << std::endl; test_from_stream(); + std::cout << " before test_escape_chars()" << std::endl; test_escape_chars(); + std::cout << " before test_values()" << std::endl; test_values(); + std::cout << " before test_error_cases()" << std::endl; test_error_cases(); + std::cout << " before test_sequence_of_values()" << std::endl; test_sequence_of_values(); + std::cout << " before test_uint64()" << std::endl; test_uint64(); + std::cout << " before test_types()" << std::endl; test_types(); + std::cout << " before test_comments()" << std::endl; test_comments(); } }; @@ -848,17 +875,25 @@ void test_extended_ascii() { void json5_parser::test_reader() { #ifdef JSON_SPIRIT_VALUE_ENABLED + std::cout << " JSON_SPIRIT_VALUE_ENABLED" << std::endl; Test_runner().run_tests(); test_extended_ascii(); #endif #ifdef JSON_SPIRIT_MVALUE_ENABLED + std::cout << " JSON_SPIRIT_MVALUE_ENABLED" << std::endl; Test_runner().run_tests(); #endif #if defined(JSON_SPIRIT_WVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + std::cout << " defined(JSON_SPIRIT_WVALUE_ENABLED) && " + "!defined(BOOST_NO_STD_WSTRING)" + << std::endl; Test_runner().run_tests(); test_wide_esc_u(); #endif #if defined(JSON_SPIRIT_WMVALUE_ENABLED) && !defined(BOOST_NO_STD_WSTRING) + std::cout << " defined(JSON_SPIRIT_WMVALUE_ENABLED) && " + "!defined(BOOST_NO_STD_WSTRING)" + << std::endl; Test_runner().run_tests(); #endif @@ -880,7 +915,7 @@ void json5_parser::test_reader() { // cout << t.elapsed() << endl; -// const string so = write( value ); + // const string so = write( value ); // Object obj; diff --git a/json_test/json5_parser_value_test.cpp b/json_test/json5_parser_value_test.cpp index 554721b..5c650a4 100644 --- a/json_test/json5_parser_value_test.cpp +++ b/json_test/json5_parser_value_test.cpp @@ -341,20 +341,27 @@ class Container_constructor_runner { Container_constructor_runner() { vector vd = list_of(1.2)(1.3); test_container_constructor(vd); + vector vi = list_of(1); test_container_constructor(vi); - vi = list_of(1)(2); - test_container_constructor(vi); - vi = list_of(1)(2)(3); - test_container_constructor(vi); + + vector vi2 = list_of(1)(2); + test_container_constructor(vi2); + + vector vi3 = list_of(1)(2)(3); + test_container_constructor(vi3); + list ld = list_of(1.2)(1.3); test_container_constructor(ld); + list li = list_of(1); test_container_constructor(li); - li = list_of(1)(2); - test_container_constructor(li); - li = list_of(1)(2)(3); - test_container_constructor(li); + + list li2 = list_of(1)(2); + test_container_constructor(li2); + + list li3 = list_of(1)(2)(3); + test_container_constructor(li3); } private: @@ -413,20 +420,27 @@ class Variant_constructor_runner { vector vd = list_of(1.2)(1.3); test_variant_array_constructor(vd); + vector vi = list_of(1); test_variant_array_constructor(vi); - vi = list_of(1)(2); - test_variant_array_constructor(vi); - vi = list_of(1)(2)(3); - test_variant_array_constructor(vi); + + vector vi2 = list_of(1)(2); + test_variant_array_constructor(vi2); + + vector vi3 = list_of(1)(2)(3); + test_variant_array_constructor(vi3); + list ld = list_of(1.2)(1.3); test_variant_array_constructor(ld); + list li = list_of(1); test_variant_array_constructor(li); - li = list_of(1)(2); - test_variant_array_constructor(li); - li = list_of(1)(2)(3); - test_variant_array_constructor(li); + + list li2 = list_of(1)(2); + test_variant_array_constructor(li2); + + list li3 = list_of(1)(2)(3); + test_variant_array_constructor(li3); } private: @@ -469,7 +483,7 @@ void test_variant_constructor() { Variant_constructor_runner(); #endif } -} +} // namespace void json5_parser::test_value() { #ifdef JSON_SPIRIT_VALUE_ENABLED diff --git a/json_test/json_test.cpp b/json_test/json_test.cpp index bc7bad4..ebfb89b 100644 --- a/json_test/json_test.cpp +++ b/json_test/json_test.cpp @@ -16,12 +16,17 @@ using namespace std; using namespace json5_parser; int main() { + std::cout << "before test_value()" << std::endl; test_value(); + std::cout << "before test_writer()" << std::endl; test_writer(); + std::cout << "before test_reader()" << std::endl; test_reader(); + std::cout << "before test_stream_reader()" << std::endl; test_stream_reader(); + std::cout << "before test_utils()" << std::endl; test_utils(); - cout << "all tests passed" << endl << endl; + std::cout << "json_test tests all passed" << std::endl; return 0; } diff --git a/wscript b/wscript index 8017a38..cc52cae 100644 --- a/wscript +++ b/wscript @@ -8,7 +8,7 @@ def configure(conf): conf.check_boost(lib='system thread') def build(bld): - default_flags=['-Wall', '-Wextra', '-Ofast'] + default_flags=['-Wall', '-Wextra', '-O3'] # default_flags=['-Wall', '-Wextra', '-g'] use_packages=['BOOST'] includes=['json5_parser']