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