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_TUPLE_RULE_HPP
11  
#ifndef BOOST_URL_GRAMMAR_TUPLE_RULE_HPP
12  
#define BOOST_URL_GRAMMAR_TUPLE_RULE_HPP
12  
#define BOOST_URL_GRAMMAR_TUPLE_RULE_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/error_types.hpp>
15  
#include <boost/url/error_types.hpp>
16  
#include <boost/url/grammar/error.hpp>
16  
#include <boost/url/grammar/error.hpp>
17  
#include <boost/url/grammar/detail/tuple.hpp>
17  
#include <boost/url/grammar/detail/tuple.hpp>
18  
#include <boost/url/grammar/type_traits.hpp>
18  
#include <boost/url/grammar/type_traits.hpp>
19  
#include <boost/mp11/algorithm.hpp>
19  
#include <boost/mp11/algorithm.hpp>
20  
#include <boost/core/detail/static_assert.hpp>
20  
#include <boost/core/detail/static_assert.hpp>
21  
#include <boost/core/empty_value.hpp>
21  
#include <boost/core/empty_value.hpp>
22  
#include <tuple>
22  
#include <tuple>
23  

23  

24  
namespace boost {
24  
namespace boost {
25  
namespace urls {
25  
namespace urls {
26  
namespace grammar {
26  
namespace grammar {
27  

27  

28  
namespace implementation_defined {
28  
namespace implementation_defined {
29  
template<
29  
template<
30  
    class R0,
30  
    class R0,
31  
    class... Rn>
31  
    class... Rn>
32  
class tuple_rule_t
32  
class tuple_rule_t
33  
    : empty_value<
33  
    : empty_value<
34  
        detail::tuple<R0, Rn...>>
34  
        detail::tuple<R0, Rn...>>
35  
{
35  
{
36  
    using T = mp11::mp_remove<
36  
    using T = mp11::mp_remove<
37  
        std::tuple<
37  
        std::tuple<
38  
            typename R0::value_type,
38  
            typename R0::value_type,
39  
            typename Rn::value_type...>,
39  
            typename Rn::value_type...>,
40  
        void>;
40  
        void>;
41  
    static constexpr bool IsList =
41  
    static constexpr bool IsList =
42  
        mp11::mp_size<T>::value != 1;
42  
        mp11::mp_size<T>::value != 1;
43  

43  

44  
public:
44  
public:
45  
    using value_type =
45  
    using value_type =
46  
        mp11::mp_eval_if_c<IsList,
46  
        mp11::mp_eval_if_c<IsList,
47  
            T, mp11::mp_first, T>;
47  
            T, mp11::mp_first, T>;
48  

48  

49  
    constexpr
49  
    constexpr
50  
    tuple_rule_t(
50  
    tuple_rule_t(
51  
        R0 const& r0,
51  
        R0 const& r0,
52  
        Rn const&... rn) noexcept
52  
        Rn const&... rn) noexcept
53  
        : empty_value<
53  
        : empty_value<
54  
            detail::tuple<R0, Rn...>>(
54  
            detail::tuple<R0, Rn...>>(
55  
                empty_init,
55  
                empty_init,
56  
                r0, rn...)
56  
                r0, rn...)
57  
    {
57  
    {
58  
    }
58  
    }
59  

59  

60  
    BOOST_URL_CXX14_CONSTEXPR
60  
    BOOST_URL_CXX14_CONSTEXPR
61  
    system::result<value_type>
61  
    system::result<value_type>
62  
    parse(
62  
    parse(
63  
        char const*& it,
63  
        char const*& it,
64  
        char const* end) const;
64  
        char const* end) const;
65  

65  

66  
};
66  
};
67  
} // implementation_defined
67  
} // implementation_defined
68  

68  

69  
/** Match a series of rules in order
69  
/** Match a series of rules in order
70  

70  

71  
    This matches a series of rules in the
71  
    This matches a series of rules in the
72  
    order specified. Upon success the input
72  
    order specified. Upon success the input
73  
    is adjusted to point to the first
73  
    is adjusted to point to the first
74  
    unconsumed character. There is no
74  
    unconsumed character. There is no
75  
    implicit specification of linear white
75  
    implicit specification of linear white
76  
    space between each rule.
76  
    space between each rule.
77  

77  

78  
    @par Value Type
78  
    @par Value Type
79  
    @code
79  
    @code
80  
    using value_type = __see_below__;
80  
    using value_type = __see_below__;
81  
    @endcode
81  
    @endcode
82  

82  

83  
    The sequence rule usually returns a
83  
    The sequence rule usually returns a
84  
    `std::tuple` containing the the `value_type`
84  
    `std::tuple` containing the the `value_type`
85  
    of each corresponding rule in the sequence,
85  
    of each corresponding rule in the sequence,
86  
    except that `void` values are removed.
86  
    except that `void` values are removed.
87  
    However, if there is exactly one non-void
87  
    However, if there is exactly one non-void
88  
    value type `T`, then the sequence rule
88  
    value type `T`, then the sequence rule
89  
    returns `system::result<T>` instead of
89  
    returns `system::result<T>` instead of
90  
    `system::result<tuple<...>>`.
90  
    `system::result<tuple<...>>`.
91  

91  

92  
    @par Example
92  
    @par Example
93  
    Rules are used with the function @ref parse.
93  
    Rules are used with the function @ref parse.
94  
    @code
94  
    @code
95  
    system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv =
95  
    system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv =
96  
        parse( "192.168.0.1",
96  
        parse( "192.168.0.1",
97  
            tuple_rule(
97  
            tuple_rule(
98  
                dec_octet_rule,
98  
                dec_octet_rule,
99  
                squelch( delim_rule('.') ),
99  
                squelch( delim_rule('.') ),
100  
                dec_octet_rule,
100  
                dec_octet_rule,
101  
                squelch( delim_rule('.') ),
101  
                squelch( delim_rule('.') ),
102  
                dec_octet_rule,
102  
                dec_octet_rule,
103  
                squelch( delim_rule('.') ),
103  
                squelch( delim_rule('.') ),
104  
                dec_octet_rule ) );
104  
                dec_octet_rule ) );
105  
    @endcode
105  
    @endcode
106  

106  

107  
    @par BNF
107  
    @par BNF
108  
    @code
108  
    @code
109  
    sequence     = rule1 rule2 rule3...
109  
    sequence     = rule1 rule2 rule3...
110  
    @endcode
110  
    @endcode
111  

111  

112  
    @par Specification
112  
    @par Specification
113  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.1"
113  
    @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.1"
114  
        >3.1.  Concatenation (rfc5234)</a>
114  
        >3.1.  Concatenation (rfc5234)</a>
115  

115  

116  
    @param r0 The first rule to match
116  
    @param r0 The first rule to match
117  
    @param rn A list of one or more rules to match
117  
    @param rn A list of one or more rules to match
118  
    @return The sequence rule
118  
    @return The sequence rule
119  

119  

120  
    @see
120  
    @see
121  
        @ref dec_octet_rule,
121  
        @ref dec_octet_rule,
122  
        @ref delim_rule,
122  
        @ref delim_rule,
123  
        @ref parse,
123  
        @ref parse,
124  
        @ref squelch.
124  
        @ref squelch.
125  
*/
125  
*/
126  
template<
126  
template<
127  
    BOOST_URL_CONSTRAINT(Rule) R0,
127  
    BOOST_URL_CONSTRAINT(Rule) R0,
128  
    BOOST_URL_CONSTRAINT(Rule)... Rn>
128  
    BOOST_URL_CONSTRAINT(Rule)... Rn>
129  
constexpr
129  
constexpr
130  
auto
130  
auto
131  
tuple_rule(
131  
tuple_rule(
132  
    R0 const& r0,
132  
    R0 const& r0,
133  
    Rn const&... rn) noexcept ->
133  
    Rn const&... rn) noexcept ->
134  
        implementation_defined::tuple_rule_t<
134  
        implementation_defined::tuple_rule_t<
135  
            R0, Rn...>
135  
            R0, Rn...>
136  
{
136  
{
137  
    BOOST_CORE_STATIC_ASSERT(
137  
    BOOST_CORE_STATIC_ASSERT(
138  
        mp11::mp_all<
138  
        mp11::mp_all<
139  
            is_rule<R0>,
139  
            is_rule<R0>,
140  
            is_rule<Rn>...>::value);
140  
            is_rule<Rn>...>::value);
141  
    return { r0, rn... };
141  
    return { r0, rn... };
142  
}
142  
}
143  

143  

144  
namespace implementation_defined {
144  
namespace implementation_defined {
145  

145  

146  
template<class Rule>
146  
template<class Rule>
147  
struct squelch_rule_t
147  
struct squelch_rule_t
148  
    : empty_value<Rule>
148  
    : empty_value<Rule>
149  
{
149  
{
150  
    using value_type = void;
150  
    using value_type = void;
151  

151  

152  
    constexpr
152  
    constexpr
153  
    squelch_rule_t(
153  
    squelch_rule_t(
154  
        Rule const& r) noexcept
154  
        Rule const& r) noexcept
155  
        : empty_value<Rule>(
155  
        : empty_value<Rule>(
156  
            empty_init, r)
156  
            empty_init, r)
157  
    {
157  
    {
158  
    }
158  
    }
159  

159  

160  
    BOOST_URL_CXX14_CONSTEXPR
160  
    BOOST_URL_CXX14_CONSTEXPR
161  
    system::result<value_type>
161  
    system::result<value_type>
162  
    parse(
162  
    parse(
163  
        char const*& it,
163  
        char const*& it,
164  
        char const* end) const
164  
        char const* end) const
165  
    {
165  
    {
166  
        auto rv = this->get().parse(it, end);
166  
        auto rv = this->get().parse(it, end);
167  
        if(rv.error())
167  
        if(rv.error())
168  
            return rv.error();
168  
            return rv.error();
169  
        return {}; // void
169  
        return {}; // void
170  
    }
170  
    }
171  
};
171  
};
172  

172  

173  
} // implementation_defined
173  
} // implementation_defined
174  

174  

175  
/** Squelch the value of a rule
175  
/** Squelch the value of a rule
176  

176  

177  
    This function returns a new rule which
177  
    This function returns a new rule which
178  
    matches the specified rule, and converts
178  
    matches the specified rule, and converts
179  
    its value type to `void`. This is useful
179  
    its value type to `void`. This is useful
180  
    for matching delimiters in a grammar,
180  
    for matching delimiters in a grammar,
181  
    where the value for the delimiter is not
181  
    where the value for the delimiter is not
182  
    needed.
182  
    needed.
183  

183  

184  
    @par Value Type
184  
    @par Value Type
185  
    @code
185  
    @code
186  
    using value_type = void;
186  
    using value_type = void;
187  
    @endcode
187  
    @endcode
188  

188  

189  
    @par Example 1
189  
    @par Example 1
190  
    With `squelch`:
190  
    With `squelch`:
191  
    @code
191  
    @code
192  
    system::result< std::tuple< decode_view, core::string_view > > rv = parse(
192  
    system::result< std::tuple< decode_view, core::string_view > > rv = parse(
193  
        "www.example.com:443",
193  
        "www.example.com:443",
194  
        tuple_rule(
194  
        tuple_rule(
195  
            pct_encoded_rule(unreserved_chars + '-' + '.'),
195  
            pct_encoded_rule(unreserved_chars + '-' + '.'),
196  
            squelch( delim_rule( ':' ) ),
196  
            squelch( delim_rule( ':' ) ),
197  
            token_rule( digit_chars ) ) );
197  
            token_rule( digit_chars ) ) );
198  
    @endcode
198  
    @endcode
199  

199  

200  
    @par Example 2
200  
    @par Example 2
201  
    Without `squelch`:
201  
    Without `squelch`:
202  
    @code
202  
    @code
203  
    system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse(
203  
    system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse(
204  
        "www.example.com:443",
204  
        "www.example.com:443",
205  
        tuple_rule(
205  
        tuple_rule(
206  
            pct_encoded_rule(unreserved_chars + '-' + '.'),
206  
            pct_encoded_rule(unreserved_chars + '-' + '.'),
207  
            delim_rule( ':' ),
207  
            delim_rule( ':' ),
208  
            token_rule( digit_chars ) ) );
208  
            token_rule( digit_chars ) ) );
209  
    @endcode
209  
    @endcode
210  

210  

211  
    @param r The rule to squelch
211  
    @param r The rule to squelch
212  
    @return The squelched rule
212  
    @return The squelched rule
213  

213  

214  
    @see
214  
    @see
215  
        @ref delim_rule,
215  
        @ref delim_rule,
216  
        @ref digit_chars,
216  
        @ref digit_chars,
217  
        @ref parse,
217  
        @ref parse,
218  
        @ref tuple_rule,
218  
        @ref tuple_rule,
219  
        @ref token_rule,
219  
        @ref token_rule,
220  
        @ref decode_view,
220  
        @ref decode_view,
221  
        @ref pct_encoded_rule,
221  
        @ref pct_encoded_rule,
222  
        @ref unreserved_chars.
222  
        @ref unreserved_chars.
223  
*/
223  
*/
224  
template<BOOST_URL_CONSTRAINT(Rule) R>
224  
template<BOOST_URL_CONSTRAINT(Rule) R>
225  
constexpr
225  
constexpr
226  
BOOST_URL_IMPLEMENTATION_DEFINED(implementation_defined::squelch_rule_t<R>)
226  
BOOST_URL_IMPLEMENTATION_DEFINED(implementation_defined::squelch_rule_t<R>)
227  
squelch( R const& r ) noexcept
227  
squelch( R const& r ) noexcept
228  
{
228  
{
229  
    BOOST_CORE_STATIC_ASSERT(is_rule<R>::value);
229  
    BOOST_CORE_STATIC_ASSERT(is_rule<R>::value);
230  
    return { r };
230  
    return { r };
231  
}
231  
}
232  

232  

233  
} // grammar
233  
} // grammar
234  
} // urls
234  
} // urls
235  
} // boost
235  
} // boost
236  

236  

237  
#include <boost/url/grammar/impl/tuple_rule.hpp>
237  
#include <boost/url/grammar/impl/tuple_rule.hpp>
238  

238  

239  
#endif
239  
#endif