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 : #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 2926 : decode_compare(decode_view s0, S const& s1) noexcept
593 : {
594 2926 : 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 2471 : 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 2471 : 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 739 : 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 739 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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 8 : 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
|