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  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/url
7  
// Official repository: https://github.com/boostorg/url
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
10  
#ifndef BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
11  
#define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
11  
#define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
12  

12  

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

18  

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

22  

23  
namespace detail {
23  
namespace detail {
24  

24  

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

32  

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

36  

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

42  

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

46  

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

50  

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

59  

60  
    void
60  
    void
61  
    apply(
61  
    apply(
62  
        char const*&,
62  
        char const*&,
63  
        char const*,
63  
        char const*,
64  
        ...) const noexcept
64  
        ...) const noexcept
65  
    {
65  
    {
66  
    }
66  
    }
67  

67  

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

92  

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

116  

117  
    template<
117  
    template<
118  
        std::size_t Ir = 0,
118  
        std::size_t Ir = 0,
119  
        std::size_t Iv = 0>
119  
        std::size_t Iv = 0>
120  
    typename std::enable_if<
120  
    typename std::enable_if<
121  
        Ir < 1 + sizeof...(Rn)>::type
121  
        Ir < 1 + sizeof...(Rn)>::type
122  
    apply(
122  
    apply(
123  
        char const*& it,
123  
        char const*& it,
124  
        char const* end,
124  
        char const* end,
125  
        mp11::mp_size_t<Ir> const& ir = {},
125  
        mp11::mp_size_t<Ir> const& ir = {},
126  
        mp11::mp_size_t<Iv> const& iv = {}
126  
        mp11::mp_size_t<Iv> const& iv = {}
127  
            ) noexcept
127  
            ) noexcept
128  
    {
128  
    {
129  
        apply(it, end, ir, iv, is_void<Ir>{});
129  
        apply(it, end, ir, iv, is_void<Ir>{});
130  
    }
130  
    }
131  

131  

132  
    struct deref
132  
    struct deref
133  
    {
133  
    {
134  
        template<class R>
134  
        template<class R>
135  
        auto
135  
        auto
136  
        operator()(R const& r) const ->
136  
        operator()(R const& r) const ->
137  
            decltype(*r)
137  
            decltype(*r)
138  
        {
138  
        {
139  
            return *r;
139  
            return *r;
140  
        }
140  
        }
141  
    };
141  
    };
142  

142  

143  
    auto
143  
    auto
144  
    make_result() noexcept ->
144  
    make_result() noexcept ->
145  
        system::result<typename implementation_defined::tuple_rule_t<
145  
        system::result<typename implementation_defined::tuple_rule_t<
146  
            R0, Rn...>::value_type>
146  
            R0, Rn...>::value_type>
147  
    {
147  
    {
148  
        if(ec.failed())
148  
        if(ec.failed())
149  
            return ec;
149  
            return ec;
150  
        return mp11::tuple_transform(
150  
        return mp11::tuple_transform(
151  
            deref{}, vn);
151  
            deref{}, vn);
152  
    }
152  
    }
153  
};
153  
};
154  

154  

155  
// returns a value_type
155  
// returns a value_type
156  
template<class R0, class... Rn>
156  
template<class R0, class... Rn>
157  
struct parse_sequence<false, R0, Rn...>
157  
struct parse_sequence<false, R0, Rn...>
158  
{
158  
{
159  
    using R = detail::tuple<R0, Rn...>;
159  
    using R = detail::tuple<R0, Rn...>;
160  

160  

161  
    using L = mp11::mp_list<
161  
    using L = mp11::mp_list<
162  
        typename R0::value_type,
162  
        typename R0::value_type,
163  
        typename Rn::value_type...>;
163  
        typename Rn::value_type...>;
164  

164  

165  
    using V = mp11::mp_first<
165  
    using V = mp11::mp_first<
166  
        mp11::mp_remove<
166  
        mp11::mp_remove<
167  
            mp11::mp_list<
167  
            mp11::mp_list<
168  
                system::result<typename R0::value_type>,
168  
                system::result<typename R0::value_type>,
169  
                system::result<typename Rn::value_type>...>,
169  
                system::result<typename Rn::value_type>...>,
170  
            system::result<void>>>;
170  
            system::result<void>>>;
171  

171  

172  
    template<std::size_t I>
172  
    template<std::size_t I>
173  
    using is_void = std::is_same<
173  
    using is_void = std::is_same<
174  
        mp11::mp_at_c<L, I>, void>;
174  
        mp11::mp_at_c<L, I>, void>;
175  

175  

176  
    R const& rn;
176  
    R const& rn;
177  
    V v;
177  
    V v;
178  

178  

179  
    explicit
179  
    explicit
180  
    parse_sequence(
180  
    parse_sequence(
181  
        R const& rn_) noexcept
181  
        R const& rn_) noexcept
182  
        : rn(rn_)
182  
        : rn(rn_)
183  
        , v(system::error_code{})
183  
        , v(system::error_code{})
184  
    {
184  
    {
185  
    }
185  
    }
186  

186  

187  
    void
187  
    void
188  
    apply(
188  
    apply(
189  
        char const*&,
189  
        char const*&,
190  
        char const*,
190  
        char const*,
191  
        ...) const noexcept
191  
        ...) const noexcept
192  
    {
192  
    {
193  
    }
193  
    }
194  

194  

195  
    // for system::result<void>
195  
    // for system::result<void>
196  
    template<
196  
    template<
197  
        std::size_t Ir,
197  
        std::size_t Ir,
198  
        std::size_t Iv>
198  
        std::size_t Iv>
199  
    BOOST_URL_NO_INLINE
199  
    BOOST_URL_NO_INLINE
200  
    void
200  
    void
201  
    apply(
201  
    apply(
202  
        char const*& it,
202  
        char const*& it,
203  
        char const* end,
203  
        char const* end,
204  
        mp11::mp_size_t<Ir> const&,
204  
        mp11::mp_size_t<Ir> const&,
205  
        mp11::mp_size_t<Iv> const&,
205  
        mp11::mp_size_t<Iv> const&,
206  
        mp11::mp_true const&)
206  
        mp11::mp_true const&)
207  
    {
207  
    {
208  
        system::result<void> rv =
208  
        system::result<void> rv =
209  
            grammar::parse(
209  
            grammar::parse(
210  
                it, end, get<Ir>(rn));
210  
                it, end, get<Ir>(rn));
211  
        if( !rv )
211  
        if( !rv )
212  
        {
212  
        {
213  
            v = rv.error();
213  
            v = rv.error();
214  
            return;
214  
            return;
215  
        }
215  
        }
216  
        apply(it, end,
216  
        apply(it, end,
217  
            mp11::mp_size_t<Ir+1>{},
217  
            mp11::mp_size_t<Ir+1>{},
218  
            mp11::mp_size_t<Iv>{});
218  
            mp11::mp_size_t<Iv>{});
219  
    }
219  
    }
220  

220  

221  
    template<
221  
    template<
222  
        std::size_t Ir,
222  
        std::size_t Ir,
223  
        std::size_t Iv>
223  
        std::size_t Iv>
224  
    void
224  
    void
225  
    apply(
225  
    apply(
226  
        char const*& it,
226  
        char const*& it,
227  
        char const* end,
227  
        char const* end,
228  
        mp11::mp_size_t<Ir> const&,
228  
        mp11::mp_size_t<Ir> const&,
229  
        mp11::mp_size_t<Iv> const&,
229  
        mp11::mp_size_t<Iv> const&,
230  
        mp11::mp_false const&)
230  
        mp11::mp_false const&)
231  
    {
231  
    {
232  
        v = grammar::parse(
232  
        v = grammar::parse(
233  
            it, end, get<Ir>(rn));
233  
            it, end, get<Ir>(rn));
234  
        if( !v )
234  
        if( !v )
235  
            return;
235  
            return;
236  
        apply(it, end,
236  
        apply(it, end,
237  
            mp11::mp_size_t<Ir+1>{},
237  
            mp11::mp_size_t<Ir+1>{},
238  
            mp11::mp_size_t<Iv+1>{});
238  
            mp11::mp_size_t<Iv+1>{});
239  
    }
239  
    }
240  

240  

241  
    template<
241  
    template<
242  
        std::size_t Ir = 0,
242  
        std::size_t Ir = 0,
243  
        std::size_t Iv = 0>
243  
        std::size_t Iv = 0>
244  
    typename std::enable_if<
244  
    typename std::enable_if<
245  
        Ir < 1 + sizeof...(Rn)>::type
245  
        Ir < 1 + sizeof...(Rn)>::type
246  
    apply(
246  
    apply(
247  
        char const*& it,
247  
        char const*& it,
248  
        char const* end,
248  
        char const* end,
249  
        mp11::mp_size_t<Ir> const& ir = {},
249  
        mp11::mp_size_t<Ir> const& ir = {},
250  
        mp11::mp_size_t<Iv> const& iv = {}
250  
        mp11::mp_size_t<Iv> const& iv = {}
251  
            ) noexcept
251  
            ) noexcept
252  
    {
252  
    {
253  
        apply(it, end, ir, iv, is_void<Ir>{});
253  
        apply(it, end, ir, iv, is_void<Ir>{});
254  
    }
254  
    }
255  

255  

256  
    V
256  
    V
257  
    make_result() noexcept
257  
    make_result() noexcept
258  
    {
258  
    {
259  
        return v;
259  
        return v;
260  
    }
260  
    }
261  
};
261  
};
262  

262  

263  
} // detail
263  
} // detail
264  

264  

265  
template<
265  
template<
266  
    class R0,
266  
    class R0,
267  
    class... Rn>
267  
    class... Rn>
268  
auto
268  
auto
269  
implementation_defined::tuple_rule_t<R0, Rn...>::
269  
implementation_defined::tuple_rule_t<R0, Rn...>::
270  
parse(
270  
parse(
271  
    char const*& it,
271  
    char const*& it,
272  
    char const* end) const ->
272  
    char const* end) const ->
273  
        system::result<value_type>
273  
        system::result<value_type>
274  
{
274  
{
275  
    detail::parse_sequence<
275  
    detail::parse_sequence<
276  
        IsList, R0, Rn...> t(this->get());
276  
        IsList, R0, Rn...> t(this->get());
277  
    t.apply(it, end);
277  
    t.apply(it, end);
278  
    return t.make_result();
278  
    return t.make_result();
279  
}
279  
}
280  

280  

281  
} // grammar
281  
} // grammar
282  
} // urls
282  
} // urls
283  
} // boost
283  
} // boost
284  

284  

285  
#endif
285  
#endif