include/boost/url/impl/url_view_base.hpp

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