libs/url/include/boost/url/grammar/impl/tuple_rule.hpp

100.0% Lines (60/60) 98.2% Functions (275/280) 93.8% Branches (15/16)
libs/url/include/boost/url/grammar/impl/tuple_rule.hpp
Line Branch Hits 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 3881 parse_sequence(
53 R const& rn_) noexcept
54 3881 : rn(rn_)
55 3881 , vn(mp11::mp_fill<
56 3881 V, system::error_code>{})
57 {
58 3881 }
59
60 void
61 1229 apply(
62 char const*&,
63 char const*,
64 ...) const noexcept
65 {
66 1229 }
67
68 // for system::result<void>
69 template<
70 std::size_t Ir,
71 std::size_t Iv>
72 void
73 1606 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
1/1
✓ Branch 1 taken 1606 times.
1606 grammar::parse(
82 1606 it, end, get<Ir>(rn));
83
2/2
✓ Branch 1 taken 387 times.
✓ Branch 2 taken 1219 times.
1606 if( !rv )
84 {
85 387 ec = rv.error();
86 387 return;
87 }
88 1219 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 5121 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 5121 auto& rv = get<Iv>(vn);
105
1/1
✓ Branch 1 taken 1781 times.
5121 rv = grammar::parse(
106 5121 it, end, get<Ir>(rn));
107
2/2
✓ Branch 1 taken 2265 times.
✓ Branch 2 taken 2856 times.
5121 if( !rv )
108 {
109 2265 ec = rv.error();
110 2265 return;
111 }
112 2856 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 6727 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 6727 apply(it, end, ir, iv, is_void<Ir>{});
130 6727 }
131
132 struct deref
133 {
134 template<class R>
135 auto
136 2725 operator()(R const& r) const ->
137 decltype(*r)
138 {
139 2725 return *r;
140 }
141 };
142
143 auto
144 3881 make_result() noexcept ->
145 system::result<typename implementation_defined::tuple_rule_t<
146 R0, Rn...>::value_type>
147 {
148
2/2
✓ Branch 1 taken 2652 times.
✓ Branch 2 taken 1229 times.
3881 if(ec.failed())
149 2652 return ec;
150 return mp11::tuple_transform(
151 1229 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 8004 parse_sequence(
181 R const& rn_) noexcept
182 8004 : rn(rn_)
183 8004 , v(system::error_code{})
184 {
185 8004 }
186
187 void
188 3738 apply(
189 char const*&,
190 char const*,
191 ...) const noexcept
192 {
193 3738 }
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 7019 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
2/2
✓ Branch 1 taken 2353 times.
✓ Branch 1 taken 4666 times.
7019 grammar::parse(
210 7019 it, end, get<Ir>(rn));
211
2/2
✓ Branch 1 taken 3224 times.
✓ Branch 2 taken 3795 times.
7019 if( !rv )
212 {
213 3224 v = rv.error();
214 3224 return;
215 }
216 3795 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 6658 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
1/2
✓ Branch 1 taken 187 times.
✗ Branch 1 not taken.
6658 v = grammar::parse(
233 6658 it, end, get<Ir>(rn));
234
2/2
✓ Branch 1 taken 1042 times.
✓ Branch 2 taken 5616 times.
6658 if( !v )
235 1042 return;
236 5616 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 13677 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 13677 apply(it, end, ir, iv, is_void<Ir>{});
254 13677 }
255
256 V
257 8004 make_result() noexcept
258 {
259 8004 return v;
260 }
261 };
262
263 } // detail
264
265 template<
266 class R0,
267 class... Rn>
268 auto
269 11885 implementation_defined::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 11885 IsList, R0, Rn...> t(this->get());
277 11885 t.apply(it, end);
278 11885 return t.make_result();
279 3234 }
280
281 } // grammar
282 } // urls
283 } // boost
284
285 #endif
286