Line data Source code
1 : //
2 : // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/boostorg/url
8 : //
9 :
10 : #ifndef BOOST_URL_GRAMMAR_TUPLE_RULE_HPP
11 : #define BOOST_URL_GRAMMAR_TUPLE_RULE_HPP
12 :
13 : #include <boost/url/detail/config.hpp>
14 : #include <boost/url/error_types.hpp>
15 : #include <boost/url/grammar/error.hpp>
16 : #include <boost/url/grammar/detail/tuple.hpp>
17 : #include <boost/url/grammar/type_traits.hpp>
18 : #include <boost/mp11/algorithm.hpp>
19 : #include <boost/static_assert.hpp>
20 : #include <boost/core/empty_value.hpp>
21 : #include <tuple>
22 :
23 : namespace boost {
24 : namespace urls {
25 : namespace grammar {
26 :
27 : namespace implementation_defined {
28 : template<
29 : class R0,
30 : class... Rn>
31 : class tuple_rule_t
32 : : empty_value<
33 : detail::tuple<R0, Rn...>>
34 : {
35 : using T = mp11::mp_remove<
36 : std::tuple<
37 : typename R0::value_type,
38 : typename Rn::value_type...>,
39 : void>;
40 : static constexpr bool IsList =
41 : mp11::mp_size<T>::value != 1;
42 :
43 : public:
44 : using value_type =
45 : mp11::mp_eval_if_c<IsList,
46 : T, mp11::mp_first, T>;
47 :
48 : constexpr
49 7799 : tuple_rule_t(
50 : R0 const& r0,
51 : Rn const&... rn) noexcept
52 : : empty_value<
53 : detail::tuple<R0, Rn...>>(
54 : empty_init,
55 7799 : r0, rn...)
56 : {
57 7799 : }
58 :
59 : system::result<value_type>
60 : parse(
61 : char const*& it,
62 : char const* end) const;
63 :
64 : };
65 : } // implementation_defined
66 :
67 : /** Match a series of rules in order
68 :
69 : This matches a series of rules in the
70 : order specified. Upon success the input
71 : is adjusted to point to the first
72 : unconsumed character. There is no
73 : implicit specification of linear white
74 : space between each rule.
75 :
76 : @par Value Type
77 : @code
78 : using value_type = __see_below__;
79 : @endcode
80 :
81 : The sequence rule usually returns a
82 : `std::tuple` containing the the `value_type`
83 : of each corresponding rule in the sequence,
84 : except that `void` values are removed.
85 : However, if there is exactly one non-void
86 : value type `T`, then the sequence rule
87 : returns `system::result<T>` instead of
88 : `system::result<tuple<...>>`.
89 :
90 : @par Example
91 : Rules are used with the function @ref parse.
92 : @code
93 : system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv =
94 : parse( "192.168.0.1",
95 : tuple_rule(
96 : dec_octet_rule,
97 : squelch( delim_rule('.') ),
98 : dec_octet_rule,
99 : squelch( delim_rule('.') ),
100 : dec_octet_rule,
101 : squelch( delim_rule('.') ),
102 : dec_octet_rule ) );
103 : @endcode
104 :
105 : @par BNF
106 : @code
107 : sequence = rule1 rule2 rule3...
108 : @endcode
109 :
110 : @par Specification
111 : @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.1"
112 : >3.1. Concatenation (rfc5234)</a>
113 :
114 : @param rn A list of one or more rules to match
115 :
116 : @see
117 : @ref dec_octet_rule,
118 : @ref delim_rule,
119 : @ref parse,
120 : @ref squelch.
121 : */
122 : template<
123 : BOOST_URL_CONSTRAINT(Rule) R0,
124 : BOOST_URL_CONSTRAINT(Rule)... Rn>
125 : constexpr
126 : auto
127 7799 : tuple_rule(
128 : R0 const& r0,
129 : Rn const&... rn) noexcept ->
130 : implementation_defined::tuple_rule_t<
131 : R0, Rn...>
132 : {
133 : BOOST_STATIC_ASSERT(
134 : mp11::mp_all<
135 : is_rule<R0>,
136 : is_rule<Rn>...>::value);
137 7799 : return { r0, rn... };
138 : }
139 :
140 : namespace implementation_defined {
141 :
142 : template<class Rule>
143 : struct squelch_rule_t
144 : : empty_value<Rule>
145 : {
146 : using value_type = void;
147 :
148 : constexpr
149 11438 : squelch_rule_t(
150 : Rule const& r) noexcept
151 : : empty_value<Rule>(
152 11438 : empty_init, r)
153 : {
154 11438 : }
155 :
156 : system::result<value_type>
157 8064 : parse(
158 : char const*& it,
159 : char const* end) const
160 : {
161 8064 : auto rv = this->get().parse(it, end);
162 8064 : if(rv.error())
163 3330 : return rv.error();
164 4734 : return {}; // void
165 113 : }
166 : };
167 :
168 : } // implementation_defined
169 :
170 : /** Squelch the value of a rule
171 :
172 : This function returns a new rule which
173 : matches the specified rule, and converts
174 : its value type to `void`. This is useful
175 : for matching delimiters in a grammar,
176 : where the value for the delimiter is not
177 : needed.
178 :
179 : @par Value Type
180 : @code
181 : using value_type = void;
182 : @endcode
183 :
184 : @par Example 1
185 : With `squelch`:
186 : @code
187 : system::result< std::tuple< decode_view, core::string_view > > rv = parse(
188 : "www.example.com:443",
189 : tuple_rule(
190 : pct_encoded_rule(unreserved_chars + '-' + '.'),
191 : squelch( delim_rule( ':' ) ),
192 : token_rule( digit_chars ) ) );
193 : @endcode
194 :
195 : @par Example 2
196 : Without `squelch`:
197 : @code
198 : system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse(
199 : "www.example.com:443",
200 : tuple_rule(
201 : pct_encoded_rule(unreserved_chars + '-' + '.'),
202 : delim_rule( ':' ),
203 : token_rule( digit_chars ) ) );
204 : @endcode
205 :
206 : @param r The rule to squelch
207 :
208 : @see
209 : @ref delim_rule,
210 : @ref digit_chars,
211 : @ref parse,
212 : @ref tuple_rule,
213 : @ref token_rule,
214 : @ref decode_view,
215 : @ref pct_encoded_rule,
216 : @ref unreserved_chars.
217 : */
218 : template<BOOST_URL_CONSTRAINT(Rule) R>
219 : constexpr
220 : BOOST_URL_IMPLEMENTATION_DEFINED(implementation_defined::squelch_rule_t<R>)
221 11438 : squelch( R const& r ) noexcept
222 : {
223 : BOOST_STATIC_ASSERT(is_rule<R>::value);
224 11438 : return { r };
225 : }
226 :
227 : } // grammar
228 : } // urls
229 : } // boost
230 :
231 : #include <boost/url/grammar/impl/tuple_rule.hpp>
232 :
233 : #endif
|