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 +
#ifndef BOOST_URL_IMPL_URL_VIEW_BASE_HPP
 
12 +
#define BOOST_URL_IMPL_URL_VIEW_BASE_HPP
 
13 +

 
14 +
#include <boost/url/detail/except.hpp>
 
15 +
#include <boost/url/detail/fnv_1a.hpp>
 
16 +
#include <boost/assert.hpp>
 
17 +
#include <cstring>
 
18 +
#include <memory>
 
19 +

 
20 +
namespace boost {
 
21 +
namespace urls {
 
22 +

 
23 +
namespace detail {
 
24 +

 
25 +
// Forward declarations for normalize functions
 
26 +
// defined in src/detail/normalize.cpp
 
27 +
BOOST_URL_DECL
 
28 +
void
 
29 +
ci_digest(
 
30 +
    core::string_view s,
 
31 +
    fnv_1a& hasher) noexcept;
 
32 +

 
33 +
BOOST_URL_DECL
 
34 +
void
 
35 +
digest_encoded(
 
36 +
    core::string_view s,
 
37 +
    fnv_1a& hasher) noexcept;
 
38 +

 
39 +
BOOST_URL_DECL
 
40 +
void
 
41 +
ci_digest_encoded(
 
42 +
    core::string_view s,
 
43 +
    fnv_1a& hasher) noexcept;
 
44 +

 
45 +
BOOST_URL_DECL
 
46 +
void
 
47 +
normalized_path_digest(
 
48 +
    core::string_view str,
 
49 +
    bool remove_unmatched,
 
50 +
    fnv_1a& hasher) noexcept;
 
51 +

 
52 +
BOOST_URL_DECL
 
53 +
int
 
54 +
ci_compare(
 
55 +
    core::string_view lhs,
 
56 +
    core::string_view rhs) noexcept;
 
57 +

 
58 +
BOOST_URL_DECL
 
59 +
int
 
60 +
compare_encoded(
 
61 +
    core::string_view lhs,
 
62 +
    core::string_view rhs) noexcept;
 
63 +

 
64 +
BOOST_URL_DECL
 
65 +
int
 
66 +
compare_encoded_query(
 
67 +
    core::string_view lhs,
 
68 +
    core::string_view rhs) noexcept;
 
69 +

 
70 +
BOOST_URL_DECL
 
71 +
int
 
72 +
segments_compare(
 
73 +
    segments_encoded_view seg0,
 
74 +
    segments_encoded_view seg1) noexcept;
 
75 +

 
76 +
} // detail
 
77 +

 
78 +
//------------------------------------------------
 
79 +

 
80 +
inline
 
81 +
std::size_t
 
82 +
url_view_base::
 
83 +
digest(std::size_t salt) const noexcept
 
84 +
{
 
85 +
    detail::fnv_1a h(salt);
 
86 +
    detail::ci_digest(impl().get(id_scheme), h);
 
87 +
    detail::digest_encoded(impl().get(id_user), h);
 
88 +
    detail::digest_encoded(impl().get(id_pass), h);
 
89 +
    detail::ci_digest_encoded(impl().get(id_host), h);
 
90 +
    h.put(impl().get(id_port));
 
91 +
    detail::normalized_path_digest(
 
92 +
        impl().get(id_path), is_path_absolute(), h);
 
93 +
    detail::digest_encoded(impl().get(id_query), h);
 
94 +
    detail::digest_encoded(impl().get(id_frag), h);
 
95 +
    return h.digest();
 
96 +
}
 
97 +

 
98 +
//------------------------------------------------
 
99 +
//
 
100 +
// Scheme
 
101 +
//
 
102 +
//------------------------------------------------
 
103 +

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

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

 
135 +
inline
 
136 +
urls::scheme
 
137 +
url_view_base::
 
138 +
scheme_id() const noexcept
 
139 +
{
 
140 +
    return impl().scheme_;
 
141 +
}
 
142 +

 
143 +
//------------------------------------------------
 
144 +
//
 
145 +
// Authority
 
146 +
//
 
147 +
//------------------------------------------------
 
148 +

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

 
180 +
inline
 
181 +
pct_string_view
 
182 +
url_view_base::
 
183 +
encoded_authority() const noexcept
 
184 +
{
 
185 +
    auto s = impl().get(id_user, id_path);
 
186 +
    if(! s.empty())
 
187 +
    {
 
188 +
        BOOST_ASSERT(has_authority());
 
189 +
        s.remove_prefix(2);
 
190 +
    }
 
191 +
    return make_pct_string_view_unsafe(
 
192 +
        s.data(),
 
193 +
        s.size(),
 
194 +
        impl().decoded_[id_user] +
 
195 +
            impl().decoded_[id_pass] +
 
196 +
            impl().decoded_[id_host] +
 
197 +
            impl().decoded_[id_port] +
 
198 +
            has_password());
 
199 +
}
 
200 +

 
201 +
//------------------------------------------------
 
202 +
//
 
203 +
// Userinfo
 
204 +
//
 
205 +
//------------------------------------------------
 
206 +

 
207 +
inline
 
208 +
bool
 
209 +
url_view_base::
 
210 +
has_userinfo() const noexcept
 
211 +
{
 
212 +
    auto n = impl().len(id_pass);
 
213 +
    if(n == 0)
 
214 +
        return false;
 
215 +
    BOOST_ASSERT(has_authority());
 
216 +
    BOOST_ASSERT(impl().get(
 
217 +
        id_pass).ends_with('@'));
 
218 +
    return true;
 
219 +
}
 
220 +

 
221 +
inline
 
222 +
bool
 
223 +
url_view_base::
 
224 +
has_password() const noexcept
 
225 +
{
 
226 +
    auto const n = impl().len(id_pass);
 
227 +
    if(n > 1)
 
228 +
    {
 
229 +
        BOOST_ASSERT(impl().get(id_pass
 
230 +
            ).starts_with(':'));
 
231 +
        BOOST_ASSERT(impl().get(id_pass
 
232 +
            ).ends_with('@'));
 
233 +
        return true;
 
234 +
    }
 
235 +
    BOOST_ASSERT(n == 0 || impl().get(
 
236 +
        id_pass).ends_with('@'));
 
237 +
    return false;
 
238 +
}
 
239 +

 
240 +
inline
 
241 +
pct_string_view
 
242 +
url_view_base::
 
243 +
encoded_userinfo() const noexcept
 
244 +
{
 
245 +
    auto s = impl().get(
 
246 +
        id_user, id_host);
 
247 +
    if(s.empty())
 
248 +
        return s;
 
249 +
    BOOST_ASSERT(
 
250 +
        has_authority());
 
251 +
    s.remove_prefix(2);
 
252 +
    if(s.empty())
 
253 +
        return s;
 
254 +
    BOOST_ASSERT(
 
255 +
        s.ends_with('@'));
 
256 +
    s.remove_suffix(1);
 
257 +
    return make_pct_string_view_unsafe(
 
258 +
        s.data(),
 
259 +
        s.size(),
 
260 +
        impl().decoded_[id_user] +
 
261 +
            impl().decoded_[id_pass] +
 
262 +
            has_password());
 
263 +
}
 
264 +

 
265 +
inline
 
266 +
pct_string_view
 
267 +
url_view_base::
 
268 +
encoded_user() const noexcept
 
269 +
{
 
270 +
    auto s = impl().get(id_user);
 
271 +
    if(! s.empty())
 
272 +
    {
 
273 +
        BOOST_ASSERT(
 
274 +
            has_authority());
 
275 +
        s.remove_prefix(2);
 
276 +
    }
 
277 +
    return make_pct_string_view_unsafe(
 
278 +
        s.data(),
 
279 +
        s.size(),
 
280 +
        impl().decoded_[id_user]);
 
281 +
}
 
282 +

 
283 +
inline
 
284 +
pct_string_view
 
285 +
url_view_base::
 
286 +
encoded_password() const noexcept
 
287 +
{
 
288 +
    auto s = impl().get(id_pass);
 
289 +
    switch(s.size())
 
290 +
    {
 
291 +
    case 1:
 
292 +
        BOOST_ASSERT(
 
293 +
            s.starts_with('@'));
 
294 +
        s.remove_prefix(1);
 
295 +
        BOOST_FALLTHROUGH;
 
296 +
    case 0:
 
297 +
        return make_pct_string_view_unsafe(
 
298 +
            s.data(), s.size(), 0);
 
299 +
    default:
 
300 +
        break;
 
301 +
    }
 
302 +
    BOOST_ASSERT(s.ends_with('@'));
 
303 +
    BOOST_ASSERT(s.starts_with(':'));
 
304 +
    return make_pct_string_view_unsafe(
 
305 +
        s.data() + 1,
 
306 +
        s.size() - 2,
 
307 +
        impl().decoded_[id_pass]);
 
308 +
}
 
309 +

 
310 +
//------------------------------------------------
 
311 +
//
 
312 +
// Host
 
313 +
//
 
314 +
//------------------------------------------------
 
315 +

 
316 +
inline
 
317 +
pct_string_view
 
318 +
url_view_base::
 
319 +
encoded_host() const noexcept
 
320 +
{
 
321 +
    return impl().pct_get(id_host);
 
322 +
}
 
323 +

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

 
339 +
    case urls::host_type::name:
 
340 +
    case urls::host_type::ipv4:
 
341 +
        n = impl().decoded_[id_host];
 
342 +
        break;
 
343 +

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

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

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

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

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

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

 
443 +
//------------------------------------------------
 
444 +

 
445 +
inline
 
446 +
bool
 
447 +
url_view_base::
 
448 +
has_port() const noexcept
 
449 +
{
 
450 +
    auto const n = impl().len(id_port);
 
451 +
    if(n == 0)
 
452 +
        return false;
 
453 +
    BOOST_ASSERT(
 
454 +
        impl().get(id_port).starts_with(':'));
 
455 +
    return true;
 
456 +
}
 
457 +

 
458 +
inline
 
459 +
core::string_view
 
460 +
url_view_base::
 
461 +
port() const noexcept
 
462 +
{
 
463 +
    auto s = impl().get(id_port);
 
464 +
    if(s.empty())
 
465 +
        return s;
 
466 +
    BOOST_ASSERT(has_port());
 
467 +
    return s.substr(1);
 
468 +
}
 
469 +

 
470 +
inline
 
471 +
std::uint16_t
 
472 +
url_view_base::
 
473 +
port_number() const noexcept
 
474 +
{
 
475 +
    BOOST_ASSERT(
 
476 +
        has_port() ||
 
477 +
        impl().port_number_ == 0);
 
478 +
    return impl().port_number_;
 
479 +
}
 
480 +

 
481 +
//------------------------------------------------
 
482 +
//
 
483 +
// Path
 
484 +
//
 
485 +
//------------------------------------------------
 
486 +

 
487 +
inline
 
488 +
pct_string_view
 
489 +
url_view_base::
 
490 +
encoded_path() const noexcept
 
491 +
{
 
492 +
    return impl().pct_get(id_path);
 
493 +
}
 
494 +

 
495 +
inline
 
496 +
segments_view
 
497 +
url_view_base::
 
498 +
segments() const noexcept
 
499 +
{
 
500 +
    return {detail::path_ref(impl())};
 
501 +
}
 
502 +

 
503 +
inline
 
504 +
segments_encoded_view
 
505 +
url_view_base::
 
506 +
encoded_segments() const noexcept
 
507 +
{
 
508 +
    return segments_encoded_view(
 
509 +
        detail::path_ref(impl()));
 
510 +
}
 
511 +

 
512 +
//------------------------------------------------
 
513 +
//
 
514 +
// Query
 
515 +
//
 
516 +
//------------------------------------------------
 
517 +

 
518 +
inline
 
519 +
bool
 
520 +
url_view_base::
 
521 +
has_query() const noexcept
 
522 +
{
 
523 +
    auto const n = impl().len(
 
524 +
        id_query);
 
525 +
    if(n == 0)
 
526 +
        return false;
 
527 +
    BOOST_ASSERT(
 
528 +
        impl().get(id_query).
 
529 +
            starts_with('?'));
 
530 +
    return true;
 
531 +
}
 
532 +

 
533 +
inline
 
534 +
pct_string_view
 
535 +
url_view_base::
 
536 +
encoded_query() const noexcept
 
537 +
{
 
538 +
    auto s = impl().get(id_query);
 
539 +
    if(s.empty())
 
540 +
        return s;
 
541 +
    BOOST_ASSERT(
 
542 +
        s.starts_with('?'));
 
543 +
    return s.substr(1);
 
544 +
}
 
545 +

 
546 +
inline
 
547 +
params_encoded_view
 
548 +
url_view_base::
 
549 +
encoded_params() const noexcept
 
550 +
{
 
551 +
    return params_encoded_view(impl());
 
552 +
}
 
553 +

 
554 +
inline
 
555 +
params_view
 
556 +
url_view_base::
 
557 +
params() const noexcept
 
558 +
{
 
559 +
    return params_view(
 
560 +
        impl(),
 
561 +
        encoding_opts{
 
562 +
            true,false,false});
 
563 +
}
 
564 +

 
565 +
inline
 
566 +
params_view
 
567 +
url_view_base::
 
568 +
params(encoding_opts opt) const noexcept
 
569 +
{
 
570 +
    return params_view(impl(), opt);
 
571 +
}
 
572 +

 
573 +
//------------------------------------------------
 
574 +
//
 
575 +
// Fragment
 
576 +
//
 
577 +
//------------------------------------------------
 
578 +

 
579 +
inline
 
580 +
bool
 
581 +
url_view_base::
 
582 +
has_fragment() const noexcept
 
583 +
{
 
584 +
    auto const n = impl().len(id_frag);
 
585 +
    if(n == 0)
 
586 +
        return false;
 
587 +
    BOOST_ASSERT(
 
588 +
        impl().get(id_frag).
 
589 +
            starts_with('#'));
 
590 +
    return true;
 
591 +
}
 
592 +

 
593 +
inline
 
594 +
pct_string_view
 
595 +
url_view_base::
 
596 +
encoded_fragment() const noexcept
 
597 +
{
 
598 +
    auto s = impl().get(id_frag);
 
599 +
    if(! s.empty())
 
600 +
    {
 
601 +
        BOOST_ASSERT(
 
602 +
            s.starts_with('#'));
 
603 +
        s.remove_prefix(1);
 
604 +
    }
 
605 +
    return make_pct_string_view_unsafe(
 
606 +
        s.data(),
 
607 +
        s.size(),
 
608 +
        impl().decoded_[id_frag]);
 
609 +
}
 
610 +

 
611 +
//------------------------------------------------
 
612 +
//
 
613 +
// Compound Fields
 
614 +
//
 
615 +
//------------------------------------------------
 
616 +

 
617 +
inline
 
618 +
pct_string_view
 
619 +
url_view_base::
 
620 +
encoded_host_and_port() const noexcept
 
621 +
{
 
622 +
    return impl().pct_get(id_host, id_path);
 
623 +
}
 
624 +

 
625 +
inline
 
626 +
pct_string_view
 
627 +
url_view_base::
 
628 +
encoded_origin() const noexcept
 
629 +
{
 
630 +
    if(impl().len(id_user) < 2)
 
631 +
        return {};
 
632 +
    return impl().get(id_scheme, id_path);
 
633 +
}
 
634 +

 
635 +
inline
 
636 +
pct_string_view
 
637 +
url_view_base::
 
638 +
encoded_resource() const noexcept
 
639 +
{
 
640 +
    auto n =
 
641 +
        impl().decoded_[id_path] +
 
642 +
        impl().decoded_[id_query] +
 
643 +
        impl().decoded_[id_frag];
 
644 +
    if(has_query())
 
645 +
        ++n;
 
646 +
    if(has_fragment())
 
647 +
        ++n;
 
648 +
    BOOST_ASSERT(pct_string_view(
 
649 +
        impl().get(id_path, id_end)
 
650 +
            ).decoded_size() == n);
 
651 +
    auto s = impl().get(id_path, id_end);
 
652 +
    return make_pct_string_view_unsafe(
 
653 +
        s.data(), s.size(), n);
 
654 +
}
 
655 +

 
656 +
inline
 
657 +
pct_string_view
 
658 +
url_view_base::
 
659 +
encoded_target() const noexcept
 
660 +
{
 
661 +
    auto n =
 
662 +
        impl().decoded_[id_path] +
 
663 +
        impl().decoded_[id_query];
 
664 +
    if(has_query())
 
665 +
        ++n;
 
666 +
    BOOST_ASSERT(pct_string_view(
 
667 +
        impl().get(id_path, id_frag)
 
668 +
            ).decoded_size() == n);
 
669 +
    auto s = impl().get(id_path, id_frag);
 
670 +
    return make_pct_string_view_unsafe(
 
671 +
        s.data(), s.size(), n);
 
672 +
}
 
673 +

 
674 +
//------------------------------------------------
 
675 +
//
 
676 +
// Comparisons
 
677 +
//
 
678 +
//------------------------------------------------
 
679 +

 
680 +
inline
 
681 +
int
 
682 +
url_view_base::
 
683 +
compare(const url_view_base& other) const noexcept
 
684 +
{
 
685 +
    int comp =
 
686 +
        static_cast<int>(has_scheme()) -
 
687 +
        static_cast<int>(other.has_scheme());
 
688 +
    if ( comp != 0 )
 
689 +
        return comp;
 
690 +

 
691 +
    if (has_scheme())
 
692 +
    {
 
693 +
        comp = detail::ci_compare(
 
694 +
            scheme(),
 
695 +
            other.scheme());
 
696 +
        if ( comp != 0 )
 
697 +
            return comp;
 
698 +
    }
 
699 +

 
700 +
    comp =
 
701 +
        static_cast<int>(has_authority()) -
 
702 +
        static_cast<int>(other.has_authority());
 
703 +
    if ( comp != 0 )
 
704 +
        return comp;
 
705 +

 
706 +
    if (has_authority())
 
707 +
    {
 
708 +
        comp = authority().compare(other.authority());
 
709 +
        if ( comp != 0 )
 
710 +
            return comp;
 
711 +
    }
 
712 +

 
713 +
    comp = detail::segments_compare(
 
714 +
        encoded_segments(),
 
715 +
        other.encoded_segments());
 
716 +
    if ( comp != 0 )
 
717 +
        return comp;
 
718 +

 
719 +
    comp =
 
720 +
        static_cast<int>(has_query()) -
 
721 +
        static_cast<int>(other.has_query());
 
722 +
    if ( comp != 0 )
 
723 +
        return comp;
 
724 +

 
725 +
    if (has_query())
 
726 +
    {
 
727 +
        comp = detail::compare_encoded_query(
 
728 +
            encoded_query(),
 
729 +
            other.encoded_query());
 
730 +
        if ( comp != 0 )
 
731 +
            return comp;
 
732 +
    }
 
733 +

 
734 +
    comp =
 
735 +
        static_cast<int>(has_fragment()) -
 
736 +
        static_cast<int>(other.has_fragment());
 
737 +
    if ( comp != 0 )
 
738 +
        return comp;
 
739 +

 
740 +
    if (has_fragment())
 
741 +
    {
 
742 +
        comp = detail::compare_encoded(
 
743 +
            encoded_fragment(),
 
744 +
            other.encoded_fragment());
 
745 +
        if ( comp != 0 )
 
746 +
            return comp;
 
747 +
    }
 
748 +

 
749 +
    return 0;
 
750 +
}
 
751 +

 
752 +
} // urls
 
753 +
} // boost
 
754 +

 
755 +
#endif