Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:07:55

0001 //
0002 // Copyright (c) 2022 Vinnie Falco (vinnie.falco@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_GRAMMAR_STRING_VIEW_BASE_HPP
0011 #define BOOST_URL_GRAMMAR_STRING_VIEW_BASE_HPP
0012 
0013 #include <boost/url/detail/config.hpp>
0014 #include <boost/url/detail/string_view.hpp>
0015 #include <boost/core/detail/string_view.hpp>
0016 #include <cstddef>
0017 #include <iterator>
0018 #include <string>
0019 #include <type_traits>
0020 #include <utility>
0021 
0022 namespace boost {
0023 namespace urls {
0024 namespace grammar {
0025 
0026 /** Common functionality for string views
0027 
0028     This base class is used to provide common
0029     member functions for reference types that
0030     behave like string views. This cannot be
0031     instantiated directly; Instead, derive
0032     from the type and provide constructors
0033     which offer any desired preconditions
0034     and invariants.
0035 */
0036 class string_view_base
0037 {
0038 protected:
0039     /** The referenced character buffer
0040     */
0041     core::string_view s_;
0042 
0043     /** Constructor
0044 
0045         @param s The string view
0046     */
0047     constexpr
0048     string_view_base(
0049         core::string_view s) noexcept
0050         : s_(s)
0051     {
0052     }
0053 
0054     /** Constructor
0055 
0056         @param data The character buffer
0057         @param size The number of characters
0058     */
0059     constexpr
0060     string_view_base(
0061         char const* data,
0062         std::size_t size) noexcept
0063         : s_(data, size)
0064     {
0065     }
0066 
0067     /** Swap
0068 
0069         @param s The object to swap with
0070     */
0071     // VFALCO No idea why this fails in msvc
0072     /*BOOST_CXX14_CONSTEXPR*/
0073     void
0074     swap(
0075         string_view_base& s ) noexcept
0076     {
0077         std::swap(s_, s.s_);
0078     }
0079 
0080     /** Constructor
0081     */
0082     string_view_base() = default;
0083 
0084     /** Constructor
0085     */
0086     string_view_base(
0087         string_view_base const&) = default;
0088 
0089     /** Assignment
0090 
0091         @param other The object to assign
0092         @return A reference to this object
0093     */
0094     string_view_base& operator=(
0095         string_view_base const& other) = default;
0096 
0097 public:
0098     /// The character traits
0099     typedef std::char_traits<char> traits_type;
0100     /// The value type
0101     typedef char value_type;
0102     /// The pointer type
0103     typedef char* pointer;
0104     /// The const pointer type
0105     typedef char const* const_pointer;
0106     /// The reference type
0107     typedef char& reference;
0108     /// The const reference type
0109     typedef char const& const_reference;
0110     /// The const iterator type
0111     typedef char const* const_iterator;
0112     /// The iterator type
0113     typedef const_iterator iterator;
0114     /// The const reverse iterator type
0115     typedef std::reverse_iterator<
0116         const_iterator> const_reverse_iterator;
0117     /// The reverse iterator type
0118     typedef const_reverse_iterator reverse_iterator;
0119     /// The size type
0120     typedef std::size_t size_type;
0121     /// The difference type
0122     typedef std::ptrdiff_t difference_type;
0123 
0124     /// A constant used to represent "no position"
0125     static constexpr std::size_t npos = core::string_view::npos;
0126 
0127     //--------------------------------------------
0128 
0129     /** Conversion
0130 
0131         @return A string view with the same contents
0132      */
0133     operator
0134     core::string_view() const noexcept
0135     {
0136         return s_;
0137     }
0138 
0139     /** Conversion
0140 
0141         @return A string view with the same contents
0142      */
0143 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
0144     operator
0145     std::string_view() const noexcept
0146     {
0147         return std::string_view(s_);
0148     }
0149 #endif
0150 
0151     /** Conversion
0152 
0153         Conversion to std::string is explicit
0154         because assigning to string using an
0155         implicit constructor does not preserve
0156         capacity.
0157 
0158         @return A string with the same contents
0159     */
0160     explicit
0161     operator
0162     std::string() const noexcept
0163     {
0164         return std::string(s_);
0165     }
0166 
0167     //--------------------------------------------
0168 
0169     // iterator support
0170 
0171     /** Return an iterator to the beginning
0172 
0173         See `core::string_view::begin`
0174 
0175         @return An iterator to the beginning
0176     */
0177     BOOST_CONSTEXPR const_iterator begin() const noexcept
0178     {
0179         return s_.begin();
0180     }
0181 
0182     /** Return an iterator to the end
0183 
0184         See `core::string_view::end`
0185 
0186         @return An iterator to the end
0187     */
0188     BOOST_CONSTEXPR const_iterator end() const noexcept
0189     {
0190         return s_.end();
0191     }
0192 
0193     /** Return an iterator to the beginning
0194 
0195         See `core::string_view::cbegin`
0196 
0197         @return An iterator to the beginning
0198     */
0199     BOOST_CONSTEXPR const_iterator cbegin() const noexcept
0200     {
0201         return s_.cbegin();
0202     }
0203 
0204     /** Return an iterator to the end
0205 
0206         See `core::string_view::cend`
0207 
0208         @return An iterator to the end
0209     */
0210     BOOST_CONSTEXPR const_iterator cend() const noexcept
0211     {
0212         return s_.cend();
0213     }
0214 
0215     /** Return a reverse iterator to the end
0216 
0217         See `core::string_view::rbegin`
0218 
0219         @return A reverse iterator to the end
0220     */
0221     BOOST_URL_LIB_ARRAY_CONSTEXPR
0222     const_reverse_iterator rbegin() const noexcept
0223     {
0224         return s_.rbegin();
0225     }
0226 
0227     /** Return a reverse iterator to the beginning
0228 
0229         See `core::string_view::rend`
0230 
0231         @return A reverse iterator to the beginning
0232     */
0233     BOOST_URL_LIB_ARRAY_CONSTEXPR
0234     const_reverse_iterator rend() const noexcept
0235     {
0236         return s_.rend();
0237     }
0238 
0239     /** Return a reverse iterator to the end
0240 
0241         See `core::string_view::crbegin`
0242 
0243         @return A reverse iterator to the end
0244     */
0245     BOOST_URL_LIB_ARRAY_CONSTEXPR
0246     const_reverse_iterator crbegin() const noexcept
0247     {
0248         return s_.crbegin();
0249     }
0250 
0251     /** Return a reverse iterator to the beginning
0252 
0253         See `core::string_view::crend`
0254 
0255         @return A reverse iterator to the beginning
0256     */
0257     BOOST_URL_LIB_ARRAY_CONSTEXPR
0258     const_reverse_iterator crend() const noexcept
0259     {
0260         return s_.crend();
0261     }
0262 
0263     // capacity
0264 
0265     /** Return the size
0266 
0267         See `core::string_view::size`
0268 
0269         @return The size
0270     */
0271     BOOST_CONSTEXPR size_type size() const noexcept
0272     {
0273         return s_.size();
0274     }
0275 
0276     /** Return the size
0277 
0278         See `core::string_view::length`
0279 
0280         @return The size
0281     */
0282     BOOST_CONSTEXPR size_type length() const noexcept
0283     {
0284         return s_.length();
0285     }
0286 
0287     /** Return the maximum allowed size
0288 
0289         See `core::string_view::max_size`
0290 
0291         @return The maximum allowed size
0292     */
0293     BOOST_CONSTEXPR size_type max_size() const noexcept
0294     {
0295         return s_.max_size();
0296     }
0297 
0298     /** Return true if the string is empty
0299 
0300         See `core::string_view::size`
0301 
0302         @return `true` if the string is empty
0303     */
0304     BOOST_CONSTEXPR bool empty() const noexcept
0305     {
0306         return s_.empty();
0307     }
0308    
0309     // element access
0310 
0311     /** Access a character
0312 
0313         See `core::string_view::operator[]`
0314 
0315         @param pos The position to access
0316         @return The character at the position
0317     */
0318     BOOST_CXX14_CONSTEXPR const_reference
0319         operator[]( size_type pos ) const noexcept
0320     {
0321         return s_[pos];
0322     }
0323 
0324     /** Access a character
0325 
0326         See `core::string_view::at`
0327 
0328         @param pos The position to access
0329         @return The character at the position
0330     */
0331     BOOST_CXX14_CONSTEXPR const_reference
0332         at( size_type pos ) const
0333     {
0334         return s_.at(pos);
0335     }
0336 
0337     /** Return the first character
0338 
0339         See `core::string_view::front`
0340 
0341         @return The first character
0342     */
0343     BOOST_CXX14_CONSTEXPR const_reference
0344         front() const noexcept
0345     {
0346         return s_.front();
0347     }
0348 
0349     /** Return the last character
0350 
0351         See `core::string_view::back`
0352 
0353         @return The last character
0354     */
0355     BOOST_CXX14_CONSTEXPR const_reference
0356         back() const noexcept
0357     {
0358         return s_.back();
0359     }
0360 
0361     /** Return a pointer to the character buffer
0362 
0363         See `core::string_view::data`
0364 
0365         @return A pointer to the character buffer
0366     */
0367     BOOST_CONSTEXPR const_pointer
0368         data() const noexcept
0369     {
0370         return s_.data();
0371     }
0372 
0373     // string operations
0374 
0375     /** Copy the characters to another buffer
0376 
0377         See `core::string_view::copy`
0378 
0379         @param s The destination buffer
0380         @param n The number of characters to copy
0381         @param pos The position to start from
0382         @return The number of characters copied
0383     */
0384     BOOST_CXX14_CONSTEXPR size_type copy(
0385         char* s, size_type n, size_type pos = 0 ) const
0386     {
0387         return s_.copy(s, n, pos);
0388     }
0389 
0390     /** Return a view to part of the string
0391 
0392         See `core::string_view::substr`
0393 
0394         @param pos The position to start from
0395         @param n The number of characters
0396         @return A view to the substring
0397     */
0398     BOOST_CXX14_CONSTEXPR core::string_view substr(
0399         size_type pos = 0, size_type n = core::string_view::npos ) const
0400     {
0401         return s_.substr(pos, n);
0402     }
0403 
0404     // comparison
0405 
0406     /** Return the result of comparing to another string
0407 
0408         See `core::string_view::compare`
0409 
0410         @param str The string to compare
0411         @return The result of the comparison
0412     */
0413     BOOST_CXX14_CONSTEXPR int
0414         compare( core::string_view str ) const noexcept
0415     {
0416         return s_.compare(str);
0417     }
0418 
0419     /** Return the result of comparing to another string
0420 
0421         See `core::string_view::compare`
0422 
0423         @param pos1 The position to start comparing from
0424         @param n1 The number of characters to compare
0425         @param str The string to compare
0426         @return The result of the comparison
0427     */
0428     BOOST_CONSTEXPR int compare(
0429         size_type pos1, size_type n1, core::string_view str ) const
0430     {
0431         return s_.compare(pos1, n1, str);
0432     }
0433 
0434     /** Return the result of comparing to another string
0435 
0436         See `core::string_view::compare`
0437 
0438         @param pos1 The position to start comparing from
0439         @param n1 The number of characters to compare
0440         @param str The string to compare
0441         @param pos2 The position to start comparing from
0442         @param n2 The number of characters to compare
0443         @return The result of the comparison
0444     */
0445     BOOST_CONSTEXPR int compare(
0446         size_type pos1, size_type n1, core::string_view str,
0447         size_type pos2, size_type n2 ) const
0448     {
0449         return s_.compare(pos1, n1, str, pos2, n2);
0450     }
0451 
0452     /** Return the result of comparing to another string
0453 
0454         See `core::string_view::compare`
0455 
0456         @param s The string to compare
0457         @return The result of the comparison
0458     */
0459     BOOST_CONSTEXPR int compare(
0460         char const* s ) const noexcept
0461     {
0462         return s_.compare(s);
0463     }
0464 
0465     /** Return the result of comparing to another string
0466 
0467         See `core::string_view::compare`
0468 
0469         @param pos1 The position to start comparing from
0470         @param n1 The number of characters to compare
0471         @param s The string to compare
0472         @return The result of the comparison
0473     */
0474     BOOST_CONSTEXPR int compare(
0475         size_type pos1, size_type n1, char const* s ) const
0476     {
0477         return s_.compare(pos1, n1, s);
0478     }
0479 
0480     /** Return the result of comparing to another string
0481 
0482         See `core::string_view::compare`
0483 
0484         @param pos1 The position to start comparing from
0485         @param n1 The number of characters to compare
0486         @param s The string to compare
0487         @param n2 The number of characters to compare
0488         @return The result of the comparison
0489     */
0490     BOOST_CONSTEXPR int compare(
0491         size_type pos1, size_type n1,
0492         char const* s, size_type n2 ) const
0493     {
0494         return s_.compare(pos1, n1, s, n2);
0495     }
0496 
0497     // starts_with
0498 
0499     /** Return true if a matching prefix exists
0500 
0501         See `core::string_view::starts_with`
0502 
0503         @param x The string to search for
0504         @return `true` if the prefix matches
0505     */
0506     BOOST_CONSTEXPR bool starts_with(
0507         core::string_view x ) const noexcept
0508     {
0509         return s_.starts_with(x);
0510     }
0511 
0512     /** Return true if a matching prefix exists
0513 
0514         See `core::string_view::starts_with`
0515 
0516         @param x The character to search for
0517         @return `true` if the prefix matches
0518     */
0519     BOOST_CONSTEXPR bool starts_with(
0520         char x ) const noexcept
0521     {
0522         return s_.starts_with(x);
0523     }
0524 
0525     /** Return true if a matching prefix exists
0526 
0527         See `core::string_view::starts_with`
0528 
0529         @param x The string to search for
0530         @return `true` if the prefix matches
0531     */
0532     BOOST_CONSTEXPR bool starts_with(
0533         char const* x ) const noexcept
0534     {
0535         return s_.starts_with(x);
0536     }
0537 
0538     // ends_with
0539 
0540     /** Return true if a matching suffix exists
0541 
0542         See `core::string_view::ends_with`
0543 
0544         @param x The string to search for
0545         @return `true` if the suffix matches
0546     */
0547     BOOST_CONSTEXPR bool ends_with(
0548         core::string_view x ) const noexcept
0549     {
0550         return s_.ends_with(x);
0551     }
0552 
0553     /** Return true if a matching suffix exists
0554 
0555         See `core::string_view::ends_with`
0556 
0557         @param x The character to search for
0558         @return `true` if the suffix matches
0559     */
0560     BOOST_CONSTEXPR bool ends_with(
0561         char x ) const noexcept
0562     {
0563         return s_.ends_with(x);
0564     }
0565 
0566     /** Return true if a matching suffix exists
0567 
0568         See `core::string_view::ends_with`
0569 
0570         @param x The string to search for
0571         @return `true` if the suffix matches
0572     */
0573     BOOST_CONSTEXPR bool ends_with(
0574         char const* x ) const noexcept
0575     {
0576         return s_.ends_with(x);
0577     }
0578 
0579     // find
0580 
0581     /** Return the position of matching characters
0582 
0583         See `core::string_view::find`
0584 
0585         @param str The characters to search for
0586         @param pos The position to start searching from
0587         @return The position of the first match
0588     */
0589     BOOST_CONSTEXPR size_type find(
0590         core::string_view str, size_type pos = 0 ) const noexcept
0591     {
0592         return s_.find(str, pos);
0593     }
0594 
0595     /** Return the position of matching characters
0596 
0597         See `core::string_view::find`
0598 
0599         @param c The character to search for
0600         @param pos The position to start searching from
0601         @return The position of the first match
0602     */
0603     BOOST_CXX14_CONSTEXPR size_type find(
0604         char c, size_type pos = 0 ) const noexcept
0605     {
0606         return s_.find(c, pos);
0607     }
0608 
0609     /** Return the position of matching characters
0610 
0611         See `core::string_view::find`
0612 
0613         @param s The characters to search for
0614         @param pos The position to start searching from
0615         @param n The number of characters to search for
0616         @return The position of the first match
0617     */
0618     BOOST_CXX14_CONSTEXPR size_type find(
0619         char const* s, size_type pos, size_type n ) const noexcept
0620     {
0621         return s_.find(s, pos, n);
0622     }
0623 
0624     /** Return the position of matching characters
0625 
0626         See `core::string_view::find`
0627 
0628         @param s The characters to search for
0629         @param pos The position to start searching from
0630         @return The position of the first match
0631     */
0632     BOOST_CONSTEXPR size_type find(
0633         char const* s, size_type pos = 0 ) const noexcept
0634     {
0635         return s_.find(s, pos);
0636     }
0637 
0638     // rfind
0639 
0640     /** Return the position of matching characters
0641 
0642         See `core::string_view::rfind`
0643 
0644         @param str The characters to search for
0645         @param pos The position to start searching from
0646         @return The position of the first match
0647     */
0648     BOOST_CONSTEXPR size_type rfind(
0649         core::string_view str, size_type pos = core::string_view::npos ) const noexcept
0650     {
0651         return s_.rfind(str, pos);
0652     }
0653 
0654     /** Return the position of matching characters
0655 
0656         See `core::string_view::rfind`
0657 
0658         @param c The character to search for
0659         @param pos The position to start searching from
0660         @return The position of the first match
0661     */
0662     BOOST_CXX14_CONSTEXPR size_type rfind(
0663         char c, size_type pos = core::string_view::npos ) const noexcept
0664     {
0665         return s_.rfind(c, pos);
0666     }
0667 
0668     /** Return the position of matching characters
0669 
0670         See `core::string_view::rfind`
0671 
0672         @param s The characters to search for
0673         @param pos The position to start searching from
0674         @param n The number of characters to search for
0675         @return The position of the first match
0676     */
0677     BOOST_CXX14_CONSTEXPR size_type rfind(
0678         char const* s, size_type pos, size_type n ) const noexcept
0679     {
0680         return s_.rfind(s, pos, n);
0681     }
0682 
0683     /** Return the position of matching characters
0684 
0685         See `core::string_view::rfind`
0686 
0687         @param s The characters to search for
0688         @param pos The position to start searching from
0689         @return The position of the first match
0690     */
0691     BOOST_CONSTEXPR size_type rfind(
0692         char const* s, size_type pos = core::string_view::npos ) const noexcept
0693     {
0694         return s_.rfind(s, pos);
0695     }
0696 
0697     // find_first_of
0698 
0699     /** Return the position of the first match
0700 
0701         See `core::string_view::find_first_of`
0702 
0703         @param str The characters to search for
0704         @param pos The position to start searching from
0705         @return The position of the first match
0706     */
0707     BOOST_CXX14_CONSTEXPR size_type find_first_of(
0708         core::string_view str, size_type pos = 0 ) const noexcept
0709     {
0710         return s_.find_first_of(str, pos);
0711     }
0712 
0713     /** Return the position of the first match
0714 
0715         See `core::string_view::find_first_of`
0716 
0717         @param c The character to search for
0718         @param pos The position to start searching from
0719         @return The position of the first match
0720     */
0721     BOOST_CONSTEXPR size_type find_first_of(
0722         char c, size_type pos = 0 ) const noexcept
0723     {
0724         return s_.find_first_of(c, pos);
0725     }
0726 
0727     /** Return the position of the first match
0728 
0729         See `core::string_view::find_first_of`
0730 
0731         @param s The characters to search for
0732         @param pos The position to start searching from
0733         @param n The number of characters to search for
0734         @return The position of the first match
0735     */
0736     BOOST_CXX14_CONSTEXPR size_type find_first_of(
0737         char const* s, size_type pos, size_type n ) const noexcept
0738     {
0739         return s_.find_first_of(s, pos, n);
0740     }
0741 
0742     /** Return the position of the first match
0743 
0744         See `core::string_view::find_first_of`
0745 
0746         @param s The characters to search for
0747         @param pos The position to start searching from
0748         @return The position of the first match
0749     */
0750     BOOST_CXX14_CONSTEXPR size_type find_first_of(
0751         char const* s, size_type pos = 0 ) const noexcept
0752     {
0753         return s_.find_first_of(s, pos);
0754     }
0755 
0756     // find_last_of
0757 
0758     /** Return the position of the last match
0759 
0760         See `core::string_view::find_last_of`
0761 
0762         @param str The characters to search for
0763         @param pos The position to start searching from
0764         @return The position of the last match
0765     */
0766     BOOST_CXX14_CONSTEXPR size_type find_last_of(
0767         core::string_view str, size_type pos = core::string_view::npos ) const noexcept
0768     {
0769         return s_.find_last_of(str, pos);
0770     }
0771 
0772     /** Return the position of the last match
0773 
0774         See `core::string_view::find_last_of`
0775 
0776         @param c The character to search for
0777         @param pos The position to start searching from
0778         @return The position of the last match
0779     */
0780     BOOST_CONSTEXPR size_type find_last_of(
0781         char c, size_type pos = core::string_view::npos ) const noexcept
0782     {
0783         return s_.find_last_of(c, pos);
0784     }
0785 
0786     /** Return the position of the last match
0787 
0788         See `core::string_view::find_last_of`
0789 
0790         @param s The characters to search for
0791         @param pos The position to start searching from
0792         @param n The number of characters to search for
0793         @return The position of the last match
0794     */
0795     BOOST_CXX14_CONSTEXPR size_type find_last_of(
0796         char const* s, size_type pos, size_type n ) const noexcept
0797     {
0798         return s_.find_last_of(s, pos, n);
0799     }
0800 
0801     /** Return the position of the last match
0802 
0803         See `core::string_view::find_last_of`
0804 
0805         @param s The characters to search for
0806         @param pos The position to start searching from
0807         @return The position of the last match
0808     */
0809     BOOST_CXX14_CONSTEXPR size_type find_last_of(
0810         char const* s, size_type pos = core::string_view::npos ) const noexcept
0811     {
0812         return s_.find_last_of(s, pos);
0813     }
0814 
0815     // find_first_not_of
0816 
0817     /** Return the position of the first non-match
0818 
0819         See `core::string_view::find_first_not_of`
0820 
0821         @param str The characters to search for
0822         @param pos The position to start searching from
0823         @return The position of the first non-match
0824     */
0825     BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
0826         core::string_view str, size_type pos = 0 ) const noexcept
0827     {
0828         return s_.find_first_not_of(str, pos);
0829     }
0830 
0831     /** Return the position of the first non-match
0832 
0833         See `core::string_view::find_first_not_of`
0834 
0835         @param c The character to search for
0836         @param pos The position to start searching from
0837         @return The position of the first non-match
0838     */
0839     BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
0840         char c, size_type pos = 0 ) const noexcept
0841     {
0842         return s_.find_first_not_of(c, pos);
0843     }
0844 
0845     /** Return the position of the first non-match
0846 
0847         See `core::string_view::find_first_not_of`
0848 
0849         @param s The characters to search for
0850         @param pos The position to start searching from
0851         @param n The number of characters to search for
0852         @return The position of the first non-match
0853     */
0854     BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
0855         char const* s, size_type pos, size_type n ) const noexcept
0856     {
0857         return s_.find_first_not_of(s, pos, n);
0858     }
0859 
0860     /** Return the position of the first non-match
0861 
0862         See `core::string_view::find_first_not_of`
0863 
0864         @param s The characters to search for
0865         @param pos The position to start searching from
0866         @return The position of the first non-match
0867     */
0868     BOOST_CXX14_CONSTEXPR size_type find_first_not_of(
0869         char const* s, size_type pos = 0 ) const noexcept
0870     {
0871         return s_.find_first_not_of(s, pos);
0872     }
0873 
0874     // find_last_not_of
0875 
0876     /** Return the position of the last non-match
0877 
0878         See `core::string_view::find_last_not_of`
0879 
0880         @param str The characters to search for
0881         @param pos The position to start searching from
0882         @return The position of the last non-match
0883     */
0884     BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
0885         core::string_view str, size_type pos = core::string_view::npos ) const noexcept
0886     {
0887         return s_.find_last_not_of(str, pos);
0888     }
0889 
0890     /** Return the position of the last non-match
0891 
0892         See `core::string_view::find_last_not_of`
0893 
0894         @param c The character to search for
0895         @param pos The position to start searching from
0896         @return The position of the last non-match
0897     */
0898     BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
0899         char c, size_type pos = core::string_view::npos ) const noexcept
0900     {
0901         return s_.find_last_not_of(c, pos);
0902     }
0903 
0904     /** Return the position of the last non-match
0905 
0906         See `core::string_view::find_last_not_of`
0907 
0908         @param s The characters to search for
0909         @param pos The position to start searching from
0910         @param n The number of characters to search for
0911         @return The position of the last non-match
0912     */
0913     BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
0914         char const* s, size_type pos, size_type n ) const noexcept
0915     {
0916         return s_.find_last_not_of(s, pos, n);
0917     }
0918 
0919     /** Return the position of the last non-match
0920 
0921         See `core::string_view::find_last_not_of`
0922 
0923         @param s The characters to search for
0924         @param pos The position to start searching from
0925         @return The position of the last non-match
0926     */
0927     BOOST_CXX14_CONSTEXPR size_type find_last_not_of(
0928         char const* s, size_type pos = core::string_view::npos ) const noexcept
0929     {
0930         return s_.find_last_not_of(s, pos);
0931     }
0932 
0933     // contains
0934 
0935     /** Return true if matching characters are found
0936 
0937         See `core::string_view::contains`
0938 
0939         @param sv The string to search for
0940         @return `true` if the string contains the characters, otherwise `false`
0941     */
0942     BOOST_CONSTEXPR bool contains( core::string_view sv ) const noexcept
0943     {
0944         return s_.contains(sv);
0945     }
0946 
0947     /** Return true if matching characters are found
0948 
0949         See `core::string_view::contains`
0950 
0951         @param c The character to search for
0952         @return `true` if the string contains the character, otherwise `false`
0953     */
0954     BOOST_CXX14_CONSTEXPR bool contains( char c ) const noexcept
0955     {
0956         return s_.contains(c);
0957     }
0958 
0959     /** Return true if matching characters are found
0960 
0961         See `core::string_view::contains`
0962 
0963         @param s The string to search for
0964         @return `true` if the string contains the characters, otherwise `false`
0965     */
0966     BOOST_CONSTEXPR bool contains( char const* s ) const noexcept
0967     {
0968         return s_.contains(s);
0969     }
0970 
0971     // relational operators
0972 #ifndef BOOST_URL_DOCS
0973 private:
0974     template<class S0, class S1>
0975     using is_match = std::integral_constant<bool,
0976         std::is_convertible<S0, core::string_view>::value &&
0977         std::is_convertible<S1, core::string_view>::value && (
0978             (std::is_base_of<string_view_base,
0979                 typename std::decay<S0>::type>::value &&
0980             std::is_convertible<S0 const volatile*,
0981                 string_view_base const volatile*>::value) ||
0982             (std::is_base_of<string_view_base,
0983                 typename std::decay<S1>::type>::value &&
0984             std::is_convertible<S1 const volatile*,
0985                 string_view_base const volatile*>::value))>;
0986 public:
0987 
0988     /** Compare two string views for equality
0989 
0990         This function is only enabled if both arguments
0991         are convertible to `core::string_view` and at least
0992         one of the arguments is derived from `string_view_base`.
0993 
0994         @param s0 The first string
0995         @param s1 The second string
0996         @return `true` if the strings are equal, otherwise `false`
0997      */
0998     template<class S0, class S1>
0999     BOOST_CXX14_CONSTEXPR friend auto operator==(
1000         S0 const& s0, S1 const& s1) noexcept ->
1001         typename std::enable_if<
1002             is_match<S0, S1>::value, bool>::type
1003     {
1004         return urls::detail::to_sv(s0) == urls::detail::to_sv(s1);
1005     }
1006 
1007     /** Compare two string views for inequality
1008 
1009         This function is only enabled if both arguments
1010         are convertible to `core::string_view` and at least
1011         one of the arguments is derived from `string_view_base`.
1012 
1013         @param s0 The first string
1014         @param s1 The second string
1015         @return `true` if the strings are not equal, otherwise `false`
1016      */
1017     template<class S0, class S1>
1018     BOOST_CXX14_CONSTEXPR friend auto operator!=(
1019         S0 const& s0, S1 const& s1) noexcept ->
1020         typename std::enable_if<
1021             is_match<S0, S1>::value, bool>::type
1022     {
1023         return urls::detail::to_sv(s0) != urls::detail::to_sv(s1);
1024     }
1025 
1026     /** Compare two string views for less than
1027 
1028         This function is only enabled if both arguments
1029         are convertible to `core::string_view` and at least
1030         one of the arguments is derived from `string_view_base`.
1031 
1032         @param s0 The first string
1033         @param s1 The second string
1034         @return `true` if the first string is less than the second, otherwise `false`
1035      */
1036     template<class S0, class S1>
1037     BOOST_CXX14_CONSTEXPR friend auto operator<(
1038         S0 const& s0, S1 const& s1) noexcept ->
1039         typename std::enable_if<
1040             is_match<S0, S1>::value, bool>::type
1041     {
1042         return urls::detail::to_sv(s0) < urls::detail::to_sv(s1);
1043     }
1044 
1045     /** Compare two string views for less than or equal
1046 
1047         This function is only enabled if both arguments
1048         are convertible to `core::string_view` and at least
1049         one of the arguments is derived from `string_view_base`.
1050 
1051         @param s0 The first string
1052         @param s1 The second string
1053         @return `true` if the first string is less than or equal to the second, otherwise `false`
1054      */
1055     template<class S0, class S1>
1056     BOOST_CXX14_CONSTEXPR friend auto operator<=(
1057         S0 const& s0, S1 const& s1) noexcept ->
1058         typename std::enable_if<
1059             is_match<S0, S1>::value, bool>::type
1060     {
1061         return urls::detail::to_sv(s0) <= urls::detail::to_sv(s1);
1062     }
1063 
1064     /** Compare two string views for greater than
1065 
1066         This function is only enabled if both arguments
1067         are convertible to `core::string_view` and at least
1068         one of the arguments is derived from `string_view_base`.
1069 
1070         @param s0 The first string
1071         @param s1 The second string
1072         @return `true` if the first string is greater than the second, otherwise `false`
1073      */
1074     template<class S0, class S1>
1075     BOOST_CXX14_CONSTEXPR friend auto operator>(
1076         S0 const& s0, S1 const& s1) noexcept ->
1077         typename std::enable_if<
1078             is_match<S0, S1>::value, bool>::type
1079     {
1080         return urls::detail::to_sv(s0) > urls::detail::to_sv(s1);
1081     }
1082 
1083     /** Compare two string views for greater than or equal
1084 
1085         This function is only enabled if both arguments
1086         are convertible to `core::string_view` and at least
1087         one of the arguments is derived from `string_view_base`.
1088 
1089         @param s0 The first string
1090         @param s1 The second string
1091         @return `true` if the first string is greater than or equal to the second, otherwise `false`
1092      */
1093     template<class S0, class S1>
1094     BOOST_CXX14_CONSTEXPR friend auto operator>=(
1095         S0 const& s0, S1 const& s1) noexcept ->
1096         typename std::enable_if<
1097             is_match<S0, S1>::value, bool>::type
1098     {
1099         return urls::detail::to_sv(s0) >= urls::detail::to_sv(s1);
1100     }
1101 #endif
1102 
1103     //--------------------------------------------
1104 
1105     /** Format a string to an output stream
1106 
1107         @param os The output stream to write to
1108         @param s The string to write
1109         @return A reference to the output stream, for chaining
1110      */
1111     BOOST_URL_DECL
1112     friend
1113     std::ostream&
1114     operator<<(
1115         std::ostream& os,
1116         string_view_base const& s);
1117 };
1118 
1119 //------------------------------------------------
1120 
1121 /** Format a string to an output stream
1122 */
1123 BOOST_URL_DECL
1124 std::ostream&
1125 operator<<(
1126     std::ostream& os,
1127     string_view_base const& s);
1128 
1129 } // grammar
1130 
1131 #ifndef BOOST_URL_DOCS
1132 namespace detail {
1133 template <>
1134 inline
1135 core::string_view
1136 to_sv(grammar::string_view_base const& s) noexcept
1137 {
1138     return s.operator core::string_view();
1139 }
1140 } // detail
1141 #endif
1142 
1143 } // urls
1144 } // boost
1145 
1146 #endif