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