From dab707bdca625fc2a5841727d5af4b86516120e7 Mon Sep 17 00:00:00 2001 From: Judith Silverman Date: Tue, 7 Apr 2020 12:17:17 -0700 Subject: [PATCH 1/6] 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/6] 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/6] 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'] From f8c6c015a56d90962e7a2987e3d38f8cdad32b16 Mon Sep 17 00:00:00 2001 From: Judith Silverman Date: Wed, 1 Jun 2022 09:45:44 -0700 Subject: [PATCH 4/6] Port to Debian 11 Added 'waf-1.7.13' and 'waf-2.0.23'; replaced 'waf' with a symlink. --- waf | Bin 90876 -> 10 bytes waf-1.7.13 | Bin 0 -> 90876 bytes waf-2.0.23 | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+) mode change 100755 => 120000 waf create mode 100755 waf-1.7.13 create mode 100755 waf-2.0.23 diff --git a/waf b/waf deleted file mode 100755 index fa386e25fa2a785ccb37ac1005801cdf8f42f200..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90876 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: + WAF='waf3' + def b(x): + return x.encode() + +def err(m): + print(('\033[91mError: %s\033[0m' % m)) + sys.exit(1) + +def unpack_wafdir(dir, src): + f = open(src,'rb') + c = 'corrupt archive (%d)' + while 1: + line = f.readline() + if not line: err('run waf-light from a folder containing waflib') + if line == b('#==>\n'): + txt = f.readline() + if not txt: err(c % 1) + if f.readline() != b('#<==\n'): err(c % 2) + break + if not txt: err(c % 3) + txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00')) + + import shutil, tarfile + try: shutil.rmtree(dir) + except OSError: pass + try: + for x in ('Tools', 'extras'): + os.makedirs(join(dir, 'waflib', x)) + except OSError: + err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) + + os.chdir(dir) + tmp = 't.bz2' + t = open(tmp,'wb') + try: t.write(txt) + finally: t.close() + + try: + t = tarfile.open(tmp) + except: + try: + os.system('bunzip2 t.bz2') + t = tarfile.open('t') + tmp = 't' + except: + os.chdir(cwd) + try: shutil.rmtree(dir) + except OSError: pass + err("Waf cannot be unpacked, check that bzip2 support is present") + + try: + for x in t: t.extract(x) + finally: + t.close() + + for x in ('Tools', 'extras'): + os.chmod(join('waflib',x), 493) + + if sys.hexversion<0x300000f: + sys.path = [join(dir, 'waflib')] + sys.path + import fixpy2 + fixpy2.fixdir(dir) + + os.remove(tmp) + os.chdir(cwd) + + try: dir = unicode(dir, 'mbcs') + except: pass + try: + from ctypes import windll + windll.kernel32.SetFileAttributesW(dir, 2) + except: + pass + +def test(dir): + try: + os.stat(join(dir, 'waflib')) + return os.path.abspath(dir) + except OSError: + pass + +def find_lib(): + src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) + base, name = os.path.split(src) + + #devs use $WAFDIR + w=test(os.environ.get('WAFDIR', '')) + if w: return w + + #waf-light + if name.endswith('waf-light'): + w = test(base) + if w: return w + for dir in sys.path: + if test(dir): + return dir + err('waf-light requires waflib -> export WAFDIR=/folder') + + dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) + for i in (INSTALL,'/usr','/usr/local','/opt'): + w = test(i + '/lib/' + dirname) + if w: return w + + #waf-local + dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) + w = test(dir) + if w: return w + + #unpack + unpack_wafdir(dir, src) + return dir + +wafdir = find_lib() +sys.path.insert(0, wafdir) + +if __name__ == '__main__': + + from waflib import Scripting + Scripting.waf_entry_point(cwd, VERSION, wafdir) + +#==> +#BZh91AY&SY1a&#-Pe(,0M0b<{eЀ#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-:KVFv#2J6gۻt6[6MmF;}]]kZۺO[{ ٳn{nhݷeR=8v{2͹kCM|:[6opȾ#-Oc@QӀ#(ݝ`m뽤t}5i#-uݻG6{`)zSJ#-@E*R9#2$#-P:4UZz{Gzٽޙ^nɘjlZeJkGO#-۽e[޸g]wqRIom{{Oewe__=^= z:0%hYZk'v{[^{n`СxѬ6ZdTS#-( ̗USx#1eS{kqQ}k>3҉#-#-֖muԺ}{;]ym=}/zܡ}|+/ʹuqק oq+Qml[v-s]mӻ̓/{˻{n^c}juí:>aOѭňzioq۷Sk{=}foq1Wl^펯0>ܞO#-}]}ץx$#2H\Lk7kC.BA1:UޘnW]=]-#Bf#-#-wyD#-#-/zr;콙#6}{jwwFn;H{zg}wRSit0}3oD3޽{׺k|[DfzQr]]<}޲wa6{s^uqYăjVP{:we]׷^ xWeWtj㷛ӹzT#-4΢cm{w:8;\;x§uy͌ġ}^ztgЧ[vݵziΏ N{yw|#-9fյ#-וyq7ؕ#2ZHVݜۜ{4mL4U;۝Nꓥ×#13Xӽ1{Zo^;=Wޯ{ϻo F7>^ƻuy7;wwۏO㼣M_-]M&@#-@&FɣC@M?4Ҁ OSA䙈 M@#- LC$d#-#-#-#-#- bh2i15)*yOҞ)jڙ#-#-#-#-#-#- =R!h&bz{CJzzhCC@#-Gh#-#-#-#-#-"HBh#-@Fi1M=4#1#-#-4#-21#-Q@@#- zT)eO)Pd#-@#-#-U/5+1$ |jݦ&FLF(T$Gb#-wt+@3S+2g0.o#ciw/Oj! R0&d)dxʧ+.V0vʱ5>#xJ@ZxXDF串p ``#2Z+mb6mlUI E:N$F$rX 튔EKAPU 2(HS2d,fjf"h"m3Pc RiE6l(LA(jj5Fmi"4KD!HJh$#-5,h`i*m"dZ)e[D BHlLFfc5Pd#1)E %a-#Jmlm6VѦbK3!4D2ɶm4ԔlZl͔&b(*"iE2(6B#hhBI*"#2b6!PH,@2#$!X!fI# )ee3 i,E,ɱ,e!#FҚ`RdQI&&$%D4d$X&e- f Q͈&#ZMIea"IIX*!$J4H` !F(L3cFRjHb iM$"H[b2F̒3bdE(͑&U4Đ)HlX $iJd%Ȧb l XbjIeAF4)&beMY)2&iQ0IAF&R 1`dXLPF2fe-DLjE1#2Dfƅ#2TE"$$cc*iňHRf`Rͦ؈Djd2#2CDR4EM,ԩJJh6FLdȦY#)!H,UhM)i5Dc`LF4*4"mBi2E"d,ȂSd1J"L66X K&2* XR$cc1 2RXYJ&EM(ZhII$2ɲ#)E,ѥ15e"$4J5S4e214fDEh5),f)4,QiHQM(B4mtBT" 1Qح)M5-!j6MFDai2F`%Iȃ134d1))j6d ŋ S-,ɐ&TlHSe,RS#2lfjdEledJe6URd[dh Me-!TbCQFJVMdjEHkD$mbj6hZLQLM14-4m15[$XDRֲC!2k&*F$"i$Vԫ6)MRT,+SHҩdLbВMe#1MeebTi"BƈaL D#1 BѪ QC&M&M%DeE6RA"f%#2J6i i#6I#cd)SL#21#11$d#!4LQJdRP5BT4 JBj-"ͨQ)$ hRE0MIXE,-4) Ě4Yda, jE54ECF)6b)-F#!&@4ؒ2)6I RaId&1M(idF3D $(MF&LBM%$$EEbљl4i$Сd(6(Vid3(b$lD[FjQ&,( RjA B1R6JiB4ILjb2EJ*cI"ɢ)BԢ̔ISbQ*F*dlY5FŚQl+֓"[&*IL)Qa`(4Im$50A2`BJl͉*ed244QAQDjJŲX1h& "4ZYhj$Ze(Ml!j6Ƥ""R#l56*ŴjJUZ&mH5Q*TҬmFIQ f-F+iQQJVf*I52VœlѣXRcFѫmՊDʅDĔF*HhѱM$ژc$FضŦj1eRɶ jM5bh(ё#1Rjo;vlQTI$Im,l{OD&k7)*miE̴_V/JFgsm^v77^nu>m1E'VE7ڳK9a,K#2I$mA??^dg˯'mɌXH_74Ju8gBj?evjŧlNI-I勲rrX?l٩8QhZ!II #dMɍl~47wHLo\үRYA&HYeS\RJH#Mt#-c38#2Pܲ3znhlAL^,0qز w }ۙ4Yt\ɯ&)-)>dzo_VkA;][E0›Bd咬4Dϗ11؞j%?͹r,NN["M+{Ϟ͗7bRSo״1#- ֭l6w^lsES+t^;llOu6Pk+-ȦWȶu.nmBd<|s>6Lf=4vh_;k{۔Ft##1 HzeaۮhMu;GJ̔et9̏[oWt1iu#^sqrjł)G֓Ohƕiu=%MOM,X#2*C#-nҚ )p3ƾ@:?- 6rfLuBY[dl집^~+(2)iD1pq-k#œG'V65ף6&/z3(fV9=;PW}|YH)ɨ>~s=ۻ[&$EQHNBʝɺgFѣBRYm6GƂJ:[2ŔҠwKg~x\/]h٘IP#M+e#2i*Q]Tƈb1A9G,t>!klJ0TTMtehUbZLqW͕7e]iBTTQWL͑dDiGDPaLֶjϽ$![QJ+aCP;] I+^e5Z A~:F;KH~|>8499q#11K0܆%[ ;~㎙L*"sMՆS_mGSN^<=98Q94}Jr;}pu0!it?Xף]|r_4ꅙw`ҟfIC?,Y VԀpBy=-%mEa)3eF^,z*G p:a#[C./̗0t"m#1h5v*F]ǁzU2>l<p"G]dmmLZ$:#cG4Hi:#+PF:E&}ٞvC}X#1 `8FW_fSr#10(Nv3L~Y=g b<R:I2\q.{ϩ,8`=jP4ovpoB9dkrmǨEƽ]nC=6|Z5aSו)FswEw+^{5ZU|#2)˾cT @^ǡ*L yZۍo/[1É ̋e>ؾi[w25^/!*n4WOٿ.RYTNLYP:ZPPNm(7+]}}]Mi Ja>еTE”Tϕr~|Tj+aGR|(ES>lv߿[InC_Y>sչY$OknFx*F5e!ުy8O6S!jz@J[FSJ.]{#m* ҊV'؝j'6ʴOb\Rv/B>?\ Aq#-˨#҆ `098I /NP4QHXE':r-|74c>ގ7DYTN{NБ(<צk8S;?[u2 y=skCjJb)ج7îpv^/FZև|\TGX^rEԒμ/H"")C m쪤<ݥbRhrHطP*#1ͮS">0ȊŊTQΥ DFKύ=!tCDh,I YV˂¤X#14oW,#-@% h#󹚲^!)'.:o1>>!??7tWwrrsY,-|'U㯢;eFÃN=:$ Чej#ܯ1/q [kŢ;CT*D,L}uT;ng z%G6"IDo]9M;aA8Hcr#16 9܊SRϦ H+67ĶSb!ܭvჿRf(PS.O}y^=uv|1G] #1@yFluƜXȘZ1ƲCݵYxh֣DhTTNpCN% 9D9өuꢇmuVFzU/76=,cy^\`˳K|q+wpuI#Z=sazFK4CџF7v:ߒ_Ť\鵚_'eͿ|CidBn##lJ#2sR4ř"{r6uTG(4X Te; 1$V@dR#DT1Ԁ:9R(,4č3=f].ylcV~хb?g3d[ EX)c$E kc|dbrKNzXs3#2 +&j|#2xE\dymqKzvud#2/x@lj9ݶC<#1ӂf0⺒c ^];8ŋqVBnjuJf*D94̰+5OLI ,ڪn7'3#6Hqox6uga>~#1Usf]|У$IDmyȹև/-"QD@zmG1as=<'>(f7@adyQk#-EDL <Q9k-]=wZe"35%#2U2ߑh W5v물,Q#e|gPꔰbI$i#2't̅6#-'n_ON%w5йB6/Kٓ`B"6Ư /#dIzW% in-b;{#eJcfέVgWT$3Yc0kn)VnԬu3M%.l)kZC$3T^fn5#1sp{k\(ۭNl;S)rj̮?m/#1o1o8e:)do6hжFAxkh[hܦo6LlT'8EikGlبX?OL)sد*3ʝ/ykSq(ŨAHoh=KRoF.#Pd{pH.]Ũs÷#2]75hΕD.{%=W/F(5#;D9_y%0Ij[J3NMT9OxcHIeSy֚]"Vm\~[ >@uޯ-6h]d~Mr'߸X(׬(dogÇhiA^3lJYko첊LtZ(a85#1*!= !Ԫ#1ͪÃIΉ^aمXIȅOnd!\9N3t>{lxA(j=#2\ڶӑK48F@h#2fY5Zj֙c^bSߴqۋȤ&X HE^l-kUeľ6N{Ym{i(R)1P^ۖ\3kNJNbDghjw嶔: omr-R P$Qky qFٹL~{Ϫ|_,H}}:yo:&8~rPhʗ̰mߧ*}$Fʁ/<}ܐfH.'Uw|[>M=Æ{y$*j .##-aI3p#18h!ш 0#1f2wZpiWf,`R;/ G1h}4s2eҝ<`u^#1XNźiDbyg(t_iE-y.F/.=:I^NǤҜ4j~ou?vhĜU4KD[鷏e +#-4IC0`| +MɿF㧽jCIε{Oz4z\.TVwG8Ld*#-Kp##xMD|w"#1ŻP 4#-y՘~Pc4uXHqdn4ÓU?ׯo?h8싐H[\(( z :NUwSMH=rH.qQq|"J)?0բɤ[Mw4~^ @̢nҝ_fN`OQ ! ğL@ a#! #-$'oVw卣`vܻ #1cc 2#-@?ӌ#2Lo#-C"JHu(&.wU DR}U7##- TpTX O <1DGP気Wll-(#-VOqPo#2kC, ]%Þ,F9h}\}i }t|kRjcc;4Rf0SM>U\t)3/驟uOOc슻`0l$iwPk mK/2eOsrBd:[3#1qr,GG 7ϣP}x ^#7ئcѓ;Krvdjbg_zupmuQFP\$55AXBY9E\Fb>bi#1 AQݏ"s !!XM%FB(qF!@Yc=ƒ EyzyK8&di%#1bGn~LbJQ;f3t#-X1OF\(7)ɚ{O䭪@=W,]b"8#2Թ{  ^6kp[g* f=>Wi n|&ҕ2ԧ-`y=F5q{m ~e>{A4׮[H8ۨ9CK y'L&)#2#1˩kU9-ʯ((^Sq#|w m=+BE l<5#2Žib[#85S 4#2`#1~H5ٝ>:{?##-1s,9`Z'Ƀ2"ooNiƲ†17ƄNIwSnqMLYj0;Ƚ}xHmmy'Ujue;30Msmp>i$UBiY̨uPY֡1u5V!Uj: 2r4C,C Y(6HAh 5z ާNuCR}x# 0ud#-N_0efeRh,a#IfTQY{ԜKUkAuhM%I(k[F#23-b=cJ4y>3:2(uy!jN#8sy#1bn=>ty3 #C!L97[#2ġ̺-us.ܨQ' czcv!#V:;ɽ:w+coF1Tl[,#1ϟO5엟[ftn5<⬲me>%{q&=t8&abʆ?e,ٟ;%>3SSgC\*5% s5CsDc^8x=#2͖2_]Kv.wu`#G7Hۖ!?͞[LE|y_9^Ѹ01ЛiRH6#1SXSF(ʍ{3ۂbh4\JDq#-6 H N5Plxwj>0َ.Z4HFõW>UzJ);I0FJnԯh? v#1l < ņ+s=EP_mnnԼR˱!}E#2*2-¯2uAO7&#(d@@;gMeC*a t"}~};,dδР$|zkTj;Ͽ䥧`p+:a eI?h­#7͚yx/cZ4ۮ&*8BFzIS᎖bJ☦J(Bwʼb&a0eA2l0uX$qR"wHH>x 9XLs]_}"iУNy'#1&y<42@ 6K|[a#ۤɎ4$;>)͙n$"ص7 hz&`p.`cc[t.V"v/){l7nLice~ԉؘ̼|sb3ӎ7;5l+cBf#1]reZHQBU QCZpٲL8Z!'d8+S!9_TbD*l?f#1B[f)yw0}X`n#-&H:G֚'~(L2uM`IX_>'_v AOLj8+E^LYMn*AjJۖo`C/L7Dz[UMB!()o.-/íCQ?-d\>[Zi,QlFzZmId& 3eK8MlUQFҊhTI?'Xҿ߷8nzɆ8dmv ,PXTR* @I)R Wt/bkSWKF'×ܤ|i>:##29bnȤ(O0"Y4J:3#'&@(AU#1ү#-"aTUS!<v~Z{vFlF'Y(iAX!~S_/$~`r}jDC7گ.c8=cGo틀 9o/klU\kX8~(*q.Bƛg_],jwh~6~X Lovθ$mUHU#2z$?0c€Kޡpվ뭢j1P (+p`3er cRC~-:ݛmR](2t\_ >2. ** 1 =6qv Q}GMbq#c?1 =<(#2.0|^e#b)qPdL]A] $-)[q*FH tFK#TX#-صEVuke둇q?oHKb''%=-k(]ޠ~!:$5KVZg|g?bv$S{KTMxh25%}#-]ҀvHs@%ʼW $'}i#11 J TM_#-^.Lr>SκW('3 b+uih9b@bPB#-ZAB-#EED{ Rszy>}]{xKFb: UKDZ!DRoT:żWߟii٭7V}~L:wp(}GlT:}SRe}UKUz,`]5CAK)Z꯭޶Enf߷Xݳ-ՈX Zh.p?j[u<17k7!_rqiovsly喏t{vǃhТXKVo#2Y1>{0x=CO_K} qH#1Ϲ{3wO>*>>?Mr!< 5JmZ׺-gϯ]%m}0͆^=85U4ѵ|dm|-Z>cDv=o\C(ݱ˵c:$V3#-}ٮ])/P6r)9WvU΂^]>x7xۤѯO)1]YS3<ƿiQyaLˆ,ovQ6#1/_|mݳwn#2sCƺбvUǟMRD8;DXh[11it{?GxJx e^߸=ɇ6#=N8zU_۲6|P؊ﮟ^~nC(S;B/@`rwok/ؠ2@xx}2pU4dGZTR}iϊ_6\2t.m؞o7]g㥵m:?2wbv=#1jiUP#ee9|{7 ߚ+wz}I}`pwul|VJYXINpTX\ʟ7}fȩ@# ;)dj_*WX9ez}?ih]-8Om2ѪQ;1͋K~ZДQB099DX?|r^ag㛯#2ͽ.Qyv)~+?dZL9Y:;ufO~<o'/j?o5O/_^]_xwupKG1E,^^ͮBfN_ (3r<]U=x(\v5ct?5;k@D}S>j>qߏ|lԷ]#1B_7Gwٓק:!u}4'?-"c=Y(4|8#1{bVÿ˼p#-UhI_#Sjg?h)vFfxcغK[OU~3=[HmXn=}UVD}LO'}@/2A=-]_I$!%'i(յE/23kKwyoMե|Y1x|AagNcw6+8t ś|6hZv:>D*}T)8:JU/uhЂiG6}JiuZcӻMS-͑2fq`{s|O#-/`r_xvMK\,/iWz-X=jv$nۂM3B*=ԭT8j0X & #2Jf&c56*hi'oG|L1~+S<& =a5G%u޽NBu!alar(eA(u_OS88G^Gbh1"GGJfm IAH(TQ&Fը,MمUTU@J*fiQըϛL~YtdowA!E]FK#2njeu?#?t_ٰK=*}]1wO>`o;οל;#1]1s|VT&ꮗ|*[mecWj $ow.=~٧ѧQ,$AW#1#-p/QMjߓӫ'p~~z$^o_=ްeNk C7MPTԥ]My+5pog"mƿʯGuB,/uz%0=5hq_;cFmxUբEm(dR+Far*Cvҭ7z̥Q&5׭נt`ZONE1J Gakhh@e;n0SCUZڌF0DV7FpmdI7#2F5ېMȠ`B#1Qfbpuںl611fD3#2ΕE> ;Bx [ZXJc?#-\oK#2kSyhlbbeCN"GDtdHA(6ESh##2*1H!!'Khl#21$Jb H{ ~qa(NUT7Vc'u'Fh2_;y:?Ix_;O`QKthz}O\=g#**_uy"X{3\\QzA=ɰQJTh!<=2 H~R3MqOʽUj㪳WχCpe8~/ &~Cb|]gϹg|0#^U) Tnt؈mƈ#1= 7=7+k}PYN͓:1i}dGe)ua!\}1UMB_:/ֽR0ː*镞z!U($٬[heU4%#-u?їM%і( ݉YCFFdk>Ny~#{~hy^ ˢ$H#6̈=(R0 i KCۦR6kOZ,[W2ajViVEXf h#qTS3 (4Ej,&-/؈L{#[VuYo ߯@V5Ja jFʘYsdX1HȺ% jEfޭ:m6,鸙D63h2@PL&#-Z7rƣ-oFVF#1ut(%lҬeɶ*=SѣAݏn0C^e]w u끹(Ik V߅NМ#x8$tAb'~m :˓#1^uJH#/5BРhcŘd/YM8a#2y{sq8"2ӿb=4Ǐ?(xiBtz3?<bŅUO•T@/WHԎqqť%N9U]:R7Sq;Y:EA1!Dg{l=qzM7BvGlf" iHۍˆDCiޫzh㧼b WFQDOU)t&ϺM[1@|t>PALmENsHKK҃93Ŋ#2|kjmYۆXC~6?lY#2AT8p@Q}Ͷ3U\(L6860&Ì޳BLRr8;\;$3 #2|_Ĉam犁'W`=6V&sGMeuv7jHpm!& HHc,_>F:Ƶ-#-ƼP>QcV+UZL]IK*Nj;c`om;F2iJ-8Mk]+I(5#2#GFFK~6uQuvwPVM%*78(6]qq(5#1k[r+V;B'F)9;6TZfP;5KM1dፑXe '91#2A䓜lQHK]naZu `my&֤ȃ#1e{V6&-g[3hM_y*q=s^NII*JC1OGi/_~NX7Za8!U6#1}#1%dIF6$,5\m4b-TM^"R".f哽FrI5Q&㨇RVLCLe/ZFUB@␲||†LHT>D*}B`0&FtEs_`0c&/taNٽuçw/+#2Lj-,Sv~:Ki!>CЉgnqX#1ԏM_}biRYQTe*mX7Hr*L#27'm^YtNWd:/VRͲc pFiU|,nÄg* L(Ŕ:gMP_Okc֯ -[AJ6E;҃(;te4su %;Qc3X vdzksOJ%闕kMuӅƎO'0Ɋ:PjuO]hgqSgq='=5)7Q쬃X,cm|)M{ o1g%q/G_ݺݣL!Ե80]I 9G)+w%8#1FR/(?7sGTNnQ 9,=UDyΏZVۃ+ů=c][|#1U_1 28|.zߛ򯢍#1VۀqBlq@P<K28w01!Sb PWi]uܗ\p 08'h #-!!(#21VƍG+;hJ8*& >%RYpP+r y]A.X 9yos&ǡ8.}TusEZ!owp|Mb F8{`BtfθO2?=s7 ď^qBU>SP7x"ner(AF%6L[2;BZ#24d[pP{>ǿտ3t|G^nJwoYLDU;;Q vEx1 |ﻮ6]滷N+EIEbVR ([;_mtGIRN4ew\P݋5(>BޚNќTCpM_=x噺yB5ьNyLjoLk.˞N=_t&aY7ϒ 8y#2E6rhϬ^g[{7jhKѷC[-ux <jif#Yׂ1a\1M?KZQMvڟ;╏#27_f4Ɍq^nM2s=^3'?&(~ ]NcB9~Q8672{[uY4bG6‚HcA9:vßL ԅ?V/`"8ǀu飢M,ͱHʙ`Z)U̅.Cx=8!1ȣ 3"нĽvwbl -r<0Ywnr=ӆ;-=F0h\%B[iӮOU/;d&Gyݧ#1d#11YfCM|#1U`Ɏ"߇c0$1|Vޞf08# t EdV;99~ܻx)kǃٚORtK`ETjްQDT}mq߳2#25ε{Cjo(Vxfᯗ^Sސ\'R!ًhf;C;N* r4+2Ӄ>Q9\`>۬nqFד;7Z%XpvG&2U a/*tƭzA!T`A+%s,M#s뮊V-V>QET <ωՒ'lļpHUVoec3 ɴm ٬jwr jrGE/A!\jl>bE#2!si+UKgnM,M#2յ^}xBBHӔ,<>w9K#2M9շA#s`Oa~sP8s5鉏CFBΎ6|Z< z'#PF*0W{UF%6z~!/Kcjьs;ۉڕ|."vd$Gd]..EEp;94oOK|܅գ;L= ::(~%ڑHIj/W=}㩮0kO<%ŁOg)Uxmt0Kx*VfFVۛ[hr$޴:#CcDOtߚ"7Q0t>_at-b$LȂ߯ǭ:DX\愦5 6/-Į$Ҷ|ļkgX3qSghOF9;bOpoc'UD$ϕ-O``20j⚛?qMW[6zta*} 6EOmµ-^#2 ΩƐJUC6!H$oJwKRs>RaEnzSEˎ!O!$t|g@eٍ44ʖܴsj +$uT]u<:rNIKM$Wѝ0b$Qd0;5rе:MnsWXtF͍s#2{ZHA9&UU1},%gX'g(a!B$#1+j"8ϓ0o-e#29梩u|]Cu!qʞ!\M|~ފmq#~H#2<~H̲x!]=][J^TF!N#1r_ߧbS<U F5c o!uYe)gjێ㇛5&gPk;ZsÉDmyL?q^Ngդ:8덺5c"+-L2̮Mj# "DֳstjGLA#1:D&/Ϯ靶dVMreVѵK KM)U;,= xSg>O1]\Aع'j*hl/u|bw0 #23Qц*&R<XO, u`L_o٪LKRQ6hf2ngsT$Xr=ްRc^+ZmH% ?}$$n!i)#1nB#1 sT-(r"dF.oܱGKwڳGcۍA |{eպuh>$hU:f-r)p·f@p(@3y'"%k,J ͵MΗخsn4seM)g(eP\ k2;P G?QWhUW% M h&F&}#13Rd/alGN&X8m7fuAǹ]2ׇC&r[0g=bh7HOmUc꒴w@9RcTkimb :#2mjIf%ZlP{nZ}Qg䷷\љ~kvQZ!mNd[ƄVMrpo rH,#21C~iɃO]l'OOd Js_tHcs{5.ߡ%j{p2WUr#1!:֘@embTvaXRUU 7R*,ga.W40G<س2A#ۭ߿޸jgt[zLE;<Ϡu+s #2# < P{@dI?-UfRDcyeO}kR?*tl*8̵R$*/c 9n4aK&{0:D2iOL;-;9"WG][`,>7$9η9|a%tOE׏ꍷ~M#lFhқrMbf!\ACht[qv ^w7ڎh*fAs}51ZWB^JUM^p!L!ŸUӫEUe}+F!~0ckdT#2f=)h=Xfg~CA-En$HLM__Y=c'jN[:B*.)F(= 66M1@|]f.s۞(::l=~|Yw'ൔ8+=kӵ؋5j+k$3RLv+2HR+ rيmdYy:6as}9ڣ̈́k6"*rHE@#ިɦ:c7[7u 49ѹg f5C3v=!Zl\^2q6ɇt%,tFn_\T Rz |'+}loE}B;G 83h+(ju)9&Bul)@QpoOu-)* ç4Н셥^[?5!p99E}Jf#-4lVܴ AWX\д99kCvYބCXK uvFL$Px}DywP>o>x:b3`<9Ko,w="<DBN#2үE\D͋RNw^hB-L зUr7bQTxCs:i8]m#-ƜULfi#w)T[ǛYr~Ziq L$cfnj绣D-8}r!eg]0^2VOM*b7{b>|#1X،`! A (e\pr?>k/۔jɽDRq5,l:El7 "%U>wVn%8bPC(Cpt<4שU=}胠/`mk1B+6Xrsy |v_.2o$#1䲤W3&8fZX,eٽ>I hdYKon'%F/+Q Q`sqG5]nAq$s=>Ӭ?,; =>o}v"_ 4dRRZ"B_ЊMW0w9Mj~95'JbO5ohq`FZڮ@mmpkefõFctmFhMr k^Ga^#m#1#2ul*(%.QayFSA#-q3r9 1X}9#1rT<5]q~ʨ<B1F!#2Ha v#2$#-?@9GC'S^X $8@".@@>\4O72rH<P @rR=#-Sկ#-cG9xN\cQT<#29^ )Yʻ8)0~>F:s}؟:/>d*T:DYqqaE@RBBUSD;N=mulJ"0o"c' <%P#@q>ROA}#1h+ g($8PҀ5?]U#2'+s**#2>d҉n̡`W{{ (켬#ѭSp AP#1xJ#-|G&kMJ/H$wY8+Bb;B˖k  fSQ#-rP\ ܠXt@äB=TLdG&(r,#-!n`Eu؅,"jKA[&TE5),dEI:\tQPY#2/ace(lJ4.tXAİ"YT$*Gt#24(4*=`@PKޙ Wr5x]#1$ڛrn Ufߜ^{=j~zp)\uU2p️уVtde;68#16lTx4XC); +F3s ddOCdGV[kj:ɦ.%8L/U]^`NUΙy&\}天DE5MbӍXHj~ h_#-6uA &ǁ`;&$!S4f̔ŏ8$f EUTe@$hKmnx'takg=7%*vnT34_:"1"(p*dP!(+iןN#2jMH"Bvheϥ#2]ЛD\i*Hla54+qtvappX#10P{H6*i!`ԀFv5(nC}sI?7ʛYIߩ29OcBz#[0 m4#cdgvdzdb+NlS#-;K"U~+7eVJbսJ5o%ʵIF ,'3U_GϦIzF. F*(Qj6xIyz@+#1-7@Â\!{!r&x) 5ʲ@by&_6!GF )|;ǍC<'tsH-hE_[_ׂ@^wL)dx7O#մk5JsFT9WlQIIoWksTJ2@Z"Tlսﶵ/ر`̅$HU(:MtJ:k;zߠxv`#V&0B"#2@Y%(9ҎgL%#2VFE F 22U!7yqFtԁ=gff@(#2=LW#1N<ϳEMUc>G^1`BJC]x3/7vjRJe0TP Ӿj/@{|8aWoB"cɨ4 p~(!Cb=w-S-Oc%F=6ӶD)@m\#D=8~Q01C=rgBmV.(;. ݍb7ηsKf }>-voY-N{+|j}wN>Qζ{^E︸ه}QuNPѷ 9:|{,Im$>,$v!׻7B(\L* ;mB$ӗk]SJDy>%$U^ Pپ/ `;c Ra39x78 *Zh~ݔ1!4He:n tMDَ%}/곬t։ΎX* {'icLB"YPOi$!#-6><*]rm[♰#5ǯ\4\qeԮX=bPe~*ulD?]/fA~N}bl6ǐH$I?̶]̯D@cW]Kd7k3Ŧ,k^>RtCb<'|7]G(ʂDC(boO4inOUk,V;H#1PQ{ӷ'BΤRuڹiDi6mI)6־^sd 3G|7OZyVxaUd8΀`>,`^-j15V8;>eP#-P׍K-<*x,Ԕl~u7aX:0!!ޕ:#1v(ʼn3XnNG`b7&$g/a  cgĤKO?fPa@UѰ#Z~(:0`(@P#-}k;?ǃrOV Aҷ'v/eWȖx32}V'_§en{lp)qE;qNuY_܋;~{#-ŝDjd݊4 ߟd&-Vdt)FH)#1r<+#1n✼wڲD#uaHk!)'_·]%|_,Th?l( p[^x"i DO_o_KQQu'**4EE>oƕNp [UӋ8>+349#2Ă "w ^Z'ĺ2$#.]8L[Oߋ|dEP IC?|ss*}-{q$#Ig|;9cH0iS!?2P!mܡi)_?g?1k9 e5J]ԩڷu_4&BT*E:6&ΠC&#b`$X'KTAQeμ?7 #-Cstb$ ,L˖߭#-!%qYD-5lifɰa6C{ps?76>T(ŸD+ODK#2=Mcﶴ'#1YNʦ1EGݷe†zʩ KtDH@H!#)(rOΞ\^.X>Wg)F$'1P0/#ygesc&el?|4HDz ȹÆ^rU-]+UGANU'Y-|WK03pDO *H<\::8y`YwR?%춹\|d%7z,*>!СE@#--n&GJř[c)pHNΪ}&c>ҿG#2过 TK,.]O  {PhƐ,zJ#-#-s?P^O.XMe;eӰ ,G aEu={#-E ?rz;m^'祑zy%}#1C#-@2AwD2SwCs_̀@#-+d1-qX#-yŹ39#-{}7޻"#-΃j4BՁՌ1IPfģ2zvmC֞~eWOhxeCTg2 FC(>xBe4#-6UHBmǣFh6'&#-`2YUӜZ#2x;N!G7@A!BBd@7>uo!iv9ǝoT?݂=CX`۹u_*lX閬&3qԼL~2g#-f=3sZ7=*\}[Pt|<5Bl#-vU(/t#-Z~D?z̻u`O%jP_nb'^u#1mi_Mv2}c/@#-@b^|;[;eAb@6Fvc1uYW^.t5pxq*4B$3W^P#-;֢ϭpa#- w>b;@=0,)"-aR{Njz檴`ۨ]cRpkQSN褑掗.?_{Ӣ՜\ofQ} wZkV<ֽ3g܃Jm1LDU2wIJQUMy6؇^Ec҈[?[WYqfD.^!!yKyxCufҕ%u6>MKES0a#2(5q#2SP$G)\<`eCPTfPF82}7_ka`+ZXF#-ïc?eVǞ#2ߏ_X(9>Of2 }`ı!#1[-3+Z 隈0Rdi^QY|WDٵGOw}!)he6dv=6UZW+K -+h~X5J]vĺBIA#N~ڜr\1c2cG1V͙rJy{o=9t;:3y=X3;h(ɉ_}f8\[Ekv=A~+ |yLz䧈SW5ߖ,2X~K' ^/MNǕx#1}Q.oly$E{CmF7o̮h ߪAK=hj7Β?O9<6ڊmTZ}\ Xձ#2`]*'y0;͝8ޝ~zsCLH%ȵڝG}j{_]Fٜ_zv"lgH/Tӳl{l(N5bq ІS.t%nOf#XaJr{oi}}'#2ÒIBLy߸[ѫU/(beWHs_c9#2=*P#2Cm/{Jmی+X6k)F/=~Is*T< ,YZB#2'6y,/Y4Nq+~0l{|dD۟""N]8o4Y.E42r+ܦҾ1aN"{#kq۸A[mgTŮ#2`98.)Sx^.);κǦd񨟓0xiws!'B[=BWkIgM#G^ H:sX3kF(p KclϽX.!Ԅ#\o?!-sR/7'ywVު2&D14'ufDΩm&#2W|3V3'[}!cATkw|T"xwY1ˆ#2r@(h[To`!XQBr yg5ܪ{( mcA5c |l8>ьNWEݽ@Be#N<;_\ߵD{9-9ڄy9N] Z# pN)| z}x 8җwKނl<2$$QqNQA݈ԻL8;ol;Agq~F=)8q~>٣ρ7ʽ8uChM*ɆzN2/g/l?#13#1#ϤQ9ɇ/!G$;PP4=Z~xOs̛z^O;谉)d!7b>7m? k$~NǤlW>ϳ:I à\#0Wh<"/TyJ1]xi)ؼi'Sf8P`|Զ Q*AF}1$T"~$#1YqrA@f#-+ 54 =;p>޲)q,&IO# zeO$>hf) #1OxBDbE\yw;9q34Ƚ4otj;#2`Mjê#-~(T:~̏J7Z~X88iTbP]C9Pjg\d;$9* k34{tx: %#-,aebT:q#-jR}=jnCE#-}zT)AY`A#2K_Is6 P!DA&N0#2#zY*Mt tl,tgg2jbON@2q7&-#2SmLzP>:Q8w76NWU(~'q>D;#]jQ%x.-\mcЪjQR?#,3|;rџqeYj~ieu'ݘe;gTO sQАyA@Ǘ `Ic04mTԯmߓWIyC?hӶQBT#( 'U|R8^M#1ۖ<`?EJhDp͓èM<ӪnU[EmځA/o5\xj#1ȅЋe["Bc VǮhh$~5E Qg֥||BJD*2iy(ZOo{onX(u.R#ܕ‹>I-CQ{>oztm>:{+mb_\AR(]{bȤ^?YɄ&?fVls;ز8"#F{)G]cNWL?$#2׳IXL9<'휇( oT!ؠT>(SHV#2%夬1^#UeM73vnu _놩x/7n9p8gN"4fفBQ#158.Os;8{$e*[墫eVNۤnyYi,'d #1}(FOONN/8J&c޸A$]TG\ˈ2Ӝ~*Eۑ"c|T<2V3#x#2^ƠKYՎ7 CqՇzv~6Gy#Ze됝}K#2tDZ#1WLK犫[E=/+A6)~NZYh#nCDmO].7ֈ\Gtttrj-s1W(9|Ni(s#<$.zhyWVa(#-|)hfKR^Ϧ2J00`Si)#2W+KA0 <}#2#1s# $yWj@;l߯e"W;G73^+r5S#-^;<X@eVf#tҿ tñZA%9kbTΫ;ˁxMr>_s^#Sw%03ZEw/{U>)ZvV/$rDHXw_-TpRH(X.}*) [ׇ~^N扟?vǥT/lϽr]}Z#1ՎGRjpwe`"Y#RF0.dY Dr r9#VfV,v_!m]%,eXO%B*3k*L-tt`ԫ5j#2B 40ȅȡACkFnW_Oh0"g9%ws@,Mǝ9$WsH]$X6#2$LVΈ;Ũ"48Qw"z0]^LFӓ7.%bE.f">M~J'fUuD5dK}Vc*cBy-ciNdi>XlL,l#荳:Ε;"mnZUAeEMb'˵jۈ .;%CTp'a7)bGnȉIQ:<6[%z ?`ouJG0ga/yUU}p?S#-"(U(R,`-3_@|hIxP X  2H#1UB_Ke_T;EڍE.``ş[=^OnwXmY?P(a8 v 8#246p"f'.bW9}(&-AaBɞo}JR#1Z9wUN2kG{ܝgTa|}nA/4#1#+Q_a_w;,/r iC h\wے#-jP5u_zz?ђ kHt}הqV®q|t1f ws_߻whS삹"8%#2#-W2phOO+Yi8X52Q E:GL30}ۡ&!Ph4;!m%7i%>Ҷ_vv  0ƞA_wVkU,)rmn #-jv ҁ>V(IY >̗#2XPd@|<Nb#1? #1e%0)K~OJ^/78S(SR"哏wXke#1jhr Zq MdHUUNI$:ܹ#n1Lj{!Mx\?{̸=)2 o:22ӡfAivd2Kjm}?`}EB#/#-?>͏t'% .e\l|tAF c'ׅWJ#1gp'#1;t:^hD4d&B?#1sH4P"]n75^ܚю0#2DIy#1"`Q?\6ׅR?bRŇٜU^2IpdEM4DA&P4ܩF0à32l90;w H̪šR&_Pf5^ArC봐C`goX[FEjI"8(.d?;Aܷ}r9*P%q#2J?n0²~V8@fdn"EG;j1-.Xf]dmffT!>r[CTF2JD4Yy$IXLԖy-f7V`ax˨cX@z#1#1kz)nXd{uc@(Ƣf/o_wf59i$zD_Kș-2I}MXͿ$nqH;ܟ5ѓM"J*!NAW]*00(E,nʳ}Ehz}>9Sרx:޻F"*Y5Nhcbq{|s MCi ;-:]5B#2MLqg&I#1^j>y'W,DiĴAGWہzm6N_O?u;"/Sᒛo Xc#}:Ϲ6F+0?EN3v7(#27)DKf7p`y ywǑ#2T-{ ?{B>D~D#1g#1mS#1dOy!8{5W߀ԸcgUJ*JRDS|HhC>7#-٪YPP |ΔOnϛ\{Jhyé?Aԝ^I X-2b'ޤ CQKFA; Yf0k ܬxw]/v`G ,[xSh0#-#sՇ ]==s(Df>'#-9!>J]`@|ۼD:>"<#-$dj?zX"Dgxh=~N{3:yOE67rXhkiϣ$VA~೪u<dP e~-A@:DH?&@}E 启ɩo+X~[Ϻ U[bbFI$ _X&!V+ ]4d>?֯I>S;B:|!i9XQ=gǓk*.Z?|lØv8\: !^o;C##2_q+;O3>Ax]>@;sN90XŇ}w9u2il<>%YUң% ?S98νy8DX#WRq֡CJOg!yA$U,ן7m70F=lpa.x=eu&ڛzL*$ZЫFIwyN#1ː)]Av(Tt@>>Ph^o`v`u@<{ƽчKh )SjEy|~~=aR7Z'K{*"&$ ʤ_Hl9CUqb*ΛH#-obJ )*F=g|`sEri|̄O:oI/D5h?{mJ=P@^"rq3F;OA2AF POIdEԨOQHK5yK՜%OsgA (C(T->/0c>Z[Q`7S,:LJ#-ͻt~"PkLh_[H7r 7b\~bTej#-#1X f`~ kA*n#-@Y)dE".% F*AJ*"9 $8tM@FOM~aȚ >*sX1K-o*U/UڝNCmO`~lS3P٩bY():3 0bgZun{OЇfHz3JH+oPާkî6!FFoy[\VL6T& [w^yB#1Sl-a(bY_WXS,S=yWGO0dH>)g7FR9w7?f)A5w!b #D(̂` jC! _J9)ak1<(LntK~ZFB6h;7}q#-6R#2;#-y:Fygukۚ. 4l-*K첏QK'ov /I.{"~6)#2(߽`>'!'%I(;};w)ۧQ![fXq}G{B$?rVGt*3&jB!k6IVI$}z}wɺ;kR)@]C{pKHQAETϟ*)7{(GaDs'$/g^#-۵HT!6`HD{@=w{~GvdF;:RԟPCC'ϽSHS,a]cp%dþ bz \I^~{f#1ďf_#-PC2??RS?3adk4QDAJEQ;3Bo#2r=E +;TiX QXp#1QB%N$$"KC@RȁNi#2|z\jBP:mUR!qpb~wlj`\z @ #1g = ߟ{zBo. S#2 =]< nMGNΧ;I%h?ep#5vDH`ؑyGS@>3I.2IT9;Q:Kgק]n*Gە%9pc9Wmi;6^sT4:)i$mRz#CÙ:гFDUfUQ-"8;9NvӴ،"(%?nuPn)=#-_{#23׏L' II_kd#2)rĀLMf#-?J}On-4u#s#PIg?~{~-\T=]X&5ZMrcooh9osF`r^#1eq>#-!?UvoMxK0N|)MP L`vHieDLnfH#27oX!(4$H|<\ !`#;R`]L}ߝ#1,'>zJ뵇zM=?#- 2!K$zwa|N(#-50۷݄x'o=TkᴨHII!]^7:g#/z΋ma=jQQEV17\D$0R$r/OZC0?Ja'm =vvD#14-슴3gP`6 u.*U #&L@H-'bO׆\~ga"y|g։T7ոS^t(Mg)b?/(BoP~?#-ٖ׺HcW ɐ섉"2qjͰ{Jk02#-{;McGrVΖ F$q&󰨡Ƌ(q"d(9 P 8CƮ̩PO#cj"Xl?`{r1 R$`:\."Ax+0{ܖ?^9g؇ q?#-J._K_rv1d<7¹IV DHSt̶O)Nͷl#o/eRdȂ$Bem <9B:xjai*f)\a+*MC43Rt*Bcaj10~݈Q-1j * 1zS.3~W3.%Q=Z-r `٬< $(C>E~%3Oݺa!#2koΟ+gaU+`/C Q̒t:5U*9&tB(/|n#=$T"%嶜W.|'|k\Nt#-O΃Ͼu@TU`n-=@/"iJ<t͏"qF']~}|_Tj2ݢܴcCO~v[}6#2 #-@#1x#2 shl@VIGbT 7g;H=gPJޝbiCL3L\gfá?҇/ ?A7D$˗t̛d?'"CǗןO3h3n#W0&3uM6m#-<6J|Nk=[eԙLpu;f,2P]S}MBD|.Zw=ciw|šky!ҌT<#2;_+"6ƸPp=( vzw#1d/*ozx`FM_4CGC LT>1Ks4v~vzH~r֌%AUG@ C[ k/4s*>۵nAEcb%9#1= Wg q(V#2[ð˲mWQ4GJ b/UX'}ǣ邯8q`gkVppQG67/uZ6cS@~<@NkD0r>b?L{kw턋> &NxD|&j#2Q'}e8ԾB+CV.60PtCzEoAzƇB»(Fui~-?z\U)#1! (%mڇfu@u /ս̵ZTqЩa*cs³o:G3gm|2^s!ukISaٲ{;gq+޵ٜ4-[J=>./$ƽ4E5ۮcʱNlrvv鋂2w՘opʾwsws&e]]239b2ozkST!n"F&AklԐ)8ѬNZ{+tS#2PQ;T C#1q[GU?#2#-A>O񏠻Kюt#2!x|c? {$LgWr3]2+?N>wƛYSD['%%_2t>OC]u6fyF#2ѷYvfTX4W9UaHp2#-bjpZ"lҢDZrmB;V3d@.( #2/vg3ӋZbhD'Vzqh!8uAfHTX[FH/^~zv 0N#1A7#! =>cAQbx3 #2ueɫm(~#?c}T}ABH p^U%dg^IR2* h 4B^o HU2R3ͼLwY#1v򱵟yu~Ī%r}JJ65h)N2Ouk#-`TPtb}۰yQX+;{>¤\_gUgC怰m"d$qC{q[j4azͽz- g]xx3r&Hc`;wmϸmU ni锗r!˅`u.a[~r@C\,ycSySqL`,ݴG.v;LJ#1+ʉQ϶쳤%^!;]$4558G׳O hw߳Kzq]wcJV4{o:{c<-!u /9)z35z8AuhBR:?#1u 3tn(޷9c͏5[TжY(#2E)n[; 5rKxWhu/h׿gٸ8e3=fIs0G #<ǻᯇ;/qvdwaDKK#1]yLR}1s3oE(Dr#1^@+1(}Aèq3Ӽb =H͹}Q{Ft!hbׁv#`g f^2\<fhQimum<yQr.;|2R2o(nDJmeA/@uC313̏#1B*Xr{#2hMmn]d LF- lӀQbiRqytZ[#2lnl#-!y@Ynt#lr+7GZgHv߇veUIiemfutOx3=FChYCS8G+}95Gsid%#2nBih>IwP%,h ^4{+#2]nԍJ,!25.!bΒ[sHƶg6|kP奕 e#1dӒCG)AkotcC~^d#22h -npIF#2!تn+Tjegh5B@-7))ѭ@qh`4ucc.\,XzkP=V%O2(J(Hk2fdqDGhm䋠itv$H&f \Qn-#-6tUk@ptd4wECX`Xbu:+ς:@P{phȖ[!fDHDlbyV&7nn8ۀ6 Tu#1Y)t]#2o~M3v.VY)F.wrXJS}GYiñ2M}B:l7M(zQN%%9NF,#-gp8q[&ᨡrGX!"u.FD $UTl#1:lPΚ0M4 G8UyNWpq*#-;@!}0nW#-X chl3oJwd=GP$M;C#uW2}Zݑy[XW3 6ڽ{ }+,y;PRri(,}2yv#-}͛0{1.u=C#1/>DCxn|~ͤLEC[OٛaCٵ0$zBf>fۻt:Bz" H}z:D6?˭mdM'Xvc=oX`؝eGJU)noovz;((Q7puӵϯSuy ^SvΨ9omr.#2Hz!WQf[i'x A>Q{u[kS](f!qVQ%P CDzE@~}a"@&MR1+{wQ&[v$A%0"j@XW jVt>NJ6$$KZy}V]arn60Z X3鄍"#1{{0󕑕Y}>9Rra>7D_ J*A  { XL<&yg+E+sҼN2<4My*/"pD< bn=UB#-A!)#-"2p|DRD Xhd@N&9?0'IKp.3DJ> (FZR{aY[k@'Z54H I !bue>k"EJI1oWvzbQA%Qmy.nwW7,ݣ_.n^4E!QɎc`3#hdekzH!@mMs<$OPVNA;Cx^OoEnEEtVw6u/9xsLXCDo7 ɮ[q>.<|=۴v;C !ybhU=MhT#2@Z8.ȃE}YrQyWķh{RGVk;U}\; paQ.a#27( hYt2TBE7(뻅D@AA5a'LB(ZhVY+Vm͒f•2`TCQP)>Ͼx5A59#-$ Jp#-y^/Pa:iF\"od CN|.$ T#HqS $=zPB|#dwyA`☪ʢ`v#-Bz#? Q@ ,(UT2>F㫫dMN(^(m GoݦQO X1al!̠V- L_Q u'.sy@q$`fCs gx {e"@˿lN݄)2%́ovA%O'%F?o#(t#2#2ю@4B(ba5K0މ|PbN(#2C.278#2N'(AY{>w/<4nq}<->Wl?<G%#1ʼiNgeSb^ew7 1@Woo`@ 댋؇}em)M3hG&#޹0mݽijho#1#*8U*Ar_᛻5gl Ӡ m .9؁PYAbdDFOIQPy#-1>S"{9+5[whY2ƚ*#1(D>‌WwkCEX_tP Eby;7v/eӞpMPb7qBM=id0p5g] ;T:(#-K 2@#-#-#̂)R|s.ؿ3)^#-@dݶ(upxfP8!ٺ!+$#2 uaW n#-U+7 }zc1[ OyEߟ=N1\^:*^#&#17ҍU ;ְ:<=tjxv<(mY4%B0.Qۇ>5Zbǹ6#1ۦ:~xTq̐=4 K`ྛlɶvj ;z7~56|ZڷeǏrNZ #2A "ŀ)8Oho_+bsaצ#-YbdSdƁ#1ps{Il0 7B'>Z}PT>pr7#-J#>iI"&__t͎,KvpҼ=/4Z0C:퉩VU RM3۹+mP'Lrտ3еxWGP>r5{vq}=) B,5<{-CU}>̾~݆nfuxgsbX9Љ`=6Kٟ$Հ8i}H@m1׸fܱ1P4ls/Pv ȋUR"!>{䉜G3R)/dF ; Ϫf/ϩle @#~gf28sӡ66.5c^=䴁ǦM$';=Ӂs6KvuON9U$"Wq'?aYbt`ʇ+I:Q~}Yי"N(DﮗK\GN"ٛfn9vȦrv#-+R;C0_#-bo*F[fUiM{H'4'R>2TkxnE.ڀ"TcM7BJbJHE%(6J%! ΰy#2Xn%D(s:+#1cj+F_/fsabEx4WoחZk,d.lp:k;d&(`S'\DP ijMť1sJy" _ImUUSIw ND{6Qcn. #2#2`xP9㮮^*ŌP#"n46E$L߆@εL$8jͼkzy#2@؊Z&P*#-tZ9LQD^}XlhX"E3^utʦ*qϫqI!YiZQ'(oӓ7ZsX`#g:yz{^BФTM޻o=_HM˹sp:X^6M3H@ɜoddS?ճlr9nqKI#buȑ@-nM6Qx 3@CaJTKut )L;BH#pK5Qz 5Zt%^EA@@Ȝ_e{> < #̰$#-#2A׬,Ѥfb2l. #H`Ș`3KZ#caL7,d-%$6-5)LL BMD2+o.eAP#V*&/yh#1b,ddBk1X|# @\FEّʥi.e]vH]zoM!I8ZGY%"m|<}/7Sa$nqX#1)ac'HC-&#2TH4;Z@d #1hZA,rd8t-S#-fudܿ/0" `beKLsשw~uGK  pp7DYO(VMBsRFYYD*Ɔ4CA4S•bĜv"(SW;IE.B$x=>vH.cf!0ɻ/յ6*3!cE}4aDO L=4ķh<0dYC*;C #2M_a#-*Ijn(2_) +V[jF)6uJka=xfY]}6*IT/ YTL T,2xQ#2\zHc] ;mwfAbYHǒ3ʰiM'cѨ`)"?7} 7k4g4˓4Fvp.c4Hʽ :P-5Ԅ-SQ-e"Fnh/}]WDXS`(nF9`#2֮L?lV>-<2[%$/T3vKb&T"ĉ1e4FnH ޽.\wOLf<Z vy7xG9͋M8n2{ijՆ阄Јȡ$*$D Lp_KeYJ9-UAXI.#1ĥ qJDMCsAAa% fnh4QD7Mi)M`I`鉉e8QTR@i"m.]xjd%RhCAز ŀY+VəhyK|!wSS&sMH/&cVgPbf"QFЍc#;1\#1B@x~&,~Xw#2q#0:h%mKOTa_@Xʇ:xG`3EH".D$@jȜ}8K{k2r\R>FLv:)>#1w1(F^a:MID&)-tʗN, 2I+Fmk>)4+.b$리(˶?mS>^O㍳*0h'~;j0m[R[d`:[3#1t"KBu#1`zHKF`X,bdېEl#-Syv>JaBXPE#1&3ҒCEia#-J*:UR Xb#-YV#co0ߥ&%)P$ xa#$C~ێC]/0M*&9aT,=Yߍݗ'r) $:fzHJoO֜ 3lhtqts/⨌^v47C'ʸ#12<0ҩ+1`#2B`|@z>#2 )mh[^*5rն5kolj"D4.{Rt !(Vb_3JR#-~:xms5st>pF`#A)2idfRa-i jPM(Q,k߷(d֓IDV#2d3$fTPĥCwQE#2D)%%0AD(ɒ5Dd)24iLcIMEoG7ɷłdU50CoCa?yQ'q*7#2eG8LUea9c!q$K#1#14czK #-b3}N vSEF?E~&7birO'3 9lWj=ZU#:FS|w.vc [gxi'_}oPۊ2:#10/PW\e_%3#2't&1#235h6KL$&}?az-X6A)PSi<4TnqEF))$Sթ)ɥsۂmq9{+P~;SWSiOrāpbGBm@G ^blCvG;D!]o7+]vEѢb!LpIGkU1-.D/m>1Jx nkw%FrWMխ'kWATM?(-lf8XBfEԮycF0va}yG8\OxھMo%e $vQ+1-/YӇ:whג]mw3FWbTrCs/ pZ4!0xwn#1?;Ǿ]1gifPcQF &}h$0`E$ڏG@#2'M?'Nƭlv gy;;l}~1%Ƃq{êu*Hg/xT"$"#-5ϟY<e=ؔxW i=`%kTwzD M(-<6rAUٱRWմbDtue g>zd#1f#7j%CNhtX 9_ԝ^4tw}NIdY}LԦ&y>mёa\kR1-ֆٓTPz” Q.posYi30W>ًӤujfZf^lfԺHb84j(L"UkXP mΖL›WVMC3s}7LZRqkY.N0n y~Mlu_0E;STzK#2jf[CՙH#2'S;:ܱkuκ#1.S06{P#INVKΣQblP,lkC3'xLƠ}$ O3Ĉyr4߸Y:n 2Z1=]ƙGAӤ>#1Y5V\0N{d Ï,;$5ΌX!\u#140`,"du;m^3:/$g}n@upB텴ց=,Y?9@íRPɬ `vu?D]Qe=:MQR؇jll:TX0ai51zz⳶`z" v68ӕyxęe[wk38o[Ft8ElxX6#1 !?[Is)eZU9,PFvƇ593Hr5\sf ی{CQ|\d8}^I =7A֙Ս&1u&<= pkfM(}m%m@K#B RK]i-k$i"奅AAzaEPXiSW(m\*raEJXVo}m{#)!L j66g9㜕'ubJ]%4:߄:-f^3r (E&`F:P6D>idcRNLܢ7L:8FMb䦽dڨ#-@ie#2qu¥ǠP̧]bT.n 0M4vEí'#-.\ PN7szH ͝a&YN |ҢCgKћᣦ>u\y#1\+lŨ$d!L6m3 8I١ա#Y֋M!#2y}e3IC\Ć}@XPbއYN~| ohoS)AXգrLoƆ7׃uU6uublz)&2S8O/ R=:%)(#1ink-ff3kn]111yku8Yժ5WaG'TgMGYj#-L@9ik& SxN=[0mp2 !:H=Խ*mBpN 53Sii.To^M;ٚ,j6^oLyY=19ZoK2-ݥ/E[nrm3d}&Б "Gq,^ IodKeT}vuu4tP)QIIAJ=Xȁ tf'CJ"t@#-a݋OQOP/#2 m#t02,OsZO_A~I# #X#])*+#d0 -û#1ұp$4@gys( Ac4&RNR`25djfe24҂[%3j"ݚvVS%#2# i"23SdtvNI-"S#1['2`Rqf d5eR#1XsL%q~SlN)H=d'ϚUbx\Pu짒6у:8D Q prle K؃v,Sdw"6'{ UPffk`(!`hF80F nhg4g.3hn#1 jKUN bE6LJII4dpjs iu7.et]#1aL,44)3 WvXQv;%H`m#-NM,7:EF$#b ݼH "kMMȚ.QR kQaD6rRIՌ0KR-~u/oh$#-q;!tnI-oW[`+׶ *#-)vZ{rx1t?\,O;eU& P{%iOpq] u,ťkFw[.k*Í#|8XE0@Cq*G\'IeKZrCCk! 47a7u% exnX!Ս#-M9\SymB<8rbH$c(B%H湩LY7U#-Bȼ<Ev B~=i!0Z!&k!kkJJ2ir!D="M>YrPzͪW/*r1veMlO/nNTx2X(ҘUN#-q?^#-9 !r(`DZEz(|L' /܍^8d?7'lOɎ[2!gfiZLPOB0@cK.'Bh M1ȅ4bޢUJh.9\ZRgH#4"j4x1"[󷗐\b^zo$k~{zVDlUcFkFIDL`3-lX}?D(Tv'x{yiZ*w)]q&A.ú#-;=N Dׅ %cX"+Q@G(m[6n;ݎǪI8K֠0`׫@.H_,{#-"F+Ƞ#;EDWz#1 )-b"bkh#1MM.-WnNs&;4*D4cfBFbIU %@B-Ab#1ThN]Xn6+F(-Gp0~]l&Lp;v$wgFb 9E$P&5ъHVV#1>d\mKf98J .q=}l7;VƄAB|PD¤A6۷Wk 1!5tE,i2D͌DĹ!@8#-ZPRIMQZ#2#2T#]`3myG̪F߶[^%5XQ(0HtS#1SC5meZ?0nAlA]fsҘG"쬻]vVōQmXV˵--S4> OMq*12V!5?KZ)}W[㥳W n5VVuVoj9l9VW"ɽ4M2eZR,Ni6PۡԵQ*J"hd65ɄM$iLi[xR@e0qfmG#1I{tprDSNDIeRn.h͸t8P1mN."طg͢)]Q1&܈h5)a=`C8ۧ E2±J|&-M 315ędgU3d0%Ol ɲ!ej^Nen&=\dV\C]sУl ( g/!Ňt51b H6yZJMKy5Zmbwgyɘ ;LR$ȁ)qT" P i@dDr@lBZ**Hvv%mX]# ֏o˭/r0_Fi0oNA\-je2+@RDd5᧷]:#=4\Txn7:ۆ݄B.DU9q:c|bZ C&$B`w?6lx3ݟbL8o\rEDSXLloht=7bw#--(~0T/c]Oͭ'(qPeCB߬* K`FmD5dQ-$ʣ$YC-Y&5j&M)m&6-")Y,JU,ځJ3񮰦՚f6cLIQSDȭJmB_si^ݻ*b(2#2fҌ֤֔1UZ}.D߻d"X+[l$Mk[ZZ4TRyxRZm6PMXmm&vթmb];t݋f͵1hd2Avw 꾔n5I1:P Ya%6hH9˦G#22u#-I_P[R(KP}Fݗ75#1N|•QRgJ pM28E}`~E1Sޒqݶӳ\x zUjV7bbM<Â3l(nؑe?R>B.r)gpl@ҫYsߡv&p*/P.F©)i[cB}6Ƴ& x%g87rͨ Ζ_#1F&Y#P̵}a‘X%WK{{vb]#-mU2N"QRR+r'8#2t("2! D"'6ܿ)nZ2f,"O|dV#-Y;+s8e%Pn#k͕{,cf3z&[C>" t+zy4 MS`,;`Ib"rYE%"qZ"BY.µbm"F1ˑ#21AQ)#2T `h{CRMn @M zu6Sp:hPXA# /,"An"!LbqK U"IL*c)#1qHߥI #--Un.s%J!##1!6N 8n#1f=#F+GJ7gxןϙ^3pgx0'M;}{7%1nn{zC0 X#2(-AXAKꭢlkX?o:Qb I0RA":捱4q)䓝3#2VZ|]j[|4Uj[mrkiQIf!`v2b7 5o,I+*e@ ^!R5_Zb A!B7[i#2|zE+>Va8ƑnbHhT ILdш*WϞً~#2_JS XIS ~2&¤id-,0d URMJJO-DVCCpP!0=p[Ca׮u36Af.KшU Tr-oy!31EAN'#2 ^ʝS4Z5$&N8GQVZ`J~N~UD=9J^P'e\fzLݭ_Pp@EBC-*8J&&M1@eFdPA ?_ F]p%@SK^#1k(XNt#-Ą$y@L=hG McsLC}8U3kJ%ؔއ$TB;Dt6|Qx~+^#1촴QwNlM6&W$wDI9:ŵ.DP]l#-<(%V"^LYv1v35{u< ʫڻB&;@Ci: @rfP\/Q#-(ukP(#H4 PEx`PduQŢP.,ե&ӎ76ZmYw5O}IHR*ZDI4uԛ3U1"kHADL78\N\UT)I3h`nz3D By1gaxs!*oZh/!ߪ&{׼Gۡ>|8׋ u#]F\h̎NRGewh?ؘ 8Ҏ7yzAZW)PNM;{p݌<1!"ON-вMdRf>уA,uOZ!BӾ%٣H?;IfA9yr6-2 ެBdcJUTJ˭kORӻqHM\^K̵yɷ,Q@EM,9$CQSnI܇D䀌˳C|gNw\i0;Ċv@=5~Ľ/kY͐RO͡)6ֽZ5dګ#0 X*JLl#--BhF2-jFU4ii.mĖFb6ʷ#"k_Tx\%PF _ʴUKim1QPآ#Ҕ<omxZ?_&v"sxa\b(x뫁G˹tͦciD!(Uh5#1CBcSɵPލe'X5Zޣ$: eeFޫ}9`:d[#1$,Ŭ S8g叿#-0#2t\ m :{FaA$@*Gla\~S`;,7DY D_& m&F#1=Il0}#2G'k:@ PHQ+# pf!#1#2,<㷨exOࢬI|9QPsB"HC]f\^ިoG\3шYPG8r@~a:B@8Aτ))O_P'[_diݵmfA**TE`(^#PD$B "5 f}Nk3.?d[̅#2-X#u'QX6yV!&(u7$칡ZXNڪJ-R(ZJEp(]F&+?W.,K ry@_ |m{|A4m W%"!('R'y"HI:Nϳ"JQH!H֚?kXɦK: XR#2gG-4tHFh*>#ZeC@ h2^rV#-" AM$QC ]B;DiW;gLHv#bYdȂL[R2 ޡL -F̬FBjcUFQT|Zjhŷ"#1T*ZQ@`Z{5ʱmo&ͥF01rǶ,#jIeD3a--`Rd 7 6ȫ#2p´XCU&X9:#1mĕmbݝۚ\ՍwE并+oR[(6dF*‘^6jLgI1N,f0AΤ]Ya#M\5;wCH\rCXtjֶeaݪj8*HQĻ}k`ӹhud 0>[mҤTE{LȚMf75jh41#CՉt1 ו{ޯxxhϚ#2=ao'i(KB $,V_ͫNn^kcReWmiQ&KźJƱEUu+FsuKM5JZ7V-J *?d}Xw#2l ,b$"?xX#1*)g]#1_w䆇IZ(R~vJF2A#1A HݺhfӦζO>~h71?|rxު$*ЅAQ_;u)Rʮk6̈+XlTzŊ$hFdLDh#2KX10Ԛ&ijqUڽ$#-(E=a#:-J˨MI`(b!vb"05#2\#-$CL,e$/,ipq#بȳ6S #20+$?e8L2oXr[l'~@C4Kfg;L@zi}%d]ZNt{vFBq.*.2j&C8 N#8b޺**>a(#-naH#1\{@lz.;t aW$-RU(" JTcj׼Uk)WQ5!!x#-n;x1.Wt~@Ÿ^L!}ύ8!w$GgtĹiZ{%=4fka5n*y0Hb! 1bd:\7$H0Јh#&Č0a`(mJb9'z*$IhTUGNG@7n6a(tzV30@K EJjh(naj-5! `eߣf4pl s/S<0gQUɳn HěGGk RıO쒀i/I v|JQM e`#26HJK34OAD1ͷ><'13p,q5FLrgf?BY2"Gv&$lOsgR}'֞>٠뎦J?nAΠ_ $TXEefjkijMhS_WDhS-,#1[̵6EbcmVYZ̶ZťTڙU&ت4d-O}o]9nbB&W=N_ʔBT:j]Mk\#2.*Y?| 2)dX <'@7Q#Q#2j,@ 2#-x$XObw2O*(4*#iʣ@(d~DBB|\1lC$N#-Nq@J"#-|@'D6#y!Ą[AE*@?<[DnHƕ=O0b<ǁzn߻ ]Y$4#;ZpF) e+Sx2.e4ff`8G/.*3T4.k#2|oTDg2E/Zvo:ZkZB.q.lOa#-'C7y#- b6]4 Y$kAB#2PP68`nV;Մcj"$44I$0l,X*xOtl(!~E?egled~\}qOOM j6OrNK\`ΦVMtGF*ADQ=vm>m}&Jz#-nsvn4 9+S: L }~jwM*6iVMu"PX;1LOϕ3M#-2O03f ~N4㔥014׾HB8.7AT!eR"{n#1fMkߋ&7#CӀX["$c+ i%cax}LKIqF1kVy0fLUi bj@Qdta-Ԋ*cuhF&(}#-DByւ))QyzRX&^:o7#1LPSB7/C0Ђ#2Ĩ(B\iU9xAzMlA":aAzKk۫tP%1T$I͠O5'K:!oZw_ޝeo{6V*LD4aJ66(- 4#2L#2S}g؀x#15tԲP)/p-CEd*ciMH\fg'%E ͐ RYX"A@P ay{)to.S%!wy#2Ј,U#2AHCz]2%ـG95@c#1.)cY+[aal!<2%}#2ʟKiR\er(z~ݚ#-HRfmlT*(4#1rc}g%׿.jrI]iARPet[uAjYAH$+4G?#-rHʼnɛ 7#-cpvvGʃMQRx:"ɜAۗɢGS,-ZA/aV]TSĺ+njB~9Br,1rsU:qs~1}ik_:yr-[PPY)$gC#-PR@1BC"+J#-R*&·ǼL#-Y;]=s#-#1|l2ۄ#2+߮0O4y :y#-2@,"ryhQ'gRD{weV[Z#-]~4l2li8H~>f<ԩ  )lWty]bMɶ&K/`BDTJ1 Pguf `ƅݾH< (6W1`Gob ƀHX jD2g›w{o]ecwE.鼚\2/q*WA`H&UcVQrQsw[j8Pr"*=}ֳVBM̥9up;M>9e%V>qtJ+T-d1 vI{!WoUx6ѩ«ȶ #1Iൾkq{!@]0 vǁ]traX jP"7 #r# \p88DY!lb}:rØŌX=^û&a26#1`qKh <陂)fiMA=ȥ{}[bH$/unv_]Nv;52<{O3_=8[ C2&ͽgPTGUGႝ!p6=}#2N0~"b!d%]-.JZʝ0O^A0>wi:sy䃉eSZȾ$3o/:Qrܥ,o ;#wH_ąOarL #`„U*78O/rL;LzQ,r r&6HM>kͽ#1v#1#2Z/~[~7T!~[%iΣuX,XFLu$,EE ``ؠ'bH0!iLPofK>D A!.2ʐq|]/cMJ@)7lLTV &#p"P TVSmnںd-4W)vo,•5[-my77Q @JV5 9[\$9k)&_Rnl )uITUa!})vo+jM͎3 cƃa-S# ɜ#1 tCCbE,4#1qA#-D| smxṇ#vez{4#1x&red!dgrׁpERz 7c-笯W 1$o<ΓƾWv4U#1@yJF?Fk&1 p]bA!HTU_EQ!GKK ȡW?So_?Wp_buE|Le w>]#2rlv,6JB#1klL/H~Y{@Z$*mk_z.#mlAAX Zip0];`R×4fpx\bdXwZ5(b#?XDy%FMM#.:J\E#+<:^RI'Z fsͻŶˆ9h솹"& ̌PiL <[ hoG 4:{-6/Cx,Fxܽ:[mt!p<ˡ1JL#23LHIҶהe՚_{sHh >,#3-ؒn7B*yjCd??%O?]!hwn[43`tb̐j=4=zlWvƓս6KBjlſߵ뮘% gRDJ_=Vdף:]D)ceE. "1@5eB\_`bD*Vm5#2 Ď=V3.DFq#1 ̪MZPvgKS1xb @qI0MT B(Obzۜ`Xd3vT;O.-R<[VczQGXfx:-2wûk8Mr,Z#-f/  #291>?mu۩~A{6nQ >t6vSVS?}Re&1T*]hفuEFD :#2 MIڍBILlaRapPiґ33Xhk6,hB_{*#1QfZ&2K-ȃ\5:#`dq=[GihʘD#-H11#C@ghk}##1^ȟ`TEDB,#-5ҮoȳdJUΓ#͆M3P6R7WH*llJPh9وAZ 2)AvX==Ycn#1dZS#1 }-B`8aO#1'2m67#&Y`ģ[#-eaM x#2]nՊzE!jr8i͙KFvq>V%<5fуδ.i\6Ɩٍ1*<1#2XPCt 6 m#1S2#F5AzhgP;[n#Y ݡ%}畅1s{xxqҺ>5ƆŦy9a]2bɆy08aL$ZoMjIN)x֤0I\VXiP*ةB-Ml&`űxa#}=oK!wB]8d YV[pVo&|%}<ᆐE@ h B#2#1.P) D)D ]@0DFA!DPHF*(.Ӣa(Sd&O, H?,?wlBFԈڭ..Yiaz,lc]̓MBbA1H4id8w&GiJ;])˛ǟװ$ק!Ɋge[ØTDI]hŒa0ȟ;6wme>-kJ뇣+fUq K&b]s4I$kΉ#2/hH;.E#2>a#2&6g-c!ɊzL)+j֥!lOez!\phq}0U-[QKo>tԘHD^"F#26 P@$Y ,I_?m%n\?ynE}T (X@/1O1'd#2dŭͪ[%BNRX3#(a(Iƕ" p ɑ? \+td̓5m\X>*˼UDF>\ɫlͬ'9ƗTnU)1a cmlթJ q#2D3VkTchT…I%TBBb2#-f!oU)/XF. #-->Fac#2 =dۘ׳;D!y?Adsa`s8#1V3̙M Qf5%ݻO ;m}魪[_VpUH M<>D uPQt?PE }>WɇEsTTcNA@~[-]>߭Lxm(p6?M&8oÆUQK3Du4n#2 Јa8 zbg3/|:0}l!) 4&!QU14YE#-غ"Xt,B"#-L˲DC4b9&K`ȰyD_ 5{/=@J;>HשT79lޭ`gĪt$Uf>'|v~U*5tUݶ[k#2 p#2P#1/s}VUWYILd?-팋"/-k ;F\pҎ^CbSydM$Rxvd͌7A+scwלɸG:+H^-TsMye*ёm]6ѩKnSfY,+wwtnݙ\KFs*:ʋFV)#Dl#-#1R {#-#H"@w4P={ !z?UܒE}ym+PTSuN) o=PЯ]~&(!R~j(?/^gy>#-8XF1TXĆѹP"Td*?V0u9YL@dՊաKC-ozj#2RT,D) `:qLϗ;Jf 1%fRr.#2hR֫!#vmA!>EՁ@:1E!$|gsќ,hZG?P wfi*Oa|F#1IY%#2Kuunn+\KX a„%0(D@#1M[TlԄW@#2#1c0f+M#11UaPQmyEW*KrI,a2;6*슙'XPU|I*U`?-$.*j#-.fl$_VѦXiFCv$(S#2AhLHĒcZ*ޭ˩p h$ l6 WR~.cGMED!#2C̬=abVEDAՉ`=aPP&iP4`D$5K>#14~0y17NjPR #1TEU9?L2H1Lһz횷-Wo5-PE:YՉE'WØkt;s ,SS!DMp:6sd)#2ŴBV8冃_La9g;!KdKv0$I#L+ǃQS1쐊В_1l#-qWCg#]Gx|PJl+ݦyhuL#!OWhw܃#2ڍwOT@GiӀ(dT@B" =4Uc"C DC!QN٢e)vž^!,O\wF#2),3FZmߙsaS`~g}uX_V)uA_dEQ{8KYopV]L51t\z0#-HhTwء[r摷1(Ծ+Ѯm{sU#2b8b}DۿyTj^kVغy$LdUC#1xYLmiq)38R#1D#-adƍ-!c?xHW b :ti gx(<NDZ9nah0}$Fwdp6f/qP\LSp,ڶ+hB㜏cCԿؚ>=SE5&1++#OBHl1c$ [#1lֱZc&F*iv>ݐȲsH;3d:H4Bē6>h1ӵ)旷zͳ`_WI7]J3d-^϶9@Ѽ#13]7@Xݥ_s#KK0:7#1} ;cIJqLB X ٌ#1 E]/gMd.H[4B!@6R}h#-몚AKӿ=ervډU ~Q<8ndwp?O>3O,WT.YW/vm/k|ͩ`zRPDAm"#- IQLsԱtY&ah$KISqKP*HcsO>]L25mY8^nc~x:VfG_#2eI[$[֫p~F/֛Ɓm!`*Ĉ2n4mY_̄n!ª;B`@UPAoY@knxy}N${ŏ C! N~AdY&I#-|R4{(}@?+#-Q$D$H(w/Wڃp炤{k=iS#-qcwKz6L[ .6<>wr1rqI@Y24bϩ4A^E9V@vR (IL~Uqrrϳ"zn9(Y6{:s+ZQ;CU,|1X#-j{[c=uj:@7<l;Ѕ1V9\־~ee$^zAFJZ#wm hFDtbYC`iИ 56;R8z((#13ͷŸy#1hc_"(\ELgCF|DXcK|Wɑv`?T']uawJo)`T%xCzNv\NUggpok 8\AruX1vŸ%z4 )Cr=~V !/ *T9I#uLoxW8KhB`ӂz6FRXpC=ء$Ed}ީ#Pb *$B!LhC^>d*))Q[RjΘ~U .'Yv_%FA}h%>;_i :\rWtM]F-5K5iJD$P"l[H#-:.k/ :| 2 MZ#-HWz'@&љFT3f ($ƉF"4ҤdhRl2*#22rsdٓ0I)h#tJ';iDW#2 Ål8D#iDg DC#- 5!0%?a=L!ʕ5NA Se*(ehUjQ77ZV9?/mL4'[LA4#/]g1.`-MUNB7TRznO"20<515MvU.l!4c'kaHNJƃ:~PRp" ~u0Ϲƴe&lux$L&wΣ>d*#1IOވYlJ2Ri`RZbfڼTkTmguJm7WZyCk3[qcYC#21&1;/B*%*FIjdL`F֊ɩ5U\hJ#9quW:^ ʃ!YR Eirèi-knqH܉.c.&ڦNwF\MZ 00#2Tr!S`jGHFC"FJۊ7*xІb Bw3SSeq"4&+oE^˼!yYEU{y! ڣ`3 DCd#8Bm68#$[ji6iLj0ҚccX(0jlOCrXQ:UJKvaeuB#1'XQ*FHT+evinJ*[%TaU`ң .j%)Oq*A)V("ۦ#1QcSOyl2-\s<64a7n1+Z5Z dd LF:pcc4 rF{f,l%DpIm:(hjJ#1膚,őB0qx8B ټ1CԔ*8ۘ0O#24LJQ%G:81`KVQM*-й( tI 5G gF d# _D y3#2ئm#emVBDiv8HRS\Pɑ&UC-f +rׯ;j񬻪^B#2cFt-R8x#1dӃ bhT"m#1,,)FRQ7fl%7kb:QaXfi/I(0bQHD5qen#1n`LnDDayQ]~gZoq,(WRfV#1]#-czƢ*"CQ_6$&p@V[m2"ijcwN`H\Tj\0 b\c(P#2$,IQAdT!P[A`h#-i&Ċ*=7wowLZWB~)G"#1R!5'#-DmE Sf6Y2huVYD?@JxzItثi܎<2,P ;#2?~Xz!7Gj0Or@D#- B$b1RzE KzS|a4'7]>8J\ B,I%}sT`(ic;4ACGedX5#]]6])ZE\Ca`9=4HMi$?Rː:Ss].ZBfAADG8޺/kaoQBfڛgy,kd7/͊򷆷 u 0|^z ӡl+ }gDTB9O׉ex(a(Cȑ%gA&h?~_ذXPė(W!&š9kڇ2@^˿˼P8~O#-loo+-We}5f[~ZG]$,]p 7O`!y$Px}i1m~'> 31_it[rz#1#-e#2T7wMk-:O>8NY["5rPGb ,"*KgԝPکIUFWαUVXi3v%e!]5F7:DukXE$P!HhCPUIJ3X[Ei-ͭؖշ2#1FmmVCXۛIʭ͝r,mj Q+j,KpD8É9睂z" (ȣ3^k|31+0xzEu$B(o4Di({D #2oªy?(#2׿"E]$2PR(V ʯJaHJIBHD$>?#}P+,bd25 0#-#m۵hkk-):y&B]ޅEU~,ImJD?>Q #:Gp= xuv[V %(z"eyR#-;f_O` HrVMt_eH(z큛#-2"e5m)jflJPK$eICjJ+6RS&ѡJDZmEiS*V-h6BM#2f}5Ik2l# )mT|/ X"U#2qC)`G po27b4yR@TҀ"Q1n6FAX1-a"#2@`i KQ#2)Xh2TQ@T`H|B@}ŝRЀKD]t;Z~^S-("!bB chC7@M%_ B3~/gZ\E*W"@/nllkTE&0f?Su44 -d!\ܢXhD(AL\"Uc3E8R(6U#n> ;T4O9pfW[.JfP]rѵhZp:·Z?H "̑ƴ#1C6ʔe퇴 l"!Ge*"fGlb+u=XQQKF{8SWR)fh&"jUR.UwN$O$;B,<*&dr# X}vt~;/X~ pPzvL_s7N^B}ixp犢}=Ip訨hD S#ҋ` M͆jm_GWq r]ڣ]u\ʨJ\?x#Mf$r@mqWofh1'ZV')bQ$覓st .m)MF')]۳z]⚭]N3nN4{yKP>7$NHlal;vء)=#2{3~ܿuj-|Ju>̱g֓N-R㳨CA:*n謄y*^GW{K2MRzT.nn_dƛ=c1:gHE&~ulEGӊ-u,87CC(!r&Sq\Ԯ>c&A31o#1\pׇGcLJxcȻ5$CgrsByo,pѾa& q_6z707%k9]Fb|++d]oQx[qwb73vXqXic0t&PK3bgV #1G0MS{ )N?~HjG.PPt1fJeީtvь3z8Q>8ğئ`Wb4wbAd,KKXn] p6#5M36r8E&<#1Kx^C8StB:Q G4U%5C4qҀ#1aSfTl!C)Op`{H^+kfBx\-hSn(9$88rbP(Ul  "#1+ a}S߽8] ub("rG>27q:J5SACl3d眽c+*fA.f]UM0򆳔(j}M`#-@AJժifyw5\ [k,*2pLWʕ3J}vdymI8:ms],?(vYLTGT1Rғ߬sQB(J"jiߌE*~s؁l[Oh> 8!kJچ#1rrqaw~B`8]>*tBT<3E9[F/KEZyނkdvxwuJkZ-;hF|km^Qء~%@vhiVkQ-29ys83D^[)Xd;2ѝcMXu鉻\!jm;vW#1`5eOn=LsGcF:Wqг!w;۞%Ѫ`Nq^%3Ͷ FoLɣ[(sq yH﷌yN#yfˬx)oX1ibn X=#16msxfkF:COHŒ\LfO6t֜hĕf#upJY ǓA,Pd$)*2ʠ+ƞw$Kȑ`B&n1n9Q5MƤXKLh \T{g@Njw[ z$z1iPRɀd4ĊaүJabnF;ۯc/MJie܌F!!XֵLp\y'[#1jǩ9eohDQ%\T548/6YC.(-T2L-~[Zv0;ĬRͅ@e C(Lq4ƌ{⮱W;Q Uq9YTW24)Yzل˩D M#1Xm)v #t]M95JG(#2Qg1=릞DuB4gAƣPh *P FSC .-yd6r@ehȩQFL`sU"05C7c.ۺ#2~OB)0lSI眖!ѬPѴMT6+<Ѳfc*)`0ހcL"Nr#1VFq#BZmWX h3B։339QUo)Ӿ*7=!ҳm4@=[GW( (X׫A_-$u)#14b78cMA@=6alS!vH#10ՌKE}V ƙ2R͝jhT H<ՂZm3slֈZ F ֦)I@ZXpED+k1#1ec׃3#2Qf1l3cU{ʪv̇#TJ;Ku#1s獰~է+M 0"a'C!ҖTbА<>˦$?3)*vc65p#1![v~A=ޢ})i8YX Ll#2Hx?@k@PVb#1 ~ . F#-1g&ssfq?4Ny䣬PlR<gnj߿}wW܍7tɄE*#U*229шv{+Üz/Q757EvQD,P'<:zCFO"|ނa ^HdM6RUڦRե5d#2#h(6((WCf#-5y">_ߟ$!#%jkl(2cƐ-jV)lڱIFؒhТ*6C64ԍ)6IF)!%DhcM5-!LR"MZIa$dA$$#-᧑\@z=C؆BeAvW~$!Ȁ';8]f%vX*%-H@ڈ!l6I$lmHvg VSzkpC%߁(2#21XMwoMv[ãrF"U1 w.;*U)C:Gf?#1M4(@s/ O&@X#-66RZƏkMJH΅!Q0B(U*%.w#!GJjj4?½%gp*#4F~]ht%b9I-`䉱0l-L rB+@6lxRXZLH/>I-C4K*#2yo:koi^RoL60M0Q;3PQ. a#-!`СGLԥAy6OY̕tYlStI-M솑RQb75hۚ݅&bnZMvG.!`3g6#xmbJ%L&XC=hhN3đAB R]P #2' BE ȷ$$GM`s#-M4L)\tn)iXHl1+~gØ3z#1z$#!?"d셄o cpu:Q 5T:o`CHO"Y0Lmmjfa~'#-}89<~|$0e>1TD9^$͊{dS#-t '[v2>c35\'#1#-R*lfL~;n>#-9My~_,mI@}^ľTCR'߂\tO823>^u!6yd*hHaeMwg#-9C{3ecg|x_#-O/NB#EA/U\ye)^=sDR1*);(r ȶd#e}(imX;Kxvmw aDU]0?LNUL4240S8&#-!M&vfD@@5) H!QTNr$|rkFt I4CGt+.@N28dB#2(Zi9Ѐ^À4.}KCd\TURۧ=#1ۭJnֽ,rHn`"iM,"qn$B!0l GH`ژ0:8Ã9I*$m65D0HRq:6ހҡo^{oGn(]uGF`&-t3ZL+t0e^~UoY8;f'a)2m,$P\(fZRV2љrY#1&Ƅ˒b9dnaS^M) WMH;5M.0S9A'X\t.|BiYs(tR0^F $cR 1ñ+;`Vb}2!垈HFhz8̫ <8%8g2٣ *pH̍X3W5kyt!|߼g#a[&&7 %&3`Ħ,>9n,-˜dִzcvTBRBY7[t` #1p+,'щL׀g}ix$3@̷gnՠ#2@RhZF6#12+Us (CBB1^jÃC;amSA\ koL2CgFl\U:3M7 a1(ouY![l&].\uLL&抨65#-ha`1evRS_;$0#2h89玽n> 0!fCnq #2fT,.0fhL2 4TR)"'I1mcjE= %@ ABD`j*PEx~ޭy|~Yj!LqJPi#Z0T1`aMrdzWԢѵ|0m_89IC5F#1x3b[:V#-5Z*=/A7C9w(^Ed#-88T"k%Ԡvh'VaǮhޚd<Upw%Fdw*De"diې?#2Q-#1y菼"Țdߓ#XtݼqOɭ+pD1PC5h¢Br _fn[4W۝xnhyYg-1չ[-VE쏱Q*2RG0#-l uߓCK )PBGdUS"1BThJ D79 n7p#2VX"#˻[$2IEMNbD6fH $H06B#2AvaHXi#ԭ! F@z&<dPi[nRx h1EC04Vfȳ"88OWgl}a1xlxֈAt[>M1#1XFFLR|1<#P$xähU+D2S#26&I(,$% \7ړmO6s}vs속UFUS֦,E~٠5DgԚ=d,X[#2q`wvܵ}JeVK1#2#[3>ӅӔd#1 8P%=H)y䐁#2ӕ.LHz(Řmw~6+F+{skʌʸ0')HH2DOmڊJ-fִ&4"*8","b$P`W@؍" `P#-ᗫ"B!tD"&wy'M.ovdF Ba#-D{x0}lUbp4ڬ("*H b;]})I"7L#-9p]bbNtJ1F/NEJZ!(…<@A#1*m ēaY.UZ((Gj$Lbr K^+nRQd,*K4g#1P3:$#1G\dhK Hnh\Bjmvr<òwȂ.jϿ`,0Chk}3PJ2P_d^ciSmqQ ` M b϶e-!5,*,C脊#2`1640h_M s8XXXpr2?ǃ$Dža_CCX.2ۑFnn9\r33nĤΦ(W#2{OзRk/zhL#7PPugt$TSа*P)C:Dq%YޯzF+d#2#"DmͤԒLbJPU[hMT֘mZ+WtDb(w#1=Ŋy~x(êpDP\绞mH"Ϩف|yunm{;&DTS#-! FC>m`QSkA#2642D(~4E{jrl-<aI"j=L8Ք]b|色W77gE&;jeК5|q!:#2j7NU\я¶5FVR፶f܀#-PYkb- V, &ֆN$ XD_@2K1YAبփZbZagfLeeaNO.HH&dW5H@R#2"?dH8#-<'XwՋĺexTNO !##CG4*X:'PW3I% QQo ˴${҆@iD rH:O3{bG?Fsclm#1n9-T<DuAf/me^_M`HddxL4"D`F*$m$2l*%t#2,FrC-VmQQjR)H#2m'c{3꾐 SԠtd#-(Iu#=!a IH,MW5NAFcSQUM4mN%/kx&ޚU^5JZ{F9FSȈStPo~illk YThّV*e';IJTvRhE@$DMWy>癇\'!Pd2ː۶ 1> h"99|OXc}^V{TxJj@O7<`Lo!P(b1HBY?4 A mjdHE:@P^!BSlh("!$hD&ړJMRvWPkA)#1J.))VEea_Ҩ~xgb1H>3iQ%dBٚN9_6 "\Ho6 r^?8}2h.>(!E#-jHyԍ0-SLJdj)lbMo~6aQe@ ]Me!T4* :#B&zqF`8j|.wة"!d #1CThJe $"J<ogvҲ6~@с#1KQL5V:]|1Iw$ȫmiGl3"LD9`7Q}hoofSE*[l+kkkmMoJ*-7feW\ݵsȳjƚ&wWw[IchV@U#1V$JN.CrDMi^חjMIUZuuyZJ2e-yvE3[.5)fE7ւ[i ٢ 4.TM>`hٞ-S$#2|Q1zLfPRe A#1Ic#-`ptNX46p,_qB"<;z1Xovoq6)uF{q!nx#cԉS-٬M0F0fa됧aݷA(^&7I5:Spٶ/t.N@]ÃkWIYw]*O]ocr-8ː(Ģqf󂛔kLZԒ`^Cim^h{ӴMȁBnYBG5D+mwĝujWeoMs)MEG+nr?$ W#1#-X%8֐C,SNa67@@KR-)! LUBQdj"*v+VmAbKmc4҈/6t[FWNbU#278pt6'G#2#160aL;<-,E ))Z fa]x !y#-Pl~&Nx~'F1BG_p + 9C"2V#1~OaH#2OKB*?@Y4ʂG(٤7T;(W&JB{sp{S3XzcfBlT&_#-#-{'gw~?_; ]>g|U_?m?~a /GP+AYw) #2GV)N*"x V̋6#2@*ȤRh`RUwQ$&f|Vʷ #-QݐjB ML^D m#2xeBIvܙ !B۩?Ǒ^A:03nBGql·er=CLC2*ڼPQ`$0XHtA#1hwH ×;dފvlx3iZlrݗ,6P*f,$IHb=y 1#-厄3?#10u)zבA!gZtlJw{"ur_L Ոh3^$i IqacFU1].`AHIz{p`#-fֱJd#Q "IEqO~ۘ\Z4ncP4@b,)1wN|7jf#-s2k.\*PdGh_ͅ ID$ R ַ#-` S{gbX1d_'y;; *.#1#1:Q:FB LjJlkY3[FmDŅS_;ڪ|:t!")ȇ UKQVJ/.꽞;T5 ӣ_[Ms#k5ULF"%^>i:o&؅h<0wPaP>#-!\jnQ05噫w#-aJN3R5/bhɎf٨$>,5Ez«n$#Ykz͖є7cn/ʴhŶ[ƼV#1o1h6+zQjަT6{UZwv m#-\9!Ȥ`AS#$^YS\@v;\nYdSw!q!4n5«ŏTs#2P=atؼh5,H㘥=Z=HGc/2 (zPȢŊr;%#2TXY-Z-_qbl5@OY E$#-\~Yh6E!xuzz珔emZ~׬@o{bEx?#- 0q5I@QdpہN*,= h *[a-]٠W՘gϣ~ 4Nx}QS=>Rbo=O}?Ghg̤RsSK ~lYVo{c-:iz*4 3 q%>pDy?p:Wo)}5\.2`þG6;hVV?9bo1yl%xFDm9 0rV&HK}<bEV!쐖OwT8ǧx)91CoDzZ_0?iO?0)„~wP +#<== +#-----BEGIN PGP SIGNATURE-----\n\niQIzBAABCgAdFiEECzlystnjLqtCPS4PIr4MYv+/pUgFAmG5Pz0ACgkQIr4MYv+/\npUiZBA/+PH1uI+xWcT67oY7I5kcHxmriqgaV2vskG9AdNzPIRgJ24xYNR6KcZVDD\nrPiKjAfo2YgdLyglXxYttEg7t1QTXZDLnEf/19AoCwyQDqf+GstOtmEEYVRluavW\nwykb6FfR/ivth3UZ9Qb2ZREIQq3CpKfoz+IcHTECrGTbQEmUtR9pBTxhne2K0Bgo\nTz+aIIMePIVBn/8rRwja59D1P4PabvkaSGwyGtX2wdeDIhJnN3Ak8RoBw/xm+rpG\nCyZVLks6m2LFqN8MvJacytKlaNTgGN+QIjYlEDqQispyxi2TKOMl9hThQ8ZrYByl\nHaLnVGJgqJJpvnsymUORRRUtNYrKw+tIpizwjCltLBf1eFk2M62qCZaNr3aRvKKz\n9X1i4tQFKqSfZeKxeAo6C/AnnTQ5y4FWvkjDveZZmAe5x9LCoJ+5DjXQaEBC9X/x\nl7RhvMnrXF5Bhom67DaHaemc9Ul2qlPD8Q2LjgQbis74TCGtXtb2dWorGtsVtOMt\nSc/9hAizDp2Hw0O0d+dqFHJ45VrVYgk0tmIwOQMAeSGKtqggzajkfxUQIDGUMbRR\n43FYzxp8YcdVtQ0XVsj0/8VejiDct5YNSJLY2glxhBt6yHrNHdxBCgP5eOggErOL\nSs8mHWtqaglcLRchx6+6HgfemqCiERxmZAvTtzsWW/0eBYRbn6Q=\n=BMpA\n-----END PGP SIGNATURE-----\n From 36afd16634f90da2329db3b5e303ccc5ad726a20 Mon Sep 17 00:00:00 2001 From: Judith Silverman Date: Fri, 10 Jun 2022 16:43:34 -0700 Subject: [PATCH 5/6] Responded to compiler warnings --- json5_parser/CMakeLists.txt | 34 +++++++++---------- json5_parser/json5_parser_reader_template.h | 3 +- json5_parser/json5_parser_value.h | 4 +++ json_demo/CMakeLists.txt | 18 +++++----- json_headers_only_demo/CMakeLists.txt | 18 +++++----- .../json_headers_only_demo.cpp | 2 ++ json_map_demo/CMakeLists.txt | 18 +++++----- json_test/CMakeLists.txt | 30 ++++++++-------- json_test/json5_parser_reader_test.cpp | 2 +- 9 files changed, 68 insertions(+), 61 deletions(-) diff --git a/json5_parser/CMakeLists.txt b/json5_parser/CMakeLists.txt index e83fb38..c3d3941 100644 --- a/json5_parser/CMakeLists.txt +++ b/json5_parser/CMakeLists.txt @@ -1,17 +1,17 @@ -SET(JSON_SPIRIT_SRCS -json5_parser_reader.cpp json5_parser_reader.h -json5_parser_value.cpp json5_parser_value.h -json5_parser_writer.cpp json5_parser_writer.h -json5_parser.h -json5_parser_error_position.h -json5_parser_reader_template.h -json5_parser_stream_reader.h -json5_parser_utils.h -json5_parser_writer_options.h -json5_parser_writer_template.h ) - -FIND_PACKAGE(Boost 1.34 REQUIRED) -INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) - -ADD_LIBRARY(json5_parser STATIC ${JSON_SPIRIT_SRCS}) - +SET(JSON_SPIRIT_SRCS +json5_parser_reader.cpp json5_parser_reader.h +json5_parser_value.cpp json5_parser_value.h +json5_parser_writer.cpp json5_parser_writer.h +json5_parser.h +json5_parser_error_position.h +json5_parser_reader_template.h +json5_parser_stream_reader.h +json5_parser_utils.h +json5_parser_writer_options.h +json5_parser_writer_template.h ) + +#FIND_PACKAGE(Boost 1.34 REQUIRED) +INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) + +ADD_LIBRARY(json5_parser STATIC ${JSON_SPIRIT_SRCS}) + diff --git a/json5_parser/json5_parser_reader_template.h b/json5_parser/json5_parser_reader_template.h index be9950e..865daf7 100644 --- a/json5_parser/json5_parser_reader_template.h +++ b/json5_parser/json5_parser_reader_template.h @@ -19,7 +19,7 @@ #define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to // boost.thread -#include +#include #include #include @@ -405,6 +405,7 @@ class Json_grammar public: definition(const Json_grammar& self) { using namespace spirit_namespace; + using namespace boost::placeholders; typedef typename Value_type::String_type::value_type Char_type; diff --git a/json5_parser/json5_parser_value.h b/json5_parser/json5_parser_value.h index ecb8bd2..6181cea 100644 --- a/json5_parser/json5_parser_value.h +++ b/json5_parser/json5_parser_value.h @@ -14,6 +14,8 @@ #include #include #include +//#include + #include #include #include @@ -21,6 +23,8 @@ #include #include +//using namespace boost::placeholders; + // comment out the value types you don't need to reduce build times and intermediate // file sizes #define JSON_SPIRIT_VALUE_ENABLED diff --git a/json_demo/CMakeLists.txt b/json_demo/CMakeLists.txt index 40332dc..ae55f61 100644 --- a/json_demo/CMakeLists.txt +++ b/json_demo/CMakeLists.txt @@ -1,9 +1,9 @@ -SET(JSON_DEMO_SRCS -json_demo.cpp) - -FIND_PACKAGE(Boost 1.34 REQUIRED) -INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) - -ADD_EXECUTABLE(json_demo ${JSON_DEMO_SRCS}) -TARGET_LINK_LIBRARIES(json_demo json5_parser) - +SET(JSON_DEMO_SRCS +json_demo.cpp) + +#FIND_PACKAGE(Boost 1.34 REQUIRED) +INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) + +ADD_EXECUTABLE(json_demo ${JSON_DEMO_SRCS}) +TARGET_LINK_LIBRARIES(json_demo json5_parser) + diff --git a/json_headers_only_demo/CMakeLists.txt b/json_headers_only_demo/CMakeLists.txt index 713937f..f7a65fb 100644 --- a/json_headers_only_demo/CMakeLists.txt +++ b/json_headers_only_demo/CMakeLists.txt @@ -1,9 +1,9 @@ -SET(JSON_HEADERS_ONLY_DEMO_SRCS -json_headers_only_demo.cpp) - -FIND_PACKAGE(Boost 1.34 REQUIRED) -INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) - -ADD_EXECUTABLE(json_headers_only_demo ${JSON_HEADERS_ONLY_DEMO_SRCS}) -TARGET_LINK_LIBRARIES(json_headers_only_demo json5_parser) - +SET(JSON_HEADERS_ONLY_DEMO_SRCS +json_headers_only_demo.cpp) + +#FIND_PACKAGE(Boost 1.34 REQUIRED) +INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) + +ADD_EXECUTABLE(json_headers_only_demo ${JSON_HEADERS_ONLY_DEMO_SRCS}) +TARGET_LINK_LIBRARIES(json_headers_only_demo json5_parser) + diff --git a/json_headers_only_demo/json_headers_only_demo.cpp b/json_headers_only_demo/json_headers_only_demo.cpp index 4ea4379..2faa4ed 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 #include "json5_parser_reader_template.h" #include "json5_parser_writer_template.h" @@ -20,6 +21,7 @@ using namespace std; using namespace json5_parser; + struct Address { int house_number_; string road_; diff --git a/json_map_demo/CMakeLists.txt b/json_map_demo/CMakeLists.txt index 4a7d192..573edcd 100644 --- a/json_map_demo/CMakeLists.txt +++ b/json_map_demo/CMakeLists.txt @@ -1,9 +1,9 @@ -SET(JSON_MAP_DEMO_SRCS -json_map_demo.cpp) - -FIND_PACKAGE(Boost 1.34 REQUIRED) -INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) - -ADD_EXECUTABLE(json_map_demo ${JSON_MAP_DEMO_SRCS}) -TARGET_LINK_LIBRARIES(json_map_demo json5_parser) - +SET(JSON_MAP_DEMO_SRCS +json_map_demo.cpp) + +#FIND_PACKAGE(Boost 1.34 REQUIRED) +INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) + +ADD_EXECUTABLE(json_map_demo ${JSON_MAP_DEMO_SRCS}) +TARGET_LINK_LIBRARIES(json_map_demo json5_parser) + diff --git a/json_test/CMakeLists.txt b/json_test/CMakeLists.txt index e603f49..b367def 100644 --- a/json_test/CMakeLists.txt +++ b/json_test/CMakeLists.txt @@ -1,15 +1,15 @@ -SET(JSON_TEST_SRCS -json5_parser_reader_test.cpp json5_parser_reader_test.h -json5_parser_stream_reader_test.cpp json5_parser_stream_reader_test.h -json5_parser_utils_test.cpp json5_parser_utils_test.h -json5_parser_value_test.cpp json5_parser_value_test.h -json5_parser_writer_test.cpp json5_parser_writer_test.h -utils_test.cpp utils_test.h -json_test.cpp) - -FIND_PACKAGE(Boost 1.34 REQUIRED) -INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) - -ADD_EXECUTABLE(json_test ${JSON_TEST_SRCS}) -TARGET_LINK_LIBRARIES(json_test json5_parser) - +SET(JSON_TEST_SRCS +json5_parser_reader_test.cpp json5_parser_reader_test.h +json5_parser_stream_reader_test.cpp json5_parser_stream_reader_test.h +json5_parser_utils_test.cpp json5_parser_utils_test.h +json5_parser_value_test.cpp json5_parser_value_test.h +json5_parser_writer_test.cpp json5_parser_writer_test.h +utils_test.cpp utils_test.h +json_test.cpp) + +#FIND_PACKAGE(Boost 1.34 REQUIRED) +INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) + +ADD_EXECUTABLE(json_test ${JSON_TEST_SRCS}) +TARGET_LINK_LIBRARIES(json_test json5_parser) + diff --git a/json_test/json5_parser_reader_test.cpp b/json_test/json5_parser_reader_test.cpp index 8fbe9f0..fbbf3e2 100644 --- a/json_test/json5_parser_reader_test.cpp +++ b/json_test/json5_parser_reader_test.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include using namespace json5_parser; From ffb854cde5fea6e6bb3e9a4fab227e7290538563 Mon Sep 17 00:00:00 2001 From: suelabuzi Date: Mon, 27 Jun 2022 14:17:36 -0700 Subject: [PATCH 6/6] adding option for arch64 --- boost.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boost.py b/boost.py index d3c4869..0a23582 100644 --- a/boost.py +++ b/boost.py @@ -54,8 +54,7 @@ def build(bld): from waflib.Configure import conf from waflib.TaskGen import feature, after_method -BOOST_LIBS = ['/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu', - '/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib'] +BOOST_LIBS = ['/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu', '/usr/lib/aarch64-linux-gnu', '/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib'] BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include'] BOOST_VERSION_FILE = 'boost/version.hpp' BOOST_VERSION_CODE = '''