Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:28

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