1  
//
1  
//
2  
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
2  
// Copyright (c) 2016-2019 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_VARIANT_RULE_HPP
11  
#ifndef BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
12  
#define BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
12  
#define BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
13  

13  

14  
#include <boost/url/grammar/error.hpp>
14  
#include <boost/url/grammar/error.hpp>
15  
#include <boost/url/grammar/parse.hpp>
15  
#include <boost/url/grammar/parse.hpp>
16  
#include <boost/core/detail/static_assert.hpp>
16  
#include <boost/core/detail/static_assert.hpp>
17  
#include <cstdint>
17  
#include <cstdint>
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  
// must come first
26  
// must come first
27  
template<
27  
template<
28  
    class R0,
28  
    class R0,
29  
    class... Rn,
29  
    class... Rn,
30  
    std::size_t I>
30  
    std::size_t I>
31  
BOOST_URL_CXX20_CONSTEXPR
31  
BOOST_URL_CXX20_CONSTEXPR
32  
auto
32  
auto
33  
parse_variant(
33  
parse_variant(
34  
    char const*&,
34  
    char const*&,
35  
    char const*,
35  
    char const*,
36  
    detail::tuple<
36  
    detail::tuple<
37  
        R0, Rn...> const&,
37  
        R0, Rn...> const&,
38  
    std::integral_constant<
38  
    std::integral_constant<
39  
        std::size_t, I> const&,
39  
        std::size_t, I> const&,
40  
    std::false_type const&) ->
40  
    std::false_type const&) ->
41  
        system::result<variant2::variant<
41  
        system::result<variant2::variant<
42  
            typename R0::value_type,
42  
            typename R0::value_type,
43  
            typename Rn::value_type...>>
43  
            typename Rn::value_type...>>
44  
{
44  
{
45  
    // no match
45  
    // no match
46  
    BOOST_URL_CONSTEXPR_RETURN_EC(
46  
    BOOST_URL_CONSTEXPR_RETURN_EC(
47  
        error::mismatch);
47  
        error::mismatch);
48  
}
48  
}
49  

49  

50  
template<
50  
template<
51  
    class R0,
51  
    class R0,
52  
    class... Rn,
52  
    class... Rn,
53  
    std::size_t I>
53  
    std::size_t I>
54  
BOOST_URL_CXX20_CONSTEXPR
54  
BOOST_URL_CXX20_CONSTEXPR
55  
auto
55  
auto
56  
parse_variant(
56  
parse_variant(
57  
    char const*& it,
57  
    char const*& it,
58  
    char const* const end,
58  
    char const* const end,
59  
    detail::tuple<
59  
    detail::tuple<
60  
        R0, Rn...> const& rn,
60  
        R0, Rn...> const& rn,
61  
    std::integral_constant<
61  
    std::integral_constant<
62  
        std::size_t, I> const&,
62  
        std::size_t, I> const&,
63  
    std::true_type const&) ->
63  
    std::true_type const&) ->
64  
        system::result<variant2::variant<
64  
        system::result<variant2::variant<
65  
            typename R0::value_type,
65  
            typename R0::value_type,
66  
            typename Rn::value_type...>>
66  
            typename Rn::value_type...>>
67  
{
67  
{
68  
    auto const it0 = it;
68  
    auto const it0 = it;
69  
    auto rv = parse(
69  
    auto rv = parse(
70  
        it, end, get<I>(rn));
70  
        it, end, get<I>(rn));
71  
    if( rv )
71  
    if( rv )
72  
        return variant2::variant<
72  
        return variant2::variant<
73  
            typename R0::value_type,
73  
            typename R0::value_type,
74  
            typename Rn::value_type...>{
74  
            typename Rn::value_type...>{
75  
                variant2::in_place_index_t<I>{}, *rv};
75  
                variant2::in_place_index_t<I>{}, *rv};
76  
    it = it0;
76  
    it = it0;
77  
    return parse_variant(
77  
    return parse_variant(
78  
        it, end, rn,
78  
        it, end, rn,
79  
        std::integral_constant<
79  
        std::integral_constant<
80  
            std::size_t, I+1>{},
80  
            std::size_t, I+1>{},
81  
        std::integral_constant<bool,
81  
        std::integral_constant<bool,
82  
            ((I + 1) < (1 +
82  
            ((I + 1) < (1 +
83  
                sizeof...(Rn)))>{});
83  
                sizeof...(Rn)))>{});
84  
}
84  
}
85  

85  

86  
} // detail
86  
} // detail
87  

87  

88  
template<class R0, class... Rn>
88  
template<class R0, class... Rn>
89  
BOOST_URL_CXX20_CONSTEXPR
89  
BOOST_URL_CXX20_CONSTEXPR
90  
auto
90  
auto
91  
implementation_defined::variant_rule_t<R0, Rn...>::
91  
implementation_defined::variant_rule_t<R0, Rn...>::
92  
parse(
92  
parse(
93  
    char const*& it,
93  
    char const*& it,
94  
    char const* end) const ->
94  
    char const* end) const ->
95  
        system::result<value_type>
95  
        system::result<value_type>
96  
{
96  
{
97  
    return detail::parse_variant(
97  
    return detail::parse_variant(
98  
        it, end, rn_,
98  
        it, end, rn_,
99  
        std::integral_constant<
99  
        std::integral_constant<
100  
            std::size_t, 0>{},
100  
            std::size_t, 0>{},
101  
        std::true_type{});
101  
        std::true_type{});
102  
}
102  
}
103  

103  

104  
//------------------------------------------------
104  
//------------------------------------------------
105  

105  

106  
template<BOOST_URL_CONSTRAINT(Rule) R0, BOOST_URL_CONSTRAINT(Rule)... Rn>
106  
template<BOOST_URL_CONSTRAINT(Rule) R0, BOOST_URL_CONSTRAINT(Rule)... Rn>
107  
auto
107  
auto
108  
constexpr
108  
constexpr
109  
variant_rule(
109  
variant_rule(
110  
    R0 const& r0,
110  
    R0 const& r0,
111  
    Rn const&... rn) noexcept ->
111  
    Rn const&... rn) noexcept ->
112  
        implementation_defined::variant_rule_t<R0, Rn...>
112  
        implementation_defined::variant_rule_t<R0, Rn...>
113  
{
113  
{
114  
    BOOST_CORE_STATIC_ASSERT(
114  
    BOOST_CORE_STATIC_ASSERT(
115  
        mp11::mp_all<
115  
        mp11::mp_all<
116  
            is_rule<R0>,
116  
            is_rule<R0>,
117  
            is_rule<Rn>...>::value);
117  
            is_rule<Rn>...>::value);
118  
    return { r0, rn... };
118  
    return { r0, rn... };
119  
}
119  
}
120  

120  

121  
} // grammar
121  
} // grammar
122  
} // urls
122  
} // urls
123  
} // boost
123  
} // boost
124  

124  

125  
#endif
125  
#endif