1 -
//
 
2 -
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
 
3 -
// Copyright (c) 2022 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 -

 
12 -
#include <boost/url/detail/config.hpp>
 
13 -
#include <boost/url/url_view_base.hpp>
 
14 -
#include <boost/url/url_view.hpp>
 
15 -
#include <boost/url/detail/except.hpp>
 
16 -
#include "detail/normalize.hpp"
 
17 -
#include "detail/over_allocator.hpp"
 
18 -

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

 
22 -
// construct empty view
 
23 -
url_view_base::
 
24 -
url_view_base() noexcept
 
25 -
    : impl_(from::url)
 
26 -
    , pi_(&impl_)
 
27 -
{
 
28 -
}
 
29 -

 
30 -
// construct reference
 
31 -
url_view_base::
 
32 -
url_view_base(
 
33 -
    detail::url_impl const& impl) noexcept
 
34 -
    : impl_(impl)
 
35 -
    , pi_(&impl_)
 
36 -
{
 
37 -
}
 
38 -

 
39 -
//------------------------------------------------
 
40 -

 
41 -
std::size_t
 
42 -
url_view_base::
 
43 -
digest(std::size_t salt) const noexcept
 
44 -
{
 
45 -
    detail::fnv_1a h(salt);
 
46 -
    detail::ci_digest(pi_->get(id_scheme), h);
 
47 -
    detail::digest_encoded(pi_->get(id_user), h);
 
48 -
    detail::digest_encoded(pi_->get(id_pass), h);
 
49 -
    detail::ci_digest_encoded(pi_->get(id_host), h);
 
50 -
    h.put(pi_->get(id_port));
 
51 -
    detail::normalized_path_digest(
 
52 -
        pi_->get(id_path), is_path_absolute(), h);
 
53 -
    detail::digest_encoded(pi_->get(id_query), h);
 
54 -
    detail::digest_encoded(pi_->get(id_frag), h);
 
55 -
    return h.digest();
 
56 -
}
 
57 -

 
58 -
//------------------------------------------------
 
59 -
//
 
60 -
// Observers
 
61 -
//
 
62 -
//------------------------------------------------
 
63 -

 
64 -
struct url_view_base::shared_impl
 
65 -
    : url_view
 
66 -
{
 
67 -
    virtual
 
68 -
    ~shared_impl()
 
69 -
    {
 
70 -
    }
 
71 -

 
72 -
    shared_impl(
 
73 -
        url_view const& u) noexcept
 
74 -
        : url_view(u)
 
75 -
    {
 
76 -
        impl_.cs_ = reinterpret_cast<
 
77 -
            char const*>(this + 1);
 
78 -
    }
 
79 -
};
 
80 -

 
81 -
std::shared_ptr<url_view const>
 
82 -
url_view_base::
 
83 -
persist() const
 
84 -
{
 
85 -
    using T = shared_impl;
 
86 -
    using Alloc = std::allocator<char>;
 
87 -
    Alloc a;
 
88 -
    auto p = std::allocate_shared<T>(
 
89 -
        detail::over_allocator<T, Alloc>(
 
90 -
            size(), a), url_view(*pi_));
 
91 -
    std::memcpy(
 
92 -
        reinterpret_cast<char*>(
 
93 -
            p.get() + 1), data(), size());
 
94 -
    return p;
 
95 -
}
 
96 -

 
97 -
//------------------------------------------------
 
98 -
//
 
99 -
// Scheme
 
100 -
//
 
101 -
//------------------------------------------------
 
102 -

 
103 -
bool
 
104 -
url_view_base::
 
105 -
has_scheme() const noexcept
 
106 -
{
 
107 -
    auto const n = pi_->len(
 
108 -
        id_scheme);
 
109 -
    if(n == 0)
 
110 -
        return false;
 
111 -
    BOOST_ASSERT(n > 1);
 
112 -
    BOOST_ASSERT(
 
113 -
        pi_->get(id_scheme
 
114 -
            ).ends_with(':'));
 
115 -
    return true;
 
116 -
}
 
117 -

 
118 -
core::string_view
 
119 -
url_view_base::
 
120 -
scheme() const noexcept
 
121 -
{
 
122 -
    auto s = pi_->get(id_scheme);
 
123 -
    if(! s.empty())
 
124 -
    {
 
125 -
        BOOST_ASSERT(s.size() > 1);
 
126 -
        BOOST_ASSERT(s.ends_with(':'));
 
127 -
        s.remove_suffix(1);
 
128 -
    }
 
129 -
    return s;
 
130 -
}
 
131 -

 
132 -
urls::scheme
 
133 -
url_view_base::
 
134 -
scheme_id() const noexcept
 
135 -
{
 
136 -
    return pi_->scheme_;
 
137 -
}
 
138 -

 
139 -
//------------------------------------------------
 
140 -
//
 
141 -
// Authority
 
142 -
//
 
143 -
//------------------------------------------------
 
144 -

 
145 -
authority_view
 
146 -
url_view_base::
 
147 -
authority() const noexcept
 
148 -
{
 
149 -
    detail::url_impl u(from::authority);
 
150 -
    u.cs_ = encoded_authority().data();
 
151 -
    if(has_authority())
 
152 -
    {
 
153 -
        u.set_size(id_user, pi_->len(id_user) - 2);
 
154 -
        u.set_size(id_pass, pi_->len(id_pass));
 
155 -
        u.set_size(id_host, pi_->len(id_host));
 
156 -
        u.set_size(id_port, pi_->len(id_port));
 
157 -
    }
 
158 -
    else
 
159 -
    {
 
160 -
        u.set_size(id_user, pi_->len(id_user));
 
161 -
        BOOST_ASSERT(pi_->len(id_pass) == 0);
 
162 -
        BOOST_ASSERT(pi_->len(id_host) == 0);
 
163 -
        BOOST_ASSERT(pi_->len(id_port) == 0);
 
164 -
    }
 
165 -
    u.decoded_[id_user] = pi_->decoded_[id_user];
 
166 -
    u.decoded_[id_pass] = pi_->decoded_[id_pass];
 
167 -
    u.decoded_[id_host] = pi_->decoded_[id_host];
 
168 -
    for (int i = 0; i < 16; ++i)
 
169 -
        u.ip_addr_[i] = pi_->ip_addr_[i];
 
170 -
    u.port_number_ = pi_->port_number_;
 
171 -
    u.host_type_ = pi_->host_type_;
 
172 -
    return u.construct_authority();
 
173 -
}
 
174 -

 
175 -
pct_string_view
 
176 -
url_view_base::
 
177 -
encoded_authority() const noexcept
 
178 -
{
 
179 -
    auto s = pi_->get(id_user, id_path);
 
180 -
    if(! s.empty())
 
181 -
    {
 
182 -
        BOOST_ASSERT(has_authority());
 
183 -
        s.remove_prefix(2);
 
184 -
    }
 
185 -
    return make_pct_string_view_unsafe(
 
186 -
        s.data(),
 
187 -
        s.size(),
 
188 -
        pi_->decoded_[id_user] +
 
189 -
            pi_->decoded_[id_pass] +
 
190 -
            pi_->decoded_[id_host] +
 
191 -
            pi_->decoded_[id_port] +
 
192 -
            has_password());
 
193 -
}
 
194 -

 
195 -
//------------------------------------------------
 
196 -
//
 
197 -
// Userinfo
 
198 -
//
 
199 -
//------------------------------------------------
 
200 -

 
201 -
bool
 
202 -
url_view_base::
 
203 -
has_userinfo() const noexcept
 
204 -
{
 
205 -
    auto n = pi_->len(id_pass);
 
206 -
    if(n == 0)
 
207 -
        return false;
 
208 -
    BOOST_ASSERT(has_authority());
 
209 -
    BOOST_ASSERT(pi_->get(
 
210 -
        id_pass).ends_with('@'));
 
211 -
    return true;
 
212 -
}
 
213 -

 
214 -
bool
 
215 -
url_view_base::
 
216 -
has_password() const noexcept
 
217 -
{
 
218 -
    auto const n = pi_->len(id_pass);
 
219 -
    if(n > 1)
 
220 -
    {
 
221 -
        BOOST_ASSERT(pi_->get(id_pass
 
222 -
            ).starts_with(':'));
 
223 -
        BOOST_ASSERT(pi_->get(id_pass
 
224 -
            ).ends_with('@'));
 
225 -
        return true;
 
226 -
    }
 
227 -
    BOOST_ASSERT(n == 0 || pi_->get(
 
228 -
        id_pass).ends_with('@'));
 
229 -
    return false;
 
230 -
}
 
231 -

 
232 -
pct_string_view
 
233 -
url_view_base::
 
234 -
encoded_userinfo() const noexcept
 
235 -
{
 
236 -
    auto s = pi_->get(
 
237 -
        id_user, id_host);
 
238 -
    if(s.empty())
 
239 -
        return s;
 
240 -
    BOOST_ASSERT(
 
241 -
        has_authority());
 
242 -
    s.remove_prefix(2);
 
243 -
    if(s.empty())
 
244 -
        return s;
 
245 -
    BOOST_ASSERT(
 
246 -
        s.ends_with('@'));
 
247 -
    s.remove_suffix(1);
 
248 -
    return make_pct_string_view_unsafe(
 
249 -
        s.data(),
 
250 -
        s.size(),
 
251 -
        pi_->decoded_[id_user] +
 
252 -
            pi_->decoded_[id_pass] +
 
253 -
            has_password());
 
254 -
}
 
255 -

 
256 -
pct_string_view
 
257 -
url_view_base::
 
258 -
encoded_user() const noexcept
 
259 -
{
 
260 -
    auto s = pi_->get(id_user);
 
261 -
    if(! s.empty())
 
262 -
    {
 
263 -
        BOOST_ASSERT(
 
264 -
            has_authority());
 
265 -
        s.remove_prefix(2);
 
266 -
    }
 
267 -
    return make_pct_string_view_unsafe(
 
268 -
        s.data(),
 
269 -
        s.size(),
 
270 -
        pi_->decoded_[id_user]);
 
271 -
}
 
272 -

 
273 -
pct_string_view
 
274 -
url_view_base::
 
275 -
encoded_password() const noexcept
 
276 -
{
 
277 -
    auto s = pi_->get(id_pass);
 
278 -
    switch(s.size())
 
279 -
    {
 
280 -
    case 1:
 
281 -
        BOOST_ASSERT(
 
282 -
            s.starts_with('@'));
 
283 -
        s.remove_prefix(1);
 
284 -
        BOOST_FALLTHROUGH;
 
285 -
    case 0:
 
286 -
        return make_pct_string_view_unsafe(
 
287 -
            s.data(), s.size(), 0);
 
288 -
    default:
 
289 -
        break;
 
290 -
    }
 
291 -
    BOOST_ASSERT(s.ends_with('@'));
 
292 -
    BOOST_ASSERT(s.starts_with(':'));
 
293 -
    return make_pct_string_view_unsafe(
 
294 -
        s.data() + 1,
 
295 -
        s.size() - 2,
 
296 -
        pi_->decoded_[id_pass]);
 
297 -
}
 
298 -

 
299 -
//------------------------------------------------
 
300 -
//
 
301 -
// Host
 
302 -
//
 
303 -
//------------------------------------------------
 
304 -
/*
 
305 -
host_type       host_type()                 // ipv4, ipv6, ipvfuture, name
 
306 -

 
307 -
std::string     host()                      // return encoded_host().decode()
 
308 -
pct_string_view encoded_host()              // return host part, as-is
 
309 -
std::string     host_address()              // return encoded_host_address().decode()
 
310 -
pct_string_view encoded_host_address()      // ipv4, ipv6, ipvfut, or encoded name, no brackets
 
311 -

 
312 -
ipv4_address    host_ipv4_address()         // return ipv4_address or {}
 
313 -
ipv6_address    host_ipv6_address()         // return ipv6_address or {}
 
314 -
core::string_view     host_ipvfuture()            // return ipvfuture or {}
 
315 -
std::string     host_name()                 // return decoded name or ""
 
316 -
pct_string_view encoded_host_name()         // return encoded host name or ""
 
317 -
*/
 
318 -

 
319 -
pct_string_view
 
320 -
url_view_base::
 
321 -
encoded_host() const noexcept
 
322 -
{
 
323 -
    return pi_->pct_get(id_host);
 
324 -
}
 
325 -

 
326 -
pct_string_view
 
327 -
url_view_base::
 
328 -
encoded_host_address() const noexcept
 
329 -
{
 
330 -
    core::string_view s = pi_->get(id_host);
 
331 -
    std::size_t n;
 
332 -
    switch(pi_->host_type_)
 
333 -
    {
 
334 -
    default:
 
335 -
    case urls::host_type::none:
 
336 -
        BOOST_ASSERT(s.empty());
 
337 -
        n = 0;
 
338 -
        break;
 
339 -

 
340 -
    case urls::host_type::name:
 
341 -
    case urls::host_type::ipv4:
 
342 -
        n = pi_->decoded_[id_host];
 
343 -
        break;
 
344 -

 
345 -
    case urls::host_type::ipv6:
 
346 -
    case urls::host_type::ipvfuture:
 
347 -
    {
 
348 -
        BOOST_ASSERT(
 
349 -
            pi_->decoded_[id_host] ==
 
350 -
                s.size() ||
 
351 -
            !this->encoded_zone_id().empty());
 
352 -
        BOOST_ASSERT(s.size() >= 2);
 
353 -
        BOOST_ASSERT(s.front() == '[');
 
354 -
        BOOST_ASSERT(s.back() == ']');
 
355 -
        s = s.substr(1, s.size() - 2);
 
356 -
        n = pi_->decoded_[id_host] - 2;
 
357 -
        break;
 
358 -
    }
 
359 -
    }
 
360 -
    return make_pct_string_view_unsafe(
 
361 -
        s.data(),
 
362 -
        s.size(),
 
363 -
        n);
 
364 -
}
 
365 -

 
366 -
urls::ipv4_address
 
367 -
url_view_base::
 
368 -
host_ipv4_address() const noexcept
 
369 -
{
 
370 -
    if(pi_->host_type_ !=
 
371 -
            urls::host_type::ipv4)
 
372 -
        return {};
 
373 -
    ipv4_address::bytes_type b{{}};
 
374 -
    std::memcpy(
 
375 -
        &b[0], &pi_->ip_addr_[0], b.size());
 
376 -
    return urls::ipv4_address(b);
 
377 -
}
 
378 -

 
379 -
urls::ipv6_address
 
380 -
url_view_base::
 
381 -
host_ipv6_address() const noexcept
 
382 -
{
 
383 -
    if(pi_->host_type_ !=
 
384 -
            urls::host_type::ipv6)
 
385 -
        return {};
 
386 -
    ipv6_address::bytes_type b{{}};
 
387 -
    std::memcpy(
 
388 -
        &b[0], &pi_->ip_addr_[0], b.size());
 
389 -
    return {b};
 
390 -
}
 
391 -

 
392 -
core::string_view
 
393 -
url_view_base::
 
394 -
host_ipvfuture() const noexcept
 
395 -
{
 
396 -
    if(pi_->host_type_ !=
 
397 -
            urls::host_type::ipvfuture)
 
398 -
        return {};
 
399 -
    core::string_view s = pi_->get(id_host);
 
400 -
    BOOST_ASSERT(s.size() >= 6);
 
401 -
    BOOST_ASSERT(s.front() == '[');
 
402 -
    BOOST_ASSERT(s.back() == ']');
 
403 -
    s = s.substr(1, s.size() - 2);
 
404 -
    return s;
 
405 -
}
 
406 -

 
407 -
pct_string_view
 
408 -
url_view_base::
 
409 -
encoded_host_name() const noexcept
 
410 -
{
 
411 -
    if(pi_->host_type_ !=
 
412 -
            urls::host_type::name)
 
413 -
        return {};
 
414 -
    core::string_view s = pi_->get(id_host);
 
415 -
    return make_pct_string_view_unsafe(
 
416 -
        s.data(),
 
417 -
        s.size(),
 
418 -
        pi_->decoded_[id_host]);
 
419 -
}
 
420 -

 
421 -
pct_string_view
 
422 -
url_view_base::
 
423 -
encoded_zone_id() const noexcept
 
424 -
{
 
425 -
    if(pi_->host_type_ !=
 
426 -
        urls::host_type::ipv6)
 
427 -
        return {};
 
428 -
    core::string_view s = pi_->get(id_host);
 
429 -
    BOOST_ASSERT(s.front() == '[');
 
430 -
    BOOST_ASSERT(s.back() == ']');
 
431 -
    s = s.substr(1, s.size() - 2);
 
432 -
    auto pos = s.find("%25");
 
433 -
    if (pos == core::string_view::npos)
 
434 -
        return {};
 
435 -
    s.remove_prefix(pos + 3);
 
436 -
    return *make_pct_string_view(s);
 
437 -
}
 
438 -

 
439 -
//------------------------------------------------
 
440 -

 
441 -
bool
 
442 -
url_view_base::
 
443 -
has_port() const noexcept
 
444 -
{
 
445 -
    auto const n = pi_->len(id_port);
 
446 -
    if(n == 0)
 
447 -
        return false;
 
448 -
    BOOST_ASSERT(
 
449 -
        pi_->get(id_port).starts_with(':'));
 
450 -
    return true;
 
451 -
}
 
452 -

 
453 -
core::string_view
 
454 -
url_view_base::
 
455 -
port() const noexcept
 
456 -
{
 
457 -
    auto s = pi_->get(id_port);
 
458 -
    if(s.empty())
 
459 -
        return s;
 
460 -
    BOOST_ASSERT(has_port());
 
461 -
    return s.substr(1);
 
462 -
}
 
463 -

 
464 -
std::uint16_t
 
465 -
url_view_base::
 
466 -
port_number() const noexcept
 
467 -
{
 
468 -
    BOOST_ASSERT(
 
469 -
        has_port() ||
 
470 -
        pi_->port_number_ == 0);
 
471 -
    return pi_->port_number_;
 
472 -
}
 
473 -

 
474 -
//------------------------------------------------
 
475 -
//
 
476 -
// Path
 
477 -
//
 
478 -
//------------------------------------------------
 
479 -

 
480 -
pct_string_view
 
481 -
url_view_base::
 
482 -
encoded_path() const noexcept
 
483 -
{
 
484 -
    return pi_->pct_get(id_path);
 
485 -
}
 
486 -

 
487 -
segments_view
 
488 -
url_view_base::
 
489 -
segments() const noexcept
 
490 -
{
 
491 -
    return {detail::path_ref(*pi_)};
 
492 -
}
 
493 -

 
494 -
segments_encoded_view
 
495 -
url_view_base::
 
496 -
encoded_segments() const noexcept
 
497 -
{
 
498 -
    return segments_encoded_view(
 
499 -
        detail::path_ref(*pi_));
 
500 -
}
 
501 -

 
502 -
//------------------------------------------------
 
503 -
//
 
504 -
// Query
 
505 -
//
 
506 -
//------------------------------------------------
 
507 -

 
508 -
bool
 
509 -
url_view_base::
 
510 -
has_query() const noexcept
 
511 -
{
 
512 -
    auto const n = pi_->len(
 
513 -
        id_query);
 
514 -
    if(n == 0)
 
515 -
        return false;
 
516 -
    BOOST_ASSERT(
 
517 -
        pi_->get(id_query).
 
518 -
            starts_with('?'));
 
519 -
    return true;
 
520 -
}
 
521 -

 
522 -
pct_string_view
 
523 -
url_view_base::
 
524 -
encoded_query() const noexcept
 
525 -
{
 
526 -
    auto s = pi_->get(id_query);
 
527 -
    if(s.empty())
 
528 -
        return s;
 
529 -
    BOOST_ASSERT(
 
530 -
        s.starts_with('?'));
 
531 -
    return s.substr(1);
 
532 -
}
 
533 -

 
534 -
params_encoded_view
 
535 -
url_view_base::
 
536 -
encoded_params() const noexcept
 
537 -
{
 
538 -
    return params_encoded_view(*pi_);
 
539 -
}
 
540 -

 
541 -
params_view
 
542 -
url_view_base::
 
543 -
params() const noexcept
 
544 -
{
 
545 -
    return params_view(
 
546 -
        *pi_,
 
547 -
        encoding_opts{
 
548 -
            true,false,false});
 
549 -
}
 
550 -

 
551 -
params_view
 
552 -
url_view_base::
 
553 -
params(encoding_opts opt) const noexcept
 
554 -
{
 
555 -
    return params_view(*pi_, opt);
 
556 -
}
 
557 -

 
558 -
//------------------------------------------------
 
559 -
//
 
560 -
// Fragment
 
561 -
//
 
562 -
//------------------------------------------------
 
563 -

 
564 -
bool
 
565 -
url_view_base::
 
566 -
has_fragment() const noexcept
 
567 -
{
 
568 -
    auto const n = pi_->len(id_frag);
 
569 -
    if(n == 0)
 
570 -
        return false;
 
571 -
    BOOST_ASSERT(
 
572 -
        pi_->get(id_frag).
 
573 -
            starts_with('#'));
 
574 -
    return true;
 
575 -
}
 
576 -

 
577 -
pct_string_view
 
578 -
url_view_base::
 
579 -
encoded_fragment() const noexcept
 
580 -
{
 
581 -
    auto s = pi_->get(id_frag);
 
582 -
    if(! s.empty())
 
583 -
    {
 
584 -
        BOOST_ASSERT(
 
585 -
            s.starts_with('#'));
 
586 -
        s.remove_prefix(1);
 
587 -
    }
 
588 -
    return make_pct_string_view_unsafe(
 
589 -
        s.data(),
 
590 -
        s.size(),
 
591 -
        pi_->decoded_[id_frag]);
 
592 -
}
 
593 -

 
594 -
//------------------------------------------------
 
595 -
//
 
596 -
// Compound Fields
 
597 -
//
 
598 -
//------------------------------------------------
 
599 -

 
600 -
pct_string_view
 
601 -
url_view_base::
 
602 -
encoded_host_and_port() const noexcept
 
603 -
{
 
604 -
    return pi_->pct_get(id_host, id_path);
 
605 -
}
 
606 -

 
607 -
pct_string_view
 
608 -
url_view_base::
 
609 -
encoded_origin() const noexcept
 
610 -
{
 
611 -
    if(pi_->len(id_user) < 2)
 
612 -
        return {};
 
613 -
    return pi_->get(id_scheme, id_path);
 
614 -
}
 
615 -

 
616 -
pct_string_view
 
617 -
url_view_base::
 
618 -
encoded_resource() const noexcept
 
619 -
{
 
620 -
    auto n =
 
621 -
        pi_->decoded_[id_path] +
 
622 -
        pi_->decoded_[id_query] +
 
623 -
        pi_->decoded_[id_frag];
 
624 -
    if(has_query())
 
625 -
        ++n;
 
626 -
    if(has_fragment())
 
627 -
        ++n;
 
628 -
    BOOST_ASSERT(pct_string_view(
 
629 -
        pi_->get(id_path, id_end)
 
630 -
            ).decoded_size() == n);
 
631 -
    auto s = pi_->get(id_path, id_end);
 
632 -
    return make_pct_string_view_unsafe(
 
633 -
        s.data(), s.size(), n);
 
634 -
}
 
635 -

 
636 -
pct_string_view
 
637 -
url_view_base::
 
638 -
encoded_target() const noexcept
 
639 -
{
 
640 -
    auto n =
 
641 -
        pi_->decoded_[id_path] +
 
642 -
        pi_->decoded_[id_query];
 
643 -
    if(has_query())
 
644 -
        ++n;
 
645 -
    BOOST_ASSERT(pct_string_view(
 
646 -
        pi_->get(id_path, id_frag)
 
647 -
            ).decoded_size() == n);
 
648 -
    auto s = pi_->get(id_path, id_frag);
 
649 -
    return make_pct_string_view_unsafe(
 
650 -
        s.data(), s.size(), n);
 
651 -
}
 
652 -

 
653 -
//------------------------------------------------
 
654 -
//
 
655 -
// Comparisons
 
656 -
//
 
657 -
//------------------------------------------------
 
658 -

 
659 -
int
 
660 -
url_view_base::
 
661 -
compare(const url_view_base& other) const noexcept
 
662 -
{
 
663 -
    int comp =
 
664 -
        static_cast<int>(has_scheme()) -
 
665 -
        static_cast<int>(other.has_scheme());
 
666 -
    if ( comp != 0 )
 
667 -
        return comp;
 
668 -

 
669 -
    if (has_scheme())
 
670 -
    {
 
671 -
        comp = detail::ci_compare(
 
672 -
            scheme(),
 
673 -
            other.scheme());
 
674 -
        if ( comp != 0 )
 
675 -
            return comp;
 
676 -
    }
 
677 -

 
678 -
    comp =
 
679 -
        static_cast<int>(has_authority()) -
 
680 -
        static_cast<int>(other.has_authority());
 
681 -
    if ( comp != 0 )
 
682 -
        return comp;
 
683 -

 
684 -
    if (has_authority())
 
685 -
    {
 
686 -
        comp = authority().compare(other.authority());
 
687 -
        if ( comp != 0 )
 
688 -
            return comp;
 
689 -
    }
 
690 -

 
691 -
    comp = detail::segments_compare(
 
692 -
        encoded_segments(),
 
693 -
        other.encoded_segments());
 
694 -
    if ( comp != 0 )
 
695 -
        return comp;
 
696 -

 
697 -
    comp =
 
698 -
        static_cast<int>(has_query()) -
 
699 -
        static_cast<int>(other.has_query());
 
700 -
    if ( comp != 0 )
 
701 -
        return comp;
 
702 -

 
703 -
    if (has_query())
 
704 -
    {
 
705 -
        comp = detail::compare_encoded_query(
 
706 -
            encoded_query(),
 
707 -
            other.encoded_query());
 
708 -
        if ( comp != 0 )
 
709 -
            return comp;
 
710 -
    }
 
711 -

 
712 -
    comp =
 
713 -
        static_cast<int>(has_fragment()) -
 
714 -
        static_cast<int>(other.has_fragment());
 
715 -
    if ( comp != 0 )
 
716 -
        return comp;
 
717 -

 
718 -
    if (has_fragment())
 
719 -
    {
 
720 -
        comp = detail::compare_encoded(
 
721 -
            encoded_fragment(),
 
722 -
            other.encoded_fragment());
 
723 -
        if ( comp != 0 )
 
724 -
            return comp;
 
725 -
    }
 
726 -

 
727 -
    return 0;
 
728 -
}
 
729 -

 
730 -
} // urls
 
731 -
} // boost
 
732 -