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/mp11/algorithm.hpp>
18 : #include <boost/core/empty_value.hpp>
19 : #include <tuple>
20 :
21 : namespace boost {
22 : namespace urls {
23 : namespace grammar {
24 :
25 : /** Match a series of rules in order
26 :
27 : This matches a series of rules in the
28 : order specified. Upon success the input
29 : is adjusted to point to the first
30 : unconsumed character. There is no
31 : implicit specification of linear white
32 : space between each rule.
33 :
34 : @par Value Type
35 : @code
36 : using value_type = __see_below__;
37 : @endcode
38 :
39 : The sequence rule usually returns a
40 : `std::tuple` containing the the `value_type`
41 : of each corresponding rule in the sequence,
42 : except that `void` values are removed.
43 : However, if there is exactly one non-void
44 : value type `T`, then the sequence rule
45 : returns `system::result<T>` instead of
46 : `system::result<tuple<...>>`.
47 :
48 : @par Example
49 : Rules are used with the function @ref parse.
50 : @code
51 : system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv =
52 : parse( "192.168.0.1",
53 : tuple_rule(
54 : dec_octet_rule,
55 : squelch( delim_rule('.') ),
56 : dec_octet_rule,
57 : squelch( delim_rule('.') ),
58 : dec_octet_rule,
59 : squelch( delim_rule('.') ),
60 : dec_octet_rule ) );
61 : @endcode
62 :
63 : @par BNF
64 : @code
65 : sequence = rule1 rule2 rule3...
66 : @endcode
67 :
68 : @par Specification
69 : @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.1"
70 : >3.1. Concatenation (rfc5234)</a>
71 :
72 : @param rn A list of one or more rules to match
73 :
74 : @see
75 : @ref dec_octet_rule,
76 : @ref delim_rule,
77 : @ref parse,
78 : @ref squelch.
79 : */
80 : #ifdef BOOST_URL_DOCS
81 : template<class... Rules>
82 : constexpr
83 : __implementation_defined__
84 : tuple_rule( Rules... rn ) noexcept;
85 : #else
86 : namespace implementation_defined {
87 : template<
88 : class R0,
89 : class... Rn>
90 : class tuple_rule_t
91 : : empty_value<
92 : detail::tuple<R0, Rn...>>
93 : {
94 : using T = mp11::mp_remove<
95 : std::tuple<
96 : typename R0::value_type,
97 : typename Rn::value_type...>,
98 : void>;
99 : static constexpr bool IsList =
100 : mp11::mp_size<T>::value != 1;
101 :
102 : public:
103 : using value_type =
104 : mp11::mp_eval_if_c<IsList,
105 : T, mp11::mp_first, T>;
106 :
107 : constexpr
108 7793 : tuple_rule_t(
109 : R0 const& r0,
110 : Rn const&... rn) noexcept
111 : : empty_value<
112 : detail::tuple<R0, Rn...>>(
113 : empty_init,
114 7793 : r0, rn...)
115 : {
116 7793 : }
117 :
118 : system::result<value_type>
119 : parse(
120 : char const*& it,
121 : char const* end) const;
122 :
123 : };
124 : } // implementation_defined
125 :
126 : /** Match a series of rules in order
127 :
128 : This matches a series of rules in the
129 : order specified. Upon success the input
130 : is adjusted to point to the first
131 : unconsumed character. There is no
132 : implicit specification of linear white
133 : space between each rule.
134 :
135 : @par Value Type
136 : @code
137 : using value_type = __see_below__;
138 : @endcode
139 :
140 : The sequence rule usually returns a
141 : `std::tuple` containing the the `value_type`
142 : of each corresponding rule in the sequence,
143 : except that `void` values are removed.
144 : However, if there is exactly one non-void
145 : value type `T`, then the sequence rule
146 : returns `system::result<T>` instead of
147 : `system::result<tuple<...>>`.
148 :
149 : @par Example
150 : Rules are used with the function @ref parse.
151 : @code
152 : system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv =
153 : parse( "192.168.0.1",
154 : tuple_rule(
155 : dec_octet_rule,
156 : squelch( delim_rule('.') ),
157 : dec_octet_rule,
158 : squelch( delim_rule('.') ),
159 : dec_octet_rule,
160 : squelch( delim_rule('.') ),
161 : dec_octet_rule ) );
162 : @endcode
163 :
164 : @par BNF
165 : @code
166 : sequence = rule1 rule2 rule3...
167 : @endcode
168 :
169 : @par Specification
170 : @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.1"
171 : >3.1. Concatenation (rfc5234)</a>
172 :
173 : @param rn A list of one or more rules to match
174 :
175 : @see
176 : @ref dec_octet_rule,
177 : @ref delim_rule,
178 : @ref parse,
179 : @ref squelch.
180 : */
181 : template<
182 : class R0,
183 : class... Rn>
184 : constexpr
185 : auto
186 7793 : tuple_rule(
187 : R0 const& r0,
188 : Rn const&... rn) noexcept ->
189 : implementation_defined::tuple_rule_t<
190 : R0, Rn...>
191 : {
192 7793 : return { r0, rn... };
193 : }
194 : #endif
195 :
196 : #ifndef BOOST_URL_DOCS
197 : namespace implementation_defined {
198 :
199 : template<class Rule>
200 : struct squelch_rule_t
201 : : empty_value<Rule>
202 : {
203 : using value_type = void;
204 :
205 : constexpr
206 11426 : squelch_rule_t(
207 : Rule const& r) noexcept
208 : : empty_value<Rule>(
209 11426 : empty_init, r)
210 : {
211 11426 : }
212 :
213 : system::result<value_type>
214 8059 : parse(
215 : char const*& it,
216 : char const* end) const
217 : {
218 8059 : auto rv = this->get().parse(it, end);
219 8059 : if(rv.error())
220 3329 : return rv.error();
221 4730 : return {}; // void
222 113 : }
223 : };
224 :
225 : } // implementation_defined
226 : #endif
227 :
228 : /** Squelch the value of a rule
229 :
230 : This function returns a new rule which
231 : matches the specified rule, and converts
232 : its value type to `void`. This is useful
233 : for matching delimiters in a grammar,
234 : where the value for the delimiter is not
235 : needed.
236 :
237 : @par Value Type
238 : @code
239 : using value_type = void;
240 : @endcode
241 :
242 : @par Example 1
243 : With `squelch`:
244 : @code
245 : system::result< std::tuple< decode_view, core::string_view > > rv = parse(
246 : "www.example.com:443",
247 : tuple_rule(
248 : pct_encoded_rule(unreserved_chars + '-' + '.'),
249 : squelch( delim_rule( ':' ) ),
250 : token_rule( digit_chars ) ) );
251 : @endcode
252 :
253 : @par Example 2
254 : Without `squelch`:
255 : @code
256 : system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse(
257 : "www.example.com:443",
258 : tuple_rule(
259 : pct_encoded_rule(unreserved_chars + '-' + '.'),
260 : delim_rule( ':' ),
261 : token_rule( digit_chars ) ) );
262 : @endcode
263 :
264 : @param r The rule to squelch
265 :
266 : @see
267 : @ref delim_rule,
268 : @ref digit_chars,
269 : @ref parse,
270 : @ref tuple_rule,
271 : @ref token_rule,
272 : @ref decode_view,
273 : @ref pct_encoded_rule,
274 : @ref unreserved_chars.
275 : */
276 : template<class Rule>
277 : constexpr
278 : BOOST_URL_IMPLEMENTATION_DEFINED(implementation_defined::squelch_rule_t<Rule>)
279 11426 : squelch( Rule const& r ) noexcept
280 : {
281 11426 : return { r };
282 : }
283 :
284 : } // grammar
285 : } // urls
286 : } // boost
287 :
288 : #include <boost/url/grammar/impl/tuple_rule.hpp>
289 :
290 : #endif
|