string_view.hpp 32 KB

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