1 // Boost string_algo library finder.hpp header file ---------------------------//
3 // Copyright Pavol Droba 2002-2006.
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // See http://www.boost.org/ for updates, documentation, and revision history.
11 #ifndef BOOST_STRING_FINDER_DETAIL_HPP
12 #define BOOST_STRING_FINDER_DETAIL_HPP
14 #include <boost/algorithm/string/config.hpp>
15 #include <boost/algorithm/string/constants.hpp>
16 #include <boost/detail/iterator.hpp>
18 #include <boost/range/iterator_range.hpp>
19 #include <boost/range/begin.hpp>
20 #include <boost/range/end.hpp>
21 #include <boost/range/empty.hpp>
22 #include <boost/range/as_literal.hpp>
29 // find first functor -----------------------------------------------//
31 // find a subsequence in the sequence ( functor )
33 Returns a pair <begin,end> marking the subsequence in the sequence.
34 If the find fails, functor returns <End,End>
36 template<typename SearchIteratorT,typename PredicateT>
39 typedef SearchIteratorT search_iterator_type;
42 template< typename SearchT >
43 first_finderF( const SearchT& Search, PredicateT Comp ) :
44 m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
46 search_iterator_type SearchBegin,
47 search_iterator_type SearchEnd,
49 m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
52 template< typename ForwardIteratorT >
53 iterator_range<ForwardIteratorT>
55 ForwardIteratorT Begin,
56 ForwardIteratorT End ) const
58 typedef iterator_range<ForwardIteratorT> result_type;
59 typedef ForwardIteratorT input_iterator_type;
62 for(input_iterator_type OuterIt=Begin;
67 if( boost::empty(m_Search) )
68 return result_type( End, End );
70 input_iterator_type InnerIt=OuterIt;
71 search_iterator_type SubstrIt=m_Search.begin();
73 InnerIt!=End && SubstrIt!=m_Search.end();
76 if( !( m_Comp(*InnerIt,*SubstrIt) ) )
80 // Substring matching succeeded
81 if ( SubstrIt==m_Search.end() )
82 return result_type( OuterIt, InnerIt );
85 return result_type( End, End );
89 iterator_range<search_iterator_type> m_Search;
93 // find last functor -----------------------------------------------//
95 // find the last match a subseqeunce in the sequence ( functor )
97 Returns a pair <begin,end> marking the subsequence in the sequence.
98 If the find fails, returns <End,End>
100 template<typename SearchIteratorT, typename PredicateT>
103 typedef SearchIteratorT search_iterator_type;
104 typedef first_finderF<
105 search_iterator_type,
106 PredicateT> first_finder_type;
109 template< typename SearchT >
110 last_finderF( const SearchT& Search, PredicateT Comp ) :
111 m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
113 search_iterator_type SearchBegin,
114 search_iterator_type SearchEnd,
116 m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
119 template< typename ForwardIteratorT >
120 iterator_range<ForwardIteratorT>
122 ForwardIteratorT Begin,
123 ForwardIteratorT End ) const
125 typedef iterator_range<ForwardIteratorT> result_type;
127 if( boost::empty(m_Search) )
128 return result_type( End, End );
130 typedef BOOST_STRING_TYPENAME boost::detail::
131 iterator_traits<ForwardIteratorT>::iterator_category category;
133 return findit( Begin, End, category() );
138 template< typename ForwardIteratorT >
139 iterator_range<ForwardIteratorT>
141 ForwardIteratorT Begin,
142 ForwardIteratorT End,
143 std::forward_iterator_tag ) const
145 typedef ForwardIteratorT input_iterator_type;
146 typedef iterator_range<ForwardIteratorT> result_type;
148 first_finder_type first_finder(
149 m_Search.begin(), m_Search.end(), m_Comp );
151 result_type M=first_finder( Begin, End );
157 M=first_finder( ::boost::end(M), End );
163 // bidirectional iterator
164 template< typename ForwardIteratorT >
165 iterator_range<ForwardIteratorT>
167 ForwardIteratorT Begin,
168 ForwardIteratorT End,
169 std::bidirectional_iterator_tag ) const
171 typedef iterator_range<ForwardIteratorT> result_type;
172 typedef ForwardIteratorT input_iterator_type;
175 for(input_iterator_type OuterIt=End;
178 input_iterator_type OuterIt2=--OuterIt;
180 input_iterator_type InnerIt=OuterIt2;
181 search_iterator_type SubstrIt=m_Search.begin();
183 InnerIt!=End && SubstrIt!=m_Search.end();
184 ++InnerIt,++SubstrIt)
186 if( !( m_Comp(*InnerIt,*SubstrIt) ) )
190 // Substring matching succeeded
191 if( SubstrIt==m_Search.end() )
192 return result_type( OuterIt2, InnerIt );
195 return result_type( End, End );
199 iterator_range<search_iterator_type> m_Search;
203 // find n-th functor -----------------------------------------------//
205 // find the n-th match of a subsequence in the sequence ( functor )
207 Returns a pair <begin,end> marking the subsequence in the sequence.
208 If the find fails, returns <End,End>
210 template<typename SearchIteratorT, typename PredicateT>
213 typedef SearchIteratorT search_iterator_type;
214 typedef first_finderF<
215 search_iterator_type,
216 PredicateT> first_finder_type;
217 typedef last_finderF<
218 search_iterator_type,
219 PredicateT> last_finder_type;
222 template< typename SearchT >
224 const SearchT& Search,
227 m_Search(::boost::begin(Search), ::boost::end(Search)),
231 search_iterator_type SearchBegin,
232 search_iterator_type SearchEnd,
235 m_Search(SearchBegin, SearchEnd),
240 template< typename ForwardIteratorT >
241 iterator_range<ForwardIteratorT>
243 ForwardIteratorT Begin,
244 ForwardIteratorT End ) const
248 return find_forward(Begin, End, m_Nth);
252 return find_backward(Begin, End, -m_Nth);
258 // Implementation helpers
259 template< typename ForwardIteratorT >
260 iterator_range<ForwardIteratorT>
262 ForwardIteratorT Begin,
263 ForwardIteratorT End,
264 unsigned int N) const
266 typedef ForwardIteratorT input_iterator_type;
267 typedef iterator_range<ForwardIteratorT> result_type;
270 if( boost::empty(m_Search) )
271 return result_type( End, End );
273 // Instantiate find functor
274 first_finder_type first_finder(
275 m_Search.begin(), m_Search.end(), m_Comp );
277 result_type M( Begin, Begin );
279 for( unsigned int n=0; n<=N; ++n )
282 M=first_finder( ::boost::end(M), End );
286 // Subsequence not found, return
294 template< typename ForwardIteratorT >
295 iterator_range<ForwardIteratorT>
297 ForwardIteratorT Begin,
298 ForwardIteratorT End,
299 unsigned int N) const
301 typedef ForwardIteratorT input_iterator_type;
302 typedef iterator_range<ForwardIteratorT> result_type;
305 if( boost::empty(m_Search) )
306 return result_type( End, End );
308 // Instantiate find functor
309 last_finder_type last_finder(
310 m_Search.begin(), m_Search.end(), m_Comp );
312 result_type M( End, End );
314 for( unsigned int n=1; n<=N; ++n )
317 M=last_finder( Begin, ::boost::begin(M) );
321 // Subsequence not found, return
331 iterator_range<search_iterator_type> m_Search;
336 // find head/tail implementation helpers ---------------------------//
338 template<typename ForwardIteratorT>
339 iterator_range<ForwardIteratorT>
341 ForwardIteratorT Begin,
342 ForwardIteratorT End,
344 std::forward_iterator_tag )
346 typedef ForwardIteratorT input_iterator_type;
347 typedef iterator_range<ForwardIteratorT> result_type;
349 input_iterator_type It=Begin;
351 unsigned int Index=0;
352 Index<N && It!=End; ++Index,++It ) {};
354 return result_type( Begin, It );
357 template< typename ForwardIteratorT >
358 iterator_range<ForwardIteratorT>
360 ForwardIteratorT Begin,
361 ForwardIteratorT End,
363 std::random_access_iterator_tag )
365 typedef ForwardIteratorT input_iterator_type;
366 typedef iterator_range<ForwardIteratorT> result_type;
368 if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
369 return result_type( Begin, End );
371 return result_type(Begin,Begin+N);
374 // Find head implementation
375 template<typename ForwardIteratorT>
376 iterator_range<ForwardIteratorT>
378 ForwardIteratorT Begin,
379 ForwardIteratorT End,
382 typedef BOOST_STRING_TYPENAME boost::detail::
383 iterator_traits<ForwardIteratorT>::iterator_category category;
385 return find_head_impl( Begin, End, N, category() );
388 template< typename ForwardIteratorT >
389 iterator_range<ForwardIteratorT>
391 ForwardIteratorT Begin,
392 ForwardIteratorT End,
394 std::forward_iterator_tag )
396 typedef ForwardIteratorT input_iterator_type;
397 typedef iterator_range<ForwardIteratorT> result_type;
399 unsigned int Index=0;
400 input_iterator_type It=Begin;
401 input_iterator_type It2=Begin;
403 // Advance It2 by N increments
404 for( Index=0; Index<N && It2!=End; ++Index,++It2 ) {};
406 // Advance It, It2 to the end
407 for(; It2!=End; ++It,++It2 ) {};
409 return result_type( It, It2 );
412 template< typename ForwardIteratorT >
413 iterator_range<ForwardIteratorT>
415 ForwardIteratorT Begin,
416 ForwardIteratorT End,
418 std::bidirectional_iterator_tag )
420 typedef ForwardIteratorT input_iterator_type;
421 typedef iterator_range<ForwardIteratorT> result_type;
423 input_iterator_type It=End;
425 unsigned int Index=0;
426 Index<N && It!=Begin; ++Index,--It ) {};
428 return result_type( It, End );
431 template< typename ForwardIteratorT >
432 iterator_range<ForwardIteratorT>
434 ForwardIteratorT Begin,
435 ForwardIteratorT End,
437 std::random_access_iterator_tag )
439 typedef ForwardIteratorT input_iterator_type;
440 typedef iterator_range<ForwardIteratorT> result_type;
442 if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
443 return result_type( Begin, End );
445 return result_type( End-N, End );
449 template< typename ForwardIteratorT >
450 iterator_range<ForwardIteratorT>
452 ForwardIteratorT Begin,
453 ForwardIteratorT End,
456 typedef BOOST_STRING_TYPENAME boost::detail::
457 iterator_traits<ForwardIteratorT>::iterator_category category;
459 return find_tail_impl( Begin, End, N, category() );
464 // find head functor -----------------------------------------------//
467 // find a head in the sequence ( functor )
469 This functor find a head of the specified range. For
470 a specified N, the head is a subsequence of N starting
471 elements of the range.
476 head_finderF( int N ) : m_N(N) {}
479 template< typename ForwardIteratorT >
480 iterator_range<ForwardIteratorT>
482 ForwardIteratorT Begin,
483 ForwardIteratorT End ) const
487 return find_head_impl( Begin, End, m_N );
491 iterator_range<ForwardIteratorT> Res=
492 find_tail_impl( Begin, End, -m_N );
494 return make_iterator_range(Begin, Res.begin());
502 // find tail functor -----------------------------------------------//
505 // find a tail in the sequence ( functor )
507 This functor find a tail of the specified range. For
508 a specified N, the head is a subsequence of N starting
509 elements of the range.
514 tail_finderF( int N ) : m_N(N) {}
517 template< typename ForwardIteratorT >
518 iterator_range<ForwardIteratorT>
520 ForwardIteratorT Begin,
521 ForwardIteratorT End ) const
525 return find_tail_impl( Begin, End, m_N );
529 iterator_range<ForwardIteratorT> Res=
530 find_head_impl( Begin, End, -m_N );
532 return make_iterator_range(Res.end(), End);
540 // find token functor -----------------------------------------------//
542 // find a token in a sequence ( functor )
544 This find functor finds a token specified be a predicate
545 in a sequence. It is equivalent of std::find algorithm,
546 with an exception that it return range instead of a single
549 If bCompress is set to true, adjacent matching tokens are
550 concatenated into one match.
552 template< typename PredicateT >
558 token_compress_mode_type eCompress=token_compress_off ) :
559 m_Pred(Pred), m_eCompress(eCompress) {}
562 template< typename ForwardIteratorT >
563 iterator_range<ForwardIteratorT>
565 ForwardIteratorT Begin,
566 ForwardIteratorT End ) const
568 typedef iterator_range<ForwardIteratorT> result_type;
570 ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
574 return result_type( End, End );
578 ForwardIteratorT It2=It;
580 if( m_eCompress==token_compress_on )
582 // Find first non-matching character
583 while( It2!=End && m_Pred(*It2) ) ++It2;
587 // Advance by one position
591 return result_type( It, It2 );
597 token_compress_mode_type m_eCompress;
600 // find range functor -----------------------------------------------//
602 // find a range in the sequence ( functor )
604 This functor actually does not perform any find operation.
605 It always returns given iterator range as a result.
607 template<typename ForwardIterator1T>
610 typedef ForwardIterator1T input_iterator_type;
611 typedef iterator_range<input_iterator_type> result_type;
615 input_iterator_type Begin,
616 input_iterator_type End ) : m_Range(Begin, End) {}
618 range_finderF(const iterator_range<input_iterator_type>& Range) :
622 template< typename ForwardIterator2T >
623 iterator_range<ForwardIterator2T>
626 ForwardIterator2T ) const
628 #if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )
629 return iterator_range<const ForwardIterator2T>(this->m_Range);
630 #elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
631 return iterator_range<ForwardIterator2T>(m_Range.begin(), m_Range.end());
638 iterator_range<input_iterator_type> m_Range;
642 } // namespace detail
643 } // namespace algorithm
646 #endif // BOOST_STRING_FINDER_DETAIL_HPP