Line data Source code
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 2954 : decode_compare(decode_view s0, S const& s1) noexcept
589 : {
590 2954 : 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 2485 : 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 2485 : 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 753 : 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 753 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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
|