// // Copyright (c) 2016-2019 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_TUPLE_RULE_HPP #define BOOST_URL_GRAMMAR_TUPLE_RULE_HPP #include #include #include #include #include #include #include #include #include namespace boost { namespace urls { namespace grammar { namespace implementation_defined { template< class R0, class... Rn> class tuple_rule_t : empty_value< detail::tuple> { using T = mp11::mp_remove< std::tuple< typename R0::value_type, typename Rn::value_type...>, void>; static constexpr bool IsList = mp11::mp_size::value != 1; public: using value_type = mp11::mp_eval_if_c; constexpr tuple_rule_t( R0 const& r0, Rn const&... rn) noexcept : empty_value< detail::tuple>( empty_init, r0, rn...) { } system::result parse( char const*& it, char const* end) const; }; } // implementation_defined /** Match a series of rules in order This matches a series of rules in the order specified. Upon success the input is adjusted to point to the first unconsumed character. There is no implicit specification of linear white space between each rule. @par Value Type @code using value_type = __see_below__; @endcode The sequence rule usually returns a `std::tuple` containing the the `value_type` of each corresponding rule in the sequence, except that `void` values are removed. However, if there is exactly one non-void value type `T`, then the sequence rule returns `system::result` instead of `system::result>`. @par Example Rules are used with the function @ref parse. @code system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv = parse( "192.168.0.1", tuple_rule( dec_octet_rule, squelch( delim_rule('.') ), dec_octet_rule, squelch( delim_rule('.') ), dec_octet_rule, squelch( delim_rule('.') ), dec_octet_rule ) ); @endcode @par BNF @code sequence = rule1 rule2 rule3... @endcode @par Specification @li 3.1. Concatenation (rfc5234) @param r0 The first rule to match @param rn A list of one or more rules to match @return The sequence rule @see @ref dec_octet_rule, @ref delim_rule, @ref parse, @ref squelch. */ template< BOOST_URL_CONSTRAINT(Rule) R0, BOOST_URL_CONSTRAINT(Rule)... Rn> constexpr auto tuple_rule( R0 const& r0, Rn const&... rn) noexcept -> implementation_defined::tuple_rule_t< R0, Rn...> { BOOST_CORE_STATIC_ASSERT( mp11::mp_all< is_rule, is_rule...>::value); return { r0, rn... }; } namespace implementation_defined { template struct squelch_rule_t : empty_value { using value_type = void; constexpr squelch_rule_t( Rule const& r) noexcept : empty_value( empty_init, r) { } system::result parse( char const*& it, char const* end) const { auto rv = this->get().parse(it, end); if(rv.error()) return rv.error(); return {}; // void } }; } // implementation_defined /** Squelch the value of a rule This function returns a new rule which matches the specified rule, and converts its value type to `void`. This is useful for matching delimiters in a grammar, where the value for the delimiter is not needed. @par Value Type @code using value_type = void; @endcode @par Example 1 With `squelch`: @code system::result< std::tuple< decode_view, core::string_view > > rv = parse( "www.example.com:443", tuple_rule( pct_encoded_rule(unreserved_chars + '-' + '.'), squelch( delim_rule( ':' ) ), token_rule( digit_chars ) ) ); @endcode @par Example 2 Without `squelch`: @code system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse( "www.example.com:443", tuple_rule( pct_encoded_rule(unreserved_chars + '-' + '.'), delim_rule( ':' ), token_rule( digit_chars ) ) ); @endcode @param r The rule to squelch @return The squelched rule @see @ref delim_rule, @ref digit_chars, @ref parse, @ref tuple_rule, @ref token_rule, @ref decode_view, @ref pct_encoded_rule, @ref unreserved_chars. */ template constexpr BOOST_URL_IMPLEMENTATION_DEFINED(implementation_defined::squelch_rule_t) squelch( R const& r ) noexcept { BOOST_CORE_STATIC_ASSERT(is_rule::value); return { r }; } } // grammar } // urls } // boost #include #endif