finder.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  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.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 subseqeunce 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 ForwardIteratorT input_iterator_type;
  122. typedef iterator_range<ForwardIteratorT> result_type;
  123. first_finder_type first_finder(
  124. m_Search.begin(), m_Search.end(), m_Comp );
  125. result_type M=first_finder( Begin, End );
  126. result_type Last=M;
  127. while( M )
  128. {
  129. Last=M;
  130. M=first_finder( ::boost::end(M), End );
  131. }
  132. return Last;
  133. }
  134. // bidirectional iterator
  135. template< typename ForwardIteratorT >
  136. iterator_range<ForwardIteratorT>
  137. findit(
  138. ForwardIteratorT Begin,
  139. ForwardIteratorT End,
  140. std::bidirectional_iterator_tag ) const
  141. {
  142. typedef iterator_range<ForwardIteratorT> result_type;
  143. typedef ForwardIteratorT input_iterator_type;
  144. // Outer loop
  145. for(input_iterator_type OuterIt=End;
  146. OuterIt!=Begin; )
  147. {
  148. input_iterator_type OuterIt2=--OuterIt;
  149. input_iterator_type InnerIt=OuterIt2;
  150. search_iterator_type SubstrIt=m_Search.begin();
  151. for(;
  152. InnerIt!=End && SubstrIt!=m_Search.end();
  153. ++InnerIt,++SubstrIt)
  154. {
  155. if( !( m_Comp(*InnerIt,*SubstrIt) ) )
  156. break;
  157. }
  158. // Substring matching succeeded
  159. if( SubstrIt==m_Search.end() )
  160. return result_type( OuterIt2, InnerIt );
  161. }
  162. return result_type( End, End );
  163. }
  164. private:
  165. iterator_range<search_iterator_type> m_Search;
  166. PredicateT m_Comp;
  167. };
  168. // find n-th functor -----------------------------------------------//
  169. // find the n-th match of a subsequence in the sequence ( functor )
  170. /*
  171. Returns a pair <begin,end> marking the subsequence in the sequence.
  172. If the find fails, returns <End,End>
  173. */
  174. template<typename SearchIteratorT, typename PredicateT>
  175. struct nth_finderF
  176. {
  177. typedef SearchIteratorT search_iterator_type;
  178. typedef first_finderF<
  179. search_iterator_type,
  180. PredicateT> first_finder_type;
  181. typedef last_finderF<
  182. search_iterator_type,
  183. PredicateT> last_finder_type;
  184. // Construction
  185. template< typename SearchT >
  186. nth_finderF(
  187. const SearchT& Search,
  188. int Nth,
  189. PredicateT Comp) :
  190. m_Search(::boost::begin(Search), ::boost::end(Search)),
  191. m_Nth(Nth),
  192. m_Comp(Comp) {}
  193. nth_finderF(
  194. search_iterator_type SearchBegin,
  195. search_iterator_type SearchEnd,
  196. int Nth,
  197. PredicateT Comp) :
  198. m_Search(SearchBegin, SearchEnd),
  199. m_Nth(Nth),
  200. m_Comp(Comp) {}
  201. // Operation
  202. template< typename ForwardIteratorT >
  203. iterator_range<ForwardIteratorT>
  204. operator()(
  205. ForwardIteratorT Begin,
  206. ForwardIteratorT End ) const
  207. {
  208. if(m_Nth>=0)
  209. {
  210. return find_forward(Begin, End, m_Nth);
  211. }
  212. else
  213. {
  214. return find_backward(Begin, End, -m_Nth);
  215. }
  216. }
  217. private:
  218. // Implementation helpers
  219. template< typename ForwardIteratorT >
  220. iterator_range<ForwardIteratorT>
  221. find_forward(
  222. ForwardIteratorT Begin,
  223. ForwardIteratorT End,
  224. unsigned int N) const
  225. {
  226. typedef ForwardIteratorT input_iterator_type;
  227. typedef iterator_range<ForwardIteratorT> result_type;
  228. // Sanity check
  229. if( boost::empty(m_Search) )
  230. return result_type( End, End );
  231. // Instantiate find functor
  232. first_finder_type first_finder(
  233. m_Search.begin(), m_Search.end(), m_Comp );
  234. result_type M( Begin, Begin );
  235. for( unsigned int n=0; n<=N; ++n )
  236. {
  237. // find next match
  238. M=first_finder( ::boost::end(M), End );
  239. if ( !M )
  240. {
  241. // Subsequence not found, return
  242. return M;
  243. }
  244. }
  245. return M;
  246. }
  247. template< typename ForwardIteratorT >
  248. iterator_range<ForwardIteratorT>
  249. find_backward(
  250. ForwardIteratorT Begin,
  251. ForwardIteratorT End,
  252. unsigned int N) const
  253. {
  254. typedef ForwardIteratorT input_iterator_type;
  255. typedef iterator_range<ForwardIteratorT> result_type;
  256. // Sanity check
  257. if( boost::empty(m_Search) )
  258. return result_type( End, End );
  259. // Instantiate find functor
  260. last_finder_type last_finder(
  261. m_Search.begin(), m_Search.end(), m_Comp );
  262. result_type M( End, End );
  263. for( unsigned int n=1; n<=N; ++n )
  264. {
  265. // find next match
  266. M=last_finder( Begin, ::boost::begin(M) );
  267. if ( !M )
  268. {
  269. // Subsequence not found, return
  270. return M;
  271. }
  272. }
  273. return M;
  274. }
  275. private:
  276. iterator_range<search_iterator_type> m_Search;
  277. int m_Nth;
  278. PredicateT m_Comp;
  279. };
  280. // find head/tail implementation helpers ---------------------------//
  281. template<typename ForwardIteratorT>
  282. iterator_range<ForwardIteratorT>
  283. find_head_impl(
  284. ForwardIteratorT Begin,
  285. ForwardIteratorT End,
  286. unsigned int N,
  287. std::forward_iterator_tag )
  288. {
  289. typedef ForwardIteratorT input_iterator_type;
  290. typedef iterator_range<ForwardIteratorT> result_type;
  291. input_iterator_type It=Begin;
  292. for(
  293. unsigned int Index=0;
  294. Index<N && It!=End; ++Index,++It ) {};
  295. return result_type( Begin, It );
  296. }
  297. template< typename ForwardIteratorT >
  298. iterator_range<ForwardIteratorT>
  299. find_head_impl(
  300. ForwardIteratorT Begin,
  301. ForwardIteratorT End,
  302. unsigned int N,
  303. std::random_access_iterator_tag )
  304. {
  305. typedef ForwardIteratorT input_iterator_type;
  306. typedef iterator_range<ForwardIteratorT> result_type;
  307. if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
  308. return result_type( Begin, End );
  309. return result_type(Begin,Begin+N);
  310. }
  311. // Find head implementation
  312. template<typename ForwardIteratorT>
  313. iterator_range<ForwardIteratorT>
  314. find_head_impl(
  315. ForwardIteratorT Begin,
  316. ForwardIteratorT End,
  317. unsigned int N )
  318. {
  319. typedef BOOST_STRING_TYPENAME boost::detail::
  320. iterator_traits<ForwardIteratorT>::iterator_category category;
  321. return find_head_impl( Begin, End, N, category() );
  322. }
  323. template< typename ForwardIteratorT >
  324. iterator_range<ForwardIteratorT>
  325. find_tail_impl(
  326. ForwardIteratorT Begin,
  327. ForwardIteratorT End,
  328. unsigned int N,
  329. std::forward_iterator_tag )
  330. {
  331. typedef ForwardIteratorT input_iterator_type;
  332. typedef iterator_range<ForwardIteratorT> result_type;
  333. unsigned int Index=0;
  334. input_iterator_type It=Begin;
  335. input_iterator_type It2=Begin;
  336. // Advance It2 by N increments
  337. for( Index=0; Index<N && It2!=End; ++Index,++It2 ) {};
  338. // Advance It, It2 to the end
  339. for(; It2!=End; ++It,++It2 ) {};
  340. return result_type( It, It2 );
  341. }
  342. template< typename ForwardIteratorT >
  343. iterator_range<ForwardIteratorT>
  344. find_tail_impl(
  345. ForwardIteratorT Begin,
  346. ForwardIteratorT End,
  347. unsigned int N,
  348. std::bidirectional_iterator_tag )
  349. {
  350. typedef ForwardIteratorT input_iterator_type;
  351. typedef iterator_range<ForwardIteratorT> result_type;
  352. input_iterator_type It=End;
  353. for(
  354. unsigned int Index=0;
  355. Index<N && It!=Begin; ++Index,--It ) {};
  356. return result_type( It, End );
  357. }
  358. template< typename ForwardIteratorT >
  359. iterator_range<ForwardIteratorT>
  360. find_tail_impl(
  361. ForwardIteratorT Begin,
  362. ForwardIteratorT End,
  363. unsigned int N,
  364. std::random_access_iterator_tag )
  365. {
  366. typedef ForwardIteratorT input_iterator_type;
  367. typedef iterator_range<ForwardIteratorT> result_type;
  368. if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
  369. return result_type( Begin, End );
  370. return result_type( End-N, End );
  371. }
  372. // Operation
  373. template< typename ForwardIteratorT >
  374. iterator_range<ForwardIteratorT>
  375. find_tail_impl(
  376. ForwardIteratorT Begin,
  377. ForwardIteratorT End,
  378. unsigned int N )
  379. {
  380. typedef BOOST_STRING_TYPENAME boost::detail::
  381. iterator_traits<ForwardIteratorT>::iterator_category category;
  382. return find_tail_impl( Begin, End, N, category() );
  383. }
  384. // find head functor -----------------------------------------------//
  385. // find a head in the sequence ( functor )
  386. /*
  387. This functor find a head of the specified range. For
  388. a specified N, the head is a subsequence of N starting
  389. elements of the range.
  390. */
  391. struct head_finderF
  392. {
  393. // Construction
  394. head_finderF( int N ) : m_N(N) {}
  395. // Operation
  396. template< typename ForwardIteratorT >
  397. iterator_range<ForwardIteratorT>
  398. operator()(
  399. ForwardIteratorT Begin,
  400. ForwardIteratorT End ) const
  401. {
  402. if(m_N>=0)
  403. {
  404. return find_head_impl( Begin, End, m_N );
  405. }
  406. else
  407. {
  408. iterator_range<ForwardIteratorT> Res=
  409. find_tail_impl( Begin, End, -m_N );
  410. return make_iterator_range(Begin, Res.begin());
  411. }
  412. }
  413. private:
  414. int m_N;
  415. };
  416. // find tail functor -----------------------------------------------//
  417. // find a tail in the sequence ( functor )
  418. /*
  419. This functor find a tail of the specified range. For
  420. a specified N, the head is a subsequence of N starting
  421. elements of the range.
  422. */
  423. struct tail_finderF
  424. {
  425. // Construction
  426. tail_finderF( int N ) : m_N(N) {}
  427. // Operation
  428. template< typename ForwardIteratorT >
  429. iterator_range<ForwardIteratorT>
  430. operator()(
  431. ForwardIteratorT Begin,
  432. ForwardIteratorT End ) const
  433. {
  434. if(m_N>=0)
  435. {
  436. return find_tail_impl( Begin, End, m_N );
  437. }
  438. else
  439. {
  440. iterator_range<ForwardIteratorT> Res=
  441. find_head_impl( Begin, End, -m_N );
  442. return make_iterator_range(Res.end(), End);
  443. }
  444. }
  445. private:
  446. int m_N;
  447. };
  448. // find token functor -----------------------------------------------//
  449. // find a token in a sequence ( functor )
  450. /*
  451. This find functor finds a token specified be a predicate
  452. in a sequence. It is equivalent of std::find algorithm,
  453. with an exception that it return range instead of a single
  454. iterator.
  455. If bCompress is set to true, adjacent matching tokens are
  456. concatenated into one match.
  457. */
  458. template< typename PredicateT >
  459. struct token_finderF
  460. {
  461. // Construction
  462. token_finderF(
  463. PredicateT Pred,
  464. token_compress_mode_type eCompress=token_compress_off ) :
  465. m_Pred(Pred), m_eCompress(eCompress) {}
  466. // Operation
  467. template< typename ForwardIteratorT >
  468. iterator_range<ForwardIteratorT>
  469. operator()(
  470. ForwardIteratorT Begin,
  471. ForwardIteratorT End ) const
  472. {
  473. typedef iterator_range<ForwardIteratorT> result_type;
  474. ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
  475. if( It==End )
  476. {
  477. return result_type( End, End );
  478. }
  479. else
  480. {
  481. ForwardIteratorT It2=It;
  482. if( m_eCompress==token_compress_on )
  483. {
  484. // Find first non-matching character
  485. while( It2!=End && m_Pred(*It2) ) ++It2;
  486. }
  487. else
  488. {
  489. // Advance by one position
  490. ++It2;
  491. }
  492. return result_type( It, It2 );
  493. }
  494. }
  495. private:
  496. PredicateT m_Pred;
  497. token_compress_mode_type m_eCompress;
  498. };
  499. // find range functor -----------------------------------------------//
  500. // find a range in the sequence ( functor )
  501. /*
  502. This functor actually does not perform any find operation.
  503. It always returns given iterator range as a result.
  504. */
  505. template<typename ForwardIterator1T>
  506. struct range_finderF
  507. {
  508. typedef ForwardIterator1T input_iterator_type;
  509. typedef iterator_range<input_iterator_type> result_type;
  510. // Construction
  511. range_finderF(
  512. input_iterator_type Begin,
  513. input_iterator_type End ) : m_Range(Begin, End) {}
  514. range_finderF(const iterator_range<input_iterator_type>& Range) :
  515. m_Range(Range) {}
  516. // Operation
  517. template< typename ForwardIterator2T >
  518. iterator_range<ForwardIterator2T>
  519. operator()(
  520. ForwardIterator2T,
  521. ForwardIterator2T ) const
  522. {
  523. #if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )
  524. return iterator_range<const ForwardIterator2T>(this->m_Range);
  525. #elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  526. return iterator_range<ForwardIterator2T>(m_Range.begin(), m_Range.end());
  527. #else
  528. return m_Range;
  529. #endif
  530. }
  531. private:
  532. iterator_range<input_iterator_type> m_Range;
  533. };
  534. } // namespace detail
  535. } // namespace algorithm
  536. } // namespace boost
  537. #endif // BOOST_STRING_FINDER_DETAIL_HPP