Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:25:26

0001 #ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED
0002 #define BOOST_CORE_STRING_VIEW_HPP_INCLUDED
0003 
0004 // MS compatible compilers support #pragma once
0005 
0006 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
0007 # pragma once
0008 #endif
0009 
0010 // boost::core::basic_string_view<Ch>
0011 //
0012 // Copyright 2021 Peter Dimov
0013 // Distributed under the Boost Software License, Version 1.0.
0014 // https://www.boost.org/LICENSE_1_0.txt
0015 
0016 #include <boost/core/enable_if.hpp>
0017 #include <boost/core/detail/is_same.hpp>
0018 #include <boost/assert.hpp>
0019 #include <boost/assert/source_location.hpp>
0020 #include <boost/throw_exception.hpp>
0021 #include <boost/config.hpp>
0022 #include <string>
0023 #include <algorithm>
0024 #include <utility>
0025 #include <stdexcept>
0026 #include <cstddef>
0027 #include <cstring>
0028 #include <climits>
0029 #include <iosfwd>
0030 #include <ios>
0031 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
0032 # include <string_view>
0033 #endif
0034 #if !defined(BOOST_NO_CXX20_HDR_CONCEPTS) // std::common_reference_with
0035 # include <type_traits>
0036 #endif
0037 
0038 namespace boost
0039 {
0040 
0041 // forward declaration of boost::basic_string_view from Utility
0042 template<class Ch, class Tr> class basic_string_view;
0043 
0044 namespace core
0045 {
0046 namespace detail
0047 {
0048 
0049 template<class Ch> struct sv_to_uchar
0050 {
0051     typedef Ch type;
0052 };
0053 
0054 template<> struct sv_to_uchar<char>
0055 {
0056     typedef unsigned char type;
0057 };
0058 
0059 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406
0060 # pragma GCC diagnostic push
0061 # pragma GCC diagnostic ignored "-Wtype-limits"
0062 #endif
0063 
0064 template<class Ch> BOOST_CXX14_CONSTEXPR std::size_t find_first_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT
0065 {
0066     typedef typename sv_to_uchar<Ch>::type UCh;
0067 
0068     unsigned char table[ 256 ] = {};
0069 
0070     bool use_table = true;
0071 
0072     for( std::size_t j = 0; j < n; ++j )
0073     {
0074         UCh ch = static_cast<UCh>( s[ j ] );
0075 
0076         if( ch >= 0 && ch < 256 )
0077         {
0078             table[ ch ] = 1;
0079         }
0080         else
0081         {
0082             use_table = false;
0083             break;
0084         }
0085     }
0086 
0087     if( use_table )
0088     {
0089         for( std::size_t i = pos; i < n_; ++i )
0090         {
0091             UCh ch = static_cast<UCh>( p_[ i ] );
0092             if( ch >= 0 && ch < 256 && table[ ch ] ) return i;
0093         }
0094     }
0095     else if( n >= 16 )
0096     {
0097         for( std::size_t i = pos; i < n_; ++i )
0098         {
0099             Ch ch = p_[ i ];
0100             if( std::char_traits<Ch>::find( s, n, ch ) != 0 ) return i;
0101         }
0102     }
0103     else
0104     {
0105         for( std::size_t i = pos; i < n_; ++i )
0106         {
0107             Ch ch = p_[ i ];
0108 
0109             for( std::size_t j = 0; j < n; ++j )
0110             {
0111                 if( s[ j ] == ch ) return i;
0112             }
0113         }
0114     }
0115 
0116     return static_cast<std::size_t>( -1 );
0117 }
0118 
0119 template<class Ch> BOOST_CXX14_CONSTEXPR std::size_t find_last_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT
0120 {
0121     typedef typename sv_to_uchar<Ch>::type UCh;
0122 
0123     unsigned char table[ 256 ] = {};
0124 
0125     bool use_table = true;
0126 
0127     for( std::size_t j = 0; j < n; ++j )
0128     {
0129         UCh ch = static_cast<UCh>( s[ j ] );
0130 
0131         if( ch >= 0 && ch < 256 )
0132         {
0133             table[ ch ] = 1;
0134         }
0135         else
0136         {
0137             use_table = false;
0138             break;
0139         }
0140     }
0141 
0142     std::size_t const npos = static_cast< std::size_t >( -1 );
0143 
0144     std::size_t i = pos;
0145 
0146     if( use_table )
0147     {
0148         do
0149         {
0150             UCh ch = static_cast<UCh>( p_[ i ] );
0151 
0152             if( ch >= 0 && ch < 256 && table[ ch ] ) return i;
0153 
0154             --i;
0155         }
0156         while( i != npos );
0157     }
0158     else if( n >= 16 )
0159     {
0160         do
0161         {
0162             Ch ch = p_[ i ];
0163 
0164             if( std::char_traits<Ch>::find( s, n, ch ) != 0 ) return i;
0165 
0166             --i;
0167         }
0168         while( i != npos );
0169     }
0170     else
0171     {
0172         do
0173         {
0174             Ch ch = p_[ i ];
0175 
0176             for( std::size_t j = 0; j < n; ++j )
0177             {
0178                 if( s[ j ] == ch ) return i;
0179             }
0180 
0181             --i;
0182         }
0183         while( i != npos );
0184     }
0185 
0186     return npos;
0187 }
0188 
0189 template<class Ch> BOOST_CXX14_CONSTEXPR std::size_t find_first_not_of( Ch const* p_, std::size_t n_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT
0190 {
0191     typedef typename sv_to_uchar<Ch>::type UCh;
0192 
0193     unsigned char table[ 256 ] = {};
0194 
0195     bool use_table = true;
0196 
0197     for( std::size_t j = 0; j < n; ++j )
0198     {
0199         UCh ch = static_cast<UCh>( s[ j ] );
0200 
0201         if( ch >= 0 && ch < 256 )
0202         {
0203             table[ ch ] = 1;
0204         }
0205         else
0206         {
0207             use_table = false;
0208             break;
0209         }
0210     }
0211 
0212     if( use_table )
0213     {
0214         for( std::size_t i = pos; i < n_; ++i )
0215         {
0216             UCh ch = static_cast<UCh>( p_[ i ] );
0217             if( !( ch >= 0 && ch < 256 && table[ ch ] ) ) return i;
0218         }
0219     }
0220     else if( n >= 16 )
0221     {
0222         for( std::size_t i = pos; i < n_; ++i )
0223         {
0224             Ch ch = p_[ i ];
0225             if( std::char_traits<Ch>::find( s, n, ch ) == 0 ) return i;
0226         }
0227     }
0228     else
0229     {
0230         for( std::size_t i = pos; i < n_; ++i )
0231         {
0232             Ch ch = p_[ i ];
0233 
0234             bool r = false;
0235 
0236             for( std::size_t j = 0; j < n; ++j )
0237             {
0238                 if( s[ j ] == ch )
0239                 {
0240                     r = true;
0241                     break;
0242                 }
0243             }
0244 
0245             if( !r ) return i;
0246         }
0247     }
0248 
0249     return static_cast<std::size_t>( -1 );
0250 }
0251 
0252 template<class Ch> BOOST_CXX14_CONSTEXPR std::size_t find_last_not_of( Ch const* p_, Ch const* s, std::size_t pos, std::size_t n ) BOOST_NOEXCEPT
0253 {
0254     typedef typename sv_to_uchar<Ch>::type UCh;
0255 
0256     unsigned char table[ 256 ] = {};
0257 
0258     bool use_table = true;
0259 
0260     for( std::size_t j = 0; j < n; ++j )
0261     {
0262         UCh ch = static_cast<UCh>( s[ j ] );
0263 
0264         if( ch >= 0 && ch < 256 )
0265         {
0266             table[ ch ] = 1;
0267         }
0268         else
0269         {
0270             use_table = false;
0271             break;
0272         }
0273     }
0274 
0275     std::size_t const npos = static_cast< std::size_t >( -1 );
0276 
0277     std::size_t i = pos;
0278 
0279     if( use_table )
0280     {
0281         do
0282         {
0283             UCh ch = static_cast<UCh>( p_[ i ] );
0284 
0285             if( !( ch >= 0 && ch < 256 && table[ ch ] ) ) return i;
0286 
0287             --i;
0288         }
0289         while( i != npos );
0290     }
0291     else if( n >= 16 )
0292     {
0293         do
0294         {
0295             Ch ch = p_[ i ];
0296 
0297             if( std::char_traits<Ch>::find( s, n, ch ) == 0 ) return i;
0298 
0299             --i;
0300         }
0301         while( i != npos );
0302     }
0303     else
0304     {
0305         do
0306         {
0307             Ch ch = p_[ i ];
0308 
0309             bool r = false;
0310 
0311             for( std::size_t j = 0; j < n; ++j )
0312             {
0313                 if( s[ j ] == ch )
0314                 {
0315                     r = true;
0316                     break;
0317                 }
0318             }
0319 
0320             if( !r ) return i;
0321 
0322             --i;
0323         }
0324         while( i != npos );
0325     }
0326 
0327     return npos;
0328 }
0329 
0330 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406
0331 # pragma GCC diagnostic pop
0332 #endif
0333 
0334 } // namespace detail
0335 
0336 template<class Ch> class basic_string_view
0337 {
0338 private:
0339 
0340     Ch const* p_;
0341     std::size_t n_;
0342 
0343 public:
0344 
0345     // types
0346 
0347     typedef std::char_traits<Ch> traits_type;
0348     typedef Ch value_type;
0349     typedef Ch* pointer;
0350     typedef Ch const* const_pointer;
0351     typedef Ch& reference;
0352     typedef Ch const& const_reference;
0353     typedef Ch const* const_iterator;
0354     typedef const_iterator iterator;
0355     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
0356     typedef const_reverse_iterator reverse_iterator;
0357     typedef std::size_t size_type;
0358     typedef std::ptrdiff_t difference_type;
0359 
0360     // npos
0361 
0362     BOOST_STATIC_CONSTEXPR size_type npos = static_cast<size_type>( -1 );
0363 
0364 public:
0365 
0366     // construction and assignment
0367 
0368     BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT: p_(), n_()
0369     {
0370     }
0371 
0372     BOOST_CONSTEXPR basic_string_view( Ch const* str ) BOOST_NOEXCEPT: p_( str ), n_( traits_type::length( str ) )
0373     {
0374     }
0375 
0376     BOOST_CONSTEXPR basic_string_view( Ch const* str, size_type len ) BOOST_NOEXCEPT: p_( str ), n_( len )
0377     {
0378     }
0379 
0380     template<class End> BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* first, End last,
0381         typename boost::enable_if<boost::core::detail::is_same<End, Ch const*>, int >::type = 0 ) BOOST_NOEXCEPT: p_( first ), n_( static_cast<size_type>( last - first ) )
0382     {
0383         BOOST_ASSERT( last - first >= 0 );
0384     }
0385 
0386     template<class A> basic_string_view( std::basic_string<Ch, std::char_traits<Ch>, A> const& str ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() )
0387     {
0388     }
0389 
0390 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
0391 
0392     BOOST_CONSTEXPR basic_string_view( std::basic_string_view<Ch, std::char_traits<Ch> > const& str ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() )
0393     {
0394     }
0395 
0396 #endif
0397 
0398     template<class Ch2> basic_string_view( boost::basic_string_view<Ch2, std::char_traits<Ch2> > const& str,
0399         typename boost::enable_if<boost::core::detail::is_same<Ch, Ch2>, int >::type = 0 ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() )
0400     {
0401     }
0402 
0403 #if !defined(BOOST_NO_CXX11_NULLPTR)
0404 # if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
0405 
0406     basic_string_view( std::nullptr_t ) = delete;
0407 
0408 # else
0409 
0410 private:
0411 
0412     basic_string_view( std::nullptr_t );
0413 
0414 public:
0415 
0416 # endif
0417 #endif
0418 
0419     // BOOST_CONSTEXPR basic_string_view& operator=( basic_string_view const& ) BOOST_NOEXCEPT & = default;
0420 
0421     // conversions
0422 
0423     template<class A> operator std::basic_string<Ch, std::char_traits<Ch>, A>() const
0424     {
0425         return std::basic_string<Ch, std::char_traits<Ch>, A>( data(), size() );
0426     }
0427 
0428 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
0429 
0430     template<class Ch2, class En = typename boost::enable_if<boost::core::detail::is_same<Ch2, Ch> >::type>
0431     operator std::basic_string_view<Ch2>() const BOOST_NOEXCEPT
0432     {
0433         return std::basic_string_view<Ch>( data(), size() );
0434     }
0435 
0436 #endif
0437 
0438     template<class Ch2> operator boost::basic_string_view<Ch2,
0439         typename boost::enable_if<boost::core::detail::is_same<Ch2, Ch>, std::char_traits<Ch> >::type> () const BOOST_NOEXCEPT
0440     {
0441         return boost::basic_string_view< Ch, std::char_traits<Ch> >( data(), size() );
0442     }
0443 
0444     // iterator support
0445 
0446     BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT
0447     {
0448         return p_;
0449     }
0450 
0451     BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT
0452     {
0453         return p_ + n_;
0454     }
0455 
0456     BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT
0457     {
0458         return p_;
0459     }
0460 
0461     BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT
0462     {
0463         return p_ + n_;
0464     }
0465 
0466     BOOST_CONSTEXPR const_reverse_iterator rbegin() const BOOST_NOEXCEPT
0467     {
0468         return const_reverse_iterator( end() );
0469     }
0470 
0471     BOOST_CONSTEXPR const_reverse_iterator rend() const BOOST_NOEXCEPT
0472     {
0473         return const_reverse_iterator( begin() );
0474     }
0475 
0476     BOOST_CONSTEXPR const_reverse_iterator crbegin() const BOOST_NOEXCEPT
0477     {
0478         return const_reverse_iterator( end() );
0479     }
0480 
0481     BOOST_CONSTEXPR const_reverse_iterator crend() const BOOST_NOEXCEPT
0482     {
0483         return const_reverse_iterator( begin() );
0484     }
0485 
0486     // capacity
0487 
0488     BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT
0489     {
0490         return n_;
0491     }
0492 
0493     BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT
0494     {
0495         return n_;
0496     }
0497 
0498     BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT
0499     {
0500         return npos / sizeof( Ch );
0501     }
0502 
0503     BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT
0504     {
0505         return n_ == 0;
0506     }
0507 
0508     // element access
0509 
0510     BOOST_CXX14_CONSTEXPR const_reference operator[]( size_type pos ) const BOOST_NOEXCEPT
0511     {
0512         BOOST_ASSERT( pos < size() );
0513         return p_[ pos ];
0514     }
0515 
0516     BOOST_CXX14_CONSTEXPR const_reference at( size_type pos ) const
0517     {
0518         if( pos >= size() )
0519         {
0520             boost::throw_exception( std::out_of_range( "basic_string_view::at" ), BOOST_CURRENT_LOCATION );
0521         }
0522 
0523         return p_[ pos ];
0524     }
0525 
0526     BOOST_CXX14_CONSTEXPR const_reference front() const BOOST_NOEXCEPT
0527     {
0528         BOOST_ASSERT( !empty() );
0529         return p_[ 0 ];
0530     }
0531 
0532     BOOST_CXX14_CONSTEXPR const_reference back() const BOOST_NOEXCEPT
0533     {
0534         BOOST_ASSERT( !empty() );
0535         return p_[ n_ - 1 ];
0536     }
0537 
0538     BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT
0539     {
0540         return p_;
0541     }
0542 
0543     // modifiers
0544 
0545     BOOST_CXX14_CONSTEXPR void remove_prefix( size_type n ) BOOST_NOEXCEPT
0546     {
0547         BOOST_ASSERT( n <= size() );
0548 
0549         p_ += n;
0550         n_ -= n;
0551     }
0552 
0553     BOOST_CXX14_CONSTEXPR void remove_suffix( size_type n ) BOOST_NOEXCEPT
0554     {
0555         BOOST_ASSERT( n <= size() );
0556 
0557         n_ -= n;
0558     }
0559 
0560     BOOST_CXX14_CONSTEXPR void swap( basic_string_view& s ) BOOST_NOEXCEPT
0561     {
0562         std::swap( p_, s.p_ );
0563         std::swap( n_, s.n_ );
0564     }
0565 
0566     // string operations
0567 
0568     BOOST_CXX14_CONSTEXPR size_type copy( Ch* s, size_type n, size_type pos = 0 ) const
0569     {
0570         if( pos > size() )
0571         {
0572             boost::throw_exception( std::out_of_range( "basic_string_view::copy" ), BOOST_CURRENT_LOCATION );
0573         }
0574 
0575         std::size_t rlen = (std::min)( n, size() - pos );
0576 
0577         traits_type::copy( s, data() + pos, rlen );
0578 
0579         return rlen;
0580     }
0581 
0582     BOOST_CXX14_CONSTEXPR basic_string_view substr( size_type pos = 0, size_type n = npos ) const
0583     {
0584         if( pos > size() )
0585         {
0586             boost::throw_exception( std::out_of_range( "basic_string_view::substr" ), BOOST_CURRENT_LOCATION );
0587         }
0588 
0589         std::size_t rlen = (std::min)( n, size() - pos );
0590 
0591         return basic_string_view( data() + pos, rlen );
0592     }
0593 
0594     // compare
0595 
0596     BOOST_CXX14_CONSTEXPR int compare( basic_string_view str ) const BOOST_NOEXCEPT
0597     {
0598         std::size_t rlen = (std::min)( size(), str.size() );
0599 
0600         int cmp = traits_type::compare( data(), str.data(), rlen );
0601 
0602         if( cmp != 0 ) return cmp;
0603 
0604         if( size() == str.size() ) return 0;
0605 
0606         return size() < str.size()? -1: +1;
0607     }
0608 
0609     BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str ) const
0610     {
0611         return substr( pos1, n1 ).compare( str );
0612     }
0613 
0614     BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const
0615     {
0616         return substr( pos1, n1 ).compare( str.substr( pos2, n2 ) );
0617     }
0618 
0619     BOOST_CONSTEXPR int compare( Ch const* s ) const BOOST_NOEXCEPT
0620     {
0621         return compare( basic_string_view( s ) );
0622     }
0623 
0624     BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s ) const
0625     {
0626         return substr( pos1, n1 ).compare( basic_string_view( s ) );
0627     }
0628 
0629     BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const
0630     {
0631         return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) );
0632     }
0633 
0634     // starts_with
0635 
0636     BOOST_CONSTEXPR bool starts_with( basic_string_view x ) const BOOST_NOEXCEPT
0637     {
0638         return size() >= x.size() && traits_type::compare( data(), x.data(), x.size() ) == 0;
0639     }
0640 
0641     BOOST_CONSTEXPR bool starts_with( Ch x ) const BOOST_NOEXCEPT
0642     {
0643         return !empty() && front() == x;
0644     }
0645 
0646     BOOST_CONSTEXPR bool starts_with( Ch const* x ) const BOOST_NOEXCEPT
0647     {
0648         return starts_with( basic_string_view( x ) );
0649     }
0650 
0651     // ends_with
0652 
0653     BOOST_CONSTEXPR bool ends_with( basic_string_view x ) const BOOST_NOEXCEPT
0654     {
0655         return size() >= x.size() && traits_type::compare( data() + size() - x.size(), x.data(), x.size() ) == 0;
0656     }
0657 
0658     BOOST_CONSTEXPR bool ends_with( Ch x ) const BOOST_NOEXCEPT
0659     {
0660         return !empty() && back() == x;
0661     }
0662 
0663     BOOST_CONSTEXPR bool ends_with( Ch const* x ) const BOOST_NOEXCEPT
0664     {
0665         return ends_with( basic_string_view( x ) );
0666     }
0667 
0668     // find
0669 
0670     BOOST_CONSTEXPR size_type find( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT
0671     {
0672         return find( str.data(), pos, str.size() );
0673     }
0674 
0675     BOOST_CXX14_CONSTEXPR size_type find( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT
0676     {
0677         if( pos >= size() ) return npos;
0678 
0679         Ch const* r = traits_type::find( data() + pos, size() - pos, c );
0680 
0681         return r? static_cast<size_type>( r - data() ): npos;
0682     }
0683 
0684     BOOST_CXX14_CONSTEXPR size_type find( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
0685     {
0686         if( n == 1 ) return find( s[0], pos );
0687 
0688         if( pos + n > size() ) return npos;
0689         if( n == 0 ) return pos;
0690 
0691         Ch const* p = data() + pos;
0692         Ch const* last = data() + size() - n + 1;
0693 
0694         for( ;; )
0695         {
0696             p = traits_type::find( p, static_cast<size_type>( last - p ), s[0] );
0697 
0698             if( p == 0 ) break;
0699 
0700             if( traits_type::compare( p + 1, s + 1, n - 1 ) == 0 ) return static_cast<size_type>( p - data() );
0701 
0702             ++p;
0703         }
0704 
0705         return npos;
0706     }
0707 
0708     BOOST_CONSTEXPR size_type find( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT
0709     {
0710         return find( s, pos, traits_type::length( s ) );
0711     }
0712 
0713     // rfind
0714 
0715     BOOST_CONSTEXPR size_type rfind( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT
0716     {
0717         return rfind( str.data(), pos, str.size() );
0718     }
0719 
0720     BOOST_CXX14_CONSTEXPR size_type rfind( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT
0721     {
0722         size_type n = size();
0723 
0724         if( n == 0 )
0725         {
0726             return npos;
0727         }
0728 
0729         if( pos > n - 1 )
0730         {
0731             pos = n - 1;
0732         }
0733 
0734         do
0735         {
0736             if( p_[ pos ] == c ) return pos;
0737             --pos;
0738         }
0739         while( pos != npos );
0740 
0741         return npos;
0742     }
0743 
0744     BOOST_CXX14_CONSTEXPR size_type rfind( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
0745     {
0746         if( n > size() ) return npos;
0747 
0748         if( pos > size() - n )
0749         {
0750             pos = size() - n;
0751         }
0752 
0753         if( n == 0 ) return pos;
0754 
0755         for( ;; )
0756         {
0757             size_type xpos = rfind( s[0], pos );
0758 
0759             if( xpos == npos ) return npos;
0760 
0761             if( traits_type::compare( data() + xpos, s, n ) == 0 ) return xpos;
0762 
0763             if( xpos == 0 ) return npos;
0764 
0765             pos = xpos - 1;
0766         }
0767     }
0768 
0769     BOOST_CONSTEXPR size_type rfind( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT
0770     {
0771         return rfind( s, pos, traits_type::length( s ) );
0772     }
0773 
0774     // find_first_of
0775 
0776     BOOST_CXX14_CONSTEXPR size_type find_first_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT
0777     {
0778         return find_first_of( str.data(), pos, str.size() );
0779     }
0780 
0781     BOOST_CONSTEXPR size_type find_first_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT
0782     {
0783         return find( c, pos );
0784     }
0785 
0786     BOOST_CXX14_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
0787     {
0788         if( n == 0 || pos >= size() ) return npos;
0789         if( n == 1 ) return find( s[0], pos );
0790 
0791         return detail::find_first_of( data(), size(), s, pos, n );
0792     }
0793 
0794     BOOST_CXX14_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT
0795     {
0796         return find_first_of( s, pos, traits_type::length( s ) );
0797     }
0798 
0799     // find_last_of
0800 
0801     BOOST_CXX14_CONSTEXPR size_type find_last_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT
0802     {
0803         return find_last_of( str.data(), pos, str.size() );
0804     }
0805 
0806     BOOST_CONSTEXPR size_type find_last_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT
0807     {
0808         return rfind( c, pos );
0809     }
0810 
0811     BOOST_CXX14_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
0812     {
0813         if( n == 1 )
0814         {
0815             return rfind( s[0], pos );
0816         }
0817 
0818         size_type m = size();
0819 
0820         if( m == 0 )
0821         {
0822             return npos;
0823         }
0824 
0825         if( pos > m - 1 )
0826         {
0827             pos = m - 1;
0828         }
0829 
0830         return detail::find_last_of( data(), s, pos, n );
0831     }
0832 
0833     BOOST_CXX14_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT
0834     {
0835         return find_last_of( s, pos, traits_type::length( s ) );
0836     }
0837 
0838     // find_first_not_of
0839 
0840     BOOST_CXX14_CONSTEXPR size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT
0841     {
0842         return find_first_not_of( str.data(), pos, str.size() );
0843     }
0844 
0845     BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT
0846     {
0847         for( std::size_t i = pos; i < n_; ++i )
0848         {
0849             if( p_[ i ] != c ) return i;
0850         }
0851 
0852         return npos;
0853     }
0854 
0855     BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
0856     {
0857         if( pos >= size() ) return npos;
0858         if( n == 1 ) return find_first_not_of( s[0], pos );
0859 
0860         return detail::find_first_not_of( data(), size(), s, pos, n );
0861     }
0862 
0863     BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT
0864     {
0865         return find_first_not_of( s, pos, traits_type::length( s ) );
0866     }
0867 
0868     // find_last_not_of
0869 
0870     BOOST_CXX14_CONSTEXPR size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT
0871     {
0872         return find_last_not_of( str.data(), pos, str.size() );
0873     }
0874 
0875     BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT
0876     {
0877         size_type m = size();
0878 
0879         if( m == 0 )
0880         {
0881             return npos;
0882         }
0883 
0884         if( pos > m - 1 )
0885         {
0886             pos = m - 1;
0887         }
0888 
0889         do
0890         {
0891             if( p_[ pos ] != c ) return pos;
0892             --pos;
0893         }
0894         while( pos != npos );
0895 
0896         return npos;
0897     }
0898 
0899     BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
0900     {
0901         if( n == 1 )
0902         {
0903             return find_last_not_of( s[0], pos );
0904         }
0905 
0906         size_type m = size();
0907 
0908         if( m == 0 )
0909         {
0910             return npos;
0911         }
0912 
0913         if( pos > m - 1 )
0914         {
0915             pos = m - 1;
0916         }
0917 
0918         return detail::find_last_not_of( data(), s, pos, n );
0919     }
0920 
0921     BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT
0922     {
0923         return find_last_not_of( s, pos, traits_type::length( s ) );
0924     }
0925 
0926     // contains
0927 
0928     BOOST_CONSTEXPR bool contains( basic_string_view sv ) const BOOST_NOEXCEPT
0929     {
0930         return find( sv ) != npos;
0931     }
0932 
0933     BOOST_CXX14_CONSTEXPR bool contains( Ch c ) const BOOST_NOEXCEPT
0934     {
0935         Ch const* p = data();
0936         size_type n = size();
0937 
0938         if( n >= 16 )
0939         {
0940             return traits_type::find( p, n, c ) != 0;
0941         }
0942         else
0943         {
0944             for( size_type i = 0; i < n; ++i )
0945             {
0946                 if( p[ i ] == c ) return true;
0947             }
0948 
0949             return false;
0950         }
0951     }
0952 
0953     BOOST_CONSTEXPR bool contains( Ch const* s ) const BOOST_NOEXCEPT
0954     {
0955         return find( s ) != npos;
0956     }
0957 
0958     // relational operators
0959 
0960     BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
0961     {
0962         return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
0963     }
0964 
0965     BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
0966     {
0967         return !( sv1 == sv2 );
0968     }
0969 
0970     BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
0971     {
0972         return sv1.compare( sv2 ) < 0;
0973     }
0974 
0975     BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
0976     {
0977         return sv1.compare( sv2 ) <= 0;
0978     }
0979 
0980     BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
0981     {
0982         return sv1.compare( sv2 ) > 0;
0983     }
0984 
0985     BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
0986     {
0987         return sv1.compare( sv2 ) >= 0;
0988     }
0989 
0990 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
0991 
0992     // "sufficient number of additional overloads"
0993 
0994     // against std::string_view
0995 
0996     BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
0997     {
0998         return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
0999     }
1000 
1001     BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string_view<Ch> sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1002     {
1003         return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
1004     }
1005 
1006     BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
1007     {
1008         return !( sv1 == sv2 );
1009     }
1010 
1011     BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string_view<Ch> sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1012     {
1013         return !( sv1 == sv2 );
1014     }
1015 
1016     BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
1017     {
1018         return sv1.compare( sv2 ) < 0;
1019     }
1020 
1021     BOOST_CXX14_CONSTEXPR friend bool operator<( std::basic_string_view<Ch> sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1022     {
1023         return sv1.compare( sv2 ) < 0;
1024     }
1025 
1026     BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
1027     {
1028         return sv1.compare( sv2 ) <= 0;
1029     }
1030 
1031     BOOST_CXX14_CONSTEXPR friend bool operator<=( std::basic_string_view<Ch> sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1032     {
1033         return sv1.compare( sv2 ) <= 0;
1034     }
1035 
1036     BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
1037     {
1038         return sv1.compare( sv2 ) > 0;
1039     }
1040 
1041     BOOST_CXX14_CONSTEXPR friend bool operator>( std::basic_string_view<Ch> sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1042     {
1043         return sv1.compare( sv2 ) > 0;
1044     }
1045 
1046     BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
1047     {
1048         return sv1.compare( sv2 ) >= 0;
1049     }
1050 
1051     BOOST_CXX14_CONSTEXPR friend bool operator>=( std::basic_string_view<Ch> sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1052     {
1053         return sv1.compare( sv2 ) >= 0;
1054     }
1055 
1056     // against Ch const*
1057 
1058     BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1059     {
1060         return sv1 == basic_string_view( sv2 );
1061     }
1062 
1063     BOOST_CXX14_CONSTEXPR friend bool operator==( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1064     {
1065         return basic_string_view( sv1 ) == sv2;
1066     }
1067 
1068     BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1069     {
1070         return !( sv1 == sv2 );
1071     }
1072 
1073     BOOST_CXX14_CONSTEXPR friend bool operator!=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1074     {
1075         return !( sv1 == sv2 );
1076     }
1077 
1078     BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1079     {
1080         return sv1.compare( sv2 ) < 0;
1081     }
1082 
1083     BOOST_CXX14_CONSTEXPR friend bool operator<( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1084     {
1085         return sv2.compare( sv1 ) > 0;
1086     }
1087 
1088     BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1089     {
1090         return sv1.compare( sv2 ) <= 0;
1091     }
1092 
1093     BOOST_CXX14_CONSTEXPR friend bool operator<=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1094     {
1095         return sv2.compare( sv1 ) >= 0;
1096     }
1097 
1098     BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1099     {
1100         return sv1.compare( sv2 ) > 0;
1101     }
1102 
1103     BOOST_CXX14_CONSTEXPR friend bool operator>( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1104     {
1105         return sv2.compare( sv1 ) < 0;
1106     }
1107 
1108     BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1109     {
1110         return sv1.compare( sv2 ) >= 0;
1111     }
1112 
1113     BOOST_CXX14_CONSTEXPR friend bool operator>=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1114     {
1115         return sv2.compare( sv1 ) <= 0;
1116     }
1117 
1118     // against std::string
1119 
1120     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string<Ch, std::char_traits<Ch>, A> const& sv2 ) BOOST_NOEXCEPT
1121     {
1122         return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
1123     }
1124 
1125     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string<Ch, std::char_traits<Ch>, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1126     {
1127         return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
1128     }
1129 
1130     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string<Ch, std::char_traits<Ch>, A> const& sv2 ) BOOST_NOEXCEPT
1131     {
1132         return !( sv1 == sv2 );
1133     }
1134 
1135     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string<Ch, std::char_traits<Ch>, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1136     {
1137         return !( sv1 == sv2 );
1138     }
1139 
1140     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string<Ch, std::char_traits<Ch>, A> const& sv2 ) BOOST_NOEXCEPT
1141     {
1142         return sv1.compare( sv2 ) < 0;
1143     }
1144 
1145     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator<( std::basic_string<Ch, std::char_traits<Ch>, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1146     {
1147         return sv2.compare( sv1 ) > 0;
1148     }
1149 
1150     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, std::basic_string<Ch, std::char_traits<Ch>, A> const& sv2 ) BOOST_NOEXCEPT
1151     {
1152         return sv1.compare( sv2 ) <= 0;
1153     }
1154 
1155     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator<=( std::basic_string<Ch, std::char_traits<Ch>, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1156     {
1157         return sv2.compare( sv1 ) >= 0;
1158     }
1159 
1160     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, std::basic_string<Ch, std::char_traits<Ch>, A> const& sv2 ) BOOST_NOEXCEPT
1161     {
1162         return sv1.compare( sv2 ) > 0;
1163     }
1164 
1165     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator>( std::basic_string<Ch, std::char_traits<Ch>, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1166     {
1167         return sv2.compare( sv1 ) < 0;
1168     }
1169 
1170     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, std::basic_string<Ch, std::char_traits<Ch>, A> const& sv2 ) BOOST_NOEXCEPT
1171     {
1172         return sv1.compare( sv2 ) >= 0;
1173     }
1174 
1175     template<class A> BOOST_CXX14_CONSTEXPR friend bool operator>=( std::basic_string<Ch, std::char_traits<Ch>, A> const& sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1176     {
1177         return sv2.compare( sv1 ) <= 0;
1178     }
1179 
1180 #endif
1181 };
1182 
1183 // stream inserter
1184 
1185 template<class Ch> std::basic_ostream<Ch>& operator<<( std::basic_ostream<Ch>& os, basic_string_view<Ch> str )
1186 {
1187     Ch const* p = str.data();
1188     std::streamsize n = static_cast<std::streamsize>( str.size() );
1189 
1190     std::streamsize m = os.width();
1191 
1192     if( n >= m )
1193     {
1194         os.write( p, n );
1195     }
1196     else if( ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::left )
1197     {
1198         os.write( p, n );
1199 
1200         os.width( m - n );
1201         os << "";
1202     }
1203     else
1204     {
1205         os.width( m - n );
1206         os << "";
1207 
1208         os.write( p, n );
1209     }
1210 
1211     os.width( 0 );
1212     return os;
1213 }
1214 
1215 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
1216 template<class Ch> BOOST_CONSTEXPR_OR_CONST std::size_t basic_string_view<Ch>::npos;
1217 #endif
1218 
1219 // typedef names
1220 
1221 typedef basic_string_view<char> string_view;
1222 typedef basic_string_view<wchar_t> wstring_view;
1223 
1224 #if !defined(BOOST_NO_CXX11_CHAR16_T)
1225 typedef basic_string_view<char16_t> u16string_view;
1226 #endif
1227 
1228 #if !defined(BOOST_NO_CXX11_CHAR32_T)
1229 typedef basic_string_view<char32_t> u32string_view;
1230 #endif
1231 
1232 #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
1233 typedef basic_string_view<char8_t> u8string_view;
1234 #endif
1235 
1236 } // namespace core
1237 } // namespace boost
1238 
1239 // std::common_reference support
1240 // needed for iterators that have reference=string_view and value_type=std::string
1241 
1242 #if !defined(BOOST_NO_CXX20_HDR_CONCEPTS)
1243 
1244 template<class Ch, class A, template<class> class Q1, template<class> class Q2>
1245 struct std::basic_common_reference<
1246     boost::core::basic_string_view<Ch>,
1247     std::basic_string<Ch, std::char_traits<Ch>, A>,
1248     Q1, Q2>
1249 {
1250     using type = boost::core::basic_string_view<Ch>;
1251 };
1252 
1253 template<class Ch, class A, template<class> class Q1, template<class> class Q2>
1254 struct std::basic_common_reference<
1255     std::basic_string<Ch, std::char_traits<Ch>, A>,
1256     boost::core::basic_string_view<Ch>,
1257     Q1, Q2>
1258 {
1259     using type = boost::core::basic_string_view<Ch>;
1260 };
1261 
1262 #endif
1263 
1264 #endif  // #ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED