1  
//
1  
//
2  
// Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot com)
2  
// Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
11  
#ifndef BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
12  
#define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
12  
#define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
13  

13  

14  
#include <boost/url/grammar/parse.hpp>
14  
#include <boost/url/grammar/parse.hpp>
15  
#include <boost/mp11/integral.hpp>
15  
#include <boost/mp11/integral.hpp>
16  
#include <boost/mp11/list.hpp>
16  
#include <boost/mp11/list.hpp>
17  
#include <boost/mp11/tuple.hpp>
17  
#include <boost/mp11/tuple.hpp>
18  
#include <type_traits>
18  
#include <type_traits>
19  

19  

20  
namespace boost {
20  
namespace boost {
21  
namespace urls {
21  
namespace urls {
22  
namespace grammar {
22  
namespace grammar {
23  

23  

24  
namespace detail {
24  
namespace detail {
25  

25  

26  
// returns a tuple
26  
// returns a tuple
27  
template<
27  
template<
28  
    bool IsList,
28  
    bool IsList,
29  
    class R0, class... Rn>
29  
    class R0, class... Rn>
30  
struct parse_sequence
30  
struct parse_sequence
31  
{
31  
{
32  
    using R = detail::tuple<R0, Rn...>;
32  
    using R = detail::tuple<R0, Rn...>;
33  

33  

34  
    using L = mp11::mp_list<
34  
    using L = mp11::mp_list<
35  
        typename R0::value_type,
35  
        typename R0::value_type,
36  
        typename Rn::value_type...>;
36  
        typename Rn::value_type...>;
37  

37  

38  
    using V = mp11::mp_remove<
38  
    using V = mp11::mp_remove<
39  
        std::tuple<
39  
        std::tuple<
40  
            system::result<typename R0::value_type>,
40  
            system::result<typename R0::value_type>,
41  
            system::result<typename Rn::value_type>...>,
41  
            system::result<typename Rn::value_type>...>,
42  
        system::result<void>>;
42  
        system::result<void>>;
43  

43  

44  
    template<std::size_t I>
44  
    template<std::size_t I>
45  
    using is_void = std::is_same<
45  
    using is_void = std::is_same<
46  
        mp11::mp_at_c<L, I>, void>;
46  
        mp11::mp_at_c<L, I>, void>;
47  

47  

48  
    system::error_code ec;
48  
    system::error_code ec;
49  
    R const& rn;
49  
    R const& rn;
50  
    V vn;
50  
    V vn;
51  

51  

52  
    BOOST_URL_CXX14_CONSTEXPR
52  
    BOOST_URL_CXX14_CONSTEXPR
53  
    explicit
53  
    explicit
54  
    parse_sequence(
54  
    parse_sequence(
55  
        R const& rn_) noexcept
55  
        R const& rn_) noexcept
56  
        : rn(rn_)
56  
        : rn(rn_)
57  
        , vn(mp11::mp_fill<
57  
        , vn(mp11::mp_fill<
58  
            V, system::error_code>{})
58  
            V, system::error_code>{})
59  
    {
59  
    {
60  
    }
60  
    }
61  

61  

62  
    BOOST_URL_CXX14_CONSTEXPR
62  
    BOOST_URL_CXX14_CONSTEXPR
63  
    void
63  
    void
64  
    apply(
64  
    apply(
65  
        char const*&,
65  
        char const*&,
66  
        char const*,
66  
        char const*,
67  
        ...) const noexcept
67  
        ...) const noexcept
68  
    {
68  
    {
69  
    }
69  
    }
70  

70  

71  
    // for system::result<void>
71  
    // for system::result<void>
72  
    template<
72  
    template<
73  
        std::size_t Ir,
73  
        std::size_t Ir,
74  
        std::size_t Iv>
74  
        std::size_t Iv>
75  
    BOOST_URL_CXX14_CONSTEXPR
75  
    BOOST_URL_CXX14_CONSTEXPR
76  
    void
76  
    void
77  
    apply(
77  
    apply(
78  
        char const*& it,
78  
        char const*& it,
79  
        char const* end,
79  
        char const* end,
80  
        mp11::mp_size_t<Ir> const&,
80  
        mp11::mp_size_t<Ir> const&,
81  
        mp11::mp_size_t<Iv> const&,
81  
        mp11::mp_size_t<Iv> const&,
82  
        mp11::mp_true const&)
82  
        mp11::mp_true const&)
83  
    {
83  
    {
84  
        system::result<void> rv =
84  
        system::result<void> rv =
85  
            grammar::parse(
85  
            grammar::parse(
86  
                it, end, get<Ir>(rn));
86  
                it, end, get<Ir>(rn));
87  
        if( !rv )
87  
        if( !rv )
88  
        {
88  
        {
89  
            ec = rv.error();
89  
            ec = rv.error();
90  
            return;
90  
            return;
91  
        }
91  
        }
92  
        apply(it, end,
92  
        apply(it, end,
93  
            mp11::mp_size_t<Ir+1>{},
93  
            mp11::mp_size_t<Ir+1>{},
94  
            mp11::mp_size_t<Iv>{});
94  
            mp11::mp_size_t<Iv>{});
95  
    }
95  
    }
96  

96  

97  
    template<
97  
    template<
98  
        std::size_t Ir,
98  
        std::size_t Ir,
99  
        std::size_t Iv>
99  
        std::size_t Iv>
100  
    BOOST_URL_CXX14_CONSTEXPR
100  
    BOOST_URL_CXX14_CONSTEXPR
101  
    void
101  
    void
102  
    apply(
102  
    apply(
103  
        char const*& it,
103  
        char const*& it,
104  
        char const* end,
104  
        char const* end,
105  
        mp11::mp_size_t<Ir> const&,
105  
        mp11::mp_size_t<Ir> const&,
106  
        mp11::mp_size_t<Iv> const&,
106  
        mp11::mp_size_t<Iv> const&,
107  
        mp11::mp_false const&)
107  
        mp11::mp_false const&)
108  
    {
108  
    {
109  
        auto& rv = get<Iv>(vn);
109  
        auto& rv = get<Iv>(vn);
110  
        rv = grammar::parse(
110  
        rv = grammar::parse(
111  
            it, end, get<Ir>(rn));
111  
            it, end, get<Ir>(rn));
112  
        if( !rv )
112  
        if( !rv )
113  
        {
113  
        {
114  
            ec = rv.error();
114  
            ec = rv.error();
115  
            return;
115  
            return;
116  
        }
116  
        }
117  
        apply(it, end,
117  
        apply(it, end,
118  
            mp11::mp_size_t<Ir+1>{},
118  
            mp11::mp_size_t<Ir+1>{},
119  
            mp11::mp_size_t<Iv+1>{});
119  
            mp11::mp_size_t<Iv+1>{});
120  
    }
120  
    }
121  

121  

122  
    template<
122  
    template<
123  
        std::size_t Ir = 0,
123  
        std::size_t Ir = 0,
124  
        std::size_t Iv = 0>
124  
        std::size_t Iv = 0>
125  
    BOOST_URL_CXX14_CONSTEXPR
125  
    BOOST_URL_CXX14_CONSTEXPR
126  
    typename std::enable_if<
126  
    typename std::enable_if<
127  
        Ir < 1 + sizeof...(Rn)>::type
127  
        Ir < 1 + sizeof...(Rn)>::type
128  
    apply(
128  
    apply(
129  
        char const*& it,
129  
        char const*& it,
130  
        char const* end,
130  
        char const* end,
131  
        mp11::mp_size_t<Ir> const& ir = {},
131  
        mp11::mp_size_t<Ir> const& ir = {},
132  
        mp11::mp_size_t<Iv> const& iv = {}
132  
        mp11::mp_size_t<Iv> const& iv = {}
133  
            ) noexcept
133  
            ) noexcept
134  
    {
134  
    {
135  
        apply(it, end, ir, iv, is_void<Ir>{});
135  
        apply(it, end, ir, iv, is_void<Ir>{});
136  
    }
136  
    }
137  

137  

138  
    struct deref
138  
    struct deref
139  
    {
139  
    {
140  
        template<class R>
140  
        template<class R>
141  
        BOOST_URL_CXX14_CONSTEXPR
141  
        BOOST_URL_CXX14_CONSTEXPR
142  
        auto
142  
        auto
143  
        operator()(R const& r) const ->
143  
        operator()(R const& r) const ->
144  
            decltype(*r)
144  
            decltype(*r)
145  
        {
145  
        {
146  
            return *r;
146  
            return *r;
147  
        }
147  
        }
148  
    };
148  
    };
149  

149  

150  
    BOOST_URL_CXX14_CONSTEXPR
150  
    BOOST_URL_CXX14_CONSTEXPR
151  
    auto
151  
    auto
152  
    make_result() noexcept ->
152  
    make_result() noexcept ->
153  
        system::result<typename implementation_defined::tuple_rule_t<
153  
        system::result<typename implementation_defined::tuple_rule_t<
154  
            R0, Rn...>::value_type>
154  
            R0, Rn...>::value_type>
155  
    {
155  
    {
156  
        if(ec.failed())
156  
        if(ec.failed())
157  
            return ec;
157  
            return ec;
158  
        return mp11::tuple_transform(
158  
        return mp11::tuple_transform(
159  
            deref{}, vn);
159  
            deref{}, vn);
160  
    }
160  
    }
161  
};
161  
};
162  

162  

163  
// See error_types.hpp for details (#979)
163  
// See error_types.hpp for details (#979)
164  
#if defined(BOOST_GCC) && BOOST_GCC >= 70000
164  
#if defined(BOOST_GCC) && BOOST_GCC >= 70000
165  
#pragma GCC diagnostic push
165  
#pragma GCC diagnostic push
166  
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
166  
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
167  
#endif
167  
#endif
168  

168  

169  
// returns a value_type
169  
// returns a value_type
170  
template<class R0, class... Rn>
170  
template<class R0, class... Rn>
171  
struct parse_sequence<false, R0, Rn...>
171  
struct parse_sequence<false, R0, Rn...>
172  
{
172  
{
173  
    using R = detail::tuple<R0, Rn...>;
173  
    using R = detail::tuple<R0, Rn...>;
174  

174  

175  
    using L = mp11::mp_list<
175  
    using L = mp11::mp_list<
176  
        typename R0::value_type,
176  
        typename R0::value_type,
177  
        typename Rn::value_type...>;
177  
        typename Rn::value_type...>;
178  

178  

179  
    using V = mp11::mp_first<
179  
    using V = mp11::mp_first<
180  
        mp11::mp_remove<
180  
        mp11::mp_remove<
181  
            mp11::mp_list<
181  
            mp11::mp_list<
182  
                system::result<typename R0::value_type>,
182  
                system::result<typename R0::value_type>,
183  
                system::result<typename Rn::value_type>...>,
183  
                system::result<typename Rn::value_type>...>,
184  
            system::result<void>>>;
184  
            system::result<void>>>;
185  

185  

186  
    template<std::size_t I>
186  
    template<std::size_t I>
187  
    using is_void = std::is_same<
187  
    using is_void = std::is_same<
188  
        mp11::mp_at_c<L, I>, void>;
188  
        mp11::mp_at_c<L, I>, void>;
189  

189  

190  
    R const& rn;
190  
    R const& rn;
191  
    V v;
191  
    V v;
192  

192  

193  
    BOOST_URL_CXX14_CONSTEXPR
193  
    BOOST_URL_CXX14_CONSTEXPR
194  
    explicit
194  
    explicit
195  
    parse_sequence(
195  
    parse_sequence(
196  
        R const& rn_) noexcept
196  
        R const& rn_) noexcept
197  
        : rn(rn_)
197  
        : rn(rn_)
198  
        , v(system::error_code{})
198  
        , v(system::error_code{})
199  
    {
199  
    {
200  
    }
200  
    }
201  

201  

202  
    BOOST_URL_CXX14_CONSTEXPR
202  
    BOOST_URL_CXX14_CONSTEXPR
203  
    void
203  
    void
204  
    apply(
204  
    apply(
205  
        char const*&,
205  
        char const*&,
206  
        char const*,
206  
        char const*,
207  
        ...) const noexcept
207  
        ...) const noexcept
208  
    {
208  
    {
209  
    }
209  
    }
210  

210  

211  
    // for system::result<void>
211  
    // for system::result<void>
212  
    template<
212  
    template<
213  
        std::size_t Ir,
213  
        std::size_t Ir,
214  
        std::size_t Iv>
214  
        std::size_t Iv>
215  
    BOOST_URL_CXX14_CONSTEXPR
215  
    BOOST_URL_CXX14_CONSTEXPR
216  
    void
216  
    void
217  
    apply(
217  
    apply(
218  
        char const*& it,
218  
        char const*& it,
219  
        char const* end,
219  
        char const* end,
220  
        mp11::mp_size_t<Ir> const&,
220  
        mp11::mp_size_t<Ir> const&,
221  
        mp11::mp_size_t<Iv> const&,
221  
        mp11::mp_size_t<Iv> const&,
222  
        mp11::mp_true const&)
222  
        mp11::mp_true const&)
223  
    {
223  
    {
224  
        system::result<void> rv =
224  
        system::result<void> rv =
225  
            grammar::parse(
225  
            grammar::parse(
226  
                it, end, get<Ir>(rn));
226  
                it, end, get<Ir>(rn));
227  
        if( rv.has_error() )
227  
        if( rv.has_error() )
228  
        {
228  
        {
229  
            v = rv.error();
229  
            v = rv.error();
230  
            return;
230  
            return;
231  
        }
231  
        }
232  
        apply(it, end,
232  
        apply(it, end,
233  
            mp11::mp_size_t<Ir+1>{},
233  
            mp11::mp_size_t<Ir+1>{},
234  
            mp11::mp_size_t<Iv>{});
234  
            mp11::mp_size_t<Iv>{});
235  
    }
235  
    }
236  

236  

237  
    template<
237  
    template<
238  
        std::size_t Ir,
238  
        std::size_t Ir,
239  
        std::size_t Iv>
239  
        std::size_t Iv>
240  
    BOOST_URL_CXX14_CONSTEXPR
240  
    BOOST_URL_CXX14_CONSTEXPR
241  
    void
241  
    void
242  
    apply(
242  
    apply(
243  
        char const*& it,
243  
        char const*& it,
244  
        char const* end,
244  
        char const* end,
245  
        mp11::mp_size_t<Ir> const&,
245  
        mp11::mp_size_t<Ir> const&,
246  
        mp11::mp_size_t<Iv> const&,
246  
        mp11::mp_size_t<Iv> const&,
247  
        mp11::mp_false const&)
247  
        mp11::mp_false const&)
248  
    {
248  
    {
249  
        v = grammar::parse(
249  
        v = grammar::parse(
250  
            it, end, get<Ir>(rn));
250  
            it, end, get<Ir>(rn));
251  
        if( !v )
251  
        if( !v )
252  
            return;
252  
            return;
253  
        apply(it, end,
253  
        apply(it, end,
254  
            mp11::mp_size_t<Ir+1>{},
254  
            mp11::mp_size_t<Ir+1>{},
255  
            mp11::mp_size_t<Iv+1>{});
255  
            mp11::mp_size_t<Iv+1>{});
256  
    }
256  
    }
257  

257  

258  
    template<
258  
    template<
259  
        std::size_t Ir = 0,
259  
        std::size_t Ir = 0,
260  
        std::size_t Iv = 0>
260  
        std::size_t Iv = 0>
261  
    BOOST_URL_CXX14_CONSTEXPR
261  
    BOOST_URL_CXX14_CONSTEXPR
262  
    typename std::enable_if<
262  
    typename std::enable_if<
263  
        Ir < 1 + sizeof...(Rn)>::type
263  
        Ir < 1 + sizeof...(Rn)>::type
264  
    apply(
264  
    apply(
265  
        char const*& it,
265  
        char const*& it,
266  
        char const* end,
266  
        char const* end,
267  
        mp11::mp_size_t<Ir> const& ir = {},
267  
        mp11::mp_size_t<Ir> const& ir = {},
268  
        mp11::mp_size_t<Iv> const& iv = {}
268  
        mp11::mp_size_t<Iv> const& iv = {}
269  
            ) noexcept
269  
            ) noexcept
270  
    {
270  
    {
271  
        apply(it, end, ir, iv, is_void<Ir>{});
271  
        apply(it, end, ir, iv, is_void<Ir>{});
272  
    }
272  
    }
273  

273  

274  
    BOOST_URL_CXX14_CONSTEXPR
274  
    BOOST_URL_CXX14_CONSTEXPR
275  
    V
275  
    V
276  
    make_result() noexcept
276  
    make_result() noexcept
277  
    {
277  
    {
278  
        return v;
278  
        return v;
279  
    }
279  
    }
280  
};
280  
};
281  

281  

282  
#if defined(BOOST_GCC) && BOOST_GCC >= 70000
282  
#if defined(BOOST_GCC) && BOOST_GCC >= 70000
283  
#pragma GCC diagnostic pop
283  
#pragma GCC diagnostic pop
284  
#endif
284  
#endif
285  

285  

286  
} // detail
286  
} // detail
287  

287  

288  
template<
288  
template<
289  
    class R0,
289  
    class R0,
290  
    class... Rn>
290  
    class... Rn>
291  
BOOST_URL_CXX14_CONSTEXPR
291  
BOOST_URL_CXX14_CONSTEXPR
292  
auto
292  
auto
293  
implementation_defined::tuple_rule_t<R0, Rn...>::
293  
implementation_defined::tuple_rule_t<R0, Rn...>::
294  
parse(
294  
parse(
295  
    char const*& it,
295  
    char const*& it,
296  
    char const* end) const ->
296  
    char const* end) const ->
297  
        system::result<value_type>
297  
        system::result<value_type>
298  
{
298  
{
299  
    detail::parse_sequence<
299  
    detail::parse_sequence<
300  
        IsList, R0, Rn...> t(this->get());
300  
        IsList, R0, Rn...> t(this->get());
301  
    t.apply(it, end);
301  
    t.apply(it, end);
302  
    return t.make_result();
302  
    return t.make_result();
303  
}
303  
}
304  

304  

305  
} // grammar
305  
} // grammar
306  
} // urls
306  
} // urls
307  
} // boost
307  
} // boost
308  

308  

309  
#endif
309  
#endif