Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-05 09:03:54

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