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 : template<
87 : class R0,
88 : class... Rn>
89 : class tuple_rule_t
90 : : empty_value<
91 : detail::tuple<R0, Rn...>>
92 : {
93 : using T = mp11::mp_remove<
94 : std::tuple<
95 : typename R0::value_type,
96 : typename Rn::value_type...>,
97 : void>;
98 : static constexpr bool IsList =
99 : mp11::mp_size<T>::value != 1;
100 :
101 : public:
102 : using value_type =
103 : mp11::mp_eval_if_c<IsList,
104 : T, mp11::mp_first, T>;
105 :
106 : template<
107 : class R0_,
108 : class... Rn_>
109 : friend
110 : constexpr
111 : auto
112 : tuple_rule(
113 : R0_ const& r0,
114 : Rn_ const&... rn) noexcept ->
115 : tuple_rule_t<R0_, Rn_...>;
116 :
117 : system::result<value_type>
118 : parse(
119 : char const*& it,
120 : char const* end) const;
121 :
122 : private:
123 : constexpr
124 7781 : tuple_rule_t(
125 : R0 const& r0,
126 : Rn const&... rn) noexcept
127 : : empty_value<
128 : detail::tuple<R0, Rn...>>(
129 : empty_init,
130 7781 : r0, rn...)
131 : {
132 7781 : }
133 : };
134 :
135 : template<
136 : class R0,
137 : class... Rn>
138 : constexpr
139 : auto
140 7781 : tuple_rule(
141 : R0 const& r0,
142 : Rn const&... rn) noexcept ->
143 : tuple_rule_t<
144 : R0, Rn...>
145 : {
146 7781 : return { r0, rn... };
147 : }
148 : #endif
149 :
150 : #ifndef BOOST_URL_DOCS
151 : namespace detail {
152 :
153 : template<class Rule>
154 : struct squelch_rule_t
155 : : empty_value<Rule>
156 : {
157 : using value_type = void;
158 :
159 : constexpr
160 11406 : squelch_rule_t(
161 : Rule const& r) noexcept
162 : : empty_value<Rule>(
163 11406 : empty_init, r)
164 : {
165 11406 : }
166 :
167 : system::result<value_type>
168 8051 : parse(
169 : char const*& it,
170 : char const* end) const
171 : {
172 8164 : auto rv = this->get().parse(it, end);
173 8051 : if(rv.error())
174 3325 : return rv.error();
175 4726 : return {}; // void
176 : }
177 : };
178 :
179 : } // detail
180 : #endif
181 :
182 : /** Squelch the value of a rule
183 :
184 : This function returns a new rule which
185 : matches the specified rule, and converts
186 : its value type to `void`. This is useful
187 : for matching delimiters in a grammar,
188 : where the value for the delimiter is not
189 : needed.
190 :
191 : @par Value Type
192 : @code
193 : using value_type = void;
194 : @endcode
195 :
196 : @par Example 1
197 : With `squelch`:
198 : @code
199 : system::result< std::tuple< decode_view, core::string_view > > rv = parse(
200 : "www.example.com:443",
201 : tuple_rule(
202 : pct_encoded_rule(unreserved_chars + '-' + '.'),
203 : squelch( delim_rule( ':' ) ),
204 : token_rule( digit_chars ) ) );
205 : @endcode
206 :
207 : @par Example 2
208 : Without `squelch`:
209 : @code
210 : system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse(
211 : "www.example.com:443",
212 : tuple_rule(
213 : pct_encoded_rule(unreserved_chars + '-' + '.'),
214 : delim_rule( ':' ),
215 : token_rule( digit_chars ) ) );
216 : @endcode
217 :
218 : @param r The rule to squelch
219 :
220 : @see
221 : @ref delim_rule,
222 : @ref digit_chars,
223 : @ref parse,
224 : @ref tuple_rule,
225 : @ref token_rule,
226 : @ref decode_view,
227 : @ref pct_encoded_rule,
228 : @ref unreserved_chars.
229 : */
230 : template<class Rule>
231 : constexpr
232 : #ifdef BOOST_URL_DOCS
233 : __implementation_defined__
234 : #else
235 : detail::squelch_rule_t<Rule>
236 : #endif
237 11406 : squelch( Rule const& r ) noexcept
238 : {
239 11406 : return { r };
240 : }
241 :
242 : } // grammar
243 : } // urls
244 : } // boost
245 :
246 : #include <boost/url/grammar/impl/tuple_rule.hpp>
247 :
248 : #endif
|