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

13  

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

23  

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

27  

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

43  

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

48  

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

59  

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

65  

64  
};
66  
};
65  
} // implementation_defined
67  
} // implementation_defined
66  

68  

67  
/** Match a series of rules in order
69  
/** Match a series of rules in order
68  

70  

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

77  

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

82  

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

91  

90  
    @par Example
92  
    @par Example
91  
    Rules are used with the function @ref parse.
93  
    Rules are used with the function @ref parse.
92  
    @code
94  
    @code
93  
    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 =
94  
        parse( "192.168.0.1",
96  
        parse( "192.168.0.1",
95  
            tuple_rule(
97  
            tuple_rule(
96  
                dec_octet_rule,
98  
                dec_octet_rule,
97  
                squelch( delim_rule('.') ),
99  
                squelch( delim_rule('.') ),
98  
                dec_octet_rule,
100  
                dec_octet_rule,
99  
                squelch( delim_rule('.') ),
101  
                squelch( delim_rule('.') ),
100  
                dec_octet_rule,
102  
                dec_octet_rule,
101  
                squelch( delim_rule('.') ),
103  
                squelch( delim_rule('.') ),
102  
                dec_octet_rule ) );
104  
                dec_octet_rule ) );
103  
    @endcode
105  
    @endcode
104  

106  

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

111  

110  
    @par Specification
112  
    @par Specification
111  
    @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"
112  
        >3.1.  Concatenation (rfc5234)</a>
114  
        >3.1.  Concatenation (rfc5234)</a>
113  

115  

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

119  

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

143  

142  
namespace implementation_defined {
144  
namespace implementation_defined {
143  

145  

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

151  

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

159  

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

172  

170  
} // implementation_defined
173  
} // implementation_defined
171  

174  

172  
/** Squelch the value of a rule
175  
/** Squelch the value of a rule
173  

176  

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

183  

181  
    @par Value Type
184  
    @par Value Type
182  
    @code
185  
    @code
183  
    using value_type = void;
186  
    using value_type = void;
184  
    @endcode
187  
    @endcode
185  

188  

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

199  

197  
    @par Example 2
200  
    @par Example 2
198  
    Without `squelch`:
201  
    Without `squelch`:
199  
    @code
202  
    @code
200  
    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(
201  
        "www.example.com:443",
204  
        "www.example.com:443",
202  
        tuple_rule(
205  
        tuple_rule(
203  
            pct_encoded_rule(unreserved_chars + '-' + '.'),
206  
            pct_encoded_rule(unreserved_chars + '-' + '.'),
204  
            delim_rule( ':' ),
207  
            delim_rule( ':' ),
205  
            token_rule( digit_chars ) ) );
208  
            token_rule( digit_chars ) ) );
206  
    @endcode
209  
    @endcode
207  

210  

208  
    @param r The rule to squelch
211  
    @param r The rule to squelch
209  
    @return The squelched rule
212  
    @return The squelched rule
210  

213  

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

232  

230  
} // grammar
233  
} // grammar
231  
} // urls
234  
} // urls
232  
} // boost
235  
} // boost
233  

236  

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

238  

236  
#endif
239  
#endif