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

10  

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

13  

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

19  

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

23  

23  
namespace detail {
24  
namespace detail {
24  

25  

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

33  

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

37  

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

43  

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

47  

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

51  

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

61  

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

70  

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

96  

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

121  

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

137  

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

149  

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

162  

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

168  

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

172  

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

179  

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

183  

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

186  

 
187 +
    BOOST_URL_CXX14_CONSTEXPR
179  
    explicit
188  
    explicit
180  
    parse_sequence(
189  
    parse_sequence(
181  
        R const& rn_) noexcept
190  
        R const& rn_) noexcept
182  
        : rn(rn_)
191  
        : rn(rn_)
183  
        , v(system::error_code{})
192  
        , v(system::error_code{})
184  
    {
193  
    {
185  
    }
194  
    }
186  

195  

 
196 +
    BOOST_URL_CXX14_CONSTEXPR
187  
    void
197  
    void
188  
    apply(
198  
    apply(
189  
        char const*&,
199  
        char const*&,
190  
        char const*,
200  
        char const*,
191  
        ...) const noexcept
201  
        ...) const noexcept
192  
    {
202  
    {
193  
    }
203  
    }
194  

204  

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

230  

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

251  

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

267  

 
268 +
    BOOST_URL_CXX14_CONSTEXPR
256  
    V
269  
    V
257  
    make_result() noexcept
270  
    make_result() noexcept
258  
    {
271  
    {
259  
        return v;
272  
        return v;
260  
    }
273  
    }
261  
};
274  
};
262  

275  

263  
} // detail
276  
} // detail
264  

277  

265  
template<
278  
template<
266  
    class R0,
279  
    class R0,
267  
    class... Rn>
280  
    class... Rn>
 
281 +
BOOST_URL_CXX14_CONSTEXPR
268  
auto
282  
auto
269  
implementation_defined::tuple_rule_t<R0, Rn...>::
283  
implementation_defined::tuple_rule_t<R0, Rn...>::
270  
parse(
284  
parse(
271  
    char const*& it,
285  
    char const*& it,
272  
    char const* end) const ->
286  
    char const* end) const ->
273  
        system::result<value_type>
287  
        system::result<value_type>
274  
{
288  
{
275  
    detail::parse_sequence<
289  
    detail::parse_sequence<
276  
        IsList, R0, Rn...> t(this->get());
290  
        IsList, R0, Rn...> t(this->get());
277  
    t.apply(it, end);
291  
    t.apply(it, end);
278  
    return t.make_result();
292  
    return t.make_result();
279  
}
293  
}
280  

294  

281  
} // grammar
295  
} // grammar
282  
} // urls
296  
} // urls
283  
} // boost
297  
} // boost
284  

298  

285  
#endif
299  
#endif