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_RFC_IMPL_PCT_ENCODED_RULE_HPP
11  
#ifndef BOOST_URL_RFC_IMPL_PCT_ENCODED_RULE_HPP
12  
#define BOOST_URL_RFC_IMPL_PCT_ENCODED_RULE_HPP
12  
#define BOOST_URL_RFC_IMPL_PCT_ENCODED_RULE_HPP
13  

13  

14  
#include <boost/url/grammar/charset.hpp>
14  
#include <boost/url/grammar/charset.hpp>
15  
#include <boost/url/grammar/error.hpp>
15  
#include <boost/url/grammar/error.hpp>
16  
#include <boost/url/grammar/hexdig_chars.hpp>
16  
#include <boost/url/grammar/hexdig_chars.hpp>
17  

17  

18  
namespace boost {
18  
namespace boost {
19  
namespace urls {
19  
namespace urls {
20  

20  

21  
namespace detail {
21  
namespace detail {
22  

22  

23  
template<class CharSet>
23  
template<class CharSet>
24  
BOOST_URL_CXX20_CONSTEXPR
24  
BOOST_URL_CXX20_CONSTEXPR
25  
auto
25  
auto
26  
parse_encoded(
26  
parse_encoded(
27  
    char const*& it,
27  
    char const*& it,
28  
    char const* end,
28  
    char const* end,
29  
    CharSet const& cs) noexcept ->
29  
    CharSet const& cs) noexcept ->
30  
        system::result<pct_string_view>
30  
        system::result<pct_string_view>
31  
{
31  
{
32  
    auto const start = it;
32  
    auto const start = it;
33  
    std::size_t n = 0;
33  
    std::size_t n = 0;
34  
    for(;;)
34  
    for(;;)
35  
    {
35  
    {
36  
        auto it0 = it;
36  
        auto it0 = it;
37  
        it = grammar::find_if_not(
37  
        it = grammar::find_if_not(
38  
            it0, end, cs);
38  
            it0, end, cs);
39  
        n += it - it0;
39  
        n += it - it0;
40  
        if(it == end || *it != '%')
40  
        if(it == end || *it != '%')
41  
            break;
41  
            break;
42  
        bool at_end = false;
42  
        bool at_end = false;
43  
        for(;;)
43  
        for(;;)
44  
        {
44  
        {
45  
            ++it;
45  
            ++it;
46  
            if(it == end)
46  
            if(it == end)
47  
            {
47  
            {
48  
                // expected HEXDIG
48  
                // expected HEXDIG
49  
                BOOST_URL_CONSTEXPR_RETURN_EC(
49  
                BOOST_URL_CONSTEXPR_RETURN_EC(
50  
                    grammar::error::invalid);
50  
                    grammar::error::invalid);
51  
            }
51  
            }
52  
            auto r = grammar::hexdig_value(*it);
52  
            auto r = grammar::hexdig_value(*it);
53  
            if(r < 0)
53  
            if(r < 0)
54  
            {
54  
            {
55  
                // expected HEXDIG
55  
                // expected HEXDIG
56  
                BOOST_URL_CONSTEXPR_RETURN_EC(
56  
                BOOST_URL_CONSTEXPR_RETURN_EC(
57  
                    grammar::error::invalid);
57  
                    grammar::error::invalid);
58  
            }
58  
            }
59  
            ++it;
59  
            ++it;
60  
            if(it == end)
60  
            if(it == end)
61  
            {
61  
            {
62  
                // expected HEXDIG
62  
                // expected HEXDIG
63  
                BOOST_URL_CONSTEXPR_RETURN_EC(
63  
                BOOST_URL_CONSTEXPR_RETURN_EC(
64  
                    grammar::error::invalid);
64  
                    grammar::error::invalid);
65  
            }
65  
            }
66  
            r = grammar::hexdig_value(*it);
66  
            r = grammar::hexdig_value(*it);
67  
            if(r < 0)
67  
            if(r < 0)
68  
            {
68  
            {
69  
                // expected HEXDIG
69  
                // expected HEXDIG
70  
                BOOST_URL_CONSTEXPR_RETURN_EC(
70  
                BOOST_URL_CONSTEXPR_RETURN_EC(
71  
                    grammar::error::invalid);
71  
                    grammar::error::invalid);
72  
            }
72  
            }
73  
            ++n;
73  
            ++n;
74  
            ++it;
74  
            ++it;
75  
            if(it == end)
75  
            if(it == end)
76  
            {
76  
            {
77  
                at_end = true;
77  
                at_end = true;
78  
                break;
78  
                break;
79  
            }
79  
            }
80  
            if(*it != '%')
80  
            if(*it != '%')
81  
                break;
81  
                break;
82  
        }
82  
        }
83  
        if(at_end)
83  
        if(at_end)
84  
            break;
84  
            break;
85  
    }
85  
    }
86  
    return make_pct_string_view_unsafe(
86  
    return make_pct_string_view_unsafe(
87  
        start, it - start, n);
87  
        start, it - start, n);
88  
}
88  
}
89  

89  

90  
} // detail
90  
} // detail
91  

91  

92  
//------------------------------------------------
92  
//------------------------------------------------
93  

93  

94  
template<class CharSet>
94  
template<class CharSet>
95  
BOOST_URL_CXX20_CONSTEXPR
95  
BOOST_URL_CXX20_CONSTEXPR
96  
auto
96  
auto
97  
implementation_defined::pct_encoded_rule_t<CharSet>::
97  
implementation_defined::pct_encoded_rule_t<CharSet>::
98  
parse(
98  
parse(
99  
    char const*& it,
99  
    char const*& it,
100  
    char const* end) const noexcept ->
100  
    char const* end) const noexcept ->
101  
        system::result<value_type>
101  
        system::result<value_type>
102  
{
102  
{
103  
    return detail::parse_encoded(
103  
    return detail::parse_encoded(
104  
        it, end, cs_);
104  
        it, end, cs_);
105  
}
105  
}
106  

106  

107  
} // urls
107  
} // urls
108  
} // boost
108  
} // boost
109  

109  

110  
#endif
110  
#endif