1  
//
1  
//
2  
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.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_DETAIL_URL_IMPL_HPP
11  
#ifndef BOOST_URL_DETAIL_URL_IMPL_HPP
12  
#define BOOST_URL_DETAIL_URL_IMPL_HPP
12  
#define BOOST_URL_DETAIL_URL_IMPL_HPP
13  

13  

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

22  

23  
namespace boost {
23  
namespace boost {
24  
namespace urls {
24  
namespace urls {
25  

25  

26  
class url_view;
26  
class url_view;
27  
class authority_view;
27  
class authority_view;
28  

28  

29  
namespace detail {
29  
namespace detail {
30  

30  

31  
constexpr char const* const empty_c_str_ = "";
31  
constexpr char const* const empty_c_str_ = "";
32  

32  

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

42  

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

46  

47  
    static
47  
    static
48  
    constexpr
48  
    constexpr
49  
    std::size_t const zero_ = 0;
49  
    std::size_t const zero_ = 0;
50  

50  

51  
    // never nullptr
51  
    // never nullptr
52  
    char const* cs_ = empty_c_str_;
52  
    char const* cs_ = empty_c_str_;
53  

53  

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

65  

66  
    from from_ = from::string;
66  
    from from_ = from::string;
67  

67  

68  
    BOOST_URL_CXX14_CONSTEXPR
68  
    BOOST_URL_CXX14_CONSTEXPR
69  
    url_impl(
69  
    url_impl(
70  
        from b) noexcept
70  
        from b) noexcept
71  
        : from_(b)
71  
        : from_(b)
72  
    {
72  
    {
73  
    }
73  
    }
74  

74  

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

87  

88  
    BOOST_URL_CXX20_CONSTEXPR void apply_scheme(core::string_view) noexcept;
88  
    BOOST_URL_CXX20_CONSTEXPR void apply_scheme(core::string_view) noexcept;
89  
    BOOST_URL_CXX20_CONSTEXPR void apply_userinfo(pct_string_view const&,
89  
    BOOST_URL_CXX20_CONSTEXPR void apply_userinfo(pct_string_view const&,
90  
        pct_string_view const*) noexcept;
90  
        pct_string_view const*) noexcept;
91  
    BOOST_URL_CXX20_CONSTEXPR void apply_host(host_type, pct_string_view,
91  
    BOOST_URL_CXX20_CONSTEXPR void apply_host(host_type, pct_string_view,
92  
        unsigned char const*) noexcept;
92  
        unsigned char const*) noexcept;
93  
    BOOST_URL_CXX20_CONSTEXPR void apply_port(core::string_view, unsigned short) noexcept;
93  
    BOOST_URL_CXX20_CONSTEXPR void apply_port(core::string_view, unsigned short) noexcept;
94  
    BOOST_URL_CXX20_CONSTEXPR void apply_authority(url_impl const&) noexcept;
94  
    BOOST_URL_CXX20_CONSTEXPR void apply_authority(url_impl const&) noexcept;
95  
    BOOST_URL_CXX20_CONSTEXPR void apply_path(pct_string_view, std::size_t) noexcept;
95  
    BOOST_URL_CXX20_CONSTEXPR void apply_path(pct_string_view, std::size_t) noexcept;
96  
    BOOST_URL_CXX20_CONSTEXPR void apply_query(pct_string_view, std::size_t) noexcept;
96  
    BOOST_URL_CXX20_CONSTEXPR void apply_query(pct_string_view, std::size_t) noexcept;
97  
    BOOST_URL_CXX20_CONSTEXPR void apply_frag(pct_string_view) noexcept;
97  
    BOOST_URL_CXX20_CONSTEXPR void apply_frag(pct_string_view) noexcept;
98  
};
98  
};
99  

99  

100  
// url_impl stores 32-bit sizes; centralize narrowing with checks.
100  
// url_impl stores 32-bit sizes; centralize narrowing with checks.
101  
BOOST_URL_CXX14_CONSTEXPR_OR_INLINE
101  
BOOST_URL_CXX14_CONSTEXPR_OR_INLINE
102  
url_impl::size_type
102  
url_impl::size_type
103  
to_size_type(std::size_t n) noexcept
103  
to_size_type(std::size_t n) noexcept
104  
{
104  
{
105  
    BOOST_ASSERT(n <= BOOST_URL_MAX_SIZE);
105  
    BOOST_ASSERT(n <= BOOST_URL_MAX_SIZE);
106  
    BOOST_ASSERT(n <= UINT32_MAX);
106  
    BOOST_ASSERT(n <= UINT32_MAX);
107  
    return static_cast<url_impl::size_type>(n);
107  
    return static_cast<url_impl::size_type>(n);
108  
}
108  
}
109  

109  

110  
BOOST_URL_CXX14_CONSTEXPR_OR_INLINE
110  
BOOST_URL_CXX14_CONSTEXPR_OR_INLINE
111  
url_impl::size_type
111  
url_impl::size_type
112  
to_size_type(std::ptrdiff_t n) noexcept
112  
to_size_type(std::ptrdiff_t n) noexcept
113  
{
113  
{
114  
    BOOST_ASSERT(n >= 0);
114  
    BOOST_ASSERT(n >= 0);
115  
    return to_size_type(
115  
    return to_size_type(
116  
        static_cast<std::size_t>(n));
116  
        static_cast<std::size_t>(n));
117  
}
117  
}
118  

118  

119  
//------------------------------------------------
119  
//------------------------------------------------
120  

120  

121  
// this allows a path to come from a
121  
// this allows a path to come from a
122  
// url_impl or a separate core::string_view
122  
// url_impl or a separate core::string_view
123  
//
123  
//
124  
// Header-only and BOOST_SYMBOL_VISIBLE since all
124  
// Header-only and BOOST_SYMBOL_VISIBLE since all
125  
// members are inline. Containing classes must also be
125  
// members are inline. Containing classes must also be
126  
// BOOST_SYMBOL_VISIBLE to avoid C4251 on MSVC.
126  
// BOOST_SYMBOL_VISIBLE to avoid C4251 on MSVC.
127  
class BOOST_SYMBOL_VISIBLE path_ref
127  
class BOOST_SYMBOL_VISIBLE path_ref
128  
    : private parts_base
128  
    : private parts_base
129  
{
129  
{
130  
    url_impl const* impl_ = nullptr;
130  
    url_impl const* impl_ = nullptr;
131  
    char const* data_ = nullptr;
131  
    char const* data_ = nullptr;
132  
    std::size_t size_ = 0;
132  
    std::size_t size_ = 0;
133  
    std::size_t nseg_ = 0;
133  
    std::size_t nseg_ = 0;
134  
    std::size_t dn_ = 0;
134  
    std::size_t dn_ = 0;
135  

135  

136  
public:
136  
public:
137  
    path_ref() noexcept = default;
137  
    path_ref() noexcept = default;
138  
    path_ref(url_impl const& impl) noexcept;
138  
    path_ref(url_impl const& impl) noexcept;
139  
    path_ref(core::string_view,
139  
    path_ref(core::string_view,
140  
        std::size_t, std::size_t) noexcept;
140  
        std::size_t, std::size_t) noexcept;
141  
    pct_string_view buffer() const noexcept;
141  
    pct_string_view buffer() const noexcept;
142  
    std::size_t size() const noexcept;
142  
    std::size_t size() const noexcept;
143  
    char const* data() const noexcept;
143  
    char const* data() const noexcept;
144  
    char const* end() const noexcept;
144  
    char const* end() const noexcept;
145  
    std::size_t nseg() const noexcept;
145  
    std::size_t nseg() const noexcept;
146  
    std::size_t decoded_size() const noexcept;
146  
    std::size_t decoded_size() const noexcept;
147  

147  

148  
    bool
148  
    bool
149  
    alias_of(
149  
    alias_of(
150  
        url_impl const& impl) const noexcept
150  
        url_impl const& impl) const noexcept
151  
    {
151  
    {
152  
        return impl_ == &impl;
152  
        return impl_ == &impl;
153  
    }
153  
    }
154  

154  

155  
    bool
155  
    bool
156  
    alias_of(
156  
    alias_of(
157  
        path_ref const& ref) const noexcept
157  
        path_ref const& ref) const noexcept
158  
    {
158  
    {
159  
        if(impl_)
159  
        if(impl_)
160  
            return impl_ == ref.impl_;
160  
            return impl_ == ref.impl_;
161  
        BOOST_ASSERT(data_ != ref.data_ || (
161  
        BOOST_ASSERT(data_ != ref.data_ || (
162  
            size_ == ref.size_ &&
162  
            size_ == ref.size_ &&
163  
            nseg_ == ref.nseg_ &&
163  
            nseg_ == ref.nseg_ &&
164  
            dn_ == ref.dn_));
164  
            dn_ == ref.dn_));
165  
        return data_ == ref.data_;
165  
        return data_ == ref.data_;
166  
    }
166  
    }
167  
};
167  
};
168  

168  

169  
//------------------------------------------------
169  
//------------------------------------------------
170  

170  

171  
// This class represents a query string, which
171  
// This class represents a query string, which
172  
// can originate from either an url_impl object
172  
// can originate from either an url_impl object
173  
// or an independent core::string_view.
173  
// or an independent core::string_view.
174  
class BOOST_SYMBOL_VISIBLE query_ref
174  
class BOOST_SYMBOL_VISIBLE query_ref
175  
    : private parts_base
175  
    : private parts_base
176  
{
176  
{
177  
    url_impl const* impl_ = nullptr;
177  
    url_impl const* impl_ = nullptr;
178  
    char const* data_ = nullptr;
178  
    char const* data_ = nullptr;
179  
    std::size_t size_ = 0;
179  
    std::size_t size_ = 0;
180  
    std::size_t nparam_ = 0;
180  
    std::size_t nparam_ = 0;
181  
    std::size_t dn_ = 0;
181  
    std::size_t dn_ = 0;
182  
    bool question_mark_ = false;
182  
    bool question_mark_ = false;
183  

183  

184  
public:
184  
public:
185  
    query_ref(
185  
    query_ref(
186  
        core::string_view s,      // buffer, no '?'
186  
        core::string_view s,      // buffer, no '?'
187  
        std::size_t dn,     // decoded size
187  
        std::size_t dn,     // decoded size
188  
        std::size_t nparam
188  
        std::size_t nparam
189  
            ) noexcept;
189  
            ) noexcept;
190  
    query_ref() = default;
190  
    query_ref() = default;
191  
    query_ref(url_impl const& impl) noexcept;
191  
    query_ref(url_impl const& impl) noexcept;
192  
    pct_string_view buffer() const noexcept;
192  
    pct_string_view buffer() const noexcept;
193  
    std::size_t size() const noexcept; // with '?'
193  
    std::size_t size() const noexcept; // with '?'
194  
    char const* begin() const noexcept; // no '?'
194  
    char const* begin() const noexcept; // no '?'
195  
    char const* end() const noexcept;
195  
    char const* end() const noexcept;
196  
    std::size_t nparam() const noexcept;
196  
    std::size_t nparam() const noexcept;
197  

197  

198  
    bool
198  
    bool
199  
    alias_of(
199  
    alias_of(
200  
        url_impl const& impl) const noexcept
200  
        url_impl const& impl) const noexcept
201  
    {
201  
    {
202  
        return impl_ == &impl;
202  
        return impl_ == &impl;
203  
    }
203  
    }
204  

204  

205  
    bool
205  
    bool
206  
    alias_of(
206  
    alias_of(
207  
        query_ref const& ref) const noexcept
207  
        query_ref const& ref) const noexcept
208  
    {
208  
    {
209  
        if(impl_)
209  
        if(impl_)
210  
            return impl_ == ref.impl_;
210  
            return impl_ == ref.impl_;
211  
        BOOST_ASSERT(data_ != ref.data_ || (
211  
        BOOST_ASSERT(data_ != ref.data_ || (
212  
            size_ == ref.size_ &&
212  
            size_ == ref.size_ &&
213  
            nparam_ == ref.nparam_ &&
213  
            nparam_ == ref.nparam_ &&
214  
            dn_ == ref.dn_));
214  
            dn_ == ref.dn_));
215  
        return data_ == ref.data_;
215  
        return data_ == ref.data_;
216  
    }
216  
    }
217  
};
217  
};
218  

218  

219  
} // detail
219  
} // detail
220  

220  

221  
} // urls
221  
} // urls
222  
} // boost
222  
} // boost
223  

223  

224  
#include <boost/url/detail/impl/url_impl.hpp>
224  
#include <boost/url/detail/impl/url_impl.hpp>
225  

225  

226  
#endif
226  
#endif