// // Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/url // #ifndef BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP #define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP #include #include #include #include #include namespace boost { namespace urls { namespace grammar { namespace detail { // returns a tuple template< bool IsList, class R0, class... Rn> struct parse_sequence { using R = detail::tuple; using L = mp11::mp_list< typename R0::value_type, typename Rn::value_type...>; using V = mp11::mp_remove< std::tuple< system::result, system::result...>, system::result>; template using is_void = std::is_same< mp11::mp_at_c, void>; system::error_code ec; R const& rn; V vn; explicit parse_sequence( R const& rn_) noexcept : rn(rn_) , vn(mp11::mp_fill< V, system::error_code>{}) { } void apply( char const*&, char const*, ...) const noexcept { } // for system::result template< std::size_t Ir, std::size_t Iv> void apply( char const*& it, char const* end, mp11::mp_size_t const&, mp11::mp_size_t const&, mp11::mp_true const&) { system::result rv = grammar::parse( it, end, get(rn)); if( !rv ) { ec = rv.error(); return; } apply(it, end, mp11::mp_size_t{}, mp11::mp_size_t{}); } template< std::size_t Ir, std::size_t Iv> void apply( char const*& it, char const* end, mp11::mp_size_t const&, mp11::mp_size_t const&, mp11::mp_false const&) { auto& rv = get(vn); rv = grammar::parse( it, end, get(rn)); if( !rv ) { ec = rv.error(); return; } apply(it, end, mp11::mp_size_t{}, mp11::mp_size_t{}); } template< std::size_t Ir = 0, std::size_t Iv = 0> typename std::enable_if< Ir < 1 + sizeof...(Rn)>::type apply( char const*& it, char const* end, mp11::mp_size_t const& ir = {}, mp11::mp_size_t const& iv = {} ) noexcept { apply(it, end, ir, iv, is_void{}); } struct deref { template auto operator()(R const& r) const -> decltype(*r) { return *r; } }; auto make_result() noexcept -> system::result::value_type> { if(ec.failed()) return ec; return mp11::tuple_transform( deref{}, vn); } }; // returns a value_type template struct parse_sequence { using R = detail::tuple; using L = mp11::mp_list< typename R0::value_type, typename Rn::value_type...>; using V = mp11::mp_first< mp11::mp_remove< mp11::mp_list< system::result, system::result...>, system::result>>; template using is_void = std::is_same< mp11::mp_at_c, void>; R const& rn; V v; explicit parse_sequence( R const& rn_) noexcept : rn(rn_) , v(system::error_code{}) { } void apply( char const*&, char const*, ...) const noexcept { } // for system::result template< std::size_t Ir, std::size_t Iv> BOOST_URL_NO_INLINE void apply( char const*& it, char const* end, mp11::mp_size_t const&, mp11::mp_size_t const&, mp11::mp_true const&) { system::result rv = grammar::parse( it, end, get(rn)); if( !rv ) { v = rv.error(); return; } apply(it, end, mp11::mp_size_t{}, mp11::mp_size_t{}); } template< std::size_t Ir, std::size_t Iv> void apply( char const*& it, char const* end, mp11::mp_size_t const&, mp11::mp_size_t const&, mp11::mp_false const&) { v = grammar::parse( it, end, get(rn)); if( !v ) return; apply(it, end, mp11::mp_size_t{}, mp11::mp_size_t{}); } template< std::size_t Ir = 0, std::size_t Iv = 0> typename std::enable_if< Ir < 1 + sizeof...(Rn)>::type apply( char const*& it, char const* end, mp11::mp_size_t const& ir = {}, mp11::mp_size_t const& iv = {} ) noexcept { apply(it, end, ir, iv, is_void{}); } V make_result() noexcept { return v; } }; } // detail template< class R0, class... Rn> auto tuple_rule_t:: parse( char const*& it, char const* end) const -> system::result { detail::parse_sequence< IsList, R0, Rn...> t(this->get()); t.apply(it, end); return t.make_result(); } } // grammar } // urls } // boost #endif