100.00% Lines (36/36) 100.00% Functions (14/14)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) 2   // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/boostorg/url 7   // Official repository: https://github.com/boostorg/url
8   // 8   //
9   9  
10   #ifndef BOOST_URL_DECODE_VIEW_HPP 10   #ifndef BOOST_URL_DECODE_VIEW_HPP
11   #define BOOST_URL_DECODE_VIEW_HPP 11   #define BOOST_URL_DECODE_VIEW_HPP
12   12  
13   #include <boost/url/detail/config.hpp> 13   #include <boost/url/detail/config.hpp>
14   #include <boost/core/detail/string_view.hpp> 14   #include <boost/core/detail/string_view.hpp>
15   #include <boost/url/encoding_opts.hpp> 15   #include <boost/url/encoding_opts.hpp>
16   #include <boost/url/pct_string_view.hpp> 16   #include <boost/url/pct_string_view.hpp>
17   #include <type_traits> 17   #include <type_traits>
18   #include <iterator> 18   #include <iterator>
19   #include <iosfwd> 19   #include <iosfwd>
20   20  
21   namespace boost { 21   namespace boost {
22   namespace urls { 22   namespace urls {
23   23  
24   //------------------------------------------------ 24   //------------------------------------------------
25   25  
26   class decode_view; 26   class decode_view;
27   27  
28   namespace detail { 28   namespace detail {
29   29  
30   // unchecked 30   // unchecked
31   template<class... Args> 31   template<class... Args>
32   decode_view 32   decode_view
33   make_decode_view( 33   make_decode_view(
34   Args&&... args) noexcept; 34   Args&&... args) noexcept;
35   35  
36   } // detail 36   } // detail
37   37  
38   //------------------------------------------------ 38   //------------------------------------------------
39   39  
40   /** A reference to a valid, percent-encoded string 40   /** A reference to a valid, percent-encoded string
41   41  
42   These views reference strings in parts of URLs 42   These views reference strings in parts of URLs
43   or other components that are percent-encoded. 43   or other components that are percent-encoded.
44   The special characters (those not in the 44   The special characters (those not in the
45   allowed character set) are stored as three 45   allowed character set) are stored as three
46   character escapes that consist of a percent 46   character escapes that consist of a percent
47   sign ('%%') followed by a two-digit hexadecimal 47   sign ('%%') followed by a two-digit hexadecimal
48   number of the corresponding unescaped character 48   number of the corresponding unescaped character
49   code, which may be part of a UTF-8 code point 49   code, which may be part of a UTF-8 code point
50   depending on the context. 50   depending on the context.
51   51  
52   The view refers to the original character 52   The view refers to the original character
53   buffer and only decodes escaped sequences when 53   buffer and only decodes escaped sequences when
54   needed. In particular these operations perform 54   needed. In particular these operations perform
55   percent-decoding automatically without the 55   percent-decoding automatically without the
56   need to allocate memory: 56   need to allocate memory:
57   57  
58   @li Iteration of the string 58   @li Iteration of the string
59   @li Accessing the encoded character buffer 59   @li Accessing the encoded character buffer
60   @li Comparison to encoded or plain strings 60   @li Comparison to encoded or plain strings
61   61  
62   These objects can only be constructed from 62   These objects can only be constructed from
63   strings that have a valid percent-encoding, 63   strings that have a valid percent-encoding,
64   otherwise construction fails. The caller is 64   otherwise construction fails. The caller is
65   responsible for ensuring that the lifetime 65   responsible for ensuring that the lifetime
66   of the character buffer from which the view 66   of the character buffer from which the view
67   is constructed extends unmodified until the 67   is constructed extends unmodified until the
68   view is no longer accessed. 68   view is no longer accessed.
69   */ 69   */
70   class decode_view 70   class decode_view
71   { 71   {
72   char const* p_ = nullptr; 72   char const* p_ = nullptr;
73   std::size_t n_ = 0; 73   std::size_t n_ = 0;
74   std::size_t dn_ = 0; 74   std::size_t dn_ = 0;
75   bool space_as_plus_ = true; 75   bool space_as_plus_ = true;
76   76  
77   template<class... Args> 77   template<class... Args>
78   friend 78   friend
79   decode_view 79   decode_view
80   detail::make_decode_view( 80   detail::make_decode_view(
81   Args&&... args) noexcept; 81   Args&&... args) noexcept;
82   82  
83   // unchecked 83   // unchecked
84   BOOST_CXX14_CONSTEXPR 84   BOOST_CXX14_CONSTEXPR
85   explicit 85   explicit
HITCBC 86   7801 decode_view( 86   7802 decode_view(
87   core::string_view s, 87   core::string_view s,
88   std::size_t n, 88   std::size_t n,
89   encoding_opts opt) noexcept 89   encoding_opts opt) noexcept
HITCBC 90   7801 : p_(s.data()) 90   7802 : p_(s.data())
HITCBC 91   7801 , n_(s.size()) 91   7802 , n_(s.size())
HITCBC 92   7801 , dn_(n) 92   7802 , dn_(n)
HITCBC 93   7801 , space_as_plus_( 93   7802 , space_as_plus_(
HITCBC 94   7801 opt.space_as_plus) 94   7802 opt.space_as_plus)
HITCBC 95   7801 {} 95   7802 {}
96   96  
97   public: 97   public:
98   /** The value type 98   /** The value type
99   */ 99   */
100   using value_type = char; 100   using value_type = char;
101   101  
102   /** The reference type 102   /** The reference type
103   */ 103   */
104   using reference = char; 104   using reference = char;
105   105  
106   /// @copydoc reference 106   /// @copydoc reference
107   using const_reference = char; 107   using const_reference = char;
108   108  
109   /** The unsigned integer type 109   /** The unsigned integer type
110   */ 110   */
111   using size_type = std::size_t; 111   using size_type = std::size_t;
112   112  
113   /** The signed integer type 113   /** The signed integer type
114   */ 114   */
115   using difference_type = std::ptrdiff_t; 115   using difference_type = std::ptrdiff_t;
116   116  
117   /** An iterator of constant, decoded characters. 117   /** An iterator of constant, decoded characters.
118   118  
119   This iterator is used to access the encoded 119   This iterator is used to access the encoded
120   string as a *bidirectional* range of characters 120   string as a *bidirectional* range of characters
121   with percent-decoding applied. Escape sequences 121   with percent-decoding applied. Escape sequences
122   are not decoded until the iterator is 122   are not decoded until the iterator is
123   dereferenced. 123   dereferenced.
124   */ 124   */
125   class iterator; 125   class iterator;
126   126  
127   /// @copydoc iterator 127   /// @copydoc iterator
128   using const_iterator = iterator; 128   using const_iterator = iterator;
129   129  
130   //-------------------------------------------- 130   //--------------------------------------------
131   // 131   //
132   // Special Members 132   // Special Members
133   // 133   //
134   //-------------------------------------------- 134   //--------------------------------------------
135   135  
136   /** Constructor 136   /** Constructor
137   137  
138   Default-constructed views represent 138   Default-constructed views represent
139   empty strings. 139   empty strings.
140   140  
141   @par Example 141   @par Example
142   @code 142   @code
143   decode_view ds; 143   decode_view ds;
144   @endcode 144   @endcode
145   145  
146   @par Postconditions 146   @par Postconditions
147   @code 147   @code
148   this->empty() == true 148   this->empty() == true
149   @endcode 149   @endcode
150   150  
151   @par Complexity 151   @par Complexity
152   Constant. 152   Constant.
153   153  
154   @par Exception Safety 154   @par Exception Safety
155   Throws nothing. 155   Throws nothing.
156   */ 156   */
157   BOOST_CXX14_CONSTEXPR 157   BOOST_CXX14_CONSTEXPR
158   decode_view() noexcept = default; 158   decode_view() noexcept = default;
159   159  
160   /** Constructor 160   /** Constructor
161   161  
162   This constructs a view from the character 162   This constructs a view from the character
163   buffer `s`, which must remain valid and 163   buffer `s`, which must remain valid and
164   unmodified until the view is no longer 164   unmodified until the view is no longer
165   accessed. 165   accessed.
166   166  
167   @par Example 167   @par Example
168   @code 168   @code
169   decode_view ds( "Program%20Files" ); 169   decode_view ds( "Program%20Files" );
170   @endcode 170   @endcode
171   171  
172   @par Postconditions 172   @par Postconditions
173   @code 173   @code
174   this->encoded() == s 174   this->encoded() == s
175   @endcode 175   @endcode
176   176  
177   @par Complexity 177   @par Complexity
178   Linear in `s.size()`. 178   Linear in `s.size()`.
179   179  
180   @par Exception Safety 180   @par Exception Safety
181   Although this function does not throw exceptions, 181   Although this function does not throw exceptions,
182   implicitly constructing a @ref pct_string_view 182   implicitly constructing a @ref pct_string_view
183   for the first argument can throw exceptions 183   for the first argument can throw exceptions
184   on invalid input. 184   on invalid input.
185   185  
186   @param s A percent-encoded string that has 186   @param s A percent-encoded string that has
187   already been validated. Implicit conversion 187   already been validated. Implicit conversion
188   from other string types is supported but 188   from other string types is supported but
189   may throw exceptions. 189   may throw exceptions.
190   190  
191   @param opt The options for decoding. If 191   @param opt The options for decoding. If
192   this parameter is omitted, the default 192   this parameter is omitted, the default
193   options are used. 193   options are used.
194   */ 194   */
195   BOOST_CXX14_CONSTEXPR 195   BOOST_CXX14_CONSTEXPR
196   explicit 196   explicit
HITCBC 197   7801 decode_view( 197   7802 decode_view(
198   pct_string_view s, 198   pct_string_view s,
199   encoding_opts opt = {}) noexcept 199   encoding_opts opt = {}) noexcept
HITCBC 200   7801 : decode_view( 200   7802 : decode_view(
201   detail::to_sv(s), 201   detail::to_sv(s),
202   s.decoded_size(), 202   s.decoded_size(),
HITCBC 203   7801 opt) 203   7802 opt)
204   { 204   {
HITCBC 205   7801 } 205   7802 }
206   206  
207   //-------------------------------------------- 207   //--------------------------------------------
208   // 208   //
209   // Observers 209   // Observers
210   // 210   //
211   //-------------------------------------------- 211   //--------------------------------------------
212   212  
213   /** Return true if the string is empty 213   /** Return true if the string is empty
214   214  
215   @par Example 215   @par Example
216   @code 216   @code
217   assert( decode_view( "" ).empty() ); 217   assert( decode_view( "" ).empty() );
218   @endcode 218   @endcode
219   219  
220   @par Complexity 220   @par Complexity
221   Constant. 221   Constant.
222   222  
223   @par Exception Safety 223   @par Exception Safety
224   Throws nothing. 224   Throws nothing.
225   225  
226   @return `true` if the string is empty 226   @return `true` if the string is empty
227   */ 227   */
228   bool 228   bool
HITCBC 229   10684 empty() const noexcept 229   10684 empty() const noexcept
230   { 230   {
HITCBC 231   10684 return n_ == 0; 231   10684 return n_ == 0;
232   } 232   }
233   233  
234   /** Return the number of decoded characters 234   /** Return the number of decoded characters
235   235  
236   @par Example 236   @par Example
237   @code 237   @code
238   assert( decode_view( "Program%20Files" ).size() == 13 ); 238   assert( decode_view( "Program%20Files" ).size() == 13 );
239   @endcode 239   @endcode
240   240  
241   @par Effects 241   @par Effects
242   @code 242   @code
243   return std::distance( this->begin(), this->end() ); 243   return std::distance( this->begin(), this->end() );
244   @endcode 244   @endcode
245   245  
246   @par Complexity 246   @par Complexity
247   Constant. 247   Constant.
248   248  
249   @par Exception Safety 249   @par Exception Safety
250   Throws nothing. 250   Throws nothing.
251   251  
252   @return The number of decoded characters 252   @return The number of decoded characters
253   */ 253   */
254   size_type 254   size_type
HITCBC 255   11600 size() const noexcept 255   11601 size() const noexcept
256   { 256   {
HITCBC 257   11600 return dn_; 257   11601 return dn_;
258   } 258   }
259   259  
260   /** Return an iterator to the beginning 260   /** Return an iterator to the beginning
261   261  
262   @par Example 262   @par Example
263   @code 263   @code
264   auto it = this->begin(); 264   auto it = this->begin();
265   @endcode 265   @endcode
266   266  
267   @par Complexity 267   @par Complexity
268   Constant. 268   Constant.
269   269  
270   @par Exception Safety 270   @par Exception Safety
271   Throws nothing. 271   Throws nothing.
272   272  
273   @return An iterator to the first decoded character 273   @return An iterator to the first decoded character
274   */ 274   */
275   iterator 275   iterator
276   begin() const noexcept; 276   begin() const noexcept;
277   277  
278   /** Return an iterator to the end 278   /** Return an iterator to the end
279   279  
280   @par Example 280   @par Example
281   @code 281   @code
282   auto it = this->end(); 282   auto it = this->end();
283   @endcode 283   @endcode
284   284  
285   @par Complexity 285   @par Complexity
286   Constant. 286   Constant.
287   287  
288   @par Exception Safety 288   @par Exception Safety
289   Throws nothing. 289   Throws nothing.
290   290  
291   @return An iterator to one past the last decoded character 291   @return An iterator to one past the last decoded character
292   */ 292   */
293   iterator 293   iterator
294   end() const noexcept; 294   end() const noexcept;
295   295  
296   /** Return the first character 296   /** Return the first character
297   297  
298   @par Example 298   @par Example
299   @code 299   @code
300   assert( decode_view( "Program%20Files" ).front() == 'P' ); 300   assert( decode_view( "Program%20Files" ).front() == 'P' );
301   @endcode 301   @endcode
302   302  
303   @par Preconditions 303   @par Preconditions
304   @code 304   @code
305   not this->empty() 305   not this->empty()
306   @endcode 306   @endcode
307   307  
308   @par Complexity 308   @par Complexity
309   Constant. 309   Constant.
310   310  
311   @par Exception Safety 311   @par Exception Safety
312   Throws nothing. 312   Throws nothing.
313   313  
314   @return The first decoded character 314   @return The first decoded character
315   */ 315   */
316   reference 316   reference
317   front() const noexcept; 317   front() const noexcept;
318   318  
319   /** Return the last character 319   /** Return the last character
320   320  
321   @par Example 321   @par Example
322   @code 322   @code
323   assert( decode_view( "Program%20Files" ).back() == 's' ); 323   assert( decode_view( "Program%20Files" ).back() == 's' );
324   @endcode 324   @endcode
325   325  
326   @par Preconditions 326   @par Preconditions
327   @code 327   @code
328   not this->empty() 328   not this->empty()
329   @endcode 329   @endcode
330   330  
331   @par Complexity 331   @par Complexity
332   Constant. 332   Constant.
333   333  
334   @par Exception Safety 334   @par Exception Safety
335   Throws nothing. 335   Throws nothing.
336   336  
337   @return The last decoded character 337   @return The last decoded character
338   */ 338   */
339   reference 339   reference
340   back() const noexcept; 340   back() const noexcept;
341   341  
342   /** Checks if the string begins with the given prefix 342   /** Checks if the string begins with the given prefix
343   343  
344   @par Example 344   @par Example
345   @code 345   @code
346   assert( decode_view( "Program%20Files" ).starts_with("Program") ); 346   assert( decode_view( "Program%20Files" ).starts_with("Program") );
347   @endcode 347   @endcode
348   348  
349   @par Complexity 349   @par Complexity
350   Linear. 350   Linear.
351   351  
352   @par Exception Safety 352   @par Exception Safety
353   Throws nothing. 353   Throws nothing.
354   354  
355   @param s The string to search for 355   @param s The string to search for
356   @return `true` if the decoded string starts with `s` 356   @return `true` if the decoded string starts with `s`
357   */ 357   */
358   BOOST_URL_DECL 358   BOOST_URL_DECL
359   bool 359   bool
360   starts_with( core::string_view s ) const noexcept; 360   starts_with( core::string_view s ) const noexcept;
361   361  
362   /** Checks if the string ends with the given prefix 362   /** Checks if the string ends with the given prefix
363   363  
364   @par Example 364   @par Example
365   @code 365   @code
366   assert( decode_view( "Program%20Files" ).ends_with("Files") ); 366   assert( decode_view( "Program%20Files" ).ends_with("Files") );
367   @endcode 367   @endcode
368   368  
369   @par Complexity 369   @par Complexity
370   Linear. 370   Linear.
371   371  
372   @par Exception Safety 372   @par Exception Safety
373   Throws nothing. 373   Throws nothing.
374   374  
375   @param s The string to search for 375   @param s The string to search for
376   @return `true` if the decoded string ends with `s` 376   @return `true` if the decoded string ends with `s`
377   */ 377   */
378   BOOST_URL_DECL 378   BOOST_URL_DECL
379   bool 379   bool
380   ends_with( core::string_view s ) const noexcept; 380   ends_with( core::string_view s ) const noexcept;
381   381  
382   /** Checks if the string begins with the given prefix 382   /** Checks if the string begins with the given prefix
383   383  
384   @par Example 384   @par Example
385   @code 385   @code
386   assert( decode_view( "Program%20Files" ).starts_with('P') ); 386   assert( decode_view( "Program%20Files" ).starts_with('P') );
387   @endcode 387   @endcode
388   388  
389   @par Complexity 389   @par Complexity
390   Constant. 390   Constant.
391   391  
392   @par Exception Safety 392   @par Exception Safety
393   Throws nothing. 393   Throws nothing.
394   394  
395   @param ch The character to search for 395   @param ch The character to search for
396   @return `true` if the decoded string starts with `ch` 396   @return `true` if the decoded string starts with `ch`
397   */ 397   */
398   BOOST_URL_DECL 398   BOOST_URL_DECL
399   bool 399   bool
400   starts_with( char ch ) const noexcept; 400   starts_with( char ch ) const noexcept;
401   401  
402   /** Checks if the string ends with the given prefix 402   /** Checks if the string ends with the given prefix
403   403  
404   @par Example 404   @par Example
405   @code 405   @code
406   assert( decode_view( "Program%20Files" ).ends_with('s') ); 406   assert( decode_view( "Program%20Files" ).ends_with('s') );
407   @endcode 407   @endcode
408   408  
409   @par Complexity 409   @par Complexity
410   Constant. 410   Constant.
411   411  
412   @par Exception Safety 412   @par Exception Safety
413   Throws nothing. 413   Throws nothing.
414   414  
415   @param ch The character to search for 415   @param ch The character to search for
416   @return `true` if the decoded string ends with `ch` 416   @return `true` if the decoded string ends with `ch`
417   */ 417   */
418   BOOST_URL_DECL 418   BOOST_URL_DECL
419   bool 419   bool
420   ends_with( char ch ) const noexcept; 420   ends_with( char ch ) const noexcept;
421   421  
422   /** Finds the first occurrence of character in this view 422   /** Finds the first occurrence of character in this view
423   423  
424   @par Complexity 424   @par Complexity
425   Linear. 425   Linear.
426   426  
427   @par Exception Safety 427   @par Exception Safety
428   Throws nothing. 428   Throws nothing.
429   429  
430   @param ch The character to search for 430   @param ch The character to search for
431   @return An iterator to the first decoded occurrence of `ch` or `end()` 431   @return An iterator to the first decoded occurrence of `ch` or `end()`
432   */ 432   */
433   BOOST_URL_DECL 433   BOOST_URL_DECL
434   const_iterator 434   const_iterator
435   find( char ch ) const noexcept; 435   find( char ch ) const noexcept;
436   436  
437   /** Finds the first occurrence of character in this view 437   /** Finds the first occurrence of character in this view
438   438  
439   @par Complexity 439   @par Complexity
440   Linear. 440   Linear.
441   441  
442   @par Exception Safety 442   @par Exception Safety
443   Throws nothing. 443   Throws nothing.
444   444  
445   @param ch The character to search for 445   @param ch The character to search for
446   @return An iterator to the last occurrence of `ch` or `end()` 446   @return An iterator to the last occurrence of `ch` or `end()`
447   */ 447   */
448   BOOST_URL_DECL 448   BOOST_URL_DECL
449   const_iterator 449   const_iterator
450   rfind( char ch ) const noexcept; 450   rfind( char ch ) const noexcept;
451   451  
452   /** Remove the first characters 452   /** Remove the first characters
453   453  
454   @par Example 454   @par Example
455   @code 455   @code
456   decode_view d( "Program%20Files" ); 456   decode_view d( "Program%20Files" );
457   d.remove_prefix( 8 ); 457   d.remove_prefix( 8 );
458   assert( d == "Files" ); 458   assert( d == "Files" );
459   @endcode 459   @endcode
460   460  
461   @par Preconditions 461   @par Preconditions
462   @code 462   @code
463   n <= this->size() 463   n <= this->size()
464   @endcode 464   @endcode
465   465  
466   @par Complexity 466   @par Complexity
467   Linear. 467   Linear.
468   468  
469   @param n The number of characters to remove 469   @param n The number of characters to remove
470   */ 470   */
471   BOOST_URL_DECL 471   BOOST_URL_DECL
472   void 472   void
473   remove_prefix( size_type n ); 473   remove_prefix( size_type n );
474   474  
475   /** Remove the last characters 475   /** Remove the last characters
476   476  
477   @par Example 477   @par Example
478   @code 478   @code
479   decode_view d( "Program%20Files" ); 479   decode_view d( "Program%20Files" );
480   d.remove_suffix( 6 ); 480   d.remove_suffix( 6 );
481   assert( d == "Program" ); 481   assert( d == "Program" );
482   @endcode 482   @endcode
483   483  
484   @par Preconditions 484   @par Preconditions
485   @code 485   @code
486   n <= this->size() 486   n <= this->size()
487   @endcode 487   @endcode
488   488  
489   @par Complexity 489   @par Complexity
490   Linear. 490   Linear.
491   491  
492   @param n The number of characters to remove 492   @param n The number of characters to remove
493   */ 493   */
494   BOOST_URL_DECL 494   BOOST_URL_DECL
495   void 495   void
496   remove_suffix( size_type n ); 496   remove_suffix( size_type n );
497   497  
498   /** Return the decoding options 498   /** Return the decoding options
499   499  
500   @return The decoding options used by this view 500   @return The decoding options used by this view
501   */ 501   */
502   encoding_opts 502   encoding_opts
503   options() const noexcept 503   options() const noexcept
504   { 504   {
505   encoding_opts opt; 505   encoding_opts opt;
506   opt.space_as_plus = space_as_plus_; 506   opt.space_as_plus = space_as_plus_;
507   return opt; 507   return opt;
508   } 508   }
509   509  
510   //-------------------------------------------- 510   //--------------------------------------------
511   // 511   //
512   // Comparison 512   // Comparison
513   // 513   //
514   //-------------------------------------------- 514   //--------------------------------------------
515   515  
516   /** Return the result of comparing to another string 516   /** Return the result of comparing to another string
517   517  
518   The length of the sequences to compare is the smaller of 518   The length of the sequences to compare is the smaller of
519   `size()` and `other.size()`. 519   `size()` and `other.size()`.
520   520  
521   The function compares the two strings as if by calling 521   The function compares the two strings as if by calling
522   `char_traits<char>::compare(to_string().data(), v.data(), rlen)`. 522   `char_traits<char>::compare(to_string().data(), v.data(), rlen)`.
523   This means the comparison is performed with 523   This means the comparison is performed with
524   percent-decoding applied to the current string. 524   percent-decoding applied to the current string.
525   525  
526   @param other string to compare 526   @param other string to compare
527   527  
528   @return Negative value if this string is less than the other 528   @return Negative value if this string is less than the other
529   character sequence, zero if the both character sequences are 529   character sequence, zero if the both character sequences are
530   equal, positive value if this string is greater than the other 530   equal, positive value if this string is greater than the other
531   character sequence 531   character sequence
532   */ 532   */
533   BOOST_CXX14_CONSTEXPR 533   BOOST_CXX14_CONSTEXPR
534   int 534   int
535   compare(core::string_view other) const noexcept; 535   compare(core::string_view other) const noexcept;
536   536  
537   /** Return the result of comparing to another string 537   /** Return the result of comparing to another string
538   538  
539   The length of the sequences to compare is the smaller of 539   The length of the sequences to compare is the smaller of
540   `size()` and `other.size()`. 540   `size()` and `other.size()`.
541   541  
542   The function compares the two strings as if by calling 542   The function compares the two strings as if by calling
543   `char_traits<char>::compare(to_string().data(), v.to_string().data(), rlen)`. 543   `char_traits<char>::compare(to_string().data(), v.to_string().data(), rlen)`.
544   This means the comparison is performed with 544   This means the comparison is performed with
545   percent-decoding applied to the current string. 545   percent-decoding applied to the current string.
546   546  
547   @param other string to compare 547   @param other string to compare
548   548  
549   @return Negative value if this string is less than the other 549   @return Negative value if this string is less than the other
550   character sequence, zero if the both character sequences are 550   character sequence, zero if the both character sequences are
551   equal, positive value if this string is greater than the other 551   equal, positive value if this string is greater than the other
552   character sequence 552   character sequence
553   */ 553   */
554   BOOST_CXX14_CONSTEXPR 554   BOOST_CXX14_CONSTEXPR
555   int 555   int
556   compare(decode_view other) const noexcept; 556   compare(decode_view other) const noexcept;
557   557  
558   //-------------------------------------------- 558   //--------------------------------------------
559   559  
560   // relational operators 560   // relational operators
561   private: 561   private:
562   template<class S0, class S1> 562   template<class S0, class S1>
563   using is_match = std::integral_constant<bool, 563   using is_match = std::integral_constant<bool,
564   // both decode_view or convertible to core::string_view 564   // both decode_view or convertible to core::string_view
565   ( 565   (
566   std::is_same<typename std::decay<S0>::type, decode_view>::value || 566   std::is_same<typename std::decay<S0>::type, decode_view>::value ||
567   std::is_convertible<S0, core::string_view>::value) && 567   std::is_convertible<S0, core::string_view>::value) &&
568   ( 568   (
569   std::is_same<typename std::decay<S1>::type, decode_view>::value || 569   std::is_same<typename std::decay<S1>::type, decode_view>::value ||
570   std::is_convertible<S1, core::string_view>::value) && 570   std::is_convertible<S1, core::string_view>::value) &&
571   // not both are convertible to string view 571   // not both are convertible to string view
572   ( 572   (
573   !std::is_convertible<S0, core::string_view>::value || 573   !std::is_convertible<S0, core::string_view>::value ||
574   !std::is_convertible<S1, core::string_view>::value)>; 574   !std::is_convertible<S1, core::string_view>::value)>;
575   575  
576   BOOST_CXX14_CONSTEXPR 576   BOOST_CXX14_CONSTEXPR
577   static 577   static
578   int 578   int
HITCBC 579   332 decode_compare(decode_view s0, decode_view s1) noexcept 579   332 decode_compare(decode_view s0, decode_view s1) noexcept
580   { 580   {
HITCBC 581   332 return s0.compare(s1); 581   332 return s0.compare(s1);
582   } 582   }
583   583  
584   template <class S> 584   template <class S>
585   BOOST_CXX14_CONSTEXPR 585   BOOST_CXX14_CONSTEXPR
586   static 586   static
587   int 587   int
HITCBC 588   3291 decode_compare(decode_view s0, S const& s1) noexcept 588   3292 decode_compare(decode_view s0, S const& s1) noexcept
589   { 589   {
HITCBC 590   3291 return s0.compare(s1); 590   3292 return s0.compare(s1);
591   } 591   }
592   592  
593   template <class S> 593   template <class S>
594   BOOST_CXX14_CONSTEXPR 594   BOOST_CXX14_CONSTEXPR
595   static 595   static
596   int 596   int
597   decode_compare(S const& s0, decode_view s1) noexcept 597   decode_compare(S const& s0, decode_view s1) noexcept
598   { 598   {
599   return -s1.compare(s0); 599   return -s1.compare(s0);
600   } 600   }
601   601  
602   public: 602   public:
603   #ifndef BOOST_URL_HAS_CONCEPTS 603   #ifndef BOOST_URL_HAS_CONCEPTS
604   /** Compare two decode views for equality 604   /** Compare two decode views for equality
605   605  
606   @param lhs The left-hand-side decode view to compare 606   @param lhs The left-hand-side decode view to compare
607   @param rhs The right-hand-side decode view to compare 607   @param rhs The right-hand-side decode view to compare
608   @return `true` if decoded `lhs` is equal to the decoded `rhs` 608   @return `true` if decoded `lhs` is equal to the decoded `rhs`
609   */ 609   */
610   template<class S0, class S1> 610   template<class S0, class S1>
HITCBC 611   2748 BOOST_CXX14_CONSTEXPR friend auto operator==( 611   2749 BOOST_CXX14_CONSTEXPR friend auto operator==(
612   S0 const& lhs, S1 const& rhs) noexcept -> 612   S0 const& lhs, S1 const& rhs) noexcept ->
613   typename std::enable_if< 613   typename std::enable_if<
614   is_match<S0, S1>::value, bool>::type 614   is_match<S0, S1>::value, bool>::type
615   { 615   {
HITCBC 616   2748 return decode_compare(lhs, rhs) == 0; 616   2749 return decode_compare(lhs, rhs) == 0;
617   } 617   }
618   #else 618   #else
619   /** Compare two decode views for equality 619   /** Compare two decode views for equality
620   620  
621   @param lhs The left-hand-side decode view to compare 621   @param lhs The left-hand-side decode view to compare
622   @param rhs The right-hand-side decode view to compare 622   @param rhs The right-hand-side decode view to compare
623   @return `true` if decoded `lhs` is equal to the decoded `rhs` 623   @return `true` if decoded `lhs` is equal to the decoded `rhs`
624   */ 624   */
625   BOOST_CXX14_CONSTEXPR 625   BOOST_CXX14_CONSTEXPR
626   friend 626   friend
627   bool 627   bool
628   operator==( 628   operator==(
629   decode_view const& lhs, 629   decode_view const& lhs,
630   decode_view const& rhs) noexcept 630   decode_view const& rhs) noexcept
631   { 631   {
632   return decode_compare(lhs, rhs) == 0; 632   return decode_compare(lhs, rhs) == 0;
633   } 633   }
634   634  
635   /** Compare two decode views for equality 635   /** Compare two decode views for equality
636   636  
637   @param lhs The left-hand-side decode view to compare 637   @param lhs The left-hand-side decode view to compare
638   @param rhs The right-hand-side decode view to compare 638   @param rhs The right-hand-side decode view to compare
639   @return `true` if decoded `lhs` is equal to the decoded `rhs` 639   @return `true` if decoded `lhs` is equal to the decoded `rhs`
640   */ 640   */
641   template <std::convertible_to<core::string_view> S> 641   template <std::convertible_to<core::string_view> S>
642   BOOST_CXX14_CONSTEXPR 642   BOOST_CXX14_CONSTEXPR
643   friend 643   friend
644   bool 644   bool
645   operator==( 645   operator==(
646   decode_view const& lhs, 646   decode_view const& lhs,
647   S const& rhs) noexcept 647   S const& rhs) noexcept
648   { 648   {
649   return decode_compare(lhs, rhs) == 0; 649   return decode_compare(lhs, rhs) == 0;
650   } 650   }
651   651  
652   /** Compare two decode views for equality 652   /** Compare two decode views for equality
653   653  
654   @param lhs The left-hand-side decode view to compare 654   @param lhs The left-hand-side decode view to compare
655   @param rhs The right-hand-side decode view to compare 655   @param rhs The right-hand-side decode view to compare
656   @return `true` if decoded `lhs` is equal to the decoded `rhs` 656   @return `true` if decoded `lhs` is equal to the decoded `rhs`
657   */ 657   */
658   template <std::convertible_to<core::string_view> S> 658   template <std::convertible_to<core::string_view> S>
659   BOOST_CXX14_CONSTEXPR 659   BOOST_CXX14_CONSTEXPR
660   friend 660   friend
661   bool 661   bool
662   operator==( 662   operator==(
663   S const& lhs, 663   S const& lhs,
664   decode_view const& rhs) noexcept 664   decode_view const& rhs) noexcept
665   { 665   {
666   return decode_compare(lhs, rhs) == 0; 666   return decode_compare(lhs, rhs) == 0;
667   } 667   }
668   #endif 668   #endif
669   669  
670   #ifndef BOOST_URL_HAS_CONCEPTS 670   #ifndef BOOST_URL_HAS_CONCEPTS
671   /** Compare two decode views for inequality 671   /** Compare two decode views for inequality
672   672  
673   @param lhs The left-hand-side decode view to compare 673   @param lhs The left-hand-side decode view to compare
674   @param rhs The right-hand-side decode view to compare 674   @param rhs The right-hand-side decode view to compare
675   @return `true` if decoded `lhs` is not equal to the decoded `rhs` 675   @return `true` if decoded `lhs` is not equal to the decoded `rhs`
676   */ 676   */
677   template<class S0, class S1> 677   template<class S0, class S1>
HITCBC 678   843 BOOST_CXX14_CONSTEXPR friend auto operator!=( 678   843 BOOST_CXX14_CONSTEXPR friend auto operator!=(
679   S0 const& lhs, S1 const& rhs) noexcept -> 679   S0 const& lhs, S1 const& rhs) noexcept ->
680   typename std::enable_if< 680   typename std::enable_if<
681   is_match<S0, S1>::value, bool>::type 681   is_match<S0, S1>::value, bool>::type
682   { 682   {
HITCBC 683   843 return decode_compare(lhs, rhs) != 0; 683   843 return decode_compare(lhs, rhs) != 0;
684   } 684   }
685   #else 685   #else
686   /** Compare two decode views for inequality 686   /** Compare two decode views for inequality
687   687  
688   @param lhs The left-hand-side decode view to compare 688   @param lhs The left-hand-side decode view to compare
689   @param rhs The right-hand-side decode view to compare 689   @param rhs The right-hand-side decode view to compare
690   @return `true` if decoded `lhs` is not equal to the decoded `rhs` 690   @return `true` if decoded `lhs` is not equal to the decoded `rhs`
691   */ 691   */
692   BOOST_CXX14_CONSTEXPR 692   BOOST_CXX14_CONSTEXPR
693   friend 693   friend
694   bool 694   bool
695   operator!=( 695   operator!=(
696   decode_view const& lhs, 696   decode_view const& lhs,
697   decode_view const& rhs) noexcept 697   decode_view const& rhs) noexcept
698   { 698   {
699   return decode_compare(lhs, rhs) != 0; 699   return decode_compare(lhs, rhs) != 0;
700   } 700   }
701   701  
702   /** Compare two decode views for inequality 702   /** Compare two decode views for inequality
703   703  
704   @param lhs The left-hand-side decode view to compare 704   @param lhs The left-hand-side decode view to compare
705   @param rhs The right-hand-side decode view to compare 705   @param rhs The right-hand-side decode view to compare
706   @return `true` if decoded `lhs` is not equal to the decoded `rhs` 706   @return `true` if decoded `lhs` is not equal to the decoded `rhs`
707   */ 707   */
708   template <std::convertible_to<core::string_view> S> 708   template <std::convertible_to<core::string_view> S>
709   BOOST_CXX14_CONSTEXPR 709   BOOST_CXX14_CONSTEXPR
710   friend 710   friend
711   bool 711   bool
712   operator!=( 712   operator!=(
713   decode_view const& lhs, 713   decode_view const& lhs,
714   S const& rhs) noexcept 714   S const& rhs) noexcept
715   { 715   {
716   return decode_compare(lhs, rhs) != 0; 716   return decode_compare(lhs, rhs) != 0;
717   } 717   }
718   718  
719   /** Compare two decode views for inequality 719   /** Compare two decode views for inequality
720   720  
721   @param lhs The left-hand-side decode view to compare 721   @param lhs The left-hand-side decode view to compare
722   @param rhs The right-hand-side decode view to compare 722   @param rhs The right-hand-side decode view to compare
723   @return `true` if decoded `lhs` is not equal to the decoded `rhs` 723   @return `true` if decoded `lhs` is not equal to the decoded `rhs`
724   */ 724   */
725   template <std::convertible_to<core::string_view> S> 725   template <std::convertible_to<core::string_view> S>
726   BOOST_CXX14_CONSTEXPR 726   BOOST_CXX14_CONSTEXPR
727   friend 727   friend
728   bool 728   bool
729   operator!=( 729   operator!=(
730   S const& lhs, 730   S const& lhs,
731   decode_view const& rhs) noexcept 731   decode_view const& rhs) noexcept
732   { 732   {
733   return decode_compare(lhs, rhs) != 0; 733   return decode_compare(lhs, rhs) != 0;
734   } 734   }
735   #endif 735   #endif
736   736  
737   #ifndef BOOST_URL_HAS_CONCEPTS 737   #ifndef BOOST_URL_HAS_CONCEPTS
738   /** Compare two decode views for less than 738   /** Compare two decode views for less than
739   739  
740   @param lhs The left-hand-side decode view to compare 740   @param lhs The left-hand-side decode view to compare
741   @param rhs The right-hand-side decode view to compare 741   @param rhs The right-hand-side decode view to compare
742   @return `true` if decoded `lhs` is less than to the decoded `rhs` 742   @return `true` if decoded `lhs` is less than to the decoded `rhs`
743   */ 743   */
744   template<class S0, class S1> 744   template<class S0, class S1>
HITCBC 745   8 BOOST_CXX14_CONSTEXPR friend auto operator<( 745   8 BOOST_CXX14_CONSTEXPR friend auto operator<(
746   S0 const& lhs, S1 const& rhs) noexcept -> 746   S0 const& lhs, S1 const& rhs) noexcept ->
747   typename std::enable_if< 747   typename std::enable_if<
748   is_match<S0, S1>::value, bool>::type 748   is_match<S0, S1>::value, bool>::type
749   { 749   {
HITCBC 750   8 return decode_compare(lhs, rhs) < 0; 750   8 return decode_compare(lhs, rhs) < 0;
751   } 751   }
752   #else 752   #else
753   /** Compare two decode views for less than 753   /** Compare two decode views for less than
754   754  
755   @param lhs The left-hand-side decode view to compare 755   @param lhs The left-hand-side decode view to compare
756   @param rhs The right-hand-side decode view to compare 756   @param rhs The right-hand-side decode view to compare
757   @return `true` if decoded `lhs` is less than to the decoded `rhs` 757   @return `true` if decoded `lhs` is less than to the decoded `rhs`
758   */ 758   */
759   BOOST_CXX14_CONSTEXPR 759   BOOST_CXX14_CONSTEXPR
760   friend 760   friend
761   bool 761   bool
762   operator<( 762   operator<(
763   decode_view const& lhs, 763   decode_view const& lhs,
764   decode_view const& rhs) noexcept 764   decode_view const& rhs) noexcept
765   { 765   {
766   return decode_compare(lhs, rhs) < 0; 766   return decode_compare(lhs, rhs) < 0;
767   } 767   }
768   768  
769   /** Compare two decode views for less than 769   /** Compare two decode views for less than
770   770  
771   @param lhs The left-hand-side decode view to compare 771   @param lhs The left-hand-side decode view to compare
772   @param rhs The right-hand-side decode view to compare 772   @param rhs The right-hand-side decode view to compare
773   @return `true` if decoded `lhs` is less than to the decoded `rhs` 773   @return `true` if decoded `lhs` is less than to the decoded `rhs`
774   */ 774   */
775   template <std::convertible_to<core::string_view> S> 775   template <std::convertible_to<core::string_view> S>
776   BOOST_CXX14_CONSTEXPR 776   BOOST_CXX14_CONSTEXPR
777   friend 777   friend
778   bool 778   bool
779   operator<( 779   operator<(
780   decode_view const& lhs, 780   decode_view const& lhs,
781   S const& rhs) noexcept 781   S const& rhs) noexcept
782   { 782   {
783   return decode_compare(lhs, rhs) < 0; 783   return decode_compare(lhs, rhs) < 0;
784   } 784   }
785   785  
786   /** Compare two decode views for less than 786   /** Compare two decode views for less than
787   787  
788   @param lhs The left-hand-side decode view to compare 788   @param lhs The left-hand-side decode view to compare
789   @param rhs The right-hand-side decode view to compare 789   @param rhs The right-hand-side decode view to compare
790   @return `true` if decoded `lhs` is less than to the decoded `rhs` 790   @return `true` if decoded `lhs` is less than to the decoded `rhs`
791   */ 791   */
792   template <std::convertible_to<core::string_view> S> 792   template <std::convertible_to<core::string_view> S>
793   BOOST_CXX14_CONSTEXPR 793   BOOST_CXX14_CONSTEXPR
794   friend 794   friend
795   bool 795   bool
796   operator<( 796   operator<(
797   S const& lhs, 797   S const& lhs,
798   decode_view const& rhs) noexcept 798   decode_view const& rhs) noexcept
799   { 799   {
800   return decode_compare(lhs, rhs) < 0; 800   return decode_compare(lhs, rhs) < 0;
801   } 801   }
802   #endif 802   #endif
803   803  
804   #ifndef BOOST_URL_HAS_CONCEPTS 804   #ifndef BOOST_URL_HAS_CONCEPTS
805   /** Compare two decode views for less than or equal 805   /** Compare two decode views for less than or equal
806   806  
807   @param lhs The left-hand-side decode view to compare 807   @param lhs The left-hand-side decode view to compare
808   @param rhs The right-hand-side decode view to compare 808   @param rhs The right-hand-side decode view to compare
809   @return `true` if decoded `lhs` is less than or equal to the decoded `rhs` 809   @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
810   */ 810   */
811   template<class S0, class S1> 811   template<class S0, class S1>
HITCBC 812   8 BOOST_CXX14_CONSTEXPR friend auto operator<=( 812   8 BOOST_CXX14_CONSTEXPR friend auto operator<=(
813   S0 const& lhs, S1 const& rhs) noexcept -> 813   S0 const& lhs, S1 const& rhs) noexcept ->
814   typename std::enable_if< 814   typename std::enable_if<
815   is_match<S0, S1>::value, bool>::type 815   is_match<S0, S1>::value, bool>::type
816   { 816   {
HITCBC 817   8 return decode_compare(lhs, rhs) <= 0; 817   8 return decode_compare(lhs, rhs) <= 0;
818   } 818   }
819   #else 819   #else
820   /** Compare two decode views for less than or equal 820   /** Compare two decode views for less than or equal
821   821  
822   @param lhs The left-hand-side decode view to compare 822   @param lhs The left-hand-side decode view to compare
823   @param rhs The right-hand-side decode view to compare 823   @param rhs The right-hand-side decode view to compare
824   @return `true` if decoded `lhs` is less than or equal to the decoded `rhs` 824   @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
825   */ 825   */
826   BOOST_CXX14_CONSTEXPR 826   BOOST_CXX14_CONSTEXPR
827   friend 827   friend
828   bool 828   bool
829   operator<=( 829   operator<=(
830   decode_view const& lhs, 830   decode_view const& lhs,
831   decode_view const& rhs) noexcept 831   decode_view const& rhs) noexcept
832   { 832   {
833   return decode_compare(lhs, rhs) <= 0; 833   return decode_compare(lhs, rhs) <= 0;
834   } 834   }
835   835  
836   /** Compare two decode views for less than or equal 836   /** Compare two decode views for less than or equal
837   837  
838   @param lhs The left-hand-side decode view to compare 838   @param lhs The left-hand-side decode view to compare
839   @param rhs The right-hand-side decode view to compare 839   @param rhs The right-hand-side decode view to compare
840   @return `true` if decoded `lhs` is less than or equal to the decoded `rhs` 840   @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
841   */ 841   */
842   template <std::convertible_to<core::string_view> S> 842   template <std::convertible_to<core::string_view> S>
843   BOOST_CXX14_CONSTEXPR 843   BOOST_CXX14_CONSTEXPR
844   friend 844   friend
845   bool 845   bool
846   operator<=( 846   operator<=(
847   decode_view const& lhs, 847   decode_view const& lhs,
848   S const& rhs) noexcept 848   S const& rhs) noexcept
849   { 849   {
850   return decode_compare(lhs, rhs) <= 0; 850   return decode_compare(lhs, rhs) <= 0;
851   } 851   }
852   852  
853   /** Compare two decode views for less than or equal 853   /** Compare two decode views for less than or equal
854   854  
855   @param lhs The left-hand-side decode view to compare 855   @param lhs The left-hand-side decode view to compare
856   @param rhs The right-hand-side decode view to compare 856   @param rhs The right-hand-side decode view to compare
857   @return `true` if decoded `lhs` is less than or equal to the decoded `rhs` 857   @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
858   */ 858   */
859   template <std::convertible_to<core::string_view> S> 859   template <std::convertible_to<core::string_view> S>
860   BOOST_CXX14_CONSTEXPR 860   BOOST_CXX14_CONSTEXPR
861   friend 861   friend
862   bool 862   bool
863   operator<=( 863   operator<=(
864   S const& lhs, 864   S const& lhs,
865   decode_view const& rhs) noexcept 865   decode_view const& rhs) noexcept
866   { 866   {
867   return decode_compare(lhs, rhs) <= 0; 867   return decode_compare(lhs, rhs) <= 0;
868   } 868   }
869   #endif 869   #endif
870   870  
871   #ifndef BOOST_URL_HAS_CONCEPTS 871   #ifndef BOOST_URL_HAS_CONCEPTS
872   /** Compare two decode views for greater than 872   /** Compare two decode views for greater than
873   873  
874   @param lhs The left-hand-side decode view to compare 874   @param lhs The left-hand-side decode view to compare
875   @param rhs The right-hand-side decode view to compare 875   @param rhs The right-hand-side decode view to compare
876   @return `true` if decoded `lhs` is greater than to the decoded `rhs` 876   @return `true` if decoded `lhs` is greater than to the decoded `rhs`
877   */ 877   */
878   template<class S0, class S1> 878   template<class S0, class S1>
HITCBC 879   8 BOOST_CXX14_CONSTEXPR friend auto operator>( 879   8 BOOST_CXX14_CONSTEXPR friend auto operator>(
880   S0 const& lhs, S1 const& rhs) noexcept -> 880   S0 const& lhs, S1 const& rhs) noexcept ->
881   typename std::enable_if< 881   typename std::enable_if<
882   is_match<S0, S1>::value, bool>::type 882   is_match<S0, S1>::value, bool>::type
883   { 883   {
HITCBC 884   8 return decode_compare(lhs, rhs) > 0; 884   8 return decode_compare(lhs, rhs) > 0;
885   } 885   }
886   #else 886   #else
887   /** Compare two decode views for greater than 887   /** Compare two decode views for greater than
888   888  
889   @param lhs The left-hand-side decode view to compare 889   @param lhs The left-hand-side decode view to compare
890   @param rhs The right-hand-side decode view to compare 890   @param rhs The right-hand-side decode view to compare
891   @return `true` if decoded `lhs` is greater than to the decoded `rhs` 891   @return `true` if decoded `lhs` is greater than to the decoded `rhs`
892   */ 892   */
893   BOOST_CXX14_CONSTEXPR 893   BOOST_CXX14_CONSTEXPR
894   friend 894   friend
895   bool 895   bool
896   operator>( 896   operator>(
897   decode_view const& lhs, 897   decode_view const& lhs,
898   decode_view const& rhs) noexcept 898   decode_view const& rhs) noexcept
899   { 899   {
900   return decode_compare(lhs, rhs) > 0; 900   return decode_compare(lhs, rhs) > 0;
901   } 901   }
902   902  
903   /** Compare two decode views for greater than 903   /** Compare two decode views for greater than
904   904  
905   @param lhs The left-hand-side decode view to compare 905   @param lhs The left-hand-side decode view to compare
906   @param rhs The right-hand-side decode view to compare 906   @param rhs The right-hand-side decode view to compare
907   @return `true` if decoded `lhs` is greater than to the decoded `rhs` 907   @return `true` if decoded `lhs` is greater than to the decoded `rhs`
908   */ 908   */
909   template <std::convertible_to<core::string_view> S> 909   template <std::convertible_to<core::string_view> S>
910   BOOST_CXX14_CONSTEXPR 910   BOOST_CXX14_CONSTEXPR
911   friend 911   friend
912   bool 912   bool
913   operator>( 913   operator>(
914   decode_view const& lhs, 914   decode_view const& lhs,
915   S const& rhs) noexcept 915   S const& rhs) noexcept
916   { 916   {
917   return decode_compare(lhs, rhs) > 0; 917   return decode_compare(lhs, rhs) > 0;
918   } 918   }
919   919  
920   /** Compare two decode views for greater than 920   /** Compare two decode views for greater than
921   921  
922   @param lhs The left-hand-side decode view to compare 922   @param lhs The left-hand-side decode view to compare
923   @param rhs The right-hand-side decode view to compare 923   @param rhs The right-hand-side decode view to compare
924   @return `true` if decoded `lhs` is greater than to the decoded `rhs` 924   @return `true` if decoded `lhs` is greater than to the decoded `rhs`
925   */ 925   */
926   template <std::convertible_to<core::string_view> S> 926   template <std::convertible_to<core::string_view> S>
927   BOOST_CXX14_CONSTEXPR 927   BOOST_CXX14_CONSTEXPR
928   friend 928   friend
929   bool 929   bool
930   operator>( 930   operator>(
931   S const& lhs, 931   S const& lhs,
932   decode_view const& rhs) noexcept 932   decode_view const& rhs) noexcept
933   { 933   {
934   return decode_compare(lhs, rhs) > 0; 934   return decode_compare(lhs, rhs) > 0;
935   } 935   }
936   #endif 936   #endif
937   937  
938   #ifndef BOOST_URL_HAS_CONCEPTS 938   #ifndef BOOST_URL_HAS_CONCEPTS
939   /** Compare two decode views for greater than or equal 939   /** Compare two decode views for greater than or equal
940   940  
941   @param lhs The left-hand-side decode view to compare 941   @param lhs The left-hand-side decode view to compare
942   @param rhs The right-hand-side decode view to compare 942   @param rhs The right-hand-side decode view to compare
943   @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs` 943   @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
944   */ 944   */
945   template<class S0, class S1> 945   template<class S0, class S1>
HITCBC 946   8 BOOST_CXX14_CONSTEXPR friend auto operator>=( 946   8 BOOST_CXX14_CONSTEXPR friend auto operator>=(
947   S0 const& lhs, S1 const& rhs) noexcept -> 947   S0 const& lhs, S1 const& rhs) noexcept ->
948   typename std::enable_if< 948   typename std::enable_if<
949   is_match<S0, S1>::value, bool>::type 949   is_match<S0, S1>::value, bool>::type
950   { 950   {
HITCBC 951   8 return decode_compare(lhs, rhs) >= 0; 951   8 return decode_compare(lhs, rhs) >= 0;
952   } 952   }
953   #else 953   #else
954   /** Compare two decode views for greater than or equal 954   /** Compare two decode views for greater than or equal
955   955  
956   @param lhs The left-hand-side decode view to compare 956   @param lhs The left-hand-side decode view to compare
957   @param rhs The right-hand-side decode view to compare 957   @param rhs The right-hand-side decode view to compare
958   @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs` 958   @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
959   */ 959   */
960   BOOST_CXX14_CONSTEXPR 960   BOOST_CXX14_CONSTEXPR
961   friend 961   friend
962   bool 962   bool
963   operator>=( 963   operator>=(
964   decode_view const& lhs, 964   decode_view const& lhs,
965   decode_view const& rhs) noexcept 965   decode_view const& rhs) noexcept
966   { 966   {
967   return decode_compare(lhs, rhs) >= 0; 967   return decode_compare(lhs, rhs) >= 0;
968   } 968   }
969   969  
970   /** Compare two decode views for greater than or equal 970   /** Compare two decode views for greater than or equal
971   971  
972   @param lhs The left-hand-side decode view to compare 972   @param lhs The left-hand-side decode view to compare
973   @param rhs The right-hand-side decode view to compare 973   @param rhs The right-hand-side decode view to compare
974   @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs` 974   @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
975   */ 975   */
976   template <std::convertible_to<core::string_view> S> 976   template <std::convertible_to<core::string_view> S>
977   BOOST_CXX14_CONSTEXPR 977   BOOST_CXX14_CONSTEXPR
978   friend 978   friend
979   bool 979   bool
980   operator>=( 980   operator>=(
981   decode_view const& lhs, 981   decode_view const& lhs,
982   S const& rhs) noexcept 982   S const& rhs) noexcept
983   { 983   {
984   return decode_compare(lhs, rhs) >= 0; 984   return decode_compare(lhs, rhs) >= 0;
985   } 985   }
986   986  
987   /** Compare two decode views for greater than or equal 987   /** Compare two decode views for greater than or equal
988   988  
989   @param lhs The left-hand-side decode view to compare 989   @param lhs The left-hand-side decode view to compare
990   @param rhs The right-hand-side decode view to compare 990   @param rhs The right-hand-side decode view to compare
991   @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs` 991   @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
992   */ 992   */
993   template <std::convertible_to<core::string_view> S> 993   template <std::convertible_to<core::string_view> S>
994   BOOST_CXX14_CONSTEXPR 994   BOOST_CXX14_CONSTEXPR
995   friend 995   friend
996   bool 996   bool
997   operator>=( 997   operator>=(
998   S const& lhs, 998   S const& lhs,
999   decode_view const& rhs) noexcept 999   decode_view const& rhs) noexcept
1000   { 1000   {
1001   return decode_compare(lhs, rhs) >= 0; 1001   return decode_compare(lhs, rhs) >= 0;
1002   } 1002   }
1003   #endif 1003   #endif
1004   1004  
1005   /** Format the string with percent-decoding applied to the output stream 1005   /** Format the string with percent-decoding applied to the output stream
1006   1006  
1007   This hidden friend function serializes the decoded view 1007   This hidden friend function serializes the decoded view
1008   to the output stream. 1008   to the output stream.
1009   1009  
1010   @return A reference to the output stream, for chaining 1010   @return A reference to the output stream, for chaining
1011   1011  
1012   @param os The output stream to write to 1012   @param os The output stream to write to
1013   1013  
1014   @param s The decoded view to write 1014   @param s The decoded view to write
1015   */ 1015   */
1016   friend 1016   friend
1017   std::ostream& 1017   std::ostream&
HITCBC 1018   21 operator<<( 1018   21 operator<<(
1019   std::ostream& os, 1019   std::ostream& os,
1020   decode_view const& s) 1020   decode_view const& s)
1021   { 1021   {
1022   // hidden friend 1022   // hidden friend
HITCBC 1023   21 s.write(os); 1023   21 s.write(os);
HITCBC 1024   21 return os; 1024   21 return os;
1025   } 1025   }
1026   1026  
1027   private: 1027   private:
1028   BOOST_URL_DECL 1028   BOOST_URL_DECL
1029   void 1029   void
1030   write(std::ostream& os) const; 1030   write(std::ostream& os) const;
1031   }; 1031   };
1032   1032  
1033   /** Format the string with percent-decoding applied to the output stream 1033   /** Format the string with percent-decoding applied to the output stream
1034   1034  
1035   This function serializes the decoded view 1035   This function serializes the decoded view
1036   to the output stream. 1036   to the output stream.
1037   1037  
1038   @return A reference to the output stream, for chaining 1038   @return A reference to the output stream, for chaining
1039   1039  
1040   @param os The output stream to write to 1040   @param os The output stream to write to
1041   1041  
1042   @param s The decoded view to write 1042   @param s The decoded view to write
1043   */ 1043   */
1044   inline 1044   inline
1045   std::ostream& 1045   std::ostream&
1046   operator<<( 1046   operator<<(
1047   std::ostream& os, 1047   std::ostream& os,
1048   decode_view const& s); 1048   decode_view const& s);
1049   1049  
1050   //------------------------------------------------ 1050   //------------------------------------------------
1051   1051  
1052   inline 1052   inline
1053   decode_view 1053   decode_view
HITCBC 1054   4108 pct_string_view::operator*() const noexcept 1054   4109 pct_string_view::operator*() const noexcept
1055   { 1055   {
HITCBC 1056   4108 return decode_view(*this); 1056   4109 return decode_view(*this);
1057   } 1057   }
1058   1058  
1059   namespace detail { 1059   namespace detail {
1060   template<class... Args> 1060   template<class... Args>
1061   decode_view 1061   decode_view
1062   make_decode_view( 1062   make_decode_view(
1063   Args&&... args) noexcept 1063   Args&&... args) noexcept
1064   { 1064   {
1065   return decode_view( 1065   return decode_view(
1066   std::forward<Args>(args)...); 1066   std::forward<Args>(args)...);
1067   } 1067   }
1068   } // detail 1068   } // detail
1069   1069  
1070   //------------------------------------------------ 1070   //------------------------------------------------
1071   1071  
1072   } // urls 1072   } // urls
1073   } // boost 1073   } // boost
1074   1074  
1075   #include <boost/url/impl/decode_view.hpp> 1075   #include <boost/url/impl/decode_view.hpp>
1076   1076  
1077   //------------------------------------------------ 1077   //------------------------------------------------
1078   // 1078   //
1079   // std::ranges::enable_borrowed_range 1079   // std::ranges::enable_borrowed_range
1080   // 1080   //
1081   //------------------------------------------------ 1081   //------------------------------------------------
1082   1082  
1083   #ifdef BOOST_URL_HAS_CONCEPTS 1083   #ifdef BOOST_URL_HAS_CONCEPTS
1084   #include <ranges> 1084   #include <ranges>
1085   namespace std::ranges { 1085   namespace std::ranges {
1086   template<> 1086   template<>
1087   inline constexpr bool 1087   inline constexpr bool
1088   enable_borrowed_range< 1088   enable_borrowed_range<
1089   boost::urls::decode_view> = true; 1089   boost::urls::decode_view> = true;
1090   } // std::ranges 1090   } // std::ranges
1091   #endif 1091   #endif
1092   1092  
1093   #endif 1093   #endif