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  
//
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_VARIANT_RULE_HPP
10  
#ifndef BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
11  
#define BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
11  
#define BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
12  

12  

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

47  

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

82  

83  
} // detail
83  
} // detail
84  

84  

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

99  

100  
//------------------------------------------------
100  
//------------------------------------------------
101  

101  

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

116  

117  
} // grammar
117  
} // grammar
118  
} // urls
118  
} // urls
119  
} // boost
119  
} // boost
120  

120  

121  
#endif
121  
#endif