Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:52:42

0001 //
0002 // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/url
0008 //
0009 
0010 #ifndef BOOST_URL_DECODE_VIEW_HPP
0011 #define BOOST_URL_DECODE_VIEW_HPP
0012 
0013 #include <boost/url/detail/config.hpp>
0014 #include <boost/core/detail/string_view.hpp>
0015 #include <boost/url/encoding_opts.hpp>
0016 #include <boost/url/pct_string_view.hpp>
0017 #include <type_traits>
0018 #include <iterator>
0019 #include <iosfwd>
0020 
0021 namespace boost {
0022 namespace urls {
0023 
0024 //------------------------------------------------
0025 
0026 #ifndef BOOST_URL_DOCS
0027 class decode_view;
0028 
0029 namespace detail {
0030 
0031 // unchecked
0032 template<class... Args>
0033 decode_view
0034 make_decode_view(
0035     Args&&... args) noexcept;
0036 
0037 } // detail
0038 #endif
0039 
0040 //------------------------------------------------
0041 
0042 /** A reference to a valid, percent-encoded string
0043 
0044     These views reference strings in parts of URLs
0045     or other components that are percent-encoded.
0046     The special characters (those not in the
0047     allowed character set) are stored as three
0048     character escapes that consist of a percent
0049     sign ('%%') followed by a two-digit hexadecimal
0050     number of the corresponding unescaped character
0051     code, which may be part of a UTF-8 code point
0052     depending on the context.
0053 
0054     The view refers to the original character
0055     buffer and only decodes escaped sequences when
0056     needed. In particular these operations perform
0057     percent-decoding automatically without the
0058     need to allocate memory:
0059 
0060     @li Iteration of the string
0061     @li Accessing the encoded character buffer
0062     @li Comparison to encoded or plain strings
0063 
0064     These objects can only be constructed from
0065     strings that have a valid percent-encoding,
0066     otherwise construction fails. The caller is
0067     responsible for ensuring that the lifetime
0068     of the character buffer from which the view
0069     is constructed extends unmodified until the
0070     view is no longer accessed.
0071 */
0072 class decode_view
0073 {
0074     char const* p_ = nullptr;
0075     std::size_t n_ = 0;
0076     std::size_t dn_ = 0;
0077     bool space_as_plus_ = true;
0078 
0079 #ifndef BOOST_URL_DOCS
0080     template<class... Args>
0081     friend
0082     decode_view
0083     detail::make_decode_view(
0084         Args&&... args) noexcept;
0085 #endif
0086 
0087     // unchecked
0088     BOOST_CXX14_CONSTEXPR
0089     explicit
0090     decode_view(
0091         core::string_view s,
0092         std::size_t n,
0093         encoding_opts opt) noexcept
0094         : p_(s.data())
0095         , n_(s.size())
0096         , dn_(n)
0097         , space_as_plus_(
0098             opt.space_as_plus)
0099     {}
0100 
0101 public:
0102     /** The value type
0103     */
0104     using value_type = char;
0105 
0106     /** The reference type
0107     */
0108     using reference = char;
0109 
0110     /// @copydoc reference
0111     using const_reference = char;
0112 
0113     /** The unsigned integer type
0114     */
0115     using size_type = std::size_t;
0116 
0117     /** The signed integer type
0118     */
0119     using difference_type = std::ptrdiff_t;
0120 
0121     /** An iterator of constant, decoded characters.
0122 
0123         This iterator is used to access the encoded
0124         string as a *bidirectional* range of characters
0125         with percent-decoding applied. Escape sequences
0126         are not decoded until the iterator is
0127         dereferenced.
0128     */
0129     class iterator;
0130 
0131     /// @copydoc iterator
0132     using const_iterator = iterator;
0133 
0134     //--------------------------------------------
0135     //
0136     // Special Members
0137     //
0138     //--------------------------------------------
0139 
0140     /** Constructor
0141 
0142         Default-constructed views represent
0143         empty strings.
0144 
0145         @par Example
0146         @code
0147         decode_view ds;
0148         @endcode
0149 
0150         @par Postconditions
0151         @code
0152         this->empty() == true
0153         @endcode
0154 
0155         @par Complexity
0156         Constant.
0157 
0158         @par Exception Safety
0159         Throws nothing.
0160     */
0161     BOOST_CXX14_CONSTEXPR
0162     decode_view() noexcept = default;
0163 
0164     /** Constructor
0165 
0166         This constructs a view from the character
0167         buffer `s`, which must remain valid and
0168         unmodified until the view is no longer
0169         accessed.
0170 
0171         @par Example
0172         @code
0173         decode_view ds( "Program%20Files" );
0174         @endcode
0175 
0176         @par Postconditions
0177         @code
0178         this->encoded() == s
0179         @endcode
0180 
0181         @par Complexity
0182         Linear in `s.size()`.
0183 
0184         @par Exception Safety
0185         Although this function does not throw exceptions,
0186         implicitly constructing a @ref pct_string_view
0187         for the first argument can throw exceptions
0188         on invalid input.
0189 
0190         @param s A percent-encoded string that has
0191         already been validated. Implicit conversion
0192         from other string types is supported but
0193         may throw exceptions.
0194 
0195         @param opt The options for decoding. If
0196         this parameter is omitted, the default
0197         options are used.
0198     */
0199     BOOST_CXX14_CONSTEXPR
0200     explicit
0201     decode_view(
0202         pct_string_view s,
0203         encoding_opts opt = {}) noexcept
0204         : decode_view(
0205             detail::to_sv(s),
0206             s.decoded_size(),
0207             opt)
0208     {
0209     }
0210 
0211     //--------------------------------------------
0212     //
0213     // Observers
0214     //
0215     //--------------------------------------------
0216 
0217     /** Return true if the string is empty
0218 
0219         @par Example
0220         @code
0221         assert( decode_view( "" ).empty() );
0222         @endcode
0223 
0224         @par Complexity
0225         Constant.
0226 
0227         @par Exception Safety
0228         Throws nothing.
0229 
0230         @return `true` if the string is empty
0231     */
0232     bool
0233     empty() const noexcept
0234     {
0235         return n_ == 0;
0236     }
0237 
0238     /** Return the number of decoded characters
0239 
0240         @par Example
0241         @code
0242         assert( decode_view( "Program%20Files" ).size() == 13 );
0243         @endcode
0244 
0245         @par Effects
0246         @code
0247         return std::distance( this->begin(), this->end() );
0248         @endcode
0249 
0250         @par Complexity
0251         Constant.
0252 
0253         @par Exception Safety
0254         Throws nothing.
0255 
0256         @return The number of decoded characters
0257     */
0258     size_type
0259     size() const noexcept
0260     {
0261         return dn_;
0262     }
0263 
0264     /** Return an iterator to the beginning
0265 
0266         @par Example
0267         @code
0268         auto it = this->begin();
0269         @endcode
0270 
0271         @par Complexity
0272         Constant.
0273 
0274         @par Exception Safety
0275         Throws nothing.
0276 
0277         @return An iterator to the first decoded character
0278     */
0279     iterator
0280     begin() const noexcept;
0281 
0282     /** Return an iterator to the end
0283 
0284         @par Example
0285         @code
0286         auto it = this->end();
0287         @endcode
0288 
0289         @par Complexity
0290         Constant.
0291 
0292         @par Exception Safety
0293         Throws nothing.
0294 
0295         @return An iterator to one past the last decoded character
0296     */
0297     iterator
0298     end() const noexcept;
0299 
0300     /** Return the first character
0301 
0302         @par Example
0303         @code
0304         assert( decode_view( "Program%20Files" ).front() == 'P' );
0305         @endcode
0306 
0307         @par Preconditions
0308         @code
0309         not this->empty()
0310         @endcode
0311 
0312         @par Complexity
0313         Constant.
0314 
0315         @par Exception Safety
0316         Throws nothing.
0317 
0318         @return The first decoded character
0319     */
0320     reference
0321     front() const noexcept;
0322 
0323     /** Return the last character
0324 
0325         @par Example
0326         @code
0327         assert( decode_view( "Program%20Files" ).back() == 's' );
0328         @endcode
0329 
0330         @par Preconditions
0331         @code
0332         not this->empty()
0333         @endcode
0334 
0335         @par Complexity
0336         Constant.
0337 
0338         @par Exception Safety
0339         Throws nothing.
0340 
0341         @return The last decoded character
0342     */
0343     reference
0344     back() const noexcept;
0345 
0346     /** Checks if the string begins with the given prefix
0347 
0348         @par Example
0349         @code
0350         assert( decode_view( "Program%20Files" ).starts_with("Program") );
0351         @endcode
0352 
0353         @par Complexity
0354         Linear.
0355 
0356         @par Exception Safety
0357         Throws nothing.
0358 
0359         @param s The string to search for
0360         @return `true` if the decoded string starts with `s`
0361     */
0362     BOOST_URL_DECL
0363     bool
0364     starts_with( core::string_view s ) const noexcept;
0365 
0366     /** Checks if the string ends with the given prefix
0367 
0368         @par Example
0369         @code
0370         assert( decode_view( "Program%20Files" ).ends_with("Files") );
0371         @endcode
0372 
0373         @par Complexity
0374         Linear.
0375 
0376         @par Exception Safety
0377         Throws nothing.
0378 
0379         @param s The string to search for
0380         @return `true` if the decoded string ends with `s`
0381     */
0382     BOOST_URL_DECL
0383     bool
0384     ends_with( core::string_view s ) const noexcept;
0385 
0386     /** Checks if the string begins with the given prefix
0387 
0388         @par Example
0389         @code
0390         assert( decode_view( "Program%20Files" ).starts_with('P') );
0391         @endcode
0392 
0393         @par Complexity
0394         Constant.
0395 
0396         @par Exception Safety
0397         Throws nothing.
0398 
0399         @param ch The character to search for
0400         @return `true` if the decoded string starts with `ch`
0401     */
0402     BOOST_URL_DECL
0403     bool
0404     starts_with( char ch ) const noexcept;
0405 
0406     /** Checks if the string ends with the given prefix
0407 
0408         @par Example
0409         @code
0410         assert( decode_view( "Program%20Files" ).ends_with('s') );
0411         @endcode
0412 
0413         @par Complexity
0414         Constant.
0415 
0416         @par Exception Safety
0417         Throws nothing.
0418 
0419         @param ch The character to search for
0420         @return `true` if the decoded string ends with `ch`
0421     */
0422     BOOST_URL_DECL
0423     bool
0424     ends_with( char ch ) const noexcept;
0425 
0426     /** Finds the first occurrence of character in this view
0427 
0428         @par Complexity
0429         Linear.
0430 
0431         @par Exception Safety
0432         Throws nothing.
0433 
0434         @param ch The character to search for
0435         @return An iterator to the first decoded occurrence of `ch` or `end()`
0436     */
0437     BOOST_URL_DECL
0438     const_iterator
0439     find( char ch ) const noexcept;
0440 
0441     /** Finds the first occurrence of character in this view
0442 
0443         @par Complexity
0444         Linear.
0445 
0446         @par Exception Safety
0447         Throws nothing.
0448 
0449         @param ch The character to search for
0450         @return An iterator to the last occurrence of `ch` or `end()`
0451     */
0452     BOOST_URL_DECL
0453     const_iterator
0454     rfind( char ch ) const noexcept;
0455 
0456     /** Remove the first characters
0457 
0458         @par Example
0459         @code
0460         decode_view d( "Program%20Files" );
0461         d.remove_prefix( 8 );
0462         assert( d == "Files" );
0463         @endcode
0464 
0465         @par Preconditions
0466         @code
0467         not this->empty()
0468         @endcode
0469 
0470         @par Complexity
0471         Linear.
0472 
0473         @param n The number of characters to remove
0474     */
0475     BOOST_URL_DECL
0476     void
0477     remove_prefix( size_type n );
0478 
0479     /** Remove the last characters
0480 
0481         @par Example
0482         @code
0483         decode_view d( "Program%20Files" );
0484         d.remove_prefix( 6 );
0485         assert( d == "Program" );
0486         @endcode
0487 
0488         @par Preconditions
0489         @code
0490         not this->empty()
0491         @endcode
0492 
0493         @par Complexity
0494         Linear.
0495 
0496         @param n The number of characters to remove
0497     */
0498     BOOST_URL_DECL
0499     void
0500     remove_suffix( size_type n );
0501 
0502     /** Return the decoding options
0503 
0504         @return The decoding options used by this view
0505      */
0506     encoding_opts
0507     options() const noexcept
0508     {
0509         encoding_opts opt;
0510         opt.space_as_plus = space_as_plus_;
0511         return opt;
0512     }
0513 
0514     //--------------------------------------------
0515     //
0516     // Comparison
0517     //
0518     //--------------------------------------------
0519 
0520     /** Return the result of comparing to another string
0521 
0522         The length of the sequences to compare is the smaller of
0523         `size()` and `other.size()`.
0524 
0525         The function compares the two strings as if by calling
0526         `char_traits<char>::compare(to_string().data(), v.data(), rlen)`.
0527         This means the comparison is performed with
0528         percent-decoding applied to the current string.
0529 
0530         @param other string to compare
0531 
0532         @return Negative value if this string is less than the other
0533         character sequence, zero if the both character sequences are
0534         equal, positive value if this string is greater than the other
0535         character sequence
0536     */
0537     BOOST_CXX14_CONSTEXPR
0538     int
0539     compare(core::string_view other) const noexcept;
0540 
0541     /** Return the result of comparing to another string
0542 
0543         The length of the sequences to compare is the smaller of
0544         `size()` and `other.size()`.
0545 
0546         The function compares the two strings as if by calling
0547         `char_traits<char>::compare(to_string().data(), v.to_string().data(), rlen)`.
0548         This means the comparison is performed with
0549         percent-decoding applied to the current string.
0550 
0551         @param other string to compare
0552 
0553         @return Negative value if this string is less than the other
0554         character sequence, zero if the both character sequences are
0555         equal, positive value if this string is greater than the other
0556         character sequence
0557     */
0558     BOOST_CXX14_CONSTEXPR
0559     int
0560     compare(decode_view other) const noexcept;
0561 
0562     //--------------------------------------------
0563 
0564     // relational operators
0565 private:
0566     template<class S0, class S1>
0567     using is_match = std::integral_constant<bool,
0568         // both decode_view or convertible to core::string_view
0569         (
0570             std::is_same<typename std::decay<S0>::type, decode_view>::value ||
0571             std::is_convertible<S0, core::string_view>::value) &&
0572         (
0573             std::is_same<typename std::decay<S1>::type, decode_view>::value ||
0574             std::is_convertible<S1, core::string_view>::value) &&
0575         // not both are convertible to string view
0576         (
0577             !std::is_convertible<S0, core::string_view>::value ||
0578             !std::is_convertible<S1, core::string_view>::value)>;
0579 
0580     BOOST_CXX14_CONSTEXPR
0581     static
0582     int
0583     decode_compare(decode_view s0, decode_view s1) noexcept
0584     {
0585         return s0.compare(s1);
0586     }
0587 
0588     template <class S>
0589     BOOST_CXX14_CONSTEXPR
0590     static
0591     int
0592     decode_compare(decode_view s0, S const& s1) noexcept
0593     {
0594         return s0.compare(s1);
0595     }
0596 
0597     template <class S>
0598     BOOST_CXX14_CONSTEXPR
0599     static
0600     int
0601     decode_compare(S const& s0, decode_view s1) noexcept
0602     {
0603         return -s1.compare(s0);
0604     }
0605 
0606 public:
0607 #ifndef BOOST_URL_HAS_CONCEPTS
0608     /** Compare two decode views for equality
0609 
0610         @param lhs The left-hand-side decode view to compare
0611         @param rhs The right-hand-side decode view to compare
0612         @return `true` if decoded `lhs` is equal to the decoded `rhs`
0613      */
0614     template<class S0, class S1>
0615     BOOST_CXX14_CONSTEXPR friend auto operator==(
0616         S0 const& lhs, S1 const& rhs) noexcept ->
0617         typename std::enable_if<
0618             is_match<S0, S1>::value, bool>::type
0619     {
0620         return decode_compare(lhs, rhs) == 0;
0621     }
0622 #else
0623     /** Compare two decode views for equality
0624 
0625         @param lhs The left-hand-side decode view to compare
0626         @param rhs The right-hand-side decode view to compare
0627         @return `true` if decoded `lhs` is equal to the decoded `rhs`
0628      */
0629     BOOST_CXX14_CONSTEXPR
0630     friend
0631     bool
0632     operator==(
0633         decode_view const& lhs,
0634         decode_view const& rhs) noexcept
0635     {
0636         return decode_compare(lhs, rhs) == 0;
0637     }
0638 
0639     /** Compare two decode views for equality
0640 
0641         @param lhs The left-hand-side decode view to compare
0642         @param rhs The right-hand-side decode view to compare
0643         @return `true` if decoded `lhs` is equal to the decoded `rhs`
0644      */
0645     template <std::convertible_to<core::string_view> S>
0646     BOOST_CXX14_CONSTEXPR
0647     friend
0648     bool
0649     operator==(
0650         decode_view const& lhs,
0651         S const& rhs) noexcept
0652     {
0653         return decode_compare(lhs, rhs) == 0;
0654     }
0655 
0656     /** Compare two decode views for equality
0657 
0658         @param lhs The left-hand-side decode view to compare
0659         @param rhs The right-hand-side decode view to compare
0660         @return `true` if decoded `lhs` is equal to the decoded `rhs`
0661      */
0662     template <std::convertible_to<core::string_view> S>
0663     BOOST_CXX14_CONSTEXPR
0664     friend
0665     bool
0666     operator==(
0667         S const& lhs,
0668         decode_view const& rhs) noexcept
0669     {
0670         return decode_compare(lhs, rhs) == 0;
0671     }
0672 #endif
0673 
0674 #ifndef BOOST_URL_HAS_CONCEPTS
0675     /** Compare two decode views for inequality
0676 
0677         @param lhs The left-hand-side decode view to compare
0678         @param rhs The right-hand-side decode view to compare
0679         @return `true` if decoded `lhs` is not equal to the decoded `rhs`
0680      */
0681     template<class S0, class S1>
0682     BOOST_CXX14_CONSTEXPR friend auto operator!=(
0683         S0 const& lhs, S1 const& rhs) noexcept ->
0684         typename std::enable_if<
0685             is_match<S0, S1>::value, bool>::type
0686     {
0687         return decode_compare(lhs, rhs) != 0;
0688     }
0689 #else
0690     /** Compare two decode views for inequality
0691 
0692         @param lhs The left-hand-side decode view to compare
0693         @param rhs The right-hand-side decode view to compare
0694         @return `true` if decoded `lhs` is not equal to the decoded `rhs`
0695      */
0696     BOOST_CXX14_CONSTEXPR
0697     friend
0698     bool
0699     operator!=(
0700         decode_view const& lhs,
0701         decode_view const& rhs) noexcept
0702     {
0703         return decode_compare(lhs, rhs) != 0;
0704     }
0705 
0706     /** Compare two decode views for inequality
0707 
0708         @param lhs The left-hand-side decode view to compare
0709         @param rhs The right-hand-side decode view to compare
0710         @return `true` if decoded `lhs` is not equal to the decoded `rhs`
0711      */
0712     template <std::convertible_to<core::string_view> S>
0713     BOOST_CXX14_CONSTEXPR
0714     friend
0715     bool
0716     operator!=(
0717         decode_view const& lhs,
0718         S const& rhs) noexcept
0719     {
0720         return decode_compare(lhs, rhs) != 0;
0721     }
0722 
0723     /** Compare two decode views for inequality
0724 
0725         @param lhs The left-hand-side decode view to compare
0726         @param rhs The right-hand-side decode view to compare
0727         @return `true` if decoded `lhs` is not equal to the decoded `rhs`
0728      */
0729     template <std::convertible_to<core::string_view> S>
0730     BOOST_CXX14_CONSTEXPR
0731     friend
0732     bool
0733     operator!=(
0734         S const& lhs,
0735         decode_view const& rhs) noexcept
0736     {
0737         return decode_compare(lhs, rhs) != 0;
0738     }
0739 #endif
0740 
0741 #ifndef BOOST_URL_HAS_CONCEPTS
0742     /** Compare two decode views for less than
0743 
0744         @param lhs The left-hand-side decode view to compare
0745         @param rhs The right-hand-side decode view to compare
0746         @return `true` if decoded `lhs` is less than to the decoded `rhs`
0747      */
0748     template<class S0, class S1>
0749     BOOST_CXX14_CONSTEXPR friend auto operator<(
0750         S0 const& lhs, S1 const& rhs) noexcept ->
0751         typename std::enable_if<
0752             is_match<S0, S1>::value, bool>::type
0753     {
0754         return decode_compare(lhs, rhs) < 0;
0755     }
0756 #else
0757     /** Compare two decode views for less than
0758 
0759         @param lhs The left-hand-side decode view to compare
0760         @param rhs The right-hand-side decode view to compare
0761         @return `true` if decoded `lhs` is less than to the decoded `rhs`
0762      */
0763     BOOST_CXX14_CONSTEXPR
0764     friend
0765     bool
0766     operator<(
0767         decode_view const& lhs,
0768         decode_view const& rhs) noexcept
0769     {
0770         return decode_compare(lhs, rhs) < 0;
0771     }
0772 
0773     /** Compare two decode views for less than
0774 
0775         @param lhs The left-hand-side decode view to compare
0776         @param rhs The right-hand-side decode view to compare
0777         @return `true` if decoded `lhs` is less than to the decoded `rhs`
0778      */
0779     template <std::convertible_to<core::string_view> S>
0780     BOOST_CXX14_CONSTEXPR
0781     friend
0782     bool
0783     operator<(
0784         decode_view const& lhs,
0785         S const& rhs) noexcept
0786     {
0787         return decode_compare(lhs, rhs) < 0;
0788     }
0789 
0790     /** Compare two decode views for less than
0791 
0792         @param lhs The left-hand-side decode view to compare
0793         @param rhs The right-hand-side decode view to compare
0794         @return `true` if decoded `lhs` is less than to the decoded `rhs`
0795      */
0796     template <std::convertible_to<core::string_view> S>
0797     BOOST_CXX14_CONSTEXPR
0798     friend
0799     bool
0800     operator<(
0801         S const& lhs,
0802         decode_view const& rhs) noexcept
0803     {
0804         return decode_compare(lhs, rhs) < 0;
0805     }
0806 #endif
0807 
0808 #ifndef BOOST_URL_HAS_CONCEPTS
0809     /** Compare two decode views for less than or equal
0810 
0811         @param lhs The left-hand-side decode view to compare
0812         @param rhs The right-hand-side decode view to compare
0813         @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
0814      */
0815     template<class S0, class S1>
0816     BOOST_CXX14_CONSTEXPR friend auto operator<=(
0817         S0 const& lhs, S1 const& rhs) noexcept ->
0818         typename std::enable_if<
0819             is_match<S0, S1>::value, bool>::type
0820     {
0821         return decode_compare(lhs, rhs) <= 0;
0822     }
0823 #else
0824     /** Compare two decode views for less than or equal
0825 
0826         @param lhs The left-hand-side decode view to compare
0827         @param rhs The right-hand-side decode view to compare
0828         @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
0829      */
0830     BOOST_CXX14_CONSTEXPR
0831     friend
0832     bool
0833     operator<=(
0834         decode_view const& lhs,
0835         decode_view const& rhs) noexcept
0836     {
0837         return decode_compare(lhs, rhs) <= 0;
0838     }
0839 
0840     /** Compare two decode views for less than or equal
0841 
0842         @param lhs The left-hand-side decode view to compare
0843         @param rhs The right-hand-side decode view to compare
0844         @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
0845      */
0846     template <std::convertible_to<core::string_view> S>
0847     BOOST_CXX14_CONSTEXPR
0848     friend
0849     bool
0850     operator<=(
0851         decode_view const& lhs,
0852         S const& rhs) noexcept
0853     {
0854         return decode_compare(lhs, rhs) <= 0;
0855     }
0856 
0857     /** Compare two decode views for less than or equal
0858 
0859         @param lhs The left-hand-side decode view to compare
0860         @param rhs The right-hand-side decode view to compare
0861         @return `true` if decoded `lhs` is less than or equal to the decoded `rhs`
0862      */
0863     template <std::convertible_to<core::string_view> S>
0864     BOOST_CXX14_CONSTEXPR
0865     friend
0866     bool
0867     operator<=(
0868         S const& lhs,
0869         decode_view const& rhs) noexcept
0870     {
0871         return decode_compare(lhs, rhs) <= 0;
0872     }
0873 #endif
0874 
0875 #ifndef BOOST_URL_HAS_CONCEPTS
0876     /** Compare two decode views for greater than
0877 
0878         @param lhs The left-hand-side decode view to compare
0879         @param rhs The right-hand-side decode view to compare
0880         @return `true` if decoded `lhs` is greater than to the decoded `rhs`
0881      */
0882     template<class S0, class S1>
0883     BOOST_CXX14_CONSTEXPR friend auto operator>(
0884         S0 const& lhs, S1 const& rhs) noexcept ->
0885         typename std::enable_if<
0886             is_match<S0, S1>::value, bool>::type
0887     {
0888         return decode_compare(lhs, rhs) > 0;
0889     }
0890 #else
0891     /** Compare two decode views for greater than
0892 
0893         @param lhs The left-hand-side decode view to compare
0894         @param rhs The right-hand-side decode view to compare
0895         @return `true` if decoded `lhs` is greater than to the decoded `rhs`
0896      */
0897     BOOST_CXX14_CONSTEXPR
0898     friend
0899     bool
0900     operator>(
0901         decode_view const& lhs,
0902         decode_view const& rhs) noexcept
0903     {
0904         return decode_compare(lhs, rhs) > 0;
0905     }
0906 
0907     /** Compare two decode views for greater than
0908 
0909         @param lhs The left-hand-side decode view to compare
0910         @param rhs The right-hand-side decode view to compare
0911         @return `true` if decoded `lhs` is greater than to the decoded `rhs`
0912      */
0913     template <std::convertible_to<core::string_view> S>
0914     BOOST_CXX14_CONSTEXPR
0915     friend
0916     bool
0917     operator>(
0918         decode_view const& lhs,
0919         S const& rhs) noexcept
0920     {
0921         return decode_compare(lhs, rhs) > 0;
0922     }
0923 
0924     /** Compare two decode views for greater than
0925 
0926         @param lhs The left-hand-side decode view to compare
0927         @param rhs The right-hand-side decode view to compare
0928         @return `true` if decoded `lhs` is greater than to the decoded `rhs`
0929      */
0930     template <std::convertible_to<core::string_view> S>
0931     BOOST_CXX14_CONSTEXPR
0932     friend
0933     bool
0934     operator>(
0935         S const& lhs,
0936         decode_view const& rhs) noexcept
0937     {
0938         return decode_compare(lhs, rhs) > 0;
0939     }
0940 #endif
0941 
0942 #ifndef BOOST_URL_HAS_CONCEPTS
0943     /** Compare two decode views for greater than or equal
0944 
0945         @param lhs The left-hand-side decode view to compare
0946         @param rhs The right-hand-side decode view to compare
0947         @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
0948      */
0949     template<class S0, class S1>
0950     BOOST_CXX14_CONSTEXPR friend auto operator>=(
0951         S0 const& lhs, S1 const& rhs) noexcept ->
0952         typename std::enable_if<
0953             is_match<S0, S1>::value, bool>::type
0954     {
0955         return decode_compare(lhs, rhs) >= 0;
0956     }
0957 #else
0958     /** Compare two decode views for greater than or equal
0959 
0960         @param lhs The left-hand-side decode view to compare
0961         @param rhs The right-hand-side decode view to compare
0962         @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
0963      */
0964     BOOST_CXX14_CONSTEXPR
0965     friend
0966     bool
0967     operator>=(
0968         decode_view const& lhs,
0969         decode_view const& rhs) noexcept
0970     {
0971         return decode_compare(lhs, rhs) >= 0;
0972     }
0973 
0974     /** Compare two decode views for greater than or equal
0975 
0976         @param lhs The left-hand-side decode view to compare
0977         @param rhs The right-hand-side decode view to compare
0978         @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
0979      */
0980     template <std::convertible_to<core::string_view> S>
0981     BOOST_CXX14_CONSTEXPR
0982     friend
0983     bool
0984     operator>=(
0985         decode_view const& lhs,
0986         S const& rhs) noexcept
0987     {
0988         return decode_compare(lhs, rhs) >= 0;
0989     }
0990 
0991     /** Compare two decode views for greater than or equal
0992 
0993         @param lhs The left-hand-side decode view to compare
0994         @param rhs The right-hand-side decode view to compare
0995         @return `true` if decoded `lhs` is greater than or equal to the decoded `rhs`
0996      */
0997     template <std::convertible_to<core::string_view> S>
0998     BOOST_CXX14_CONSTEXPR
0999     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     operator<<(
1023         std::ostream& os,
1024         decode_view const& s)
1025     {
1026         // hidden friend
1027         s.write(os);
1028         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 pct_string_view::operator*() const noexcept
1059 {
1060     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