finder.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. // Boost string_algo library finder.hpp header file ---------------------------//
  2. // Copyright Pavol Droba 2002-2006.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // See http://www.boost.org/ for updates, documentation, and revision history.
  8. #ifndef BOOST_STRING_FINDER_DETAIL_HPP
  9. #define BOOST_STRING_FINDER_DETAIL_HPP
  10. #include <boost/algorithm/string/config.hpp>
  11. #include <boost/algorithm/string/constants.hpp>
  12. #include <boost/detail/iterator.hpp>
  13. #include <boost/range/iterator_range_core.hpp>
  14. #include <boost/range/begin.hpp>
  15. #include <boost/range/end.hpp>
  16. #include <boost/range/empty.hpp>
  17. #include <boost/range/as_literal.hpp>
  18. namespace boost {
  19. namespace algorithm {
  20. namespace detail {
  21. // find first functor -----------------------------------------------//
  22. // find a subsequence in the sequence ( functor )
  23. /*
  24. Returns a pair <begin,end> marking the subsequence in the sequence.
  25. If the find fails, functor returns <End,End>
  26. */
  27. template<typename SearchIteratorT,typename PredicateT>
  28. struct first_finderF
  29. {
  30. typedef SearchIteratorT search_iterator_type;
  31. // Construction
  32. template< typename SearchT >
  33. first_finderF( const SearchT& Search, PredicateT Comp ) :
  34. m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
  35. first_finderF(
  36. search_iterator_type SearchBegin,
  37. search_iterator_type SearchEnd,
  38. PredicateT Comp ) :
  39. m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
  40. // Operation
  41. template< typename ForwardIteratorT >
  42. iterator_range<ForwardIteratorT>
  43. operator()(
  44. ForwardIteratorT Begin,
  45. ForwardIteratorT End ) const
  46. {
  47. typedef iterator_range<ForwardIteratorT> result_type;
  48. typedef ForwardIteratorT input_iterator_type;
  49. // Outer loop
  50. for(input_iterator_type OuterIt=Begin;
  51. OuterIt!=End;
  52. ++OuterIt)
  53. {
  54. // Sanity check
  55. if( boost::empty(m_Search) )
  56. return result_type( End, End );
  57. input_iterator_type InnerIt=OuterIt;
  58. search_iterator_type SubstrIt=m_Search.begin();
  59. for(;
  60. InnerIt!=End && SubstrIt!=m_Search.end();
  61. ++InnerIt,++SubstrIt)
  62. {
  63. if( !( m_Comp(*InnerIt,*SubstrIt) ) )
  64. break;
  65. }
  66. // Substring matching succeeded
  67. if ( SubstrIt==m_Search.end() )
  68. return result_type( OuterIt, InnerIt );
  69. }
  70. return result_type( End, End );
  71. }
  72. private:
  73. iterator_range<search_iterator_type> m_Search;
  74. PredicateT m_Comp;
  75. };
  76. // find last functor -----------------------------------------------//
  77. // find the last match a subsequence in the sequence ( functor )
  78. /*
  79. Returns a pair <begin,end> marking the subsequence in the sequence.
  80. If the find fails, returns <End,End>
  81. */
  82. template<typename SearchIteratorT, typename PredicateT>
  83. struct last_finderF
  84. {
  85. typedef SearchIteratorT search_iterator_type;
  86. typedef first_finderF<
  87. search_iterator_type,
  88. PredicateT> first_finder_type;
  89. // Construction
  90. template< typename SearchT >
  91. last_finderF( const SearchT& Search, PredicateT Comp ) :
  92. m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
  93. last_finderF(
  94. search_iterator_type SearchBegin,
  95. search_iterator_type SearchEnd,
  96. PredicateT Comp ) :
  97. m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
  98. // Operation
  99. template< typename ForwardIteratorT >
  100. iterator_range<ForwardIteratorT>
  101. operator()(
  102. ForwardIteratorT Begin,
  103. ForwardIteratorT End ) const
  104. {
  105. typedef iterator_range<ForwardIteratorT> result_type;
  106. if( boost::empty(m_Search) )
  107. return result_type( End, End );
  108. typedef BOOST_STRING_TYPENAME boost::detail::
  109. iterator_traits<ForwardIteratorT>::iterator_category category;
  110. return findit( Begin, End, category() );
  111. }
  112. private:
  113. // forward iterator
  114. template< typename ForwardIteratorT >
  115. iterator_range<ForwardIteratorT>
  116. findit(
  117. ForwardIteratorT Begin,
  118. ForwardIteratorT End,
  119. std::forward_iterator_tag ) const
  120. {
  121. typedef iterator_range<ForwardIteratorT> result_type;
  122. first_finder_type first_finder(
  123. m_Search.begin(), m_Search.end(), m_Comp );
  124. result_type M=first_finder( Begin, End );
  125. result_type Last=M;
  126. while( M )
  127. {
  128. Last=M;
  129. M=first_finder( ::boost::end(M), End );
  130. }
  131. return Last;
  132. }
  133. // bidirectional iterator
  134. template< typename ForwardIteratorT >
  135. iterator_range<ForwardIteratorT>
  136. findit(
  137. ForwardIteratorT Begin,
  138. ForwardIteratorT End,
  139. std::bidirectional_iterator_tag ) const
  140. {
  141. typedef iterator_range<ForwardIteratorT> result_type;
  142. typedef ForwardIteratorT input_iterator_type;
  143. // Outer loop
  144. for(input_iterator_type OuterIt=End;
  145. OuterIt!=Begin; )
  146. {
  147. input_iterator_type OuterIt2=--OuterIt;
  148. input_iterator_type InnerIt=OuterIt2;
  149. search_iterator_type SubstrIt=m_Search.begin();
  150. for(;
  151. InnerIt!=End && SubstrIt!=m_Search.end();
  152. ++InnerIt,++SubstrIt)
  153. {
  154. if( !( m_Comp(*InnerIt,*SubstrIt) ) )
  155. break;
  156. }
  157. // Substring matching succeeded
  158. if( SubstrIt==m_Search.end() )
  159. return result_type( OuterIt2, InnerIt );
  160. }
  161. return result_type( End, End );
  162. }
  163. private:
  164. iterator_range<search_iterator_type> m_Search;
  165. PredicateT m_Comp;
  166. };
  167. // find n-th functor -----------------------------------------------//
  168. // find the n-th match of a subsequence in the sequence ( functor )
  169. /*
  170. Returns a pair <begin,end> marking the subsequence in the sequence.
  171. If the find fails, returns <End,End>
  172. */
  173. template<typename SearchIteratorT, typename PredicateT>
  174. struct nth_finderF
  175. {
  176. typedef SearchIteratorT search_iterator_type;
  177. typedef first_finderF<
  178. search_iterator_type,
  179. PredicateT> first_finder_type;
  180. typedef last_finderF<
  181. search_iterator_type,
  182. PredicateT> last_finder_type;
  183. // Construction
  184. template< typename SearchT >
  185. nth_finderF(
  186. const SearchT& Search,
  187. int Nth,
  188. PredicateT Comp) :
  189. m_Search(::boost::begin(Search), ::boost::end(Search)),
  190. m_Nth(Nth),
  191. m_Comp(Comp) {}
  192. nth_finderF(
  193. search_iterator_type SearchBegin,
  194. search_iterator_type SearchEnd,
  195. int Nth,
  196. PredicateT Comp) :
  197. m_Search(SearchBegin, SearchEnd),
  198. m_Nth(Nth),
  199. m_Comp(Comp) {}
  200. // Operation
  201. template< typename ForwardIteratorT >
  202. iterator_range<ForwardIteratorT>
  203. operator()(
  204. ForwardIteratorT Begin,
  205. ForwardIteratorT End ) const
  206. {
  207. if(m_Nth>=0)
  208. {
  209. return find_forward(Begin, End, m_Nth);
  210. }
  211. else
  212. {
  213. return find_backward(Begin, End, -m_Nth);
  214. }
  215. }
  216. private:
  217. // Implementation helpers
  218. template< typename ForwardIteratorT >
  219. iterator_range<ForwardIteratorT>
  220. find_forward(
  221. ForwardIteratorT Begin,
  222. ForwardIteratorT End,
  223. unsigned int N) const
  224. {
  225. typedef iterator_range<ForwardIteratorT> result_type;
  226. // Sanity check
  227. if( boost::empty(m_Search) )
  228. return result_type( End, End );
  229. // Instantiate find functor
  230. first_finder_type first_finder(
  231. m_Search.begin(), m_Search.end(), m_Comp );
  232. result_type M( Begin, Begin );
  233. for( unsigned int n=0; n<=N; ++n )
  234. {
  235. // find next match
  236. M=first_finder( ::boost::end(M), End );
  237. if ( !M )
  238. {
  239. // Subsequence not found, return
  240. return M;
  241. }
  242. }
  243. return M;
  244. }
  245. template< typename ForwardIteratorT >
  246. iterator_range<ForwardIteratorT>
  247. find_backward(
  248. ForwardIteratorT Begin,
  249. ForwardIteratorT End,
  250. unsigned int N) const
  251. {
  252. typedef iterator_range<ForwardIteratorT> result_type;
  253. // Sanity check
  254. if( boost::empty(m_Search) )
  255. return result_type( End, End );
  256. // Instantiate find functor
  257. last_finder_type last_finder(
  258. m_Search.begin(), m_Search.end(), m_Comp );
  259. result_type M( End, End );
  260. for( unsigned int n=1; n<=N; ++n )
  261. {
  262. // find next match
  263. M=last_finder( Begin, ::boost::begin(M) );
  264. if ( !M )
  265. {
  266. // Subsequence not found, return
  267. return M;
  268. }
  269. }
  270. return M;
  271. }
  272. private:
  273. iterator_range<search_iterator_type> m_Search;
  274. int m_Nth;
  275. PredicateT m_Comp;
  276. };
  277. // find head/tail implementation helpers ---------------------------//
  278. template<typename ForwardIteratorT>
  279. iterator_range<ForwardIteratorT>
  280. find_head_impl(
  281. ForwardIteratorT Begin,
  282. ForwardIteratorT End,
  283. unsigned int N,
  284. std::forward_iterator_tag )
  285. {
  286. typedef ForwardIteratorT input_iterator_type;
  287. typedef iterator_range<ForwardIteratorT> result_type;
  288. input_iterator_type It=Begin;
  289. for(
  290. unsigned int Index=0;
  291. Index<N && It!=End; ++Index,++It ) {};
  292. return result_type( Begin, It );
  293. }
  294. template< typename ForwardIteratorT >
  295. iterator_range<ForwardIteratorT>
  296. find_head_impl(
  297. ForwardIteratorT Begin,
  298. ForwardIteratorT End,
  299. unsigned int N,
  300. std::random_access_iterator_tag )
  301. {
  302. typedef iterator_range<ForwardIteratorT> result_type;
  303. if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
  304. return result_type( Begin, End );
  305. return result_type(Begin,Begin+N);
  306. }
  307. // Find head implementation
  308. template<typename ForwardIteratorT>
  309. iterator_range<ForwardIteratorT>
  310. find_head_impl(
  311. ForwardIteratorT Begin,
  312. ForwardIteratorT End,
  313. unsigned int N )
  314. {
  315. typedef BOOST_STRING_TYPENAME boost::detail::
  316. iterator_traits<ForwardIteratorT>::iterator_category category;
  317. return ::boost::algorithm::detail::find_head_impl( Begin, End, N, category() );
  318. }
  319. template< typename ForwardIteratorT >
  320. iterator_range<ForwardIteratorT>
  321. find_tail_impl(
  322. ForwardIteratorT Begin,
  323. ForwardIteratorT End,
  324. unsigned int N,
  325. std::forward_iterator_tag )
  326. {
  327. typedef ForwardIteratorT input_iterator_type;
  328. typedef iterator_range<ForwardIteratorT> result_type;
  329. unsigned int Index=0;
  330. input_iterator_type It=Begin;
  331. input_iterator_type It2=Begin;
  332. // Advance It2 by N increments
  333. for( Index=0; Index<N && It2!=End; ++Index,++It2 ) {};
  334. // Advance It, It2 to the end
  335. for(; It2!=End; ++It,++It2 ) {};
  336. return result_type( It, It2 );
  337. }
  338. template< typename ForwardIteratorT >
  339. iterator_range<ForwardIteratorT>
  340. find_tail_impl(
  341. ForwardIteratorT Begin,
  342. ForwardIteratorT End,
  343. unsigned int N,
  344. std::bidirectional_iterator_tag )
  345. {
  346. typedef ForwardIteratorT input_iterator_type;
  347. typedef iterator_range<ForwardIteratorT> result_type;
  348. input_iterator_type It=End;
  349. for(
  350. unsigned int Index=0;
  351. Index<N && It!=Begin; ++Index,--It ) {};
  352. return result_type( It, End );
  353. }
  354. template< typename ForwardIteratorT >
  355. iterator_range<ForwardIteratorT>
  356. find_tail_impl(
  357. ForwardIteratorT Begin,
  358. ForwardIteratorT End,
  359. unsigned int N,
  360. std::random_access_iterator_tag )
  361. {
  362. typedef iterator_range<ForwardIteratorT> result_type;
  363. if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
  364. return result_type( Begin, End );
  365. return result_type( End-N, End );
  366. }
  367. // Operation
  368. template< typename ForwardIteratorT >
  369. iterator_range<ForwardIteratorT>
  370. find_tail_impl(
  371. ForwardIteratorT Begin,
  372. ForwardIteratorT End,
  373. unsigned int N )
  374. {
  375. typedef BOOST_STRING_TYPENAME boost::detail::
  376. iterator_traits<ForwardIteratorT>::iterator_category category;
  377. return ::boost::algorithm::detail::find_tail_impl( Begin, End, N, category() );
  378. }
  379. // find head functor -----------------------------------------------//
  380. // find a head in the sequence ( functor )
  381. /*
  382. This functor find a head of the specified range. For
  383. a specified N, the head is a subsequence of N starting
  384. elements of the range.
  385. */
  386. struct head_finderF
  387. {
  388. // Construction
  389. head_finderF( int N ) : m_N(N) {}
  390. // Operation
  391. template< typename ForwardIteratorT >
  392. iterator_range<ForwardIteratorT>
  393. operator()(
  394. ForwardIteratorT Begin,
  395. ForwardIteratorT End ) const
  396. {
  397. if(m_N>=0)
  398. {
  399. return ::boost::algorithm::detail::find_head_impl( Begin, End, m_N );
  400. }
  401. else
  402. {
  403. iterator_range<ForwardIteratorT> Res=
  404. ::boost::algorithm::detail::find_tail_impl( Begin, End, -m_N );
  405. return ::boost::make_iterator_range(Begin, Res.begin());
  406. }
  407. }
  408. private:
  409. int m_N;
  410. };
  411. // find tail functor -----------------------------------------------//
  412. // find a tail in the sequence ( functor )
  413. /*
  414. This functor find a tail of the specified range. For
  415. a specified N, the head is a subsequence of N starting
  416. elements of the range.
  417. */
  418. struct tail_finderF
  419. {
  420. // Construction
  421. tail_finderF( int N ) : m_N(N) {}
  422. // Operation
  423. template< typename ForwardIteratorT >
  424. iterator_range<ForwardIteratorT>
  425. operator()(
  426. ForwardIteratorT Begin,
  427. ForwardIteratorT End ) const
  428. {
  429. if(m_N>=0)
  430. {
  431. return ::boost::algorithm::detail::find_tail_impl( Begin, End, m_N );
  432. }
  433. else
  434. {
  435. iterator_range<ForwardIteratorT> Res=
  436. ::boost::algorithm::detail::find_head_impl( Begin, End, -m_N );
  437. return ::boost::make_iterator_range(Res.end(), End);
  438. }
  439. }
  440. private:
  441. int m_N;
  442. };
  443. // find token functor -----------------------------------------------//
  444. // find a token in a sequence ( functor )
  445. /*
  446. This find functor finds a token specified be a predicate
  447. in a sequence. It is equivalent of std::find algorithm,
  448. with an exception that it return range instead of a single
  449. iterator.
  450. If bCompress is set to true, adjacent matching tokens are
  451. concatenated into one match.
  452. */
  453. template< typename PredicateT >
  454. struct token_finderF
  455. {
  456. // Construction
  457. token_finderF(
  458. PredicateT Pred,
  459. token_compress_mode_type eCompress=token_compress_off ) :
  460. m_Pred(Pred), m_eCompress(eCompress) {}
  461. // Operation
  462. template< typename ForwardIteratorT >
  463. iterator_range<ForwardIteratorT>
  464. operator()(
  465. ForwardIteratorT Begin,
  466. ForwardIteratorT End ) const
  467. {
  468. typedef iterator_range<ForwardIteratorT> result_type;
  469. ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
  470. if( It==End )
  471. {
  472. return result_type( End, End );
  473. }
  474. else
  475. {
  476. ForwardIteratorT It2=It;
  477. if( m_eCompress==token_compress_on )
  478. {
  479. // Find first non-matching character
  480. while( It2!=End && m_Pred(*It2) ) ++It2;
  481. }
  482. else
  483. {
  484. // Advance by one position
  485. ++It2;
  486. }
  487. return result_type( It, It2 );
  488. }
  489. }
  490. private:
  491. PredicateT m_Pred;
  492. token_compress_mode_type m_eCompress;
  493. };
  494. // find range functor -----------------------------------------------//
  495. // find a range in the sequence ( functor )
  496. /*
  497. This functor actually does not perform any find operation.
  498. It always returns given iterator range as a result.
  499. */
  500. template<typename ForwardIterator1T>
  501. struct range_finderF
  502. {
  503. typedef ForwardIterator1T input_iterator_type;
  504. typedef iterator_range<input_iterator_type> result_type;
  505. // Construction
  506. range_finderF(
  507. input_iterator_type Begin,
  508. input_iterator_type End ) : m_Range(Begin, End) {}
  509. range_finderF(const iterator_range<input_iterator_type>& Range) :
  510. m_Range(Range) {}
  511. // Operation
  512. template< typename ForwardIterator2T >
  513. iterator_range<ForwardIterator2T>
  514. operator()(
  515. ForwardIterator2T,
  516. ForwardIterator2T ) const
  517. {
  518. #if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )
  519. return iterator_range<const ForwardIterator2T>(this->m_Range);
  520. #else
  521. return m_Range;
  522. #endif
  523. }
  524. private:
  525. iterator_range<input_iterator_type> m_Range;
  526. };
  527. } // namespace detail
  528. } // namespace algorithm
  529. } // namespace boost
  530. #endif // BOOST_STRING_FINDER_DETAIL_HPP