1  
//
1  
//
2  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
2  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.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  

10  

11  
#include <boost/url/detail/config.hpp>
11  
#include <boost/url/detail/config.hpp>
12  
#include "boost/url/detail/replacement_field_rule.hpp"
12  
#include "boost/url/detail/replacement_field_rule.hpp"
13  
#include <boost/url/grammar/alnum_chars.hpp>
13  
#include <boost/url/grammar/alnum_chars.hpp>
14  
#include <boost/url/grammar/alpha_chars.hpp>
14  
#include <boost/url/grammar/alpha_chars.hpp>
15  
#include <boost/url/grammar/delim_rule.hpp>
15  
#include <boost/url/grammar/delim_rule.hpp>
16  
#include <boost/url/grammar/lut_chars.hpp>
16  
#include <boost/url/grammar/lut_chars.hpp>
17  
#include <boost/url/grammar/optional_rule.hpp>
17  
#include <boost/url/grammar/optional_rule.hpp>
18  
#include <boost/url/grammar/parse.hpp>
18  
#include <boost/url/grammar/parse.hpp>
19  
#include <boost/url/grammar/token_rule.hpp>
19  
#include <boost/url/grammar/token_rule.hpp>
20  
#include <boost/url/grammar/tuple_rule.hpp>
20  
#include <boost/url/grammar/tuple_rule.hpp>
21  
#include <boost/url/grammar/vchars.hpp>
21  
#include <boost/url/grammar/vchars.hpp>
22  

22  

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

26  

27  
auto
27  
auto
28  
replacement_field_rule_t::
28  
replacement_field_rule_t::
29  
parse(
29  
parse(
30  
    char const*& it,
30  
    char const*& it,
31  
    char const* const end) const noexcept ->
31  
    char const* const end) const noexcept ->
32  
        system::result<value_type>
32  
        system::result<value_type>
33  
{
33  
{
34  
    static constexpr auto replacement_field_rules =
34  
    static constexpr auto replacement_field_rules =
35  
        grammar::tuple_rule(
35  
        grammar::tuple_rule(
36  
            // open
36  
            // open
37  
            grammar::squelch(
37  
            grammar::squelch(
38  
                grammar::delim_rule('{')),
38  
                grammar::delim_rule('{')),
39  
            // id
39  
            // id
40  
            grammar::optional_rule(arg_id_rule),
40  
            grammar::optional_rule(arg_id_rule),
41  
            // format options
41  
            // format options
42  
            grammar::optional_rule(
42  
            grammar::optional_rule(
43  
                grammar::tuple_rule(
43  
                grammar::tuple_rule(
44  
                    grammar::squelch(
44  
                    grammar::squelch(
45  
                        grammar::delim_rule(':')),
45  
                        grammar::delim_rule(':')),
46  
                    format_spec_rule)),
46  
                    format_spec_rule)),
47  
            // close
47  
            // close
48  
            grammar::squelch(
48  
            grammar::squelch(
49  
                grammar::delim_rule('}')));
49  
                grammar::delim_rule('}')));
50  
    auto it0 = it;
50  
    auto it0 = it;
51  
    auto rv = grammar::parse(it, end, replacement_field_rules);
51  
    auto rv = grammar::parse(it, end, replacement_field_rules);
52  
    if (!rv)
52  
    if (!rv)
53  
    {
53  
    {
54  
        BOOST_URL_RETURN_EC(
54  
        BOOST_URL_RETURN_EC(
55  
            grammar::error::mismatch);
55  
            grammar::error::mismatch);
56  
    }
56  
    }
57  
    return core::string_view(it0, it);
57  
    return core::string_view(it0, it);
58  
}
58  
}
59  

59  

60  
auto
60  
auto
61  
identifier_rule_t::
61  
identifier_rule_t::
62  
parse(
62  
parse(
63  
    char const*& it,
63  
    char const*& it,
64  
    char const* const end) const noexcept
64  
    char const* const end) const noexcept
65  
        -> system::result<value_type>
65  
        -> system::result<value_type>
66  
{
66  
{
67  
    static constexpr auto identifier_rules =
67  
    static constexpr auto identifier_rules =
68  
        grammar::tuple_rule(
68  
        grammar::tuple_rule(
69  
            grammar::delim_rule(
69  
            grammar::delim_rule(
70  
                grammar::alpha_chars +
70  
                grammar::alpha_chars +
71  
                grammar::lut_chars('_')),
71  
                grammar::lut_chars('_')),
72  
            grammar::optional_rule(
72  
            grammar::optional_rule(
73  
                grammar::token_rule(
73  
                grammar::token_rule(
74  
                    grammar::alnum_chars +
74  
                    grammar::alnum_chars +
75  
                    grammar::lut_chars('_'))));
75  
                    grammar::lut_chars('_'))));
76  
    char const* it0 = it;
76  
    char const* it0 = it;
77  
    auto rv = grammar::parse(it, end, identifier_rules);
77  
    auto rv = grammar::parse(it, end, identifier_rules);
78  
    if (!rv)
78  
    if (!rv)
79  
    {
79  
    {
80  
        BOOST_URL_RETURN_EC(
80  
        BOOST_URL_RETURN_EC(
81  
            grammar::error::mismatch);
81  
            grammar::error::mismatch);
82  
    }
82  
    }
83  
    return core::string_view(it0, it);
83  
    return core::string_view(it0, it);
84  
}
84  
}
85  

85  

86  
auto
86  
auto
87  
format_spec_rule_t::
87  
format_spec_rule_t::
88  
parse(
88  
parse(
89  
    char const*& it,
89  
    char const*& it,
90  
    char const* const end) const noexcept
90  
    char const* const end) const noexcept
91  
        -> system::result<value_type>
91  
        -> system::result<value_type>
92  
{
92  
{
93  
    if (it == end)
93  
    if (it == end)
94  
        return {};
94  
        return {};
95  

95  

96  
    // any tokens allowed in fmt specs
96  
    // any tokens allowed in fmt specs
97  
    static constexpr auto fmt_specs_token_rule =
97  
    static constexpr auto fmt_specs_token_rule =
98  
        grammar::optional_rule(
98  
        grammar::optional_rule(
99  
            grammar::token_rule(
99  
            grammar::token_rule(
100  
                grammar::vchars +
100  
                grammar::vchars +
101  
                grammar::lut_chars(' ')
101  
                grammar::lut_chars(' ')
102  
                - "{}"));
102  
                - "{}"));
103  

103  

104  
    // internal ids in the fmt specs
104  
    // internal ids in the fmt specs
105  
    // "{" [arg_id] "}"
105  
    // "{" [arg_id] "}"
106  
    static constexpr auto internal_id_rule =
106  
    static constexpr auto internal_id_rule =
107  
        grammar::tuple_rule(
107  
        grammar::tuple_rule(
108  
            grammar::squelch(
108  
            grammar::squelch(
109  
                grammar::delim_rule('{')),
109  
                grammar::delim_rule('{')),
110  
            grammar::optional_rule(
110  
            grammar::optional_rule(
111  
                arg_id_rule),
111  
                arg_id_rule),
112  
            grammar::squelch(
112  
            grammar::squelch(
113  
                grammar::delim_rule('}')));
113  
                grammar::delim_rule('}')));
114  

114  

115  
    auto start = it;
115  
    auto start = it;
116  
    // consume fmt_spec chars
116  
    // consume fmt_spec chars
117  
    while (grammar::parse(it, end, fmt_specs_token_rule))
117  
    while (grammar::parse(it, end, fmt_specs_token_rule))
118  
    {
118  
    {
119  
        auto it0 = it;
119  
        auto it0 = it;
120  
        // consume internal id
120  
        // consume internal id
121  
        if (!grammar::parse(it, end, internal_id_rule))
121  
        if (!grammar::parse(it, end, internal_id_rule))
122  
        {
122  
        {
123  
            // rewind
123  
            // rewind
124  
            it = it0;
124  
            it = it0;
125  
            break;
125  
            break;
126  
        }
126  
        }
127  
    }
127  
    }
128  

128  

129  
    return core::string_view(start, it);
129  
    return core::string_view(start, it);
130  
}
130  
}
131  

131  

132  
} // detail
132  
} // detail
133  
} // urls
133  
} // urls
134  
} // boost
134  
} // boost
135  

135