1 +
//
 
2 +
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
 
3 +
// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
 
4 +
//
 
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)
 
7 +
//
 
8 +
// Official repository: https://github.com/boostorg/url
 
9 +
//
 
10 +

 
11 +
#ifndef BOOST_URL_IMPL_AUTHORITY_VIEW_HPP
 
12 +
#define BOOST_URL_IMPL_AUTHORITY_VIEW_HPP
 
13 +

 
14 +
#include <boost/url/detail/config.hpp>
 
15 +

 
16 +
namespace boost {
 
17 +
namespace urls {
 
18 +

 
19 +
namespace detail {
 
20 +

 
21 +
// Forward declarations for normalize functions
 
22 +
// defined in src/detail/normalize.cpp
 
23 +
BOOST_URL_DECL
 
24 +
int
 
25 +
compare_encoded(
 
26 +
    core::string_view lhs,
 
27 +
    core::string_view rhs) noexcept;
 
28 +

 
29 +
BOOST_URL_DECL
 
30 +
int
 
31 +
ci_compare_encoded(
 
32 +
    core::string_view lhs,
 
33 +
    core::string_view rhs) noexcept;
 
34 +

 
35 +
BOOST_URL_DECL
 
36 +
int
 
37 +
compare(
 
38 +
    core::string_view lhs,
 
39 +
    core::string_view rhs) noexcept;
 
40 +

 
41 +
} // detail
 
42 +

 
43 +
//------------------------------------------------
 
44 +

 
45 +
inline BOOST_URL_CXX20_CONSTEXPR
 
46 +
authority_view::
 
47 +
~authority_view() = default;
 
48 +

 
49 +
//------------------------------------------------
 
50 +
//
 
51 +
// Userinfo
 
52 +
//
 
53 +
//------------------------------------------------
 
54 +

 
55 +
inline BOOST_URL_CXX20_CONSTEXPR
 
56 +
bool
 
57 +
authority_view::
 
58 +
has_userinfo() const noexcept
 
59 +
{
 
60 +
    auto n = u_.len(id_pass);
 
61 +
    if(n == 0)
 
62 +
        return false;
 
63 +
    BOOST_ASSERT(u_.get(
 
64 +
        id_pass).ends_with('@'));
 
65 +
    return true;
 
66 +
}
 
67 +

 
68 +
inline BOOST_URL_CXX20_CONSTEXPR
 
69 +
pct_string_view
 
70 +
authority_view::
 
71 +
encoded_userinfo() const noexcept
 
72 +
{
 
73 +
    auto s = u_.get(
 
74 +
        id_user, id_host);
 
75 +
    if(s.empty())
 
76 +
        return s;
 
77 +
    BOOST_ASSERT(
 
78 +
        s.ends_with('@'));
 
79 +
    s.remove_suffix(1);
 
80 +
    return make_pct_string_view_unsafe(
 
81 +
        s.data(),
 
82 +
        s.size(),
 
83 +
        u_.decoded_[id_user] +
 
84 +
            u_.decoded_[id_pass] +
 
85 +
            has_password());
 
86 +
}
 
87 +

 
88 +
inline BOOST_URL_CXX20_CONSTEXPR
 
89 +
pct_string_view
 
90 +
authority_view::
 
91 +
encoded_user() const noexcept
 
92 +
{
 
93 +
    auto s = u_.get(id_user);
 
94 +
    return make_pct_string_view_unsafe(
 
95 +
        s.data(),
 
96 +
        s.size(),
 
97 +
        u_.decoded_[id_user]);
 
98 +
}
 
99 +

 
100 +
inline BOOST_URL_CXX20_CONSTEXPR
 
101 +
bool
 
102 +
authority_view::
 
103 +
has_password() const noexcept
 
104 +
{
 
105 +
    auto const n = u_.len(id_pass);
 
106 +
    if(n > 1)
 
107 +
    {
 
108 +
        BOOST_ASSERT(u_.get(id_pass
 
109 +
            ).starts_with(':'));
 
110 +
        BOOST_ASSERT(u_.get(id_pass
 
111 +
            ).ends_with('@'));
 
112 +
        return true;
 
113 +
    }
 
114 +
    BOOST_ASSERT(n == 0 || u_.get(
 
115 +
        id_pass).ends_with('@'));
 
116 +
    return false;
 
117 +
}
 
118 +

 
119 +
inline BOOST_URL_CXX20_CONSTEXPR
 
120 +
pct_string_view
 
121 +
authority_view::
 
122 +
encoded_password() const noexcept
 
123 +
{
 
124 +
    auto s = u_.get(id_pass);
 
125 +
    switch(s.size())
 
126 +
    {
 
127 +
    case 1:
 
128 +
        BOOST_ASSERT(
 
129 +
            s.starts_with('@'));
 
130 +
        s.remove_prefix(1);
 
131 +
        BOOST_FALLTHROUGH;
 
132 +
    case 0:
 
133 +
        return make_pct_string_view_unsafe(
 
134 +
            s.data(), s.size(), 0);
 
135 +
    default:
 
136 +
        break;
 
137 +
    }
 
138 +
    BOOST_ASSERT(s.ends_with('@'));
 
139 +
    BOOST_ASSERT(s.starts_with(':'));
 
140 +
    return make_pct_string_view_unsafe(
 
141 +
        s.data() + 1,
 
142 +
        s.size() - 2,
 
143 +
        u_.decoded_[id_pass]);
 
144 +
}
 
145 +

 
146 +
//------------------------------------------------
 
147 +
//
 
148 +
// Host
 
149 +
//
 
150 +
//------------------------------------------------
 
151 +

 
152 +
inline BOOST_URL_CXX20_CONSTEXPR
 
153 +
pct_string_view
 
154 +
authority_view::
 
155 +
encoded_host() const noexcept
 
156 +
{
 
157 +
    return u_.pct_get(id_host);
 
158 +
}
 
159 +

 
160 +
inline BOOST_URL_CXX20_CONSTEXPR
 
161 +
pct_string_view
 
162 +
authority_view::
 
163 +
encoded_host_address() const noexcept
 
164 +
{
 
165 +
    core::string_view s = u_.get(id_host);
 
166 +
    std::size_t n;
 
167 +
    switch(u_.host_type_)
 
168 +
    {
 
169 +
    case urls::host_type::name:
 
170 +
    case urls::host_type::ipv4:
 
171 +
        n = u_.decoded_[id_host];
 
172 +
        break;
 
173 +

 
174 +
    case urls::host_type::ipv6:
 
175 +
    case urls::host_type::ipvfuture:
 
176 +
    {
 
177 +
        BOOST_ASSERT(
 
178 +
            u_.decoded_[id_host] ==
 
179 +
                s.size());
 
180 +
        BOOST_ASSERT(s.size() >= 2);
 
181 +
        BOOST_ASSERT(s.front() == '[');
 
182 +
        BOOST_ASSERT(s.back() == ']');
 
183 +
        s = s.substr(1, s.size() - 2);
 
184 +
        n = u_.decoded_[id_host] - 2;
 
185 +
        break;
 
186 +
    }
 
187 +
    // LCOV_EXCL_START
 
188 +
    default:
 
189 +
    case urls::host_type::none:
 
190 +
        BOOST_ASSERT(s.empty());
 
191 +
        n = 0;
 
192 +
        break;
 
193 +
    // LCOV_EXCL_STOP
 
194 +
    }
 
195 +
    return make_pct_string_view_unsafe(
 
196 +
        s.data(), s.size(), n);
 
197 +
}
 
198 +

 
199 +
inline BOOST_URL_CXX20_CONSTEXPR
 
200 +
ipv4_address
 
201 +
authority_view::
 
202 +
host_ipv4_address() const noexcept
 
203 +
{
 
204 +
    if(u_.host_type_ !=
 
205 +
            urls::host_type::ipv4)
 
206 +
        return {};
 
207 +
    ipv4_address::bytes_type b{{}};
 
208 +
    for(std::size_t i = 0;
 
209 +
        i < b.size(); ++i)
 
210 +
        b[i] = u_.ip_addr_[i];
 
211 +
    return urls::ipv4_address(b);
 
212 +
}
 
213 +

 
214 +
inline BOOST_URL_CXX20_CONSTEXPR
 
215 +
ipv6_address
 
216 +
authority_view::
 
217 +
host_ipv6_address() const noexcept
 
218 +
{
 
219 +
    if(u_.host_type_ !=
 
220 +
            urls::host_type::ipv6)
 
221 +
        return {};
 
222 +
    ipv6_address::bytes_type b{{}};
 
223 +
    for(std::size_t i = 0;
 
224 +
        i < b.size(); ++i)
 
225 +
        b[i] = u_.ip_addr_[i];
 
226 +
    return urls::ipv6_address(b);
 
227 +
}
 
228 +

 
229 +
inline BOOST_URL_CXX20_CONSTEXPR
 
230 +
core::string_view
 
231 +
authority_view::
 
232 +
host_ipvfuture() const noexcept
 
233 +
{
 
234 +
    if(u_.host_type_ !=
 
235 +
            urls::host_type::ipvfuture)
 
236 +
        return {};
 
237 +
    core::string_view s = u_.get(id_host);
 
238 +
    BOOST_ASSERT(s.size() >= 6);
 
239 +
    BOOST_ASSERT(s.front() == '[');
 
240 +
    BOOST_ASSERT(s.back() == ']');
 
241 +
    s = s.substr(1, s.size() - 2);
 
242 +
    return s;
 
243 +
}
 
244 +

 
245 +
inline BOOST_URL_CXX20_CONSTEXPR
 
246 +
pct_string_view
 
247 +
authority_view::
 
248 +
encoded_host_name() const noexcept
 
249 +
{
 
250 +
    if(u_.host_type_ !=
 
251 +
            urls::host_type::name)
 
252 +
        return {};
 
253 +
    return u_.pct_get(id_host);
 
254 +
}
 
255 +

 
256 +
//------------------------------------------------
 
257 +
//
 
258 +
// Port
 
259 +
//
 
260 +
//------------------------------------------------
 
261 +

 
262 +
inline BOOST_URL_CXX20_CONSTEXPR
 
263 +
bool
 
264 +
authority_view::
 
265 +
has_port() const noexcept
 
266 +
{
 
267 +
    auto const n = u_.len(id_port);
 
268 +
    if(n == 0)
 
269 +
        return false;
 
270 +
    BOOST_ASSERT(
 
271 +
        u_.get(id_port).starts_with(':'));
 
272 +
    return true;
 
273 +
}
 
274 +

 
275 +
inline BOOST_URL_CXX20_CONSTEXPR
 
276 +
core::string_view
 
277 +
authority_view::
 
278 +
port() const noexcept
 
279 +
{
 
280 +
    auto s = u_.get(id_port);
 
281 +
    if(s.empty())
 
282 +
        return s;
 
283 +
    BOOST_ASSERT(has_port());
 
284 +
    return s.substr(1);
 
285 +
}
 
286 +

 
287 +
inline BOOST_URL_CXX20_CONSTEXPR
 
288 +
std::uint16_t
 
289 +
authority_view::
 
290 +
port_number() const noexcept
 
291 +
{
 
292 +
    BOOST_ASSERT(
 
293 +
        has_port() ||
 
294 +
        u_.port_number_ == 0);
 
295 +
    return u_.port_number_;
 
296 +
}
 
297 +

 
298 +
inline BOOST_URL_CXX20_CONSTEXPR
 
299 +
pct_string_view
 
300 +
authority_view::
 
301 +
encoded_host_and_port() const noexcept
 
302 +
{
 
303 +
    return u_.pct_get(id_host, id_end);
 
304 +
}
 
305 +

 
306 +
//------------------------------------------------
 
307 +
//
 
308 +
// Comparisons
 
309 +
//
 
310 +
//------------------------------------------------
 
311 +

 
312 +
inline
 
313 +
int
 
314 +
authority_view::
 
315 +
compare(const authority_view& other) const noexcept
 
316 +
{
 
317 +
    auto comp = static_cast<int>(has_userinfo()) -
 
318 +
        static_cast<int>(other.has_userinfo());
 
319 +
    if ( comp != 0 )
 
320 +
        return comp;
 
321 +

 
322 +
    if (has_userinfo())
 
323 +
    {
 
324 +
        comp = detail::compare_encoded(
 
325 +
            encoded_user(),
 
326 +
            other.encoded_user());
 
327 +
        if ( comp != 0 )
 
328 +
            return comp;
 
329 +

 
330 +
        comp = static_cast<int>(has_password()) -
 
331 +
               static_cast<int>(other.has_password());
 
332 +
        if ( comp != 0 )
 
333 +
            return comp;
 
334 +

 
335 +
        if (has_password())
 
336 +
        {
 
337 +
            comp = detail::compare_encoded(
 
338 +
                encoded_password(),
 
339 +
                other.encoded_password());
 
340 +
            if ( comp != 0 )
 
341 +
                return comp;
 
342 +
        }
 
343 +
    }
 
344 +

 
345 +
    comp = detail::ci_compare_encoded(
 
346 +
        encoded_host(),
 
347 +
        other.encoded_host());
 
348 +
    if ( comp != 0 )
 
349 +
        return comp;
 
350 +

 
351 +
    comp = static_cast<int>(has_port()) -
 
352 +
           static_cast<int>(other.has_port());
 
353 +
    if ( comp != 0 )
 
354 +
        return comp;
 
355 +

 
356 +
    if (has_port())
 
357 +
    {
 
358 +
        comp = detail::compare(
 
359 +
            port(),
 
360 +
            other.port());
 
361 +
        if ( comp != 0 )
 
362 +
            return comp;
 
363 +
    }
 
364 +

 
365 +
    return 0;
 
366 +
}
 
367 +

 
368 +
} // urls
 
369 +
} // boost
 
370 +

 
371 +
#endif