GCC Code Coverage Report


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