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  
// returns a value_type
163  
// returns a value_type
164  
template<class R0, class... Rn>
164  
template<class R0, class... Rn>
165  
struct parse_sequence<false, R0, Rn...>
165  
struct parse_sequence<false, R0, Rn...>
166  
{
166  
{
167  
    using R = detail::tuple<R0, Rn...>;
167  
    using R = detail::tuple<R0, Rn...>;
168  

168  

169  
    using L = mp11::mp_list<
169  
    using L = mp11::mp_list<
170  
        typename R0::value_type,
170  
        typename R0::value_type,
171  
        typename Rn::value_type...>;
171  
        typename Rn::value_type...>;
172  

172  

173  
    using V = mp11::mp_first<
173  
    using V = mp11::mp_first<
174  
        mp11::mp_remove<
174  
        mp11::mp_remove<
175  
            mp11::mp_list<
175  
            mp11::mp_list<
176  
                system::result<typename R0::value_type>,
176  
                system::result<typename R0::value_type>,
177  
                system::result<typename Rn::value_type>...>,
177  
                system::result<typename Rn::value_type>...>,
178  
            system::result<void>>>;
178  
            system::result<void>>>;
179  

179  

180  
    template<std::size_t I>
180  
    template<std::size_t I>
181  
    using is_void = std::is_same<
181  
    using is_void = std::is_same<
182  
        mp11::mp_at_c<L, I>, void>;
182  
        mp11::mp_at_c<L, I>, void>;
183  

183  

184  
    R const& rn;
184  
    R const& rn;
185  
    V v;
185  
    V v;
186  

186  

187  
    BOOST_URL_CXX14_CONSTEXPR
187  
    BOOST_URL_CXX14_CONSTEXPR
188  
    explicit
188  
    explicit
189  
    parse_sequence(
189  
    parse_sequence(
190  
        R const& rn_) noexcept
190  
        R const& rn_) noexcept
191  
        : rn(rn_)
191  
        : rn(rn_)
192  
        , v(system::error_code{})
192  
        , v(system::error_code{})
193  
    {
193  
    {
194  
    }
194  
    }
195  

195  

196  
    BOOST_URL_CXX14_CONSTEXPR
196  
    BOOST_URL_CXX14_CONSTEXPR
197  
    void
197  
    void
198  
    apply(
198  
    apply(
199  
        char const*&,
199  
        char const*&,
200  
        char const*,
200  
        char const*,
201  
        ...) const noexcept
201  
        ...) const noexcept
202  
    {
202  
    {
203  
    }
203  
    }
204  

204  

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

230  

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

251  

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

267  

268  
    BOOST_URL_CXX14_CONSTEXPR
268  
    BOOST_URL_CXX14_CONSTEXPR
269  
    V
269  
    V
270  
    make_result() noexcept
270  
    make_result() noexcept
271  
    {
271  
    {
272  
        return v;
272  
        return v;
273  
    }
273  
    }
274  
};
274  
};
275  

275  

276  
} // detail
276  
} // detail
277  

277  

278  
template<
278  
template<
279  
    class R0,
279  
    class R0,
280  
    class... Rn>
280  
    class... Rn>
281  
BOOST_URL_CXX14_CONSTEXPR
281  
BOOST_URL_CXX14_CONSTEXPR
282  
auto
282  
auto
283  
implementation_defined::tuple_rule_t<R0, Rn...>::
283  
implementation_defined::tuple_rule_t<R0, Rn...>::
284  
parse(
284  
parse(
285  
    char const*& it,
285  
    char const*& it,
286  
    char const* end) const ->
286  
    char const* end) const ->
287  
        system::result<value_type>
287  
        system::result<value_type>
288  
{
288  
{
289  
    detail::parse_sequence<
289  
    detail::parse_sequence<
290  
        IsList, R0, Rn...> t(this->get());
290  
        IsList, R0, Rn...> t(this->get());
291  
    t.apply(it, end);
291  
    t.apply(it, end);
292  
    return t.make_result();
292  
    return t.make_result();
293  
}
293  
}
294  

294  

295  
} // grammar
295  
} // grammar
296  
} // urls
296  
} // urls
297  
} // boost
297  
} // boost
298  

298  

299  
#endif
299  
#endif