From 56fcb09f2d0fcfd2fbf3aab2b88d899fa7cb54a9 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Fri, 21 Oct 2022 16:05:47 +0300 Subject: [PATCH] reusing existing conversion components --- example/parse_into.cpp | 8 +- include/boost/json/detail/parse_into.hpp | 857 ++++++++++------------- include/boost/json/detail/value_to.hpp | 6 +- include/boost/json/impl/conversion.hpp | 30 +- 4 files changed, 386 insertions(+), 515 deletions(-) diff --git a/example/parse_into.cpp b/example/parse_into.cpp index fa480ee1..2507e302 100644 --- a/example/parse_into.cpp +++ b/example/parse_into.cpp @@ -89,7 +89,7 @@ BOOST_DESCRIBE_STRUCT(coordinates, (), (coordinates, info)) struct accumulator { - using value_type = coordinate; + using iterator = coordinate*; std::size_t len = 0; @@ -105,6 +105,12 @@ struct accumulator ++len; } + + iterator + begin(); + + iterator + end(); }; struct coordinates2 diff --git a/include/boost/json/detail/parse_into.hpp b/include/boost/json/detail/parse_into.hpp index a715fbc3..cf9e5565 100644 --- a/include/boost/json/detail/parse_into.hpp +++ b/include/boost/json/detail/parse_into.hpp @@ -20,6 +20,13 @@ namespace boost { namespace json { namespace detail { +template< class Impl, class T, class Parent > +class converting_handler; + +// get_handler +template< class V, class P > +using get_handler = converting_handler< generic_conversion_category, V, P >; + template class handler_error_base { public: @@ -47,45 +54,173 @@ public: bool on_null( error_code& ec ) { BOOST_JSON_FAIL( ec, E ); return false; } }; -// integral_handler +template< class P, error E > +class scalar_handler + : public handler_error_base +{ +protected: + P* parent_; +public: + scalar_handler(scalar_handler const&) = delete; + scalar_handler& operator=(scalar_handler const&) = delete; + + scalar_handler(P* p): parent_( p ) + {} + + bool on_array_end( std::size_t, error_code& ) + { + parent_->signal_end(); + return true; + } +}; + +template< class D, class V, class P, error E > +class composite_handler +{ +protected: + using inner_handler_type = get_handler; + + P* parent_; +#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + V next_value_ = {}; + inner_handler_type inner_; + bool inner_active_ = false; + +public: + composite_handler( composite_handler const& ) = delete; + composite_handler& operator=( composite_handler const& ) = delete; + + composite_handler( P* p ) + : parent_(p), inner_( &next_value_, static_cast(this) ) + {} +#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__) +# pragma GCC diagnostic pop +#endif + + void signal_end() + { + inner_active_ = false; + parent_->signal_value(); + } + +#define BOOST_JSON_INVOKE_INNER(f) \ + if( !inner_active_ ) { \ + BOOST_JSON_FAIL(ec, E); \ + return false; \ + } \ + else \ + return inner_.f + + bool on_object_begin( error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_object_begin(ec) ); + } + + bool on_object_end( std::size_t n, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_object_end(n, ec) ); + } + + bool on_array_begin( error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_array_begin(ec) ); + } + + bool on_array_end( std::size_t n, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_array_end(n, ec) ); + } + + bool on_key_part( string_view sv, std::size_t n, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_key_part(sv, n, ec) ); + } + + bool on_key( string_view sv, std::size_t n, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_key(sv, n, ec) ); + } + + bool on_string_part( string_view sv, std::size_t n, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_string_part(sv, n, ec) ); + } + + bool on_string( string_view sv, std::size_t n, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_string(sv, n, ec) ); + } + + bool on_number_part( string_view sv, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_number_part(sv, ec) ); + } + + bool on_int64( std::int64_t v, string_view sv, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_int64(v, sv, ec) ); + } + + bool on_uint64( std::uint64_t v, string_view sv, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_uint64(v, sv, ec) ); + } + + bool on_double( double v, string_view sv, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_double(v, sv, ec) ); + } + + bool on_bool( bool v, error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_bool(v, ec) ); + } + + bool on_null( error_code& ec ) + { + BOOST_JSON_INVOKE_INNER( on_null(ec) ); + } + +#undef BOOST_JSON_INVOKE_INNER +}; + +// integral handler template::value, int>::type = 0> - bool integral_in_range( std::int64_t v ) +typename std::enable_if::value, int>::type = 0> +bool integral_in_range( std::int64_t v ) { return v >= (std::numeric_limits::min)() && v <= (std::numeric_limits::max)(); } template::value, int>::type = 0> - bool integral_in_range( std::int64_t v ) +typename std::enable_if::value, int>::type = 0> +bool integral_in_range( std::int64_t v ) { return v >= 0 && static_cast( v ) <= (std::numeric_limits::max)(); } template - bool integral_in_range( std::uint64_t v ) +bool integral_in_range( std::uint64_t v ) { return v <= static_cast::type>( (std::numeric_limits::max)() ); } -template class integral_handler: public handler_error_base +template< class V, class P > +class converting_handler + : public scalar_handler { private: - - V * value_; - P * parent_; + V* value_; public: - - integral_handler( integral_handler const& ) = delete; - integral_handler& operator=( integral_handler const& ) = delete; - -public: - - integral_handler( V* v, P* p ): value_( v ), parent_( p ) - { - } + converting_handler( V* v, P* p ) + : converting_handler::scalar_handler(p) + , value_(v) + {} bool on_number_part( string_view, error_code& ) { @@ -102,7 +237,7 @@ public: *value_ = static_cast( v ); - parent_->signal_value(); + this->parent_->signal_value(); return true; } @@ -116,36 +251,24 @@ public: *value_ = static_cast( v ); - parent_->signal_value(); - return true; - } - - bool on_array_end( std::size_t, error_code& ) - { - parent_->signal_end(); + this->parent_->signal_value(); return true; } }; -// floating_point_handler - -template class floating_point_handler: public handler_error_base +// floating point handler +template< class V, class P> +class converting_handler + : public scalar_handler { private: - - V * value_; - P * parent_; + V* value_; public: - - floating_point_handler( floating_point_handler const& ) = delete; - floating_point_handler& operator=( floating_point_handler const& ) = delete; - -public: - - floating_point_handler( V* v, P* p ): value_( v ), parent_( p ) - { - } + converting_handler( V* v, P* p ) + : converting_handler::scalar_handler(p) + , value_(v) + {} bool on_number_part( string_view, error_code& ) { @@ -156,7 +279,7 @@ public: { *value_ = static_cast( v ); - parent_->signal_value(); + this->parent_->signal_value(); return true; } @@ -164,7 +287,7 @@ public: { *value_ = static_cast( v ); - parent_->signal_value(); + this->parent_->signal_value(); return true; } @@ -172,31 +295,24 @@ public: { *value_ = static_cast( v ); - parent_->signal_value(); - return true; - } - - bool on_array_end( std::size_t, error_code& ) - { - parent_->signal_end(); + this->parent_->signal_value(); return true; } }; -// string_handler - -template class string_handler: public handler_error_base +// string handler +template< class V, class P > +class converting_handler + : public scalar_handler { private: - - V * value_; - P * parent_; + V* value_; public: - - string_handler( V* v, P* p ): value_( v ), parent_( p ) - { - } + converting_handler( V* v, P* p ) + : converting_handler::scalar_handler(p) + , value_(v) + {} bool on_string_part( string_view sv, std::size_t, error_code& ) { @@ -208,384 +324,171 @@ public: { value_->append( sv.begin(), sv.end() ); - parent_->signal_value(); - return true; - } - - bool on_array_end( std::size_t, error_code& ) - { - parent_->signal_end(); + this->parent_->signal_value(); return true; } }; -// bool_handler - -template class bool_handler: public handler_error_base +// bool handler +template< class V, class P > +class converting_handler + : public scalar_handler { private: - - V * value_; - P * parent_; + V* value_; public: - - bool_handler( bool_handler const& ) = delete; - bool_handler& operator=( bool_handler const& ) = delete; - -public: - - bool_handler( V* v, P* p ): value_( v ), parent_( p ) - { - } + converting_handler( V* v, P* p ) + : converting_handler::scalar_handler(p) + , value_(v) + {} bool on_bool( bool v, error_code& ) { *value_ = v; - parent_->signal_value(); - return true; - } - - bool on_array_end( std::size_t, error_code& ) - { - parent_->signal_end(); + this->parent_->signal_value(); return true; } }; -// null_handler - -template class null_handler: public handler_error_base +// null handler +template< class V, class P > +class converting_handler + : public scalar_handler { private: - - V * value_; - P * parent_; + V* value_; public: - - null_handler( null_handler const& ) = delete; - null_handler& operator=( null_handler const& ) = delete; - -public: - - null_handler( V* v, P* p ): value_( v ), parent_( p ) - { - } + converting_handler( V* v, P* p ) + : converting_handler::scalar_handler(p) + , value_(v) + {} bool on_null( error_code& ) { *value_ = {}; - parent_->signal_value(); - return true; - } - - bool on_array_end( std::size_t, error_code& ) - { - parent_->signal_end(); + this->parent_->signal_value(); return true; } }; -// forward declarations - -template class sequence_handler; -template class map_handler; -template class tuple_handler; -template class described_struct_handler; - -template struct unknown_type_handler +template< class V, class P > +class converting_handler { static_assert( sizeof(V) == 0, "This type is not supported" ); }; -// is_string - -template struct is_string: std::is_same -{ -}; - -// is_map - -template struct is_map: std::false_type -{ -}; - -template struct is_map().emplace( std::declval(), std::declval() ), (void)0 )>: std::true_type -{ -}; - -// is_sequence - -template struct is_sequence: std::false_type -{ -}; - -template struct is_sequence().push_back( std::declval() ), (void)0 )>: std::true_type -{ -}; - -// is_tuple - -template struct is_tuple: std::false_type -{ -}; - -template struct is_tuple::value )>: std::true_type -{ -}; - -// is_described_struct - -template struct is_described_struct: std::false_type -{ -}; - -template struct is_described_struct())>: std::true_type -{ -}; - -// get_handler - -template using get_handler = boost::mp11::mp_cond< - - std::is_same, null_handler, - std::is_same, bool_handler, - std::is_integral, integral_handler, - std::is_floating_point, floating_point_handler, - is_string, string_handler, - is_map, map_handler, - is_sequence, sequence_handler, - is_tuple, tuple_handler, - is_described_struct, described_struct_handler, - boost::mp11::mp_true, unknown_type_handler ->; - -// sequence_handler - -template class sequence_handler +// sequence handler +template< class V, class P > +class converting_handler + : public composite_handler< + converting_handler, + detail::value_type, + P, + error::not_array> { private: - - V * value_; - P * parent_; - - using value_type = typename V::value_type; - using inner_handler_type = get_handler; - - value_type next_value_ = {}; - - inner_handler_type inner_; - bool inner_active_ = false; + V* value_; public: - - sequence_handler( sequence_handler const& ) = delete; - sequence_handler& operator=( sequence_handler const& ) = delete; - -public: - - sequence_handler( V* v, P* p ): value_( v ), parent_( p ), inner_( &next_value_, this ) - { - } + converting_handler( V* v, P* p ) + : converting_handler::composite_handler(p), value_(v) + {} void signal_value() { - value_->push_back( std::move( next_value_ ) ); - next_value_ = {}; - } - - void signal_end() - { - inner_active_ = false; - parent_->signal_value(); - } - -#define BOOST_JSON_INVOKE_INNER(f) if( !inner_active_ ) { \ - BOOST_JSON_FAIL( ec, error::not_array ); return false; } else return inner_.f - - bool on_object_begin( error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_object_begin( ec ) ); - } - - bool on_object_end( std::size_t n, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_object_end( n, ec ) ); + value_->push_back( std::move(this->next_value_) ); + this->next_value_ = {}; } bool on_array_begin( error_code& ec ) { - if( inner_active_ ) + if( this->inner_active_ ) { - return inner_.on_array_begin( ec ); + return this->inner_.on_array_begin( ec ); } else { - inner_active_ = true; + this->inner_active_ = true; return true; } } bool on_array_end( std::size_t n, error_code& ec ) { - if( inner_active_ ) + if( this->inner_active_ ) { - return inner_.on_array_end( n, ec ); + return this->inner_.on_array_end( n, ec ); } else { - parent_->signal_end(); + this->parent_->signal_end(); return true; } } - - bool on_key_part( string_view sv, std::size_t n, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_key_part( sv, n, ec ) ); - } - - bool on_key( string_view sv, std::size_t n, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_key( sv, n, ec ) ); - } - - bool on_string_part( string_view sv, std::size_t n, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_string_part( sv, n, ec ) ); - } - - bool on_string( string_view sv, std::size_t n, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_string( sv, n, ec ) ); - } - - bool on_number_part( string_view sv, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_number_part( sv, ec ) ); - } - - bool on_int64( std::int64_t v, string_view sv, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_int64( v, sv, ec ) ); - } - - bool on_uint64( std::uint64_t v, string_view sv, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_uint64( v, sv, ec ) ); - } - - bool on_double( double v, string_view sv, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_double( v, sv, ec ) ); - } - - bool on_bool( bool v, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_bool( v, ec ) ); - } - - bool on_null( error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_null( ec ) ); - } - -#undef BOOST_JSON_INVOKE_INNER }; -// map_handler - -template class map_handler +// map handler +template< class V, class P > +class converting_handler + : public composite_handler< + converting_handler, + detail::mapped_type, + P, + error::not_object> { private: - - V * value_; - P * parent_; - - using mapped_type = typename V::mapped_type; - using inner_handler_type = get_handler; - + V* value_; std::string key_; - mapped_type next_value_ = {}; - - inner_handler_type inner_; - bool inner_active_ = false; public: - - map_handler( map_handler const& ) = delete; - map_handler& operator=( map_handler const& ) = delete; - -public: - - map_handler( V* v, P* p ): value_( v ), parent_( p ), inner_( &next_value_, this ) - { - } + converting_handler( V* v, P* p ) + : converting_handler::composite_handler(p), value_(v) + {} void signal_value() { - value_->emplace( std::move( key_ ), std::move( next_value_ ) ); + value_->emplace( std::move(key_), std::move(this->next_value_) ); key_ = {}; - next_value_ = {}; + this->next_value_ = {}; - inner_active_ = false; + this->inner_active_ = false; } - void signal_end() - { - inner_active_ = false; - parent_->signal_value(); - } - -#define BOOST_JSON_INVOKE_INNER(f) if( !inner_active_ ) { \ - BOOST_JSON_FAIL( ec, error::not_object ); return false; } else return inner_.f - bool on_object_begin( error_code& ec ) { - if( inner_active_ ) - { - return inner_.on_object_begin( ec ); - } + if( this->inner_active_ ) + return this->inner_.on_object_begin(ec); return true; } bool on_object_end( std::size_t n, error_code& ec ) { - if( inner_active_ ) - { - return inner_.on_object_end( n, ec ); - } + if( this->inner_active_ ) + return this->inner_.on_object_end(n, ec); - parent_->signal_value(); + this->parent_->signal_value(); return true; } - bool on_array_begin( error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_array_begin( ec ) ); - } - bool on_array_end( std::size_t n, error_code& ec ) { - if( inner_active_ ) - { - return inner_.on_array_end( n, ec ); - } + if( this->inner_active_ ) + return this->inner_.on_array_end(n, ec); - parent_->signal_end(); + this->parent_->signal_end(); return true; } bool on_key_part( string_view sv, std::size_t n, error_code& ec ) { - if( inner_active_ ) - { - return inner_.on_key_part( sv, n, ec ); - } + if( this->inner_active_ ) + return this->inner_.on_key_part(sv, n, ec); key_.append( sv.data(), sv.size() ); return true; @@ -593,62 +496,17 @@ public: bool on_key( string_view sv, std::size_t n, error_code& ec ) { - if( inner_active_ ) - { - return inner_.on_key( sv, n, ec ); - } + if( this->inner_active_ ) + return this->inner_.on_key(sv, n, ec); key_.append( sv.data(), sv.size() ); - inner_active_ = true; + this->inner_active_ = true; return true; } - - bool on_string_part( string_view sv, std::size_t n, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_string_part( sv, n, ec ) ); - } - - bool on_string( string_view sv, std::size_t n, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_string( sv, n, ec ) ); - } - - bool on_number_part( string_view sv, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_number_part( sv, ec ) ); - } - - bool on_int64( std::int64_t v, string_view sv, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_int64( v, sv, ec ) ); - } - - bool on_uint64( std::uint64_t v, string_view sv, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_uint64( v, sv, ec ) ); - } - - bool on_double( double v, string_view sv, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_double( v, sv, ec ) ); - } - - bool on_bool( bool v, error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_bool( v, ec ) ); - } - - bool on_null( error_code& ec ) - { - BOOST_JSON_INVOKE_INNER( on_null( ec ) ); - } - -#undef BOOST_JSON_INVOKE_INNER }; -// into_handler tuple - +// tuple handler #if defined(BOOST_MSVC) && BOOST_MSVC < 1910 // MSVC 2015 can't handle handler_tuple_impl @@ -662,44 +520,59 @@ template struct handler_tuple_element template struct handler_tuple_impl; -template struct handler_tuple_impl, T...>: handler_tuple_element... +template +struct handler_tuple_impl, T...> + : handler_tuple_element... { - template handler_tuple_impl( A... a ): handler_tuple_element{{ a.first, a.second }}... {} + template + handler_tuple_impl( A... a ) + : handler_tuple_element{{ a.first, a.second }}... + { } }; -template struct handler_tuple: public handler_tuple_impl, get_handler...> +template +struct handler_tuple + : public handler_tuple_impl< + mp11::index_sequence_for, get_handler...> { - using base_type = handler_tuple_impl, get_handler...>; + using base_type = handler_tuple_impl< + mp11::index_sequence_for, get_handler...>; - template handler_tuple( A... a ): base_type( a... ) - { - } + template + handler_tuple( A... a ) + : base_type( a... ) + { } handler_tuple( handler_tuple const& ) = delete; handler_tuple& operator=( handler_tuple const& ) = delete; }; -template T& get( handler_tuple_element& e ) +template +T& +get( handler_tuple_element& e ) { return e.t_; } -// tuple_handler +template< class P, class T > +struct tuple_inner_handlers; -template struct tuple_inner_handlers; - -template class L, class... V> struct tuple_inner_handlers> +template< class P, template class L, class... V > +struct tuple_inner_handlers> { handler_tuple handlers_; - template tuple_inner_handlers( L* pv, P* pp, boost::mp11::index_sequence ): handlers_( std::make_pair( &get(*pv), pp )... ) - { - } + template + tuple_inner_handlers( + L* pv, P* pp, mp11::index_sequence ) + : handlers_( std::make_pair( &get(*pv), pp )... ) + {} }; #endif -template class tuple_handler +template< class T, class P > +class converting_handler { #if BOOST_CXX_VERSION < 201400L || ( defined(BOOST_MSVC) && BOOST_MSVC < 1910 ) @@ -709,23 +582,24 @@ template class tuple_handler #else private: + T* value_; + P* parent_; - T * value_; - P * parent_; - - tuple_inner_handlers inner_; + tuple_inner_handlers inner_; int inner_active_ = -1; public: + converting_handler( converting_handler const& ) = delete; + converting_handler& operator=( converting_handler const& ) = delete; - tuple_handler( tuple_handler const& ) = delete; - tuple_handler& operator=( tuple_handler const& ) = delete; - -public: - - tuple_handler( T* v, P* p ): value_( v ), parent_( p ), inner_( v, this, boost::mp11::make_index_sequence< std::tuple_size::value >() ) - { - } + converting_handler( T* v, P* p ) + : value_( v ) + , parent_( p ) + , inner_( + v, + this, + mp11::make_index_sequence< std::tuple_size::value >()) + {} void signal_value() { @@ -750,20 +624,18 @@ public: BOOST_JSON_FAIL( ec, error::size_mismatch ); \ return false; \ } \ - return boost::mp11::mp_with_index( inner_active_, [&](auto I){ \ + return mp11::mp_with_index( inner_active_, [&](auto I){ \ return get( inner_.handlers_ ).fn; \ }); - //--- - bool on_object_begin( error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_object_begin( ec ) ); + BOOST_JSON_INVOKE_INNER( on_object_begin(ec) ); } bool on_object_end( std::size_t n, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_object_end( n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_object_end(n, ec) ); } bool on_array_begin( error_code& ec ) @@ -782,10 +654,8 @@ public: return true; } - return boost::mp11::mp_with_index( inner_active_, [&](auto I){ - - return get( inner_.handlers_ ).on_array_begin( ec ); - + return mp11::mp_with_index( inner_active_, [&](auto I){ + return get( inner_.handlers_ ).on_array_begin(ec); }); } @@ -807,61 +677,59 @@ public: return true; } - return boost::mp11::mp_with_index( inner_active_, [&](auto I){ - + return mp11::mp_with_index( inner_active_, [&](auto I){ return get( inner_.handlers_ ).on_array_end( n, ec ); - }); } bool on_key_part( string_view sv, std::size_t n, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_key_part( sv, n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_key_part(sv, n, ec) ); } bool on_key( string_view sv, std::size_t n, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_key( sv, n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_key(sv, n, ec) ); } bool on_string_part( string_view sv, std::size_t n, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_string_part( sv, n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_string_part(sv, n, ec) ); } bool on_string( string_view sv, std::size_t n, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_string( sv, n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_string(sv, n, ec) ); } bool on_number_part( string_view sv, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_number_part( sv, ec ) ); + BOOST_JSON_INVOKE_INNER( on_number_part(sv, ec) ); } bool on_int64( std::int64_t v, string_view sv, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_int64( v, sv, ec ) ); + BOOST_JSON_INVOKE_INNER( on_int64(v, sv, ec) ); } bool on_uint64( std::uint64_t v, string_view sv, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_uint64( v, sv, ec ) ); + BOOST_JSON_INVOKE_INNER( on_uint64(v, sv, ec) ); } bool on_double( double v, string_view sv, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_double( v, sv, ec ) ); + BOOST_JSON_INVOKE_INNER( on_double(v, sv, ec) ); } bool on_bool( bool v, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_bool( v, ec ) ); + BOOST_JSON_INVOKE_INNER( on_bool(v, ec) ); } bool on_null( error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_null( ec ) ); + BOOST_JSON_INVOKE_INNER( on_null(ec) ); } #undef BOOST_JSON_INVOKE_INNER @@ -869,22 +737,22 @@ public: #endif // BOOST_CXX_VERSION < 201400L }; -// described_struct_handler +// described struct handler +template +struct struct_inner_handlers; -template using struct_member_type = typename std::remove_reference< decltype( std::declval().*D::pointer ) >::type; - -template struct struct_inner_handlers; - -template class L, class... D> struct struct_inner_handlers> +template class L, class... D> +struct struct_inner_handlers> { - handler_tuple...> handlers_; + handler_tuple...> handlers_; - struct_inner_handlers( T* pv, P* pp ): handlers_( std::make_pair( &(pv->*D::pointer), pp )... ) - { - } + struct_inner_handlers( T* pv, P* pp ) + : handlers_( std::make_pair( &(pv->*D::pointer), pp )... ) + {} }; -template class described_struct_handler +template +class converting_handler { #if BOOST_CXX_VERSION < 201400L || ( defined(BOOST_MSVC) && BOOST_MSVC < 1910 ) @@ -894,27 +762,23 @@ template class described_struct_handler #else private: - - V * value_; - P * parent_; + V* value_; + P* parent_; std::string key_; - using Dm = boost::describe::describe_members; + using Dm = describe::describe_members; - struct_inner_handlers inner_; + struct_inner_handlers inner_; int inner_active_ = -1; public: + converting_handler( converting_handler const& ) = delete; + converting_handler& operator=( converting_handler const& ) = delete; - described_struct_handler( described_struct_handler const& ) = delete; - described_struct_handler& operator=( described_struct_handler const& ) = delete; - -public: - - described_struct_handler( V* v, P* p ): value_( v ), parent_( p ), inner_( v, this ) - { - } + converting_handler( V* v, P* p ) + : value_(v), parent_(p), inner_(v, this) + {} void signal_value() { @@ -936,20 +800,16 @@ public: BOOST_JSON_FAIL( ec, error::not_object ); \ return false; \ } \ - return boost::mp11::mp_with_index>( inner_active_, [&](auto I){ \ + return mp11::mp_with_index>( inner_active_, [&](auto I) { \ return get( inner_.handlers_ ).fn; \ }); - //--- - bool on_object_begin( error_code& ec ) { if( inner_active_ < 0 ) - { return true; - } - BOOST_JSON_INVOKE_INNER( on_object_begin( ec ) ); + BOOST_JSON_INVOKE_INNER( on_object_begin(ec) ); } bool on_object_end( std::size_t n, error_code& ec ) @@ -960,12 +820,12 @@ public: return true; } - BOOST_JSON_INVOKE_INNER( on_object_end( n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_object_end(n, ec) ); } bool on_array_begin( error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_array_begin( ec ) ); + BOOST_JSON_INVOKE_INNER( on_array_begin(ec) ); } bool on_array_end( std::size_t n, error_code& ec ) @@ -976,7 +836,7 @@ public: return true; } - BOOST_JSON_INVOKE_INNER( on_array_end( n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_array_end(n, ec) ); } bool on_key_part( string_view sv, std::size_t n, error_code& ec ) @@ -987,33 +847,29 @@ public: return true; } - BOOST_JSON_INVOKE_INNER( on_key_part( sv, n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_key_part(sv, n, ec) ); } bool on_key( string_view sv, std::size_t n, error_code& ec ) { if( inner_active_ >= 0 ) { - BOOST_JSON_INVOKE_INNER( on_key( sv, n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_key(sv, n, ec) ); } key_.append( sv.data(), sv.size() ); int i = 0; - boost::mp11::mp_for_each([&](auto D){ - + mp11::mp_for_each([&](auto D) { if( key_ == D.name ) - { inner_active_ = i; - } - ++i; }); if( inner_active_ < 0 ) { - BOOST_JSON_FAIL( ec, error::unknown_name ); + BOOST_JSON_FAIL(ec, error::unknown_name); return false; } @@ -1022,42 +878,42 @@ public: bool on_string_part( string_view sv, std::size_t n, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_string_part( sv, n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_string_part(sv, n, ec) ); } bool on_string( string_view sv, std::size_t n, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_string( sv, n, ec ) ); + BOOST_JSON_INVOKE_INNER( on_string(sv, n, ec) ); } bool on_number_part( string_view sv, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_number_part( sv, ec ) ); + BOOST_JSON_INVOKE_INNER( on_number_part(sv, ec) ); } bool on_int64( std::int64_t v, string_view sv, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_int64( v, sv, ec ) ); + BOOST_JSON_INVOKE_INNER( on_int64(v, sv, ec) ); } bool on_uint64( std::uint64_t v, string_view sv, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_uint64( v, sv, ec ) ); + BOOST_JSON_INVOKE_INNER( on_uint64(v, sv, ec) ); } bool on_double( double v, string_view sv, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_double( v, sv, ec ) ); + BOOST_JSON_INVOKE_INNER( on_double(v, sv, ec) ); } bool on_bool( bool v, error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_bool( v, ec ) ); + BOOST_JSON_INVOKE_INNER( on_bool(v, ec) ); } bool on_null( error_code& ec ) { - BOOST_JSON_INVOKE_INNER( on_null( ec ) ); + BOOST_JSON_INVOKE_INNER( on_null(ec) ); } #undef BOOST_JSON_INVOKE_INNER @@ -1066,8 +922,8 @@ public: }; // into_handler - -template class into_handler +template< class V > +class into_handler { private: @@ -1083,10 +939,10 @@ public: public: - constexpr static std::size_t max_object_size = std::size_t(-1); - constexpr static std::size_t max_array_size = std::size_t(-1); - constexpr static std::size_t max_key_size = std::size_t(-1); - constexpr static std::size_t max_string_size = std::size_t(-1); + static constexpr std::size_t max_object_size = object::max_size(); + static constexpr std::size_t max_array_size = array::max_size(); + static constexpr std::size_t max_key_size = string::max_size(); + static constexpr std::size_t max_string_size = string::max_size(); public: @@ -1113,7 +969,14 @@ public: return true; } -#define BOOST_JSON_INVOKE_INNER(f) if( !inner_active_ ) { BOOST_JSON_FAIL( ec, error::extra_data ); return false; } else return inner_.f +#define BOOST_JSON_INVOKE_INNER(f) \ + if( !inner_active_ ) \ + { \ + BOOST_JSON_FAIL( ec, error::extra_data ); \ + return false; \ + } \ + else \ + return inner_.f bool on_object_begin( error_code& ec ) { diff --git a/include/boost/json/detail/value_to.hpp b/include/boost/json/detail/value_to.hpp index 7bd6b224..6b43d550 100644 --- a/include/boost/json/detail/value_to.hpp +++ b/include/boost/json/detail/value_to.hpp @@ -382,10 +382,6 @@ struct to_described_member using Ds = describe::describe_members< T, describe::mod_public | describe::mod_inherited>; - template< class D > - using described_member_t = remove_cvref().* D::pointer )>; - using result_type = mp11::mp_eval_if_c< !non_throwing, T, result, T >; result_type& res; @@ -401,7 +397,7 @@ struct to_described_member return; using D = mp11::mp_at; - using M = described_member_t; + using M = described_member_t; auto const found = obj.find(D::name); if( found == obj.end() ) diff --git a/include/boost/json/impl/conversion.hpp b/include/boost/json/impl/conversion.hpp index 7e327c8d..8b008fbe 100644 --- a/include/boost/json/impl/conversion.hpp +++ b/include/boost/json/impl/conversion.hpp @@ -145,6 +145,8 @@ struct array_conversion_tag : native_conversion_tag { }; struct string_conversion_tag : native_conversion_tag { }; struct bool_conversion_tag : native_conversion_tag { }; struct number_conversion_tag : native_conversion_tag { }; +struct integral_conversion_tag : number_conversion_tag { }; +struct floating_point_conversion_tag : number_conversion_tag { }; struct null_like_conversion_tag { }; struct string_like_conversion_tag { }; struct map_like_conversion_tag { }; @@ -217,6 +219,9 @@ using described_non_public_members = describe::describe_members< template< class T > using described_bases = describe::describe_bases< T, describe::mod_any_access>; +template< class T, class D > +using described_member_t = remove_cvref().* D::pointer )>; // user conversion (via tag_invoke) template< class Ctx, class T, class Dir > @@ -236,19 +241,20 @@ using native_conversion_category = mp11::mp_cond< // generic conversions template< class T > using generic_conversion_category = mp11::mp_cond< - std::is_same, bool_conversion_tag, - std::is_arithmetic, number_conversion_tag, - is_null_like, null_like_conversion_tag, - is_string_like, string_like_conversion_tag, - is_map_like, map_like_conversion_tag, - is_sequence_like, sequence_conversion_tag, - is_tuple_like, tuple_conversion_tag, - is_described_class, described_class_conversion_tag, - is_described_enum, described_enum_conversion_tag, - is_variant_like, variant_conversion_tag, - is_optional_like, optional_conversion_tag, + std::is_same, bool_conversion_tag, + std::is_integral, integral_conversion_tag, + std::is_floating_point, floating_point_conversion_tag, + is_null_like, null_like_conversion_tag, + is_string_like, string_like_conversion_tag, + is_map_like, map_like_conversion_tag, + is_sequence_like, sequence_conversion_tag, + is_tuple_like, tuple_conversion_tag, + is_described_class, described_class_conversion_tag, + is_described_enum, described_enum_conversion_tag, + is_variant_like, variant_conversion_tag, + is_optional_like, optional_conversion_tag, // failed to find a suitable implementation - mp11::mp_true, no_conversion_tag>; + mp11::mp_true, no_conversion_tag>; template< class T > using nested_type = typename T::type;