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  
#ifndef BOOST_URL_DETAIL_URL_IMPL_HPP
10  
#ifndef BOOST_URL_DETAIL_URL_IMPL_HPP
11  
#define BOOST_URL_DETAIL_URL_IMPL_HPP
11  
#define BOOST_URL_DETAIL_URL_IMPL_HPP
12  

12  

13  
#include <boost/url/host_type.hpp>
13  
#include <boost/url/host_type.hpp>
14  
#include <boost/url/pct_string_view.hpp>
14  
#include <boost/url/pct_string_view.hpp>
15  
#include <boost/url/scheme.hpp>
15  
#include <boost/url/scheme.hpp>
16  
#include <boost/core/detail/string_view.hpp>
16  
#include <boost/core/detail/string_view.hpp>
17  
#include <boost/url/detail/parts_base.hpp>
17  
#include <boost/url/detail/parts_base.hpp>
18  
#include <boost/assert.hpp>
18  
#include <boost/assert.hpp>
 
19 +
#include <cstddef>
19  
#include <cstdint>
20  
#include <cstdint>
20  

21  

21  
namespace boost {
22  
namespace boost {
22  
namespace urls {
23  
namespace urls {
23  

24  

24  
class url_view;
25  
class url_view;
25  
class authority_view;
26  
class authority_view;
26  

27  

27  
namespace detail {
28  
namespace detail {
28  

29  

29  
constexpr char const* const empty_c_str_ = "";
30  
constexpr char const* const empty_c_str_ = "";
30  

31  

31  
// This is the private 'guts' of a
32  
// This is the private 'guts' of a
32  
// url_view, exposed so different parts
33  
// url_view, exposed so different parts
33  
// of the implementation can work on it.
34  
// of the implementation can work on it.
34  
// It stores the offsets and properties of
35  
// It stores the offsets and properties of
35  
// a URL string stored elsewhere and pointed
36  
// a URL string stored elsewhere and pointed
36  
// to by cs_.
37  
// to by cs_.
37  
struct BOOST_URL_DECL url_impl : parts_base
38  
struct BOOST_URL_DECL url_impl : parts_base
38  
{
39  
{
 
40 +
    using size_type = std::uint32_t;
 
41 +

 
42 +
    static_assert(
 
43 +
        BOOST_URL_MAX_SIZE <= UINT32_MAX,
 
44 +
        "BOOST_URL_MAX_SIZE exceeds 32-bit url_impl capacity");
 
45 +

39  
    static
46  
    static
40  
    constexpr
47  
    constexpr
41  
    std::size_t const zero_ = 0;
48  
    std::size_t const zero_ = 0;
42  

49  

43  
    // never nullptr
50  
    // never nullptr
44  
    char const* cs_ = empty_c_str_;
51  
    char const* cs_ = empty_c_str_;
45  

52  

46 -
    std::size_t offset_[id_end + 1] = {};
53 +
    size_type offset_[id_end + 1] = {};
47 -
    std::size_t decoded_[id_end] = {};
54 +
    size_type decoded_[id_end] = {};
48 -
    std::size_t nseg_ = 0;
55 +
    size_type nseg_ = 0;
49 -
    std::size_t nparam_ = 0;
56 +
    size_type nparam_ = 0;
50  
    unsigned char ip_addr_[16] = {};
57  
    unsigned char ip_addr_[16] = {};
51  
    // VFALCO don't we need a bool?
58  
    // VFALCO don't we need a bool?
52  
    std::uint16_t port_number_ = 0;
59  
    std::uint16_t port_number_ = 0;
53  
    host_type host_type_ =
60  
    host_type host_type_ =
54  
        urls::host_type::none;
61  
        urls::host_type::none;
55  
    scheme scheme_ =
62  
    scheme scheme_ =
56  
        urls::scheme::none;
63  
        urls::scheme::none;
57  

64  

58  
    from from_ = from::string;
65  
    from from_ = from::string;
59  

66  

60  
    url_impl(
67  
    url_impl(
61  
        from b) noexcept
68  
        from b) noexcept
62  
        : from_(b)
69  
        : from_(b)
63  
    {
70  
    {
64  
    }
71  
    }
65  

72  

66  
    // in url_view.ipp
73  
    // in url_view.ipp
67  
    url_view construct() const noexcept;
74  
    url_view construct() const noexcept;
68  

75  

69  
    // in authority_view.ipp
76  
    // in authority_view.ipp
70  
    authority_view
77  
    authority_view
71  
    construct_authority() const noexcept;
78  
    construct_authority() const noexcept;
72  

79  

73  
    std::size_t len(int, int) const noexcept;
80  
    std::size_t len(int, int) const noexcept;
74  
    std::size_t len(int) const noexcept;
81  
    std::size_t len(int) const noexcept;
75  
    std::size_t offset(int) const noexcept;
82  
    std::size_t offset(int) const noexcept;
76  
    core::string_view get(int) const noexcept;
83  
    core::string_view get(int) const noexcept;
77  
    core::string_view get(int, int) const noexcept;
84  
    core::string_view get(int, int) const noexcept;
78  
    pct_string_view pct_get(int) const noexcept;
85  
    pct_string_view pct_get(int) const noexcept;
79  
    pct_string_view pct_get(int, int) const noexcept;
86  
    pct_string_view pct_get(int, int) const noexcept;
80  
    void set_size(int, std::size_t) noexcept;
87  
    void set_size(int, std::size_t) noexcept;
81  
    void split(int, std::size_t) noexcept;
88  
    void split(int, std::size_t) noexcept;
82  
    void adjust_right(int first, int last, std::size_t n) noexcept;
89  
    void adjust_right(int first, int last, std::size_t n) noexcept;
83  
    void adjust_left(int first, int last, std::size_t n) noexcept;
90  
    void adjust_left(int first, int last, std::size_t n) noexcept;
84  
    void collapse(int, int, std::size_t) noexcept;
91  
    void collapse(int, int, std::size_t) noexcept;
85  

92  

86  
    void apply_scheme(core::string_view) noexcept;
93  
    void apply_scheme(core::string_view) noexcept;
87  
    void apply_userinfo(pct_string_view const&,
94  
    void apply_userinfo(pct_string_view const&,
88  
        pct_string_view const*) noexcept;
95  
        pct_string_view const*) noexcept;
89  
    void apply_host(host_type, pct_string_view,
96  
    void apply_host(host_type, pct_string_view,
90  
        unsigned char const*) noexcept;
97  
        unsigned char const*) noexcept;
91  
    void apply_port(core::string_view, unsigned short) noexcept;
98  
    void apply_port(core::string_view, unsigned short) noexcept;
92  
    void apply_authority(authority_view const&) noexcept;
99  
    void apply_authority(authority_view const&) noexcept;
93  
    void apply_path(pct_string_view, std::size_t) noexcept;
100  
    void apply_path(pct_string_view, std::size_t) noexcept;
94  
    void apply_query(pct_string_view, std::size_t) noexcept;
101  
    void apply_query(pct_string_view, std::size_t) noexcept;
95  
    void apply_frag(pct_string_view) noexcept;
102  
    void apply_frag(pct_string_view) noexcept;
96  
};
103  
};
 
104 +

 
105 +
// url_impl stores 32-bit sizes; centralize narrowing with checks.
 
106 +
inline
 
107 +
url_impl::size_type
 
108 +
to_size_type(std::size_t n) noexcept
 
109 +
{
 
110 +
    BOOST_ASSERT(n <= BOOST_URL_MAX_SIZE);
 
111 +
    BOOST_ASSERT(n <= UINT32_MAX);
 
112 +
    return static_cast<url_impl::size_type>(n);
 
113 +
}
 
114 +

 
115 +
inline
 
116 +
url_impl::size_type
 
117 +
to_size_type(std::ptrdiff_t n) noexcept
 
118 +
{
 
119 +
    BOOST_ASSERT(n >= 0);
 
120 +
    return to_size_type(
 
121 +
        static_cast<std::size_t>(n));
 
122 +
}
97  

123  

98  
//------------------------------------------------
124  
//------------------------------------------------
99  

125  

100  
// this allows a path to come from a
126  
// this allows a path to come from a
101  
// url_impl or a separate core::string_view
127  
// url_impl or a separate core::string_view
102  
class path_ref
128  
class path_ref
103  
    : private parts_base
129  
    : private parts_base
104  
{
130  
{
105  
    url_impl const* impl_ = nullptr;
131  
    url_impl const* impl_ = nullptr;
106  
    char const* data_ = nullptr;
132  
    char const* data_ = nullptr;
107  
    std::size_t size_ = 0;
133  
    std::size_t size_ = 0;
108  
    std::size_t nseg_ = 0;
134  
    std::size_t nseg_ = 0;
109  
    std::size_t dn_ = 0;
135  
    std::size_t dn_ = 0;
110  

136  

111  
public:
137  
public:
112  
    path_ref() = default;
138  
    path_ref() = default;
113  
    path_ref(url_impl const& impl) noexcept;
139  
    path_ref(url_impl const& impl) noexcept;
114  
    path_ref(core::string_view,
140  
    path_ref(core::string_view,
115  
        std::size_t, std::size_t) noexcept;
141  
        std::size_t, std::size_t) noexcept;
116  
    pct_string_view buffer() const noexcept;
142  
    pct_string_view buffer() const noexcept;
117  
    std::size_t size() const noexcept;
143  
    std::size_t size() const noexcept;
118  
    char const* data() const noexcept;
144  
    char const* data() const noexcept;
119  
    char const* end() const noexcept;
145  
    char const* end() const noexcept;
120  
    std::size_t nseg() const noexcept;
146  
    std::size_t nseg() const noexcept;
121  
    std::size_t decoded_size() const noexcept;
147  
    std::size_t decoded_size() const noexcept;
122  

148  

123  
    bool
149  
    bool
124  
    alias_of(
150  
    alias_of(
125  
        url_impl const& impl) const noexcept
151  
        url_impl const& impl) const noexcept
126  
    {
152  
    {
127  
        return impl_ == &impl;
153  
        return impl_ == &impl;
128  
    }
154  
    }
129  

155  

130  
    bool
156  
    bool
131  
    alias_of(
157  
    alias_of(
132  
        path_ref const& ref) const noexcept
158  
        path_ref const& ref) const noexcept
133  
    {
159  
    {
134  
        if(impl_)
160  
        if(impl_)
135  
            return impl_ == ref.impl_;
161  
            return impl_ == ref.impl_;
136  
        BOOST_ASSERT(data_ != ref.data_ || (
162  
        BOOST_ASSERT(data_ != ref.data_ || (
137  
            size_ == ref.size_ &&
163  
            size_ == ref.size_ &&
138  
            nseg_ == ref.nseg_ &&
164  
            nseg_ == ref.nseg_ &&
139  
            dn_ == ref.dn_));
165  
            dn_ == ref.dn_));
140  
        return data_ == ref.data_;
166  
        return data_ == ref.data_;
141  
    }
167  
    }
142  
};
168  
};
143  

169  

144  
//------------------------------------------------
170  
//------------------------------------------------
145  

171  

146  
// This class represents a query string, which
172  
// This class represents a query string, which
147  
// can originate from either an url_impl object
173  
// can originate from either an url_impl object
148  
// or an independent core::string_view.
174  
// or an independent core::string_view.
149  
class BOOST_URL_DECL query_ref
175  
class BOOST_URL_DECL query_ref
150  
    : private parts_base
176  
    : private parts_base
151  
{
177  
{
152  
    url_impl const* impl_ = nullptr;
178  
    url_impl const* impl_ = nullptr;
153  
    char const* data_ = nullptr;
179  
    char const* data_ = nullptr;
154  
    std::size_t size_ = 0;
180  
    std::size_t size_ = 0;
155  
    std::size_t nparam_ = 0;
181  
    std::size_t nparam_ = 0;
156  
    std::size_t dn_ = 0;
182  
    std::size_t dn_ = 0;
157  
    bool question_mark_ = false;
183  
    bool question_mark_ = false;
158  

184  

159  
public:
185  
public:
160  
    query_ref(
186  
    query_ref(
161  
        core::string_view s,      // buffer, no '?'
187  
        core::string_view s,      // buffer, no '?'
162  
        std::size_t dn,     // decoded size
188  
        std::size_t dn,     // decoded size
163  
        std::size_t nparam
189  
        std::size_t nparam
164  
            ) noexcept;
190  
            ) noexcept;
165  
    query_ref() = default;
191  
    query_ref() = default;
166  
    query_ref(url_impl const& impl) noexcept;
192  
    query_ref(url_impl const& impl) noexcept;
167  
    pct_string_view buffer() const noexcept;
193  
    pct_string_view buffer() const noexcept;
168  
    std::size_t size() const noexcept; // with '?'
194  
    std::size_t size() const noexcept; // with '?'
169  
    char const* begin() const noexcept; // no '?'
195  
    char const* begin() const noexcept; // no '?'
170  
    char const* end() const noexcept;
196  
    char const* end() const noexcept;
171  
    std::size_t nparam() const noexcept;
197  
    std::size_t nparam() const noexcept;
172  

198  

173  
    bool
199  
    bool
174  
    alias_of(
200  
    alias_of(
175  
        url_impl const& impl) const noexcept
201  
        url_impl const& impl) const noexcept
176  
    {
202  
    {
177  
        return impl_ == &impl;
203  
        return impl_ == &impl;
178  
    }
204  
    }
179  

205  

180  
    bool
206  
    bool
181  
    alias_of(
207  
    alias_of(
182  
        query_ref const& ref) const noexcept
208  
        query_ref const& ref) const noexcept
183  
    {
209  
    {
184  
        if(impl_)
210  
        if(impl_)
185  
            return impl_ == ref.impl_;
211  
            return impl_ == ref.impl_;
186  
        BOOST_ASSERT(data_ != ref.data_ || (
212  
        BOOST_ASSERT(data_ != ref.data_ || (
187  
            size_ == ref.size_ &&
213  
            size_ == ref.size_ &&
188  
            nparam_ == ref.nparam_ &&
214  
            nparam_ == ref.nparam_ &&
189  
            dn_ == ref.dn_));
215  
            dn_ == ref.dn_));
190  
        return data_ == ref.data_;
216  
        return data_ == ref.data_;
191  
    }
217  
    }
192  
};
218  
};
193  

219  

194  
} // detail
220  
} // detail
195  

221  

196  
} // urls
222  
} // urls
197  
} // boost
223  
} // boost
198  

224  

199  
#endif
225  
#endif