Line data Source code
1 : //
2 : // Copyright (c) 2022 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_IMPL_TUPLE_RULE_HPP
11 : #define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
12 :
13 : #include <boost/url/grammar/parse.hpp>
14 : #include <boost/mp11/integral.hpp>
15 : #include <boost/mp11/list.hpp>
16 : #include <boost/mp11/tuple.hpp>
17 : #include <type_traits>
18 :
19 : namespace boost {
20 : namespace urls {
21 : namespace grammar {
22 :
23 : namespace detail {
24 :
25 : // returns a tuple
26 : template<
27 : bool IsList,
28 : class R0, class... Rn>
29 : struct parse_sequence
30 : {
31 : using R = detail::tuple<R0, Rn...>;
32 :
33 : using L = mp11::mp_list<
34 : typename R0::value_type,
35 : typename Rn::value_type...>;
36 :
37 : using V = mp11::mp_remove<
38 : std::tuple<
39 : system::result<typename R0::value_type>,
40 : system::result<typename Rn::value_type>...>,
41 : system::result<void>>;
42 :
43 : template<std::size_t I>
44 : using is_void = std::is_same<
45 : mp11::mp_at_c<L, I>, void>;
46 :
47 : system::error_code ec;
48 : R const& rn;
49 : V vn;
50 :
51 : explicit
52 3626 : parse_sequence(
53 : R const& rn_) noexcept
54 : : rn(rn_)
55 : , vn(mp11::mp_fill<
56 3626 : V, system::error_code>{})
57 : {
58 3626 : }
59 :
60 : void
61 1180 : apply(
62 : char const*&,
63 : char const*,
64 : ...) const noexcept
65 : {
66 1180 : }
67 :
68 : // for system::result<void>
69 : template<
70 : std::size_t Ir,
71 : std::size_t Iv>
72 : void
73 1485 : apply(
74 : char const*& it,
75 : char const* end,
76 : mp11::mp_size_t<Ir> const&,
77 : mp11::mp_size_t<Iv> const&,
78 : mp11::mp_true const&)
79 : {
80 : system::result<void> rv =
81 1485 : grammar::parse(
82 1485 : it, end, get<Ir>(rn));
83 1485 : if( !rv )
84 : {
85 352 : ec = rv.error();
86 352 : return;
87 : }
88 1133 : apply(it, end,
89 : mp11::mp_size_t<Ir+1>{},
90 : mp11::mp_size_t<Iv>{});
91 : }
92 :
93 : template<
94 : std::size_t Ir,
95 : std::size_t Iv>
96 : void
97 4844 : apply(
98 : char const*& it,
99 : char const* end,
100 : mp11::mp_size_t<Ir> const&,
101 : mp11::mp_size_t<Iv> const&,
102 : mp11::mp_false const&)
103 : {
104 4844 : auto& rv = get<Iv>(vn);
105 4844 : rv = grammar::parse(
106 4844 : it, end, get<Ir>(rn));
107 4844 : if( !rv )
108 : {
109 2094 : ec = rv.error();
110 2094 : return;
111 : }
112 2750 : apply(it, end,
113 : mp11::mp_size_t<Ir+1>{},
114 : mp11::mp_size_t<Iv+1>{});
115 : }
116 :
117 : template<
118 : std::size_t Ir = 0,
119 : std::size_t Iv = 0>
120 : typename std::enable_if<
121 : Ir < 1 + sizeof...(Rn)>::type
122 6329 : apply(
123 : char const*& it,
124 : char const* end,
125 : mp11::mp_size_t<Ir> const& ir = {},
126 : mp11::mp_size_t<Iv> const& iv = {}
127 : ) noexcept
128 : {
129 6329 : apply(it, end, ir, iv, is_void<Ir>{});
130 6329 : }
131 :
132 : struct deref
133 : {
134 : template<class R>
135 : auto
136 2619 : operator()(R const& r) const ->
137 : decltype(*r)
138 : {
139 2619 : return *r;
140 : }
141 : };
142 :
143 : auto
144 3626 : make_result() noexcept ->
145 : system::result<typename tuple_rule_t<
146 : R0, Rn...>::value_type>
147 : {
148 3626 : if(ec.failed())
149 2446 : return ec;
150 : return mp11::tuple_transform(
151 1180 : deref{}, vn);
152 : }
153 : };
154 :
155 : // returns a value_type
156 : template<class R0, class... Rn>
157 : struct parse_sequence<false, R0, Rn...>
158 : {
159 : using R = detail::tuple<R0, Rn...>;
160 :
161 : using L = mp11::mp_list<
162 : typename R0::value_type,
163 : typename Rn::value_type...>;
164 :
165 : using V = mp11::mp_first<
166 : mp11::mp_remove<
167 : mp11::mp_list<
168 : system::result<typename R0::value_type>,
169 : system::result<typename Rn::value_type>...>,
170 : system::result<void>>>;
171 :
172 : template<std::size_t I>
173 : using is_void = std::is_same<
174 : mp11::mp_at_c<L, I>, void>;
175 :
176 : R const& rn;
177 : V v;
178 :
179 : explicit
180 7544 : parse_sequence(
181 : R const& rn_) noexcept
182 : : rn(rn_)
183 7544 : , v(system::error_code{})
184 : {
185 7544 : }
186 :
187 : void
188 3536 : apply(
189 : char const*&,
190 : char const*,
191 : ...) const noexcept
192 : {
193 3536 : }
194 :
195 : // for system::result<void>
196 : template<
197 : std::size_t Ir,
198 : std::size_t Iv>
199 : BOOST_URL_NO_INLINE
200 : void
201 6566 : apply(
202 : char const*& it,
203 : char const* end,
204 : mp11::mp_size_t<Ir> const&,
205 : mp11::mp_size_t<Iv> const&,
206 : mp11::mp_true const&)
207 : {
208 : system::result<void> rv =
209 6566 : grammar::parse(
210 6566 : it, end, get<Ir>(rn));
211 6566 : if( !rv )
212 : {
213 2973 : v = rv.error();
214 2973 : return;
215 : }
216 3593 : apply(it, end,
217 : mp11::mp_size_t<Ir+1>{},
218 : mp11::mp_size_t<Iv>{});
219 : }
220 :
221 : template<
222 : std::size_t Ir,
223 : std::size_t Iv>
224 : void
225 6309 : apply(
226 : char const*& it,
227 : char const* end,
228 : mp11::mp_size_t<Ir> const&,
229 : mp11::mp_size_t<Iv> const&,
230 : mp11::mp_false const&)
231 : {
232 6309 : v = grammar::parse(
233 6309 : it, end, get<Ir>(rn));
234 6309 : if( !v )
235 1035 : return;
236 5274 : apply(it, end,
237 : mp11::mp_size_t<Ir+1>{},
238 : mp11::mp_size_t<Iv+1>{});
239 : }
240 :
241 : template<
242 : std::size_t Ir = 0,
243 : std::size_t Iv = 0>
244 : typename std::enable_if<
245 : Ir < 1 + sizeof...(Rn)>::type
246 12875 : apply(
247 : char const*& it,
248 : char const* end,
249 : mp11::mp_size_t<Ir> const& ir = {},
250 : mp11::mp_size_t<Iv> const& iv = {}
251 : ) noexcept
252 : {
253 12875 : apply(it, end, ir, iv, is_void<Ir>{});
254 12875 : }
255 :
256 : V
257 7544 : make_result() noexcept
258 : {
259 7544 : return v;
260 : }
261 : };
262 :
263 : } // detail
264 :
265 : template<
266 : class R0,
267 : class... Rn>
268 : auto
269 11170 : tuple_rule_t<R0, Rn...>::
270 : parse(
271 : char const*& it,
272 : char const* end) const ->
273 : system::result<value_type>
274 : {
275 : detail::parse_sequence<
276 14237 : IsList, R0, Rn...> t(this->get());
277 11170 : t.apply(it, end);
278 11170 : return t.make_result();
279 : }
280 :
281 : } // grammar
282 : } // urls
283 : } // boost
284 :
285 : #endif
|