]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/core/detail/string_view.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / core / detail / string_view.hpp
1 #ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED
2 #define BOOST_CORE_STRING_VIEW_HPP_INCLUDED
3
4 // MS compatible compilers support #pragma once
5
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 # pragma once
8 #endif
9
10 // boost::core::basic_string_view<Ch>
11 //
12 // Copyright 2021 Peter Dimov
13 // Distributed under the Boost Software License, Version 1.0.
14 // https://www.boost.org/LICENSE_1_0.txt
15
16 #include <boost/core/enable_if.hpp>
17 #include <boost/core/is_same.hpp>
18 #include <boost/assert.hpp>
19 #include <boost/assert/source_location.hpp>
20 #include <boost/throw_exception.hpp>
21 #include <boost/config.hpp>
22 #include <string>
23 #include <algorithm>
24 #include <utility>
25 #include <stdexcept>
26 #include <cstddef>
27 #include <cstring>
28 #include <climits>
29 #include <iosfwd>
30 #include <ios>
31 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
32 # include <string_view>
33 #endif
34 #if !defined(BOOST_NO_CXX20_HDR_CONCEPTS) // std::common_reference_with
35 # include <type_traits>
36 #endif
37
38 namespace boost
39 {
40
41 template<class Ch, class Tr> class basic_string_view;
42
43 namespace core
44 {
45 namespace detail
46 {
47
48 template<class Ch> struct sv_to_uchar
49 {
50 typedef Ch type;
51 };
52
53 template<> struct sv_to_uchar<char>
54 {
55 typedef unsigned char type;
56 };
57
58 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406
59 # pragma GCC diagnostic push
60 # pragma GCC diagnostic ignored "-Wtype-limits"
61 #endif
62
63 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
64 {
65 typedef typename sv_to_uchar<Ch>::type UCh;
66
67 unsigned char table[ 256 ] = {};
68
69 bool use_table = true;
70
71 for( std::size_t j = 0; j < n; ++j )
72 {
73 UCh ch = s[ j ];
74
75 if( ch >= 0 && ch < 256 )
76 {
77 table[ ch ] = 1;
78 }
79 else
80 {
81 use_table = false;
82 break;
83 }
84 }
85
86 if( use_table )
87 {
88 for( std::size_t i = pos; i < n_; ++i )
89 {
90 UCh ch = p_[ i ];
91 if( ch >= 0 && ch < 256 && table[ ch ] ) return i;
92 }
93 }
94 else if( n >= 16 )
95 {
96 for( std::size_t i = pos; i < n_; ++i )
97 {
98 Ch ch = p_[ i ];
99 if( std::char_traits<Ch>::find( s, n, ch ) != 0 ) return i;
100 }
101 }
102 else
103 {
104 for( std::size_t i = pos; i < n_; ++i )
105 {
106 Ch ch = p_[ i ];
107
108 for( std::size_t j = 0; j < n; ++j )
109 {
110 if( s[ j ] == ch ) return i;
111 }
112 }
113 }
114
115 return static_cast<std::size_t>( -1 );
116 }
117
118 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
119 {
120 typedef typename sv_to_uchar<Ch>::type UCh;
121
122 unsigned char table[ 256 ] = {};
123
124 bool use_table = true;
125
126 for( std::size_t j = 0; j < n; ++j )
127 {
128 UCh ch = s[ j ];
129
130 if( ch >= 0 && ch < 256 )
131 {
132 table[ ch ] = 1;
133 }
134 else
135 {
136 use_table = false;
137 break;
138 }
139 }
140
141 std::size_t const npos = static_cast< std::size_t >( -1 );
142
143 std::size_t i = pos;
144
145 if( use_table )
146 {
147 do
148 {
149 UCh ch = p_[ i ];
150
151 if( ch >= 0 && ch < 256 && table[ ch ] ) return i;
152
153 --i;
154 }
155 while( i != npos );
156 }
157 else if( n >= 16 )
158 {
159 do
160 {
161 Ch ch = p_[ i ];
162
163 if( std::char_traits<Ch>::find( s, n, ch ) != 0 ) return i;
164
165 --i;
166 }
167 while( i != npos );
168 }
169 else
170 {
171 do
172 {
173 Ch ch = p_[ i ];
174
175 for( std::size_t j = 0; j < n; ++j )
176 {
177 if( s[ j ] == ch ) return i;
178 }
179
180 --i;
181 }
182 while( i != npos );
183 }
184
185 return npos;
186 }
187
188 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
189 {
190 typedef typename sv_to_uchar<Ch>::type UCh;
191
192 unsigned char table[ 256 ] = {};
193
194 bool use_table = true;
195
196 for( std::size_t j = 0; j < n; ++j )
197 {
198 UCh ch = s[ j ];
199
200 if( ch >= 0 && ch < 256 )
201 {
202 table[ ch ] = 1;
203 }
204 else
205 {
206 use_table = false;
207 break;
208 }
209 }
210
211 if( use_table )
212 {
213 for( std::size_t i = pos; i < n_; ++i )
214 {
215 UCh ch = p_[ i ];
216 if( !( ch >= 0 && ch < 256 && table[ ch ] ) ) return i;
217 }
218 }
219 else if( n >= 16 )
220 {
221 for( std::size_t i = pos; i < n_; ++i )
222 {
223 Ch ch = p_[ i ];
224 if( std::char_traits<Ch>::find( s, n, ch ) == 0 ) return i;
225 }
226 }
227 else
228 {
229 for( std::size_t i = pos; i < n_; ++i )
230 {
231 Ch ch = p_[ i ];
232
233 bool r = false;
234
235 for( std::size_t j = 0; j < n; ++j )
236 {
237 if( s[ j ] == ch )
238 {
239 r = true;
240 break;
241 }
242 }
243
244 if( !r ) return i;
245 }
246 }
247
248 return static_cast<std::size_t>( -1 );
249 }
250
251 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
252 {
253 typedef typename sv_to_uchar<Ch>::type UCh;
254
255 unsigned char table[ 256 ] = {};
256
257 bool use_table = true;
258
259 for( std::size_t j = 0; j < n; ++j )
260 {
261 UCh ch = s[ j ];
262
263 if( ch >= 0 && ch < 256 )
264 {
265 table[ ch ] = 1;
266 }
267 else
268 {
269 use_table = false;
270 break;
271 }
272 }
273
274 std::size_t const npos = static_cast< std::size_t >( -1 );
275
276 std::size_t i = pos;
277
278 if( use_table )
279 {
280 do
281 {
282 UCh ch = p_[ i ];
283
284 if( !( ch >= 0 && ch < 256 && table[ ch ] ) ) return i;
285
286 --i;
287 }
288 while( i != npos );
289 }
290 else if( n >= 16 )
291 {
292 do
293 {
294 Ch ch = p_[ i ];
295
296 if( std::char_traits<Ch>::find( s, n, ch ) == 0 ) return i;
297
298 --i;
299 }
300 while( i != npos );
301 }
302 else
303 {
304 do
305 {
306 Ch ch = p_[ i ];
307
308 bool r = false;
309
310 for( std::size_t j = 0; j < n; ++j )
311 {
312 if( s[ j ] == ch )
313 {
314 r = true;
315 break;
316 }
317 }
318
319 if( !r ) return i;
320
321 --i;
322 }
323 while( i != npos );
324 }
325
326 return npos;
327 }
328
329 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406
330 # pragma GCC diagnostic pop
331 #endif
332
333 } // namespace detail
334
335 template<class Ch> class basic_string_view
336 {
337 private:
338
339 Ch const* p_;
340 std::size_t n_;
341
342 public:
343
344 // types
345
346 typedef std::char_traits<Ch> traits_type;
347 typedef Ch value_type;
348 typedef Ch* pointer;
349 typedef Ch const* const_pointer;
350 typedef Ch& reference;
351 typedef Ch const& const_reference;
352 typedef Ch const* const_iterator;
353 typedef const_iterator iterator;
354 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
355 typedef const_reverse_iterator reverse_iterator;
356 typedef std::size_t size_type;
357 typedef std::ptrdiff_t difference_type;
358
359 // npos
360
361 BOOST_STATIC_CONSTEXPR size_type npos = static_cast<size_type>( -1 );
362
363 public:
364
365 // construction and assignment
366
367 BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT: p_(), n_()
368 {
369 }
370
371 BOOST_CONSTEXPR basic_string_view( Ch const* str ) BOOST_NOEXCEPT: p_( str ), n_( traits_type::length( str ) )
372 {
373 }
374
375 BOOST_CONSTEXPR basic_string_view( Ch const* str, size_type len ) BOOST_NOEXCEPT: p_( str ), n_( len )
376 {
377 }
378
379 template<class End> BOOST_CXX14_CONSTEXPR basic_string_view( Ch const* begin, End end,
380 typename boost::enable_if<is_same<End, Ch const*> >::type* = 0 ) BOOST_NOEXCEPT: p_( begin ), n_( end - begin )
381 {
382 BOOST_ASSERT( end - begin >= 0 );
383 }
384
385 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() )
386 {
387 }
388
389 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
390
391 basic_string_view( std::basic_string_view<Ch, std::char_traits<Ch> > const& str ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() )
392 {
393 }
394
395 #endif
396
397 template<class Ch2> basic_string_view( boost::basic_string_view<Ch2, std::char_traits<Ch2> > const& str,
398 typename boost::enable_if<is_same<Ch, Ch2> >::type* = 0 ) BOOST_NOEXCEPT: p_( str.data() ), n_( str.size() )
399 {
400 }
401
402 // BOOST_CONSTEXPR basic_string_view& operator=( basic_string_view const& ) BOOST_NOEXCEPT & = default;
403
404 // conversions
405
406 template<class A> operator std::basic_string<Ch, std::char_traits<Ch>, A>() const
407 {
408 return std::basic_string<Ch, std::char_traits<Ch>, A>( data(), size() );
409 }
410
411 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
412
413 template<class Ch2, class En = typename boost::enable_if<is_same<Ch2, Ch> >::type>
414 operator std::basic_string_view<Ch2>() const BOOST_NOEXCEPT
415 {
416 return std::basic_string_view<Ch>( data(), size() );
417 }
418
419 #endif
420
421 template<class Ch2> operator boost::basic_string_view<Ch2,
422 typename boost::enable_if<boost::core::is_same<Ch2, Ch>, std::char_traits<Ch> >::type> () const BOOST_NOEXCEPT
423 {
424 return boost::basic_string_view< Ch, std::char_traits<Ch> >( data(), size() );
425 }
426
427 // iterator support
428
429 BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT
430 {
431 return p_;
432 }
433
434 BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT
435 {
436 return p_ + n_;
437 }
438
439 BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT
440 {
441 return p_;
442 }
443
444 BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT
445 {
446 return p_ + n_;
447 }
448
449 BOOST_CONSTEXPR const_reverse_iterator rbegin() const BOOST_NOEXCEPT
450 {
451 return const_reverse_iterator( end() );
452 }
453
454 BOOST_CONSTEXPR const_reverse_iterator rend() const BOOST_NOEXCEPT
455 {
456 return const_reverse_iterator( begin() );
457 }
458
459 BOOST_CONSTEXPR const_reverse_iterator crbegin() const BOOST_NOEXCEPT
460 {
461 return const_reverse_iterator( end() );
462 }
463
464 BOOST_CONSTEXPR const_reverse_iterator crend() const BOOST_NOEXCEPT
465 {
466 return const_reverse_iterator( begin() );
467 }
468
469 // capacity
470
471 BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT
472 {
473 return n_;
474 }
475
476 BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT
477 {
478 return n_;
479 }
480
481 BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT
482 {
483 return npos / sizeof( Ch );
484 }
485
486 BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT
487 {
488 return n_ == 0;
489 }
490
491 // element access
492
493 BOOST_CXX14_CONSTEXPR const_reference operator[]( size_type pos ) const BOOST_NOEXCEPT
494 {
495 BOOST_ASSERT( pos < size() );
496 return p_[ pos ];
497 }
498
499 BOOST_CXX14_CONSTEXPR const_reference at( size_type pos ) const
500 {
501 if( pos >= size() )
502 {
503 boost::throw_exception( std::out_of_range( "basic_string_view::at" ), BOOST_CURRENT_LOCATION );
504 }
505
506 return p_[ pos ];
507 }
508
509 BOOST_CXX14_CONSTEXPR const_reference front() const BOOST_NOEXCEPT
510 {
511 BOOST_ASSERT( !empty() );
512 return p_[ 0 ];
513 }
514
515 BOOST_CXX14_CONSTEXPR const_reference back() const BOOST_NOEXCEPT
516 {
517 BOOST_ASSERT( !empty() );
518 return p_[ n_ - 1 ];
519 }
520
521 BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT
522 {
523 return p_;
524 }
525
526 // modifiers
527
528 BOOST_CXX14_CONSTEXPR void remove_prefix( size_type n ) BOOST_NOEXCEPT
529 {
530 BOOST_ASSERT( n <= size() );
531
532 p_ += n;
533 n_ -= n;
534 }
535
536 BOOST_CXX14_CONSTEXPR void remove_suffix( size_type n ) BOOST_NOEXCEPT
537 {
538 BOOST_ASSERT( n <= size() );
539
540 n_ -= n;
541 }
542
543 BOOST_CXX14_CONSTEXPR void swap( basic_string_view& s ) BOOST_NOEXCEPT
544 {
545 std::swap( p_, s.p_ );
546 std::swap( n_, s.n_ );
547 }
548
549 // string operations
550
551 BOOST_CXX14_CONSTEXPR size_type copy( Ch* s, size_type n, size_type pos = 0 ) const
552 {
553 if( pos > size() )
554 {
555 boost::throw_exception( std::out_of_range( "basic_string_view::copy" ), BOOST_CURRENT_LOCATION );
556 }
557
558 std::size_t rlen = (std::min)( n, size() - pos );
559
560 traits_type::copy( s, data() + pos, rlen );
561
562 return rlen;
563 }
564
565 BOOST_CXX14_CONSTEXPR basic_string_view substr( size_type pos = 0, size_type n = npos ) const
566 {
567 if( pos > size() )
568 {
569 boost::throw_exception( std::out_of_range( "basic_string_view::substr" ), BOOST_CURRENT_LOCATION );
570 }
571
572 std::size_t rlen = (std::min)( n, size() - pos );
573
574 return basic_string_view( data() + pos, rlen );
575 }
576
577 // compare
578
579 BOOST_CXX14_CONSTEXPR int compare( basic_string_view str ) const BOOST_NOEXCEPT
580 {
581 std::size_t rlen = (std::min)( size(), str.size() );
582
583 int cmp = traits_type::compare( data(), str.data(), rlen );
584
585 if( cmp != 0 ) return cmp;
586
587 if( size() == str.size() ) return 0;
588
589 return size() < str.size()? -1: +1;
590 }
591
592 BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str ) const
593 {
594 return substr( pos1, n1 ).compare( str );
595 }
596
597 BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2 ) const
598 {
599 return substr( pos1, n1 ).compare( str.substr( pos2, n2 ) );
600 }
601
602 BOOST_CONSTEXPR int compare( Ch const* s ) const BOOST_NOEXCEPT
603 {
604 return compare( basic_string_view( s ) );
605 }
606
607 BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s ) const
608 {
609 return substr( pos1, n1 ).compare( basic_string_view( s ) );
610 }
611
612 BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, Ch const* s, size_type n2 ) const
613 {
614 return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) );
615 }
616
617 // starts_with
618
619 BOOST_CONSTEXPR bool starts_with( basic_string_view x ) const BOOST_NOEXCEPT
620 {
621 return size() >= x.size() && traits_type::compare( data(), x.data(), x.size() ) == 0;
622 }
623
624 BOOST_CONSTEXPR bool starts_with( Ch x ) const BOOST_NOEXCEPT
625 {
626 return !empty() && front() == x;
627 }
628
629 BOOST_CONSTEXPR bool starts_with( Ch const* x ) const BOOST_NOEXCEPT
630 {
631 return starts_with( basic_string_view( x ) );
632 }
633
634 // ends_with
635
636 BOOST_CONSTEXPR bool ends_with( basic_string_view x ) const BOOST_NOEXCEPT
637 {
638 return size() >= x.size() && traits_type::compare( data() + size() - x.size(), x.data(), x.size() ) == 0;
639 }
640
641 BOOST_CONSTEXPR bool ends_with( Ch x ) const BOOST_NOEXCEPT
642 {
643 return !empty() && back() == x;
644 }
645
646 BOOST_CONSTEXPR bool ends_with( Ch const* x ) const BOOST_NOEXCEPT
647 {
648 return ends_with( basic_string_view( x ) );
649 }
650
651 // find
652
653 BOOST_CONSTEXPR size_type find( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT
654 {
655 return find( str.data(), pos, str.size() );
656 }
657
658 BOOST_CXX14_CONSTEXPR size_type find( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT
659 {
660 if( pos >= size() ) return npos;
661
662 Ch const* r = traits_type::find( data() + pos, size() - pos, c );
663
664 return r? r - data(): npos;
665 }
666
667 BOOST_CXX14_CONSTEXPR size_type find( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
668 {
669 if( n == 1 ) return find( s[0], pos );
670
671 if( pos + n > size() ) return npos;
672 if( n == 0 ) return pos;
673
674 Ch const* p = data() + pos;
675 Ch const* last = data() + size() - n + 1;
676
677 for( ;; )
678 {
679 p = traits_type::find( p, last - p, s[0] );
680
681 if( p == 0 ) break;
682
683 if( traits_type::compare( p + 1, s + 1, n - 1 ) == 0 ) return p - data();
684
685 ++p;
686 }
687
688 return npos;
689 }
690
691 BOOST_CONSTEXPR size_type find( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT
692 {
693 return find( s, pos, traits_type::length( s ) );
694 }
695
696 // rfind
697
698 BOOST_CONSTEXPR size_type rfind( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT
699 {
700 return rfind( str.data(), pos, str.size() );
701 }
702
703 BOOST_CXX14_CONSTEXPR size_type rfind( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT
704 {
705 size_type n = size();
706
707 if( n == 0 )
708 {
709 return npos;
710 }
711
712 if( pos > n - 1 )
713 {
714 pos = n - 1;
715 }
716
717 do
718 {
719 if( p_[ pos ] == c ) return pos;
720 --pos;
721 }
722 while( pos != npos );
723
724 return npos;
725 }
726
727 BOOST_CXX14_CONSTEXPR size_type rfind( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
728 {
729 if( n > size() ) return npos;
730
731 if( pos > size() - n )
732 {
733 pos = size() - n;
734 }
735
736 if( n == 0 ) return pos;
737
738 for( ;; )
739 {
740 size_type xpos = rfind( s[0], pos );
741
742 if( xpos == npos ) return npos;
743
744 if( traits_type::compare( data() + xpos, s, n ) == 0 ) return xpos;
745
746 if( xpos == 0 ) return npos;
747
748 pos = xpos - 1;
749 }
750 }
751
752 BOOST_CONSTEXPR size_type rfind( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT
753 {
754 return rfind( s, pos, traits_type::length( s ) );
755 }
756
757 // find_first_of
758
759 BOOST_CXX14_CONSTEXPR size_type find_first_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT
760 {
761 return find_first_of( str.data(), pos, str.size() );
762 }
763
764 BOOST_CONSTEXPR size_type find_first_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT
765 {
766 return find( c, pos );
767 }
768
769 BOOST_CXX14_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
770 {
771 if( n == 0 || pos >= size() ) return npos;
772 if( n == 1 ) return find( s[0], pos );
773
774 return detail::find_first_of( data(), size(), s, pos, n );
775 }
776
777 BOOST_CXX14_CONSTEXPR size_type find_first_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT
778 {
779 return find_first_of( s, pos, traits_type::length( s ) );
780 }
781
782 // find_last_of
783
784 BOOST_CXX14_CONSTEXPR size_type find_last_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT
785 {
786 return find_last_of( str.data(), pos, str.size() );
787 }
788
789 BOOST_CONSTEXPR size_type find_last_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT
790 {
791 return rfind( c, pos );
792 }
793
794 BOOST_CXX14_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
795 {
796 if( n == 1 )
797 {
798 return rfind( s[0], pos );
799 }
800
801 size_type m = size();
802
803 if( m == 0 )
804 {
805 return npos;
806 }
807
808 if( pos > m - 1 )
809 {
810 pos = m - 1;
811 }
812
813 return detail::find_last_of( data(), s, pos, n );
814 }
815
816 BOOST_CXX14_CONSTEXPR size_type find_last_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT
817 {
818 return find_last_of( s, pos, traits_type::length( s ) );
819 }
820
821 // find_first_not_of
822
823 BOOST_CXX14_CONSTEXPR size_type find_first_not_of( basic_string_view str, size_type pos = 0 ) const BOOST_NOEXCEPT
824 {
825 return find_first_not_of( str.data(), pos, str.size() );
826 }
827
828 BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch c, size_type pos = 0 ) const BOOST_NOEXCEPT
829 {
830 for( std::size_t i = pos; i < n_; ++i )
831 {
832 if( p_[ i ] != c ) return i;
833 }
834
835 return npos;
836 }
837
838 BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
839 {
840 if( pos >= size() ) return npos;
841 if( n == 1 ) return find_first_not_of( s[0], pos );
842
843 return detail::find_first_not_of( data(), size(), s, pos, n );
844 }
845
846 BOOST_CXX14_CONSTEXPR size_type find_first_not_of( Ch const* s, size_type pos = 0 ) const BOOST_NOEXCEPT
847 {
848 return find_first_not_of( s, pos, traits_type::length( s ) );
849 }
850
851 // find_last_not_of
852
853 BOOST_CXX14_CONSTEXPR size_type find_last_not_of( basic_string_view str, size_type pos = npos ) const BOOST_NOEXCEPT
854 {
855 return find_last_not_of( str.data(), pos, str.size() );
856 }
857
858 BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch c, size_type pos = npos ) const BOOST_NOEXCEPT
859 {
860 size_type m = size();
861
862 if( m == 0 )
863 {
864 return npos;
865 }
866
867 if( pos > m - 1 )
868 {
869 pos = m - 1;
870 }
871
872 do
873 {
874 if( p_[ pos ] != c ) return pos;
875 --pos;
876 }
877 while( pos != npos );
878
879 return npos;
880 }
881
882 BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos, size_type n ) const BOOST_NOEXCEPT
883 {
884 if( n == 1 )
885 {
886 return find_last_not_of( s[0], pos );
887 }
888
889 size_type m = size();
890
891 if( m == 0 )
892 {
893 return npos;
894 }
895
896 if( pos > m - 1 )
897 {
898 pos = m - 1;
899 }
900
901 return detail::find_last_not_of( data(), s, pos, n );
902 }
903
904 BOOST_CXX14_CONSTEXPR size_type find_last_not_of( Ch const* s, size_type pos = npos ) const BOOST_NOEXCEPT
905 {
906 return find_last_not_of( s, pos, traits_type::length( s ) );
907 }
908
909 // contains
910
911 BOOST_CONSTEXPR bool contains( basic_string_view sv ) const BOOST_NOEXCEPT
912 {
913 return find( sv ) != npos;
914 }
915
916 BOOST_CXX14_CONSTEXPR bool contains( Ch c ) const BOOST_NOEXCEPT
917 {
918 Ch const* p = data();
919 size_type n = size();
920
921 if( n >= 16 )
922 {
923 return traits_type::find( p, n, c ) != 0;
924 }
925 else
926 {
927 for( size_type i = 0; i < n; ++i )
928 {
929 if( p[ i ] == c ) return true;
930 }
931
932 return false;
933 }
934 }
935
936 BOOST_CONSTEXPR bool contains( Ch const* s ) const BOOST_NOEXCEPT
937 {
938 return find( s ) != npos;
939 }
940
941 // relational operators
942
943 BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
944 {
945 return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
946 }
947
948 BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
949 {
950 return !( sv1 == sv2 );
951 }
952
953 BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
954 {
955 return sv1.compare( sv2 ) < 0;
956 }
957
958 BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
959 {
960 return sv1.compare( sv2 ) <= 0;
961 }
962
963 BOOST_CXX14_CONSTEXPR friend bool operator>( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
964 {
965 return sv1.compare( sv2 ) > 0;
966 }
967
968 BOOST_CXX14_CONSTEXPR friend bool operator>=( basic_string_view sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
969 {
970 return sv1.compare( sv2 ) >= 0;
971 }
972
973 #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
974
975 // "sufficient number of additional overloads"
976
977 // against std::string_view
978
979 BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
980 {
981 return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
982 }
983
984 BOOST_CXX14_CONSTEXPR friend bool operator==( std::basic_string_view<Ch> sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
985 {
986 return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
987 }
988
989 BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
990 {
991 return !( sv1 == sv2 );
992 }
993
994 BOOST_CXX14_CONSTEXPR friend bool operator!=( std::basic_string_view<Ch> sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
995 {
996 return !( sv1 == sv2 );
997 }
998
999 BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, std::basic_string_view<Ch> sv2 ) BOOST_NOEXCEPT
1000 {
1001 return sv1.compare( sv2 ) < 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.compare( sv2 ) < 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.compare( sv2 ) <= 0;
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.compare( sv2 ) <= 0;
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 // against Ch const*
1040
1041 BOOST_CXX14_CONSTEXPR friend bool operator==( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1042 {
1043 return sv1 == basic_string_view( sv2 );
1044 }
1045
1046 BOOST_CXX14_CONSTEXPR friend bool operator==( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1047 {
1048 return basic_string_view( sv1 ) == sv2;
1049 }
1050
1051 BOOST_CXX14_CONSTEXPR friend bool operator!=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1052 {
1053 return !( sv1 == sv2 );
1054 }
1055
1056 BOOST_CXX14_CONSTEXPR friend bool operator!=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1057 {
1058 return !( sv1 == sv2 );
1059 }
1060
1061 BOOST_CXX14_CONSTEXPR friend bool operator<( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1062 {
1063 return sv1.compare( sv2 ) < 0;
1064 }
1065
1066 BOOST_CXX14_CONSTEXPR friend bool operator<( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1067 {
1068 return sv2.compare( sv1 ) > 0;
1069 }
1070
1071 BOOST_CXX14_CONSTEXPR friend bool operator<=( basic_string_view sv1, Ch const* sv2 ) BOOST_NOEXCEPT
1072 {
1073 return sv1.compare( sv2 ) <= 0;
1074 }
1075
1076 BOOST_CXX14_CONSTEXPR friend bool operator<=( Ch const* sv1, basic_string_view sv2 ) BOOST_NOEXCEPT
1077 {
1078 return sv2.compare( sv1 ) >= 0;
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 // against std::string
1102
1103 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
1104 {
1105 return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
1106 }
1107
1108 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
1109 {
1110 return sv1.size() == sv2.size() && traits_type::compare( sv1.data(), sv2.data(), sv1.size() ) == 0;
1111 }
1112
1113 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
1114 {
1115 return !( sv1 == sv2 );
1116 }
1117
1118 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
1119 {
1120 return !( sv1 == sv2 );
1121 }
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.compare( sv2 ) < 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 sv2.compare( sv1 ) > 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.compare( sv2 ) <= 0;
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 sv2.compare( sv1 ) >= 0;
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 #endif
1164 };
1165
1166 // stream inserter
1167
1168 template<class Ch> std::basic_ostream<Ch>& operator<<( std::basic_ostream<Ch>& os, basic_string_view<Ch> str )
1169 {
1170 Ch const* p = str.data();
1171 std::streamsize n = str.size();
1172
1173 std::streamsize m = os.width();
1174
1175 if( n >= m )
1176 {
1177 os.write( p, n );
1178 }
1179 else if( ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::left )
1180 {
1181 os.write( p, n );
1182
1183 os.width( m - n );
1184 os << "";
1185 }
1186 else
1187 {
1188 os.width( m - n );
1189 os << "";
1190
1191 os.write( p, n );
1192 }
1193
1194 os.width( 0 );
1195 return os;
1196 }
1197
1198 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
1199 template<class Ch> BOOST_CONSTEXPR_OR_CONST std::size_t basic_string_view<Ch>::npos;
1200 #endif
1201
1202 // typedef names
1203
1204 typedef basic_string_view<char> string_view;
1205 typedef basic_string_view<wchar_t> wstring_view;
1206
1207 #if !defined(BOOST_NO_CXX11_CHAR16_T)
1208 typedef basic_string_view<char16_t> u16string_view;
1209 #endif
1210
1211 #if !defined(BOOST_NO_CXX11_CHAR32_T)
1212 typedef basic_string_view<char32_t> u32string_view;
1213 #endif
1214
1215 #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
1216 typedef basic_string_view<char8_t> u8string_view;
1217 #endif
1218
1219 } // namespace core
1220 } // namespace boost
1221
1222 // std::common_reference support
1223 // needed for iterators that have reference=string_view and value_type=std::string
1224
1225 #if !defined(BOOST_NO_CXX20_HDR_CONCEPTS)
1226
1227 template<class Ch, class A, template<class> class Q1, template<class> class Q2>
1228 struct std::basic_common_reference<
1229 boost::core::basic_string_view<Ch>,
1230 std::basic_string<Ch, std::char_traits<Ch>, A>,
1231 Q1, Q2>
1232 {
1233 using type = boost::core::basic_string_view<Ch>;
1234 };
1235
1236 template<class Ch, class A, template<class> class Q1, template<class> class Q2>
1237 struct std::basic_common_reference<
1238 std::basic_string<Ch, std::char_traits<Ch>, A>,
1239 boost::core::basic_string_view<Ch>,
1240 Q1, Q2>
1241 {
1242 using type = boost::core::basic_string_view<Ch>;
1243 };
1244
1245 #endif
1246
1247 #endif // #ifndef BOOST_CORE_STRING_VIEW_HPP_INCLUDED