1  
//
1  
//
2  
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@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/error.hpp>
12  
#include <boost/url/error.hpp>
13  
#include <boost/url/pct_string_view.hpp>
13  
#include <boost/url/pct_string_view.hpp>
14  
#include <boost/url/detail/decode.hpp>
14  
#include <boost/url/detail/decode.hpp>
15  
#include <boost/url/grammar/hexdig_chars.hpp>
15  
#include <boost/url/grammar/hexdig_chars.hpp>
16  
#include <boost/url/detail/except.hpp>
16  
#include <boost/url/detail/except.hpp>
17  

17  

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

20  

21  
void
21  
void
22  
pct_string_view::
22  
pct_string_view::
23  
decode_impl(
23  
decode_impl(
24  
    string_token::arg& dest,
24  
    string_token::arg& dest,
25  
    encoding_opts opt) const
25  
    encoding_opts opt) const
26  
{
26  
{
27  
    auto p = dest.prepare(dn_);
27  
    auto p = dest.prepare(dn_);
28  
    if(dn_ > 0)
28  
    if(dn_ > 0)
29  
        detail::decode_unsafe(
29  
        detail::decode_unsafe(
30  
            p, p + dn_, s_, opt);
30  
            p, p + dn_, s_, opt);
31  
}
31  
}
32  

32  

33  
//------------------------------------------------
33  
//------------------------------------------------
34  

34  

35  
pct_string_view::
35  
pct_string_view::
36  
pct_string_view(
36  
pct_string_view(
37  
    core::string_view s)
37  
    core::string_view s)
38  
    : pct_string_view(
38  
    : pct_string_view(
39  
        make_pct_string_view(s
39  
        make_pct_string_view(s
40  
            ).value(BOOST_URL_POS))
40  
            ).value(BOOST_URL_POS))
41  
{
41  
{
42  
}
42  
}
43  

43  

44  
//------------------------------------------------
44  
//------------------------------------------------
45  

45  

46  
system::result<pct_string_view>
46  
system::result<pct_string_view>
47  
make_pct_string_view(
47  
make_pct_string_view(
48  
    core::string_view s) noexcept
48  
    core::string_view s) noexcept
49  
{
49  
{
50  
    auto p = s.begin();
50  
    auto p = s.begin();
51  
    auto const end = s.end();
51  
    auto const end = s.end();
52  
    std::size_t dn = 0;
52  
    std::size_t dn = 0;
53  
    if(s.size() >= 3)
53  
    if(s.size() >= 3)
54  
    {
54  
    {
55  
        auto const safe_end = end - 2;
55  
        auto const safe_end = end - 2;
56  
        while(p < safe_end)
56  
        while(p < safe_end)
57  
        {
57  
        {
58  
            if(*p != '%')
58  
            if(*p != '%')
59  
            {
59  
            {
60  
                ++p;
60  
                ++p;
61  
            }
61  
            }
62  
            else if(
62  
            else if(
63  
                grammar::hexdig_value(p[1]) >= 0 &&
63  
                grammar::hexdig_value(p[1]) >= 0 &&
64  
                grammar::hexdig_value(p[2]) >= 0)
64  
                grammar::hexdig_value(p[2]) >= 0)
65  
            {
65  
            {
66  
                // percent-escape
66  
                // percent-escape
67  
                p += 3;
67  
                p += 3;
68  
            }
68  
            }
69  
            else
69  
            else
70  
            {
70  
            {
71  
                // invalid encoding
71  
                // invalid encoding
72  
                BOOST_URL_RETURN_EC(
72  
                BOOST_URL_RETURN_EC(
73  
                    error::bad_pct_hexdig);
73  
                    error::bad_pct_hexdig);
74  
            }
74  
            }
75  
            ++dn;
75  
            ++dn;
76  
        }
76  
        }
77  
    }
77  
    }
78  
    auto const n = end - p;
78  
    auto const n = end - p;
79  
    if( (n >= 1 && p[0] == '%') ||
79  
    if( (n >= 1 && p[0] == '%') ||
80  
        (n >= 2 && p[1] == '%'))
80  
        (n >= 2 && p[1] == '%'))
81  
    {
81  
    {
82  
        // invalid encoding
82  
        // invalid encoding
83  
        BOOST_URL_RETURN_EC(
83  
        BOOST_URL_RETURN_EC(
84  
            error::incomplete_encoding);
84  
            error::incomplete_encoding);
85  
    }
85  
    }
86  
    dn += n;
86  
    dn += n;
87  
    return make_pct_string_view_unsafe(
87  
    return make_pct_string_view_unsafe(
88  
        s.data(), s.size(), dn);
88  
        s.data(), s.size(), dn);
89  
}
89  
}
90  

90  

91  
} // urls
91  
} // urls
92  
} // boost
92  
} // boost
93  

93