// // 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 namespace boost { namespace urls { namespace grammar { /** 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 `result` instead of `result>`. @par Example Rules are used with the function @ref parse. @code 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 rn A list of one or more rules to match @see @ref dec_octet_rule, @ref delim_rule, @ref parse, @ref squelch. */ #ifdef BOOST_URL_DOCS template constexpr __implementation_defined__ tuple_rule( Rules... rn ) noexcept; #else template< class R0, class... Rn> class tuple_rule_t : urls::detail::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; template< class R0_, class... Rn_> friend constexpr auto tuple_rule( R0_ const& r0, Rn_ const&... rn) noexcept -> tuple_rule_t; result parse( char const*& it, char const* end) const; private: constexpr tuple_rule_t( R0 const& r0, Rn const&... rn) noexcept : urls::detail::empty_value< detail::tuple>( urls::detail::empty_init, r0, rn...) { } }; template< class R0, class... Rn> constexpr auto tuple_rule( R0 const& r0, Rn const&... rn) noexcept -> tuple_rule_t< R0, Rn...> { return { r0, rn... }; } #endif #ifndef BOOST_URL_DOCS namespace detail { template struct squelch_rule_t : urls::detail::empty_value { using value_type = void; constexpr squelch_rule_t( Rule const& r) noexcept : urls::detail::empty_value( urls::detail::empty_init, r) { } result parse( char const*& it, char const* end) const { auto rv = this->get().parse(it, end); if(rv.error()) return rv.error(); return {}; // void } }; } // detail #endif /** 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 result< std::tuple< decode_view, 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 result< std::tuple< decode_view, string_view, 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 @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 #ifdef BOOST_URL_DOCS __implementation_defined__ #else detail::squelch_rule_t #endif squelch( Rule const& r ) noexcept { return { r }; } } // grammar } // urls } // boost #include #endif