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