Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:02:05

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     @par Operators
0073     The following operators are supported between
0074     @ref decode_view and any object that is convertible
0075     to `core::string_view`
0076 
0077     @code
0078     bool operator==( decode_view, decode_view ) noexcept;
0079     bool operator!=( decode_view, decode_view ) noexcept;
0080     bool operator<=( decode_view, decode_view ) noexcept;
0081     bool operator< ( decode_view, decode_view ) noexcept;
0082     bool operator> ( decode_view, decode_view ) noexcept;
0083     bool operator>=( decode_view, decode_view ) noexcept;
0084     @endcode
0085 
0086 */
0087 class decode_view
0088 {
0089     char const* p_ = nullptr;
0090     std::size_t n_ = 0;
0091     std::size_t dn_ = 0;
0092     bool space_as_plus_ = true;
0093 
0094 #ifndef BOOST_URL_DOCS
0095     template<class... Args>
0096     friend
0097     decode_view
0098     detail::make_decode_view(
0099         Args&&... args) noexcept;
0100 #endif
0101 
0102     // unchecked
0103     BOOST_URL_DECL
0104     explicit
0105     decode_view(
0106         core::string_view s,
0107         std::size_t n,
0108         encoding_opts opt) noexcept;
0109 
0110 public:
0111     /** The value type
0112     */
0113     using value_type = char;
0114 
0115     /** The reference type
0116     */
0117     using reference = char;
0118 
0119     /// @copydoc reference
0120     using const_reference = char;
0121 
0122     /** The unsigned integer type
0123     */
0124     using size_type = std::size_t;
0125 
0126     /** The signed integer type
0127     */
0128     using difference_type = std::ptrdiff_t;
0129 
0130     /** An iterator of constant, decoded characters.
0131 
0132         This iterator is used to access the encoded
0133         string as a bidirectional range of characters
0134         with percent-decoding applied. Escape sequences
0135         are not decoded until the iterator is
0136         dereferenced.
0137     */
0138 #ifdef BOOST_URL_DOCS
0139     using iterator = __see_below__;
0140 #else
0141     class iterator;
0142 #endif
0143 
0144     /// @copydoc iterator
0145     using const_iterator = iterator;
0146 
0147     //--------------------------------------------
0148     //
0149     // Special Members
0150     //
0151     //--------------------------------------------
0152 
0153     /** Constructor
0154 
0155         Default-constructed views represent
0156         empty strings.
0157 
0158         @par Example
0159         @code
0160         decode_view ds;
0161         @endcode
0162 
0163         @par Postconditions
0164         @code
0165         this->empty() == true
0166         @endcode
0167 
0168         @par Complexity
0169         Constant.
0170 
0171         @par Exception Safety
0172         Throws nothing.
0173     */
0174     decode_view() noexcept = default;
0175 
0176     /** Constructor
0177 
0178         This constructs a view from the character
0179         buffer `s`, which must remain valid and
0180         unmodified until the view is no longer
0181         accessed.
0182 
0183         @par Example
0184         @code
0185         decode_view ds( "Program%20Files" );
0186         @endcode
0187 
0188         @par Postconditions
0189         @code
0190         this->encoded() == s
0191         @endcode
0192 
0193         @par Complexity
0194         Linear in `s.size()`.
0195 
0196         @par Exception Safety
0197         Exceptions thrown on invalid input.
0198 
0199         @throw system_error
0200         The string contains an invalid percent encoding.
0201 
0202         @param s A percent-encoded string that has
0203         already been validated.
0204 
0205         @param opt The options for decoding. If
0206         this parameter is omitted, the default
0207         options are used.
0208     */
0209     explicit
0210     decode_view(
0211         pct_string_view s,
0212         encoding_opts opt = {}) noexcept
0213         : decode_view(
0214             detail::to_sv(s),
0215             s.decoded_size(),
0216             opt)
0217     {
0218     }
0219 
0220     //--------------------------------------------
0221     //
0222     // Observers
0223     //
0224     //--------------------------------------------
0225 
0226     /** Return true if the string is empty
0227 
0228         @par Example
0229         @code
0230         assert( decode_view( "" ).empty() );
0231         @endcode
0232 
0233         @par Complexity
0234         Constant.
0235 
0236         @par Exception Safety
0237         Throws nothing.
0238     */
0239     bool
0240     empty() const noexcept
0241     {
0242         return n_ == 0;
0243     }
0244 
0245     /** Return the number of decoded characters
0246 
0247         @par Example
0248         @code
0249         assert( decode_view( "Program%20Files" ).size() == 13 );
0250         @endcode
0251 
0252         @par Effects
0253         @code
0254         return std::distance( this->begin(), this->end() );
0255         @endcode
0256 
0257         @par Complexity
0258         Constant.
0259 
0260         @par Exception Safety
0261         Throws nothing.
0262     */
0263     size_type
0264     size() const noexcept
0265     {
0266         return dn_;
0267     }
0268 
0269     /** Return an iterator to the beginning
0270 
0271         @par Example
0272         @code
0273         auto it = this->begin();
0274         @endcode
0275 
0276         @par Complexity
0277         Constant.
0278 
0279         @par Exception Safety
0280         Throws nothing.
0281     */
0282     iterator
0283     begin() const noexcept;
0284 
0285     /** Return an iterator to the end
0286 
0287         @par Example
0288         @code
0289         auto it = this->end();
0290         @endcode
0291 
0292         @par Complexity
0293         Constant.
0294 
0295         @par Exception Safety
0296         Throws nothing.
0297     */
0298     iterator
0299     end() const noexcept;
0300 
0301     /** Return the first character
0302 
0303         @par Example
0304         @code
0305         assert( decode_view( "Program%20Files" ).front() == 'P' );
0306         @endcode
0307 
0308         @par Preconditions
0309         @code
0310         not this->empty()
0311         @endcode
0312 
0313         @par Complexity
0314         Constant.
0315 
0316         @par Exception Safety
0317         Throws nothing.
0318     */
0319     reference
0320     front() const noexcept;
0321 
0322     /** Return the last character
0323 
0324         @par Example
0325         @code
0326         assert( decode_view( "Program%20Files" ).back() == 's' );
0327         @endcode
0328 
0329         @par Preconditions
0330         @code
0331         not this->empty()
0332         @endcode
0333 
0334         @par Complexity
0335         Constant.
0336 
0337         @par Exception Safety
0338         Throws nothing.
0339     */
0340     reference
0341     back() const noexcept;
0342 
0343     /** Checks if the string begins with the given prefix
0344 
0345         @par Example
0346         @code
0347         assert( decode_view( "Program%20Files" ).starts_with("Program") );
0348         @endcode
0349 
0350         @par Complexity
0351         Linear.
0352 
0353         @par Exception Safety
0354         Throws nothing.
0355     */
0356     BOOST_URL_DECL
0357     bool
0358     starts_with( core::string_view s ) const noexcept;
0359 
0360     /** Checks if the string ends with the given prefix
0361 
0362         @par Example
0363         @code
0364         assert( decode_view( "Program%20Files" ).ends_with("Files") );
0365         @endcode
0366 
0367         @par Complexity
0368         Linear.
0369 
0370         @par Exception Safety
0371         Throws nothing.
0372     */
0373     BOOST_URL_DECL
0374     bool
0375     ends_with( core::string_view s ) const noexcept;
0376 
0377     /** Checks if the string begins with the given prefix
0378 
0379         @par Example
0380         @code
0381         assert( decode_view( "Program%20Files" ).starts_with('P') );
0382         @endcode
0383 
0384         @par Complexity
0385         Constant.
0386 
0387         @par Exception Safety
0388         Throws nothing.
0389     */
0390     BOOST_URL_DECL
0391     bool
0392     starts_with( char ch ) const noexcept;
0393 
0394     /** Checks if the string ends with the given prefix
0395 
0396         @par Example
0397         @code
0398         assert( decode_view( "Program%20Files" ).ends_with('s') );
0399         @endcode
0400 
0401         @par Complexity
0402         Constant.
0403 
0404         @par Exception Safety
0405         Throws nothing.
0406     */
0407     BOOST_URL_DECL
0408     bool
0409     ends_with( char ch ) const noexcept;
0410 
0411     /** Finds the first occurrence of character in this view
0412 
0413         @par Complexity
0414         Linear.
0415 
0416         @par Exception Safety
0417         Throws nothing.
0418     */
0419     BOOST_URL_DECL
0420     const_iterator
0421     find( char ch ) const noexcept;
0422 
0423     /** Finds the first occurrence of character in this view
0424 
0425         @par Complexity
0426         Linear.
0427 
0428         @par Exception Safety
0429         Throws nothing.
0430     */
0431     BOOST_URL_DECL
0432     const_iterator
0433     rfind( char ch ) const noexcept;
0434 
0435     /** Remove the first characters
0436 
0437         @par Example
0438         @code
0439         decode_view d( "Program%20Files" );
0440         d.remove_prefix( 8 );
0441         assert( d == "Files" );
0442         @endcode
0443 
0444         @par Preconditions
0445         @code
0446         not this->empty()
0447         @endcode
0448 
0449         @par Complexity
0450         Linear.
0451     */
0452     BOOST_URL_DECL
0453     void
0454     remove_prefix( size_type n );
0455 
0456     /** Remove the last characters
0457 
0458         @par Example
0459         @code
0460         decode_view d( "Program%20Files" );
0461         d.remove_prefix( 6 );
0462         assert( d == "Program" );
0463         @endcode
0464 
0465         @par Preconditions
0466         @code
0467         not this->empty()
0468         @endcode
0469 
0470         @par Complexity
0471         Linear.
0472     */
0473     BOOST_URL_DECL
0474     void
0475     remove_suffix( size_type n );
0476 
0477     /** Return the decoding options
0478     */
0479     encoding_opts
0480     options() const noexcept
0481     {
0482         encoding_opts opt;
0483         opt.space_as_plus = space_as_plus_;
0484         return opt;
0485     }
0486 
0487     //--------------------------------------------
0488     //
0489     // Comparison
0490     //
0491     //--------------------------------------------
0492 
0493     /** Return the result of comparing to another string
0494 
0495         The length of the sequences to compare is the smaller of
0496         `size()` and `other.size()`.
0497 
0498         The function compares the two strings as if by calling
0499         `char_traits<char>::compare(to_string().data(), v.data(), rlen)`.
0500         This means the comparison is performed with
0501         percent-decoding applied to the current string.
0502 
0503         @param other string to compare
0504 
0505         @return Negative value if this string is less than the other
0506         character sequence, zero if the both character sequences are
0507         equal, positive value if this string is greater than the other
0508         character sequence
0509     */
0510     BOOST_URL_DECL
0511     int
0512     compare(core::string_view other) const noexcept;
0513 
0514     /** Return the result of comparing to another string
0515 
0516         The length of the sequences to compare is the smaller of
0517         `size()` and `other.size()`.
0518 
0519         The function compares the two strings as if by calling
0520         `char_traits<char>::compare(to_string().data(), v.to_string().data(), rlen)`.
0521         This means the comparison is performed with
0522         percent-decoding applied to the current string.
0523 
0524         @param other string to compare
0525 
0526         @return Negative value if this string is less than the other
0527         character sequence, zero if the both character sequences are
0528         equal, positive value if this string is greater than the other
0529         character sequence
0530     */
0531     BOOST_URL_DECL
0532     int
0533     compare(decode_view other) const noexcept;
0534 
0535     //--------------------------------------------
0536 
0537     // relational operators
0538 #ifndef BOOST_URL_DOCS
0539 private:
0540     template<class S0, class S1>
0541     using is_match = std::integral_constant<bool,
0542         // both decode_view or convertible to core::string_view
0543         (
0544             std::is_same<typename std::decay<S0>::type, decode_view>::value ||
0545             std::is_convertible<S0, core::string_view>::value) &&
0546         (
0547             std::is_same<typename std::decay<S1>::type, decode_view>::value ||
0548             std::is_convertible<S1, core::string_view>::value) &&
0549         // not both are convertible to string view
0550         (
0551             !std::is_convertible<S0, core::string_view>::value ||
0552             !std::is_convertible<S1, core::string_view>::value)>;
0553 
0554     static
0555     int
0556     decode_compare(decode_view s0, decode_view s1) noexcept
0557     {
0558         return s0.compare(s1);
0559     }
0560 
0561     template <class S>
0562     static
0563     int
0564     decode_compare(decode_view s0, S const& s1) noexcept
0565     {
0566         return s0.compare(s1);
0567     }
0568 
0569     template <class S>
0570     static
0571     int
0572     decode_compare(S const& s0, decode_view s1) noexcept
0573     {
0574         return -s1.compare(s0);
0575     }
0576 public:
0577 
0578     template<class S0, class S1>
0579     BOOST_CXX14_CONSTEXPR friend auto operator==(
0580         S0 const& s0, S1 const& s1) noexcept ->
0581         typename std::enable_if<
0582             is_match<S0, S1>::value, bool>::type
0583     {
0584         return decode_compare(s0, s1) == 0;
0585     }
0586 
0587     template<class S0, class S1>
0588     BOOST_CXX14_CONSTEXPR friend auto operator!=(
0589         S0 const& s0, S1 const& s1) noexcept ->
0590         typename std::enable_if<
0591             is_match<S0, S1>::value, bool>::type
0592     {
0593         return decode_compare(s0, s1) != 0;
0594     }
0595 
0596     template<class S0, class S1>
0597     BOOST_CXX14_CONSTEXPR friend auto operator<(
0598         S0 const& s0, S1 const& s1) noexcept ->
0599         typename std::enable_if<
0600             is_match<S0, S1>::value, bool>::type
0601     {
0602         return decode_compare(s0, s1) < 0;
0603     }
0604 
0605     template<class S0, class S1>
0606     BOOST_CXX14_CONSTEXPR friend auto operator<=(
0607         S0 const& s0, S1 const& s1) noexcept ->
0608         typename std::enable_if<
0609             is_match<S0, S1>::value, bool>::type
0610     {
0611         return decode_compare(s0, s1) <= 0;
0612     }
0613 
0614     template<class S0, class S1>
0615     BOOST_CXX14_CONSTEXPR friend auto operator>(
0616         S0 const& s0, S1 const& s1) noexcept ->
0617         typename std::enable_if<
0618             is_match<S0, S1>::value, bool>::type
0619     {
0620         return decode_compare(s0, s1) > 0;
0621     }
0622 
0623     template<class S0, class S1>
0624     BOOST_CXX14_CONSTEXPR friend auto operator>=(
0625         S0 const& s0, S1 const& s1) noexcept ->
0626         typename std::enable_if<
0627             is_match<S0, S1>::value, bool>::type
0628     {
0629         return decode_compare(s0, s1) >= 0;
0630     }
0631 #endif
0632 
0633     // hidden friend
0634     friend
0635     std::ostream&
0636     operator<<(
0637         std::ostream& os,
0638         decode_view const& s)
0639     {
0640         // hidden friend
0641         s.write(os);
0642         return os;
0643     }
0644 
0645 private:
0646     BOOST_URL_DECL
0647     void
0648     write(std::ostream& os) const;
0649 };
0650 
0651 /** Format the string with percent-decoding applied to the output stream
0652 
0653     This function serializes the decoded view
0654     to the output stream.
0655 
0656     @return A reference to the output stream, for chaining
0657 
0658     @param os The output stream to write to
0659 
0660     @param s The decoded view to write
0661 */
0662 inline
0663 std::ostream&
0664 operator<<(
0665     std::ostream& os,
0666     decode_view const& s);
0667 
0668 //------------------------------------------------
0669 
0670 inline
0671 decode_view
0672 pct_string_view::operator*() const noexcept
0673 {
0674     return decode_view(*this);
0675 }
0676 
0677 #ifndef BOOST_URL_DOCS
0678 namespace detail {
0679 template<class... Args>
0680 decode_view
0681 make_decode_view(
0682     Args&&... args) noexcept
0683 {
0684     return decode_view(
0685         std::forward<Args>(args)...);
0686 }
0687 } // detail
0688 #endif
0689 
0690 //------------------------------------------------
0691 
0692 } // urls
0693 } // boost
0694 
0695 #include <boost/url/impl/decode_view.hpp>
0696 
0697 #endif