GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/decode_view.hpp
Date: 2025-11-10 19:06:22
Exec Total Coverage
Lines: 36 36 100.0%
Functions: 47 47 100.0%
Branches: 0 0 -%

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