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