include/boost/url/impl/url_view_base.hpp

98.6% Lines (290 / 294) 100.0% Functions (35 / 35)
url_view_base.hpp
f(x) Functions (35)
Function Calls Lines Blocks
boost::urls::url_view_base::digest(unsigned long) const :82 388x 100.0% 100.0% boost::urls::url_view_base::has_scheme() const :106 4629x 100.0% 85.0% boost::urls::url_view_base::scheme() const :122 1570x 100.0% 85.0% boost::urls::url_view_base::scheme_id() const :137 46x 100.0% 100.0% boost::urls::url_view_base::authority() const :151 621x 100.0% 93.0% boost::urls::url_view_base::encoded_authority() const :184 843x 100.0% 95.0% boost::urls::url_view_base::has_userinfo() const :213 1107x 100.0% 86.0% boost::urls::url_view_base::has_password() const :227 990x 100.0% 86.0% boost::urls::url_view_base::encoded_userinfo() const :246 128x 100.0% 92.0% boost::urls::url_view_base::encoded_user() const :271 150x 100.0% 93.0% boost::urls::url_view_base::encoded_password() const :289 108x 100.0% 88.0% boost::urls::url_view_base::encoded_host() const :336 631x 100.0% 100.0% boost::urls::url_view_base::encoded_host_address() const :344 142x 100.0% 86.0% boost::urls::url_view_base::host_ipv4_address() const :381 53x 100.0% 100.0% boost::urls::url_view_base::host_ipv6_address() const :395 66x 100.0% 100.0% boost::urls::url_view_base::host_ipvfuture() const :409 51x 100.0% 86.0% boost::urls::url_view_base::encoded_host_name() const :425 146x 100.0% 100.0% boost::urls::url_view_base::encoded_zone_id() const :440 28x 100.0% 91.0% boost::urls::url_view_base::has_port() const :461 389x 100.0% 91.0% boost::urls::url_view_base::port() const :474 193x 100.0% 91.0% boost::urls::url_view_base::port_number() const :486 108x 100.0% 88.0% boost::urls::url_view_base::encoded_path() const :503 2559x 100.0% 100.0% boost::urls::url_view_base::segments() const :511 5785x 100.0% 100.0% boost::urls::url_view_base::encoded_segments() const :519 1578x 100.0% 100.0% boost::urls::url_view_base::has_query() const :534 1362x 100.0% 91.0% boost::urls::url_view_base::encoded_query() const :549 445x 100.0% 92.0% boost::urls::url_view_base::encoded_params() const :562 72x 100.0% 100.0% boost::urls::url_view_base::params() const :570 5803x 100.0% 100.0% boost::urls::url_view_base::has_fragment() const :595 1161x 100.0% 91.0% boost::urls::url_view_base::encoded_fragment() const :609 198x 100.0% 93.0% boost::urls::url_view_base::encoded_host_and_port() const :633 120x 100.0% 100.0% boost::urls::url_view_base::encoded_origin() const :641 16x 100.0% 100.0% boost::urls::url_view_base::encoded_resource() const :651 98x 100.0% 96.0% boost::urls::url_view_base::encoded_target() const :672 105x 100.0% 95.0% boost::urls::url_view_base::compare(boost::urls::url_view_base const&) const :696 483x 90.9% 93.0%
Line TLA Hits Source Code
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/memcpy.hpp>
15 #include <boost/url/detail/except.hpp>
16 #include <boost/url/detail/fnv_1a.hpp>
17 #include <boost/assert.hpp>
18 #include <cstring>
19 #include <memory>
20
21 namespace boost {
22 namespace urls {
23
24 namespace detail {
25
26 // Forward declarations for normalize functions
27 // defined in src/detail/normalize.cpp
28 BOOST_URL_DECL
29 void
30 ci_digest(
31 core::string_view s,
32 fnv_1a& hasher) noexcept;
33
34 BOOST_URL_DECL
35 void
36 digest_encoded(
37 core::string_view s,
38 fnv_1a& hasher) noexcept;
39
40 BOOST_URL_DECL
41 void
42 ci_digest_encoded(
43 core::string_view s,
44 fnv_1a& hasher) noexcept;
45
46 BOOST_URL_DECL
47 void
48 normalized_path_digest(
49 segments_encoded_view segs,
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 388x url_view_base::
83 digest(std::size_t salt) const noexcept
84 {
85 388x detail::fnv_1a h(salt);
86 388x detail::ci_digest(impl().get(id_scheme), h);
87 388x detail::digest_encoded(impl().get(id_user), h);
88 388x detail::digest_encoded(impl().get(id_pass), h);
89 388x detail::ci_digest_encoded(impl().get(id_host), h);
90 388x h.put(impl().get(id_port));
91 388x detail::normalized_path_digest(
92 encoded_segments(), h);
93 388x detail::digest_encoded(impl().get(id_query), h);
94 388x detail::digest_encoded(impl().get(id_frag), h);
95 388x return h.digest();
96 }
97
98 //------------------------------------------------
99 //
100 // Scheme
101 //
102 //------------------------------------------------
103
104 inline
105 bool
106 4629x url_view_base::
107 has_scheme() const noexcept
108 {
109 4629x auto const n = impl().len(
110 id_scheme);
111 4629x if(n == 0)
112 1446x return false;
113 3183x BOOST_ASSERT(n > 1);
114 3183x BOOST_ASSERT(
115 impl().get(id_scheme
116 ).ends_with(':'));
117 3183x return true;
118 }
119
120 inline
121 core::string_view
122 1570x url_view_base::
123 scheme() const noexcept
124 {
125 1570x auto s = impl().get(id_scheme);
126 1570x if(! s.empty())
127 {
128 1469x BOOST_ASSERT(s.size() > 1);
129 1469x BOOST_ASSERT(s.ends_with(':'));
130 1469x s.remove_suffix(1);
131 }
132 1570x return s;
133 }
134
135 inline
136 urls::scheme
137 46x url_view_base::
138 scheme_id() const noexcept
139 {
140 46x return impl().scheme_;
141 }
142
143 //------------------------------------------------
144 //
145 // Authority
146 //
147 //------------------------------------------------
148
149 inline
150 authority_view
151 621x url_view_base::
152 authority() const noexcept
153 {
154 621x detail::url_impl u(from::authority);
155 621x u.cs_ = encoded_authority().data();
156 621x if(has_authority())
157 {
158 619x u.set_size(id_user, impl().len(id_user) - 2);
159 619x u.set_size(id_pass, impl().len(id_pass));
160 619x u.set_size(id_host, impl().len(id_host));
161 619x u.set_size(id_port, impl().len(id_port));
162 }
163 else
164 {
165 2x u.set_size(id_user, impl().len(id_user));
166 2x BOOST_ASSERT(impl().len(id_pass) == 0);
167 2x BOOST_ASSERT(impl().len(id_host) == 0);
168 2x BOOST_ASSERT(impl().len(id_port) == 0);
169 }
170 621x u.decoded_[id_user] = impl().decoded_[id_user];
171 621x u.decoded_[id_pass] = impl().decoded_[id_pass];
172 621x u.decoded_[id_host] = impl().decoded_[id_host];
173 detail::memcpy(
174 u.ip_addr_,
175 621x impl().ip_addr_,
176 16);
177 621x u.port_number_ = impl().port_number_;
178 621x u.host_type_ = impl().host_type_;
179 621x return authority_view(u);
180 }
181
182 inline
183 pct_string_view
184 843x url_view_base::
185 encoded_authority() const noexcept
186 {
187 843x auto s = impl().get(id_user, id_path);
188 843x if(! s.empty())
189 {
190 799x BOOST_ASSERT(has_authority());
191 799x s.remove_prefix(2);
192 }
193 // [ user [ ":" pass ] "@" ] host [ ":" port ]
194 843x return make_pct_string_view_unsafe(
195 s.data(),
196 s.size(),
197 843x impl().decoded_[id_user] +
198 843x has_password() +
199 843x impl().decoded_[id_pass] +
200 843x has_userinfo() +
201 843x impl().decoded_[id_host] +
202 1686x impl().len(id_port));
203 }
204
205 //------------------------------------------------
206 //
207 // Userinfo
208 //
209 //------------------------------------------------
210
211 inline
212 bool
213 1107x url_view_base::
214 has_userinfo() const noexcept
215 {
216 1107x auto n = impl().len(id_pass);
217 1107x if(n == 0)
218 764x return false;
219 343x BOOST_ASSERT(has_authority());
220 343x BOOST_ASSERT(impl().get(
221 id_pass).ends_with('@'));
222 343x return true;
223 }
224
225 inline
226 bool
227 990x url_view_base::
228 has_password() const noexcept
229 {
230 990x auto const n = impl().len(id_pass);
231 990x if(n > 1)
232 {
233 153x BOOST_ASSERT(impl().get(id_pass
234 ).starts_with(':'));
235 153x BOOST_ASSERT(impl().get(id_pass
236 ).ends_with('@'));
237 153x return true;
238 }
239 837x BOOST_ASSERT(n == 0 || impl().get(
240 id_pass).ends_with('@'));
241 837x return false;
242 }
243
244 inline
245 pct_string_view
246 128x url_view_base::
247 encoded_userinfo() const noexcept
248 {
249 128x auto s = impl().get(
250 id_user, id_host);
251 128x if(s.empty())
252 8x return s;
253 120x BOOST_ASSERT(
254 has_authority());
255 120x s.remove_prefix(2);
256 120x if(s.empty())
257 34x return s;
258 86x BOOST_ASSERT(
259 s.ends_with('@'));
260 86x s.remove_suffix(1);
261 86x return make_pct_string_view_unsafe(
262 s.data(),
263 s.size(),
264 86x impl().decoded_[id_user] +
265 86x impl().decoded_[id_pass] +
266 172x has_password());
267 }
268
269 inline
270 pct_string_view
271 150x url_view_base::
272 encoded_user() const noexcept
273 {
274 150x auto s = impl().get(id_user);
275 150x if(! s.empty())
276 {
277 148x BOOST_ASSERT(
278 has_authority());
279 148x s.remove_prefix(2);
280 }
281 150x return make_pct_string_view_unsafe(
282 s.data(),
283 s.size(),
284 300x impl().decoded_[id_user]);
285 }
286
287 inline
288 pct_string_view
289 108x url_view_base::
290 encoded_password() const noexcept
291 {
292 108x auto s = impl().get(id_pass);
293 108x switch(s.size())
294 {
295 24x case 1:
296 24x BOOST_ASSERT(
297 s.starts_with('@'));
298 24x s.remove_prefix(1);
299 BOOST_FALLTHROUGH;
300 43x case 0:
301 43x return make_pct_string_view_unsafe(
302 43x s.data(), s.size(), 0);
303 65x default:
304 65x break;
305 }
306 65x BOOST_ASSERT(s.ends_with('@'));
307 65x BOOST_ASSERT(s.starts_with(':'));
308 65x return make_pct_string_view_unsafe(
309 65x s.data() + 1,
310 65x s.size() - 2,
311 130x impl().decoded_[id_pass]);
312 }
313
314 //------------------------------------------------
315 //
316 // Host
317 //
318 //------------------------------------------------
319 /*
320 host_type host_type() // ipv4, ipv6, ipvfuture, name
321
322 std::string host() // return encoded_host().decode()
323 pct_string_view encoded_host() // return host part, as-is
324 std::string host_address() // return encoded_host_address().decode()
325 pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded name, no brackets
326
327 ipv4_address host_ipv4_address() // return ipv4_address or {}
328 ipv6_address host_ipv6_address() // return ipv6_address or {}
329 core::string_view host_ipvfuture() // return ipvfuture or {}
330 std::string host_name() // return decoded name or ""
331 pct_string_view encoded_host_name() // return encoded host name or ""
332 */
333
334 inline
335 pct_string_view
336 631x url_view_base::
337 encoded_host() const noexcept
338 {
339 631x return impl().pct_get(id_host);
340 }
341
342 inline
343 pct_string_view
344 142x url_view_base::
345 encoded_host_address() const noexcept
346 {
347 142x core::string_view s = impl().get(id_host);
348 std::size_t n;
349 142x switch(impl().host_type_)
350 {
351 42x default:
352 case urls::host_type::none:
353 42x BOOST_ASSERT(s.empty());
354 42x n = 0;
355 42x break;
356
357 53x case urls::host_type::name:
358 case urls::host_type::ipv4:
359 53x n = impl().decoded_[id_host];
360 53x break;
361
362 47x case urls::host_type::ipv6:
363 case urls::host_type::ipvfuture:
364 {
365 47x BOOST_ASSERT(s.size() >= 2);
366 47x BOOST_ASSERT(s.front() == '[');
367 47x BOOST_ASSERT(s.back() == ']');
368 47x s = s.substr(1, s.size() - 2);
369 47x n = impl().decoded_[id_host] - 2;
370 47x break;
371 }
372 }
373 142x return make_pct_string_view_unsafe(
374 s.data(),
375 s.size(),
376 142x n);
377 }
378
379 inline
380 urls::ipv4_address
381 53x url_view_base::
382 host_ipv4_address() const noexcept
383 {
384 53x if(impl().host_type_ !=
385 urls::host_type::ipv4)
386 35x return {};
387 18x ipv4_address::bytes_type b{{}};
388 36x std::memcpy(
389 18x &b[0], &impl().ip_addr_[0], b.size());
390 18x return urls::ipv4_address(b);
391 }
392
393 inline
394 urls::ipv6_address
395 66x url_view_base::
396 host_ipv6_address() const noexcept
397 {
398 66x if(impl().host_type_ !=
399 urls::host_type::ipv6)
400 45x return {};
401 21x ipv6_address::bytes_type b{{}};
402 42x std::memcpy(
403 21x &b[0], &impl().ip_addr_[0], b.size());
404 21x return {b};
405 }
406
407 inline
408 core::string_view
409 51x url_view_base::
410 host_ipvfuture() const noexcept
411 {
412 51x if(impl().host_type_ !=
413 urls::host_type::ipvfuture)
414 44x return {};
415 7x core::string_view s = impl().get(id_host);
416 7x BOOST_ASSERT(s.size() >= 6);
417 7x BOOST_ASSERT(s.front() == '[');
418 7x BOOST_ASSERT(s.back() == ']');
419 7x s = s.substr(1, s.size() - 2);
420 7x return s;
421 }
422
423 inline
424 pct_string_view
425 146x url_view_base::
426 encoded_host_name() const noexcept
427 {
428 146x if(impl().host_type_ !=
429 urls::host_type::name)
430 78x return {};
431 68x core::string_view s = impl().get(id_host);
432 68x return make_pct_string_view_unsafe(
433 s.data(),
434 s.size(),
435 136x impl().decoded_[id_host]);
436 }
437
438 inline
439 pct_string_view
440 28x url_view_base::
441 encoded_zone_id() const noexcept
442 {
443 28x if(impl().host_type_ !=
444 urls::host_type::ipv6)
445 6x return {};
446 22x core::string_view s = impl().get(id_host);
447 22x BOOST_ASSERT(s.front() == '[');
448 22x BOOST_ASSERT(s.back() == ']');
449 22x s = s.substr(1, s.size() - 2);
450 22x auto pos = s.find("%25");
451 22x if (pos == core::string_view::npos)
452 2x return {};
453 20x s.remove_prefix(pos + 3);
454 20x return *make_pct_string_view(s);
455 }
456
457 //------------------------------------------------
458
459 inline
460 bool
461 389x url_view_base::
462 has_port() const noexcept
463 {
464 389x auto const n = impl().len(id_port);
465 389x if(n == 0)
466 89x return false;
467 300x BOOST_ASSERT(
468 impl().get(id_port).starts_with(':'));
469 300x return true;
470 }
471
472 inline
473 core::string_view
474 193x url_view_base::
475 port() const noexcept
476 {
477 193x auto s = impl().get(id_port);
478 193x if(s.empty())
479 58x return s;
480 135x BOOST_ASSERT(has_port());
481 135x return s.substr(1);
482 }
483
484 inline
485 std::uint16_t
486 108x url_view_base::
487 port_number() const noexcept
488 {
489 108x BOOST_ASSERT(
490 has_port() ||
491 impl().port_number_ == 0);
492 108x return impl().port_number_;
493 }
494
495 //------------------------------------------------
496 //
497 // Path
498 //
499 //------------------------------------------------
500
501 inline
502 pct_string_view
503 2559x url_view_base::
504 encoded_path() const noexcept
505 {
506 2559x return impl().pct_get(id_path);
507 }
508
509 inline
510 segments_view
511 5785x url_view_base::
512 segments() const noexcept
513 {
514 5785x return {detail::path_ref(impl())};
515 }
516
517 inline
518 segments_encoded_view
519 1578x url_view_base::
520 encoded_segments() const noexcept
521 {
522 return segments_encoded_view(
523 1578x detail::path_ref(impl()));
524 }
525
526 //------------------------------------------------
527 //
528 // Query
529 //
530 //------------------------------------------------
531
532 inline
533 bool
534 1362x url_view_base::
535 has_query() const noexcept
536 {
537 1362x auto const n = impl().len(
538 id_query);
539 1362x if(n == 0)
540 1003x return false;
541 359x BOOST_ASSERT(
542 impl().get(id_query).
543 starts_with('?'));
544 359x return true;
545 }
546
547 inline
548 pct_string_view
549 445x url_view_base::
550 encoded_query() const noexcept
551 {
552 445x auto s = impl().get(id_query);
553 445x if(s.empty())
554 16x return s;
555 429x BOOST_ASSERT(
556 s.starts_with('?'));
557 429x return s.substr(1);
558 }
559
560 inline
561 params_encoded_view
562 72x url_view_base::
563 encoded_params() const noexcept
564 {
565 72x return params_encoded_view(impl());
566 }
567
568 inline
569 params_view
570 5803x url_view_base::
571 params() const noexcept
572 {
573 return params_view(
574 impl(),
575 encoding_opts{
576 5803x true,false,false});
577 }
578
579 inline
580 params_view
581 url_view_base::
582 params(encoding_opts opt) const noexcept
583 {
584 return params_view(impl(), opt);
585 }
586
587 //------------------------------------------------
588 //
589 // Fragment
590 //
591 //------------------------------------------------
592
593 inline
594 bool
595 1161x url_view_base::
596 has_fragment() const noexcept
597 {
598 1161x auto const n = impl().len(id_frag);
599 1161x if(n == 0)
600 1002x return false;
601 159x BOOST_ASSERT(
602 impl().get(id_frag).
603 starts_with('#'));
604 159x return true;
605 }
606
607 inline
608 pct_string_view
609 198x url_view_base::
610 encoded_fragment() const noexcept
611 {
612 198x auto s = impl().get(id_frag);
613 198x if(! s.empty())
614 {
615 190x BOOST_ASSERT(
616 s.starts_with('#'));
617 190x s.remove_prefix(1);
618 }
619 198x return make_pct_string_view_unsafe(
620 s.data(),
621 s.size(),
622 396x impl().decoded_[id_frag]);
623 }
624
625 //------------------------------------------------
626 //
627 // Compound Fields
628 //
629 //------------------------------------------------
630
631 inline
632 pct_string_view
633 120x url_view_base::
634 encoded_host_and_port() const noexcept
635 {
636 120x return impl().pct_get(id_host, id_path);
637 }
638
639 inline
640 pct_string_view
641 16x url_view_base::
642 encoded_origin() const noexcept
643 {
644 16x if(impl().len(id_user) < 2)
645 14x return {};
646 2x return impl().get(id_scheme, id_path);
647 }
648
649 inline
650 pct_string_view
651 98x url_view_base::
652 encoded_resource() const noexcept
653 {
654 auto n =
655 98x impl().decoded_[id_path] +
656 98x impl().decoded_[id_query] +
657 98x impl().decoded_[id_frag];
658 98x if(has_query())
659 92x ++n;
660 98x if(has_fragment())
661 1x ++n;
662 98x BOOST_ASSERT(pct_string_view(
663 impl().get(id_path, id_end)
664 ).decoded_size() == n);
665 98x auto s = impl().get(id_path, id_end);
666 98x return make_pct_string_view_unsafe(
667 98x s.data(), s.size(), n);
668 }
669
670 inline
671 pct_string_view
672 105x url_view_base::
673 encoded_target() const noexcept
674 {
675 auto n =
676 105x impl().decoded_[id_path] +
677 105x impl().decoded_[id_query];
678 105x if(has_query())
679 98x ++n;
680 105x BOOST_ASSERT(pct_string_view(
681 impl().get(id_path, id_frag)
682 ).decoded_size() == n);
683 105x auto s = impl().get(id_path, id_frag);
684 105x return make_pct_string_view_unsafe(
685 105x s.data(), s.size(), n);
686 }
687
688 //------------------------------------------------
689 //
690 // Comparisons
691 //
692 //------------------------------------------------
693
694 inline
695 int
696 483x url_view_base::
697 compare(const url_view_base& other) const noexcept
698 {
699 int comp =
700 483x static_cast<int>(has_scheme()) -
701 483x static_cast<int>(other.has_scheme());
702 483x if ( comp != 0 )
703 ✗ return comp;
704
705 483x if (has_scheme())
706 {
707 226x comp = detail::ci_compare(
708 scheme(),
709 other.scheme());
710 226x if ( comp != 0 )
711 15x return comp;
712 }
713
714 468x comp =
715 468x static_cast<int>(has_authority()) -
716 468x static_cast<int>(other.has_authority());
717 468x if ( comp != 0 )
718 ✗ return comp;
719
720 468x if (has_authority())
721 {
722 206x comp = authority().compare(other.authority());
723 206x if ( comp != 0 )
724 91x return comp;
725 }
726
727 377x comp = detail::segments_compare(
728 encoded_segments(),
729 other.encoded_segments());
730 377x if ( comp != 0 )
731 126x return comp;
732
733 251x comp =
734 251x static_cast<int>(has_query()) -
735 251x static_cast<int>(other.has_query());
736 251x if ( comp != 0 )
737 ✗ return comp;
738
739 251x if (has_query())
740 {
741 56x comp = detail::compare_encoded_query(
742 28x encoded_query(),
743 28x other.encoded_query());
744 28x if ( comp != 0 )
745 19x return comp;
746 }
747
748 232x comp =
749 232x static_cast<int>(has_fragment()) -
750 232x static_cast<int>(other.has_fragment());
751 232x if ( comp != 0 )
752 ✗ return comp;
753
754 232x if (has_fragment())
755 {
756 52x comp = detail::compare_encoded(
757 26x encoded_fragment(),
758 26x other.encoded_fragment());
759 26x if ( comp != 0 )
760 21x return comp;
761 }
762
763 211x return 0;
764 }
765
766 } // urls
767 } // boost
768
769 #endif
770