| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- //
- // 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 <boost/url/detail/config.hpp>
- #include <boost/url/error_types.hpp>
- #include <boost/url/grammar/error.hpp>
- #include <boost/url/grammar/detail/tuple.hpp>
- #include <boost/url/grammar/type_traits.hpp>
- #include <boost/mp11/algorithm.hpp>
- #include <boost/core/detail/static_assert.hpp>
- #include <boost/core/empty_value.hpp>
- #include <tuple>
- namespace boost {
- namespace urls {
- namespace grammar {
- namespace implementation_defined {
- template<
- class R0,
- class... Rn>
- class tuple_rule_t
- : empty_value<
- detail::tuple<R0, Rn...>>
- {
- using T = mp11::mp_remove<
- std::tuple<
- typename R0::value_type,
- typename Rn::value_type...>,
- void>;
- static constexpr bool IsList =
- mp11::mp_size<T>::value != 1;
- public:
- using value_type =
- mp11::mp_eval_if_c<IsList,
- T, mp11::mp_first, T>;
- constexpr
- tuple_rule_t(
- R0 const& r0,
- Rn const&... rn) noexcept
- : empty_value<
- detail::tuple<R0, Rn...>>(
- empty_init,
- r0, rn...)
- {
- }
- system::result<value_type>
- 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<T>` instead of
- `system::result<tuple<...>>`.
- @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 <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.1"
- >3.1. Concatenation (rfc5234)</a>
- @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<R0>,
- is_rule<Rn>...>::value);
- return { r0, rn... };
- }
- namespace implementation_defined {
- template<class Rule>
- struct squelch_rule_t
- : empty_value<Rule>
- {
- using value_type = void;
- constexpr
- squelch_rule_t(
- Rule const& r) noexcept
- : empty_value<Rule>(
- empty_init, r)
- {
- }
- system::result<value_type>
- 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<BOOST_URL_CONSTRAINT(Rule) R>
- constexpr
- BOOST_URL_IMPLEMENTATION_DEFINED(implementation_defined::squelch_rule_t<R>)
- squelch( R const& r ) noexcept
- {
- BOOST_CORE_STATIC_ASSERT(is_rule<R>::value);
- return { r };
- }
- } // grammar
- } // urls
- } // boost
- #include <boost/url/grammar/impl/tuple_rule.hpp>
- #endif
|