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