1  
//
1  
//
2  
// Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com)
2  
// Copyright (c) 2025 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  
#ifndef BOOST_URL_IMPL_DECODE_HPP
10  
#ifndef BOOST_URL_IMPL_DECODE_HPP
11  
#define BOOST_URL_IMPL_DECODE_HPP
11  
#define BOOST_URL_IMPL_DECODE_HPP
12  

12  

13  
#include <boost/assert.hpp>
13  
#include <boost/assert.hpp>
14  
#include <boost/url/detail/decode.hpp>
14  
#include <boost/url/detail/decode.hpp>
15  
#include <boost/url/detail/string_view.hpp>
15  
#include <boost/url/detail/string_view.hpp>
16  
#include <boost/url/pct_string_view.hpp>
16  
#include <boost/url/pct_string_view.hpp>
17  
#include <utility>
17  
#include <utility>
18  

18  

19  
namespace boost {
19  
namespace boost {
20  
namespace urls {
20  
namespace urls {
21  

21  

22  
inline
22  
inline
23  
system::result<std::size_t>
23  
system::result<std::size_t>
24  
decoded_size(core::string_view s) noexcept
24  
decoded_size(core::string_view s) noexcept
25  
{
25  
{
26  
    auto const rv = make_pct_string_view(s);
26  
    auto const rv = make_pct_string_view(s);
27  
    if(! rv)
27  
    if(! rv)
28  
        return rv.error();
28  
        return rv.error();
29  
    return rv->decoded_size();
29  
    return rv->decoded_size();
30  
}
30  
}
31  

31  

32  
inline
32  
inline
33  
system::result<std::size_t>
33  
system::result<std::size_t>
34  
decode(
34  
decode(
35  
    char* dest,
35  
    char* dest,
36  
    std::size_t size,
36  
    std::size_t size,
37  
    core::string_view s,
37  
    core::string_view s,
38  
    encoding_opts opt) noexcept
38  
    encoding_opts opt) noexcept
39  
{
39  
{
40  
    auto const rv = make_pct_string_view(s);
40  
    auto const rv = make_pct_string_view(s);
41  
    if(! rv)
41  
    if(! rv)
42  
        return rv.error();
42  
        return rv.error();
43  
    return detail::decode_unsafe(
43  
    return detail::decode_unsafe(
44  
        dest,
44  
        dest,
45  
        dest + size,
45  
        dest + size,
46  
        detail::to_sv(rv.value()),
46  
        detail::to_sv(rv.value()),
47  
        opt);
47  
        opt);
48  
}
48  
}
49  

49  

50  
template<
50  
template<
51  
    BOOST_URL_CONSTRAINT(string_token::StringToken) StringToken>
51  
    BOOST_URL_CONSTRAINT(string_token::StringToken) StringToken>
52  
system::result<typename StringToken::result_type>
52  
system::result<typename StringToken::result_type>
53  
decode(
53  
decode(
54  
    core::string_view s,
54  
    core::string_view s,
55  
    encoding_opts opt,
55  
    encoding_opts opt,
56  
    StringToken&& token) noexcept
56  
    StringToken&& token) noexcept
57  
{
57  
{
58  
    static_assert(
58  
    static_assert(
59  
        string_token::is_token<
59  
        string_token::is_token<
60  
            StringToken>::value,
60  
            StringToken>::value,
61  
        "Type requirements not met");
61  
        "Type requirements not met");
62  

62  

63  
    auto const rv = make_pct_string_view(s);
63  
    auto const rv = make_pct_string_view(s);
64  
    if(! rv)
64  
    if(! rv)
65  
        return rv.error();
65  
        return rv.error();
66  

66  

67  
    auto const n = rv->decoded_size();
67  
    auto const n = rv->decoded_size();
68  
    auto p = token.prepare(n);
68  
    auto p = token.prepare(n);
69  
    // Some tokens might hand back a null/invalid buffer for n == 0, so skip the
69  
    // Some tokens might hand back a null/invalid buffer for n == 0, so skip the
70  
    // decode call entirely in that case to avoid touching unspecified memory.
70  
    // decode call entirely in that case to avoid touching unspecified memory.
71  
    if(n > 0)
71  
    if(n > 0)
72  
        detail::decode_unsafe(
72  
        detail::decode_unsafe(
73  
            p,
73  
            p,
74  
            p + n,
74  
            p + n,
75  
            detail::to_sv(rv.value()),
75  
            detail::to_sv(rv.value()),
76  
            opt);
76  
            opt);
77  
    return token.result();
77  
    return token.result();
78  
}
78  
}
79  

79  

80  
} // urls
80  
} // urls
81  
} // boost
81  
} // boost
82  

82  

83  
#endif
83  
#endif