Chris@16: // Boost string_algo library finder.hpp header file ---------------------------// Chris@16: Chris@16: // Copyright Pavol Droba 2002-2006. Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // See http://www.boost.org/ for updates, documentation, and revision history. Chris@16: Chris@16: #ifndef BOOST_STRING_FINDER_DETAIL_HPP Chris@16: #define BOOST_STRING_FINDER_DETAIL_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace algorithm { Chris@16: namespace detail { Chris@16: Chris@16: Chris@16: // find first functor -----------------------------------------------// Chris@16: Chris@16: // find a subsequence in the sequence ( functor ) Chris@16: /* Chris@16: Returns a pair marking the subsequence in the sequence. Chris@16: If the find fails, functor returns Chris@16: */ Chris@16: template Chris@16: struct first_finderF Chris@16: { Chris@16: typedef SearchIteratorT search_iterator_type; Chris@16: Chris@16: // Construction Chris@16: template< typename SearchT > Chris@16: first_finderF( const SearchT& Search, PredicateT Comp ) : Chris@16: m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {} Chris@16: first_finderF( Chris@16: search_iterator_type SearchBegin, Chris@16: search_iterator_type SearchEnd, Chris@16: PredicateT Comp ) : Chris@16: m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {} Chris@16: Chris@16: // Operation Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: operator()( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End ) const Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: typedef ForwardIteratorT input_iterator_type; Chris@16: Chris@16: // Outer loop Chris@16: for(input_iterator_type OuterIt=Begin; Chris@16: OuterIt!=End; Chris@16: ++OuterIt) Chris@16: { Chris@16: // Sanity check Chris@16: if( boost::empty(m_Search) ) Chris@16: return result_type( End, End ); Chris@16: Chris@16: input_iterator_type InnerIt=OuterIt; Chris@16: search_iterator_type SubstrIt=m_Search.begin(); Chris@16: for(; Chris@16: InnerIt!=End && SubstrIt!=m_Search.end(); Chris@16: ++InnerIt,++SubstrIt) Chris@16: { Chris@16: if( !( m_Comp(*InnerIt,*SubstrIt) ) ) Chris@16: break; Chris@16: } Chris@16: Chris@16: // Substring matching succeeded Chris@16: if ( SubstrIt==m_Search.end() ) Chris@16: return result_type( OuterIt, InnerIt ); Chris@16: } Chris@16: Chris@16: return result_type( End, End ); Chris@16: } Chris@16: Chris@16: private: Chris@16: iterator_range m_Search; Chris@16: PredicateT m_Comp; Chris@16: }; Chris@16: Chris@16: // find last functor -----------------------------------------------// Chris@16: Chris@16: // find the last match a subsequence in the sequence ( functor ) Chris@16: /* Chris@16: Returns a pair marking the subsequence in the sequence. Chris@16: If the find fails, returns Chris@16: */ Chris@16: template Chris@16: struct last_finderF Chris@16: { Chris@16: typedef SearchIteratorT search_iterator_type; Chris@16: typedef first_finderF< Chris@16: search_iterator_type, Chris@16: PredicateT> first_finder_type; Chris@16: Chris@16: // Construction Chris@16: template< typename SearchT > Chris@16: last_finderF( const SearchT& Search, PredicateT Comp ) : Chris@16: m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {} Chris@16: last_finderF( Chris@16: search_iterator_type SearchBegin, Chris@16: search_iterator_type SearchEnd, Chris@16: PredicateT Comp ) : Chris@16: m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {} Chris@16: Chris@16: // Operation Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: operator()( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End ) const Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: if( boost::empty(m_Search) ) Chris@16: return result_type( End, End ); Chris@16: Chris@16: typedef BOOST_STRING_TYPENAME boost::detail:: Chris@16: iterator_traits::iterator_category category; Chris@16: Chris@16: return findit( Begin, End, category() ); Chris@16: } Chris@16: Chris@16: private: Chris@16: // forward iterator Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: findit( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: std::forward_iterator_tag ) const Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: first_finder_type first_finder( Chris@16: m_Search.begin(), m_Search.end(), m_Comp ); Chris@16: Chris@16: result_type M=first_finder( Begin, End ); Chris@16: result_type Last=M; Chris@16: Chris@16: while( M ) Chris@16: { Chris@16: Last=M; Chris@16: M=first_finder( ::boost::end(M), End ); Chris@16: } Chris@16: Chris@16: return Last; Chris@16: } Chris@16: Chris@16: // bidirectional iterator Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: findit( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: std::bidirectional_iterator_tag ) const Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: typedef ForwardIteratorT input_iterator_type; Chris@16: Chris@16: // Outer loop Chris@16: for(input_iterator_type OuterIt=End; Chris@16: OuterIt!=Begin; ) Chris@16: { Chris@16: input_iterator_type OuterIt2=--OuterIt; Chris@16: Chris@16: input_iterator_type InnerIt=OuterIt2; Chris@16: search_iterator_type SubstrIt=m_Search.begin(); Chris@16: for(; Chris@16: InnerIt!=End && SubstrIt!=m_Search.end(); Chris@16: ++InnerIt,++SubstrIt) Chris@16: { Chris@16: if( !( m_Comp(*InnerIt,*SubstrIt) ) ) Chris@16: break; Chris@16: } Chris@16: Chris@16: // Substring matching succeeded Chris@16: if( SubstrIt==m_Search.end() ) Chris@16: return result_type( OuterIt2, InnerIt ); Chris@16: } Chris@16: Chris@16: return result_type( End, End ); Chris@16: } Chris@16: Chris@16: private: Chris@16: iterator_range m_Search; Chris@16: PredicateT m_Comp; Chris@16: }; Chris@16: Chris@16: // find n-th functor -----------------------------------------------// Chris@16: Chris@16: // find the n-th match of a subsequence in the sequence ( functor ) Chris@16: /* Chris@16: Returns a pair marking the subsequence in the sequence. Chris@16: If the find fails, returns Chris@16: */ Chris@16: template Chris@16: struct nth_finderF Chris@16: { Chris@16: typedef SearchIteratorT search_iterator_type; Chris@16: typedef first_finderF< Chris@16: search_iterator_type, Chris@16: PredicateT> first_finder_type; Chris@16: typedef last_finderF< Chris@16: search_iterator_type, Chris@16: PredicateT> last_finder_type; Chris@16: Chris@16: // Construction Chris@16: template< typename SearchT > Chris@16: nth_finderF( Chris@16: const SearchT& Search, Chris@16: int Nth, Chris@16: PredicateT Comp) : Chris@16: m_Search(::boost::begin(Search), ::boost::end(Search)), Chris@16: m_Nth(Nth), Chris@16: m_Comp(Comp) {} Chris@16: nth_finderF( Chris@16: search_iterator_type SearchBegin, Chris@16: search_iterator_type SearchEnd, Chris@16: int Nth, Chris@16: PredicateT Comp) : Chris@16: m_Search(SearchBegin, SearchEnd), Chris@16: m_Nth(Nth), Chris@16: m_Comp(Comp) {} Chris@16: Chris@16: // Operation Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: operator()( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End ) const Chris@16: { Chris@16: if(m_Nth>=0) Chris@16: { Chris@16: return find_forward(Begin, End, m_Nth); Chris@16: } Chris@16: else Chris@16: { Chris@16: return find_backward(Begin, End, -m_Nth); Chris@16: } Chris@16: Chris@16: } Chris@16: Chris@16: private: Chris@16: // Implementation helpers Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: find_forward( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N) const Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: // Sanity check Chris@16: if( boost::empty(m_Search) ) Chris@16: return result_type( End, End ); Chris@16: Chris@16: // Instantiate find functor Chris@16: first_finder_type first_finder( Chris@16: m_Search.begin(), m_Search.end(), m_Comp ); Chris@16: Chris@16: result_type M( Begin, Begin ); Chris@16: Chris@16: for( unsigned int n=0; n<=N; ++n ) Chris@16: { Chris@16: // find next match Chris@16: M=first_finder( ::boost::end(M), End ); Chris@16: Chris@16: if ( !M ) Chris@16: { Chris@16: // Subsequence not found, return Chris@16: return M; Chris@16: } Chris@16: } Chris@16: Chris@16: return M; Chris@16: } Chris@16: Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: find_backward( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N) const Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: // Sanity check Chris@16: if( boost::empty(m_Search) ) Chris@16: return result_type( End, End ); Chris@16: Chris@16: // Instantiate find functor Chris@16: last_finder_type last_finder( Chris@16: m_Search.begin(), m_Search.end(), m_Comp ); Chris@16: Chris@16: result_type M( End, End ); Chris@16: Chris@16: for( unsigned int n=1; n<=N; ++n ) Chris@16: { Chris@16: // find next match Chris@16: M=last_finder( Begin, ::boost::begin(M) ); Chris@16: Chris@16: if ( !M ) Chris@16: { Chris@16: // Subsequence not found, return Chris@16: return M; Chris@16: } Chris@16: } Chris@16: Chris@16: return M; Chris@16: } Chris@16: Chris@16: Chris@16: private: Chris@16: iterator_range m_Search; Chris@16: int m_Nth; Chris@16: PredicateT m_Comp; Chris@16: }; Chris@16: Chris@16: // find head/tail implementation helpers ---------------------------// Chris@16: Chris@16: template Chris@16: iterator_range Chris@16: find_head_impl( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N, Chris@16: std::forward_iterator_tag ) Chris@16: { Chris@16: typedef ForwardIteratorT input_iterator_type; Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: input_iterator_type It=Begin; Chris@16: for( Chris@16: unsigned int Index=0; Chris@16: Index Chris@16: iterator_range Chris@16: find_head_impl( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N, Chris@16: std::random_access_iterator_tag ) Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: if ( (End<=Begin) || ( static_cast(End-Begin) < N ) ) Chris@16: return result_type( Begin, End ); Chris@16: Chris@16: return result_type(Begin,Begin+N); Chris@16: } Chris@16: Chris@16: // Find head implementation Chris@16: template Chris@16: iterator_range Chris@16: find_head_impl( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N ) Chris@16: { Chris@16: typedef BOOST_STRING_TYPENAME boost::detail:: Chris@16: iterator_traits::iterator_category category; Chris@16: Chris@16: return ::boost::algorithm::detail::find_head_impl( Begin, End, N, category() ); Chris@16: } Chris@16: Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: find_tail_impl( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N, Chris@16: std::forward_iterator_tag ) Chris@16: { Chris@16: typedef ForwardIteratorT input_iterator_type; Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: unsigned int Index=0; Chris@16: input_iterator_type It=Begin; Chris@16: input_iterator_type It2=Begin; Chris@16: Chris@16: // Advance It2 by N increments Chris@16: for( Index=0; Index Chris@16: iterator_range Chris@16: find_tail_impl( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N, Chris@16: std::bidirectional_iterator_tag ) Chris@16: { Chris@16: typedef ForwardIteratorT input_iterator_type; Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: input_iterator_type It=End; Chris@16: for( Chris@16: unsigned int Index=0; Chris@16: Index Chris@16: iterator_range Chris@16: find_tail_impl( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N, Chris@16: std::random_access_iterator_tag ) Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: if ( (End<=Begin) || ( static_cast(End-Begin) < N ) ) Chris@16: return result_type( Begin, End ); Chris@16: Chris@16: return result_type( End-N, End ); Chris@16: } Chris@16: Chris@16: // Operation Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: find_tail_impl( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End, Chris@16: unsigned int N ) Chris@16: { Chris@16: typedef BOOST_STRING_TYPENAME boost::detail:: Chris@16: iterator_traits::iterator_category category; Chris@16: Chris@16: return ::boost::algorithm::detail::find_tail_impl( Begin, End, N, category() ); Chris@16: } Chris@16: Chris@16: Chris@16: Chris@16: // find head functor -----------------------------------------------// Chris@16: Chris@16: Chris@16: // find a head in the sequence ( functor ) Chris@16: /* Chris@16: This functor find a head of the specified range. For Chris@16: a specified N, the head is a subsequence of N starting Chris@16: elements of the range. Chris@16: */ Chris@16: struct head_finderF Chris@16: { Chris@16: // Construction Chris@16: head_finderF( int N ) : m_N(N) {} Chris@16: Chris@16: // Operation Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: operator()( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End ) const Chris@16: { Chris@16: if(m_N>=0) Chris@16: { Chris@16: return ::boost::algorithm::detail::find_head_impl( Begin, End, m_N ); Chris@16: } Chris@16: else Chris@16: { Chris@16: iterator_range Res= Chris@16: ::boost::algorithm::detail::find_tail_impl( Begin, End, -m_N ); Chris@16: Chris@16: return ::boost::make_iterator_range(Begin, Res.begin()); Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int m_N; Chris@16: }; Chris@16: Chris@16: // find tail functor -----------------------------------------------// Chris@16: Chris@16: Chris@16: // find a tail in the sequence ( functor ) Chris@16: /* Chris@16: This functor find a tail of the specified range. For Chris@16: a specified N, the head is a subsequence of N starting Chris@16: elements of the range. Chris@16: */ Chris@16: struct tail_finderF Chris@16: { Chris@16: // Construction Chris@16: tail_finderF( int N ) : m_N(N) {} Chris@16: Chris@16: // Operation Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: operator()( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End ) const Chris@16: { Chris@16: if(m_N>=0) Chris@16: { Chris@16: return ::boost::algorithm::detail::find_tail_impl( Begin, End, m_N ); Chris@16: } Chris@16: else Chris@16: { Chris@16: iterator_range Res= Chris@16: ::boost::algorithm::detail::find_head_impl( Begin, End, -m_N ); Chris@16: Chris@16: return ::boost::make_iterator_range(Res.end(), End); Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: int m_N; Chris@16: }; Chris@16: Chris@16: // find token functor -----------------------------------------------// Chris@16: Chris@16: // find a token in a sequence ( functor ) Chris@16: /* Chris@16: This find functor finds a token specified be a predicate Chris@16: in a sequence. It is equivalent of std::find algorithm, Chris@16: with an exception that it return range instead of a single Chris@16: iterator. Chris@16: Chris@16: If bCompress is set to true, adjacent matching tokens are Chris@16: concatenated into one match. Chris@16: */ Chris@16: template< typename PredicateT > Chris@16: struct token_finderF Chris@16: { Chris@16: // Construction Chris@16: token_finderF( Chris@16: PredicateT Pred, Chris@16: token_compress_mode_type eCompress=token_compress_off ) : Chris@16: m_Pred(Pred), m_eCompress(eCompress) {} Chris@16: Chris@16: // Operation Chris@16: template< typename ForwardIteratorT > Chris@16: iterator_range Chris@16: operator()( Chris@16: ForwardIteratorT Begin, Chris@16: ForwardIteratorT End ) const Chris@16: { Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: ForwardIteratorT It=std::find_if( Begin, End, m_Pred ); Chris@16: Chris@16: if( It==End ) Chris@16: { Chris@16: return result_type( End, End ); Chris@16: } Chris@16: else Chris@16: { Chris@16: ForwardIteratorT It2=It; Chris@16: Chris@16: if( m_eCompress==token_compress_on ) Chris@16: { Chris@16: // Find first non-matching character Chris@16: while( It2!=End && m_Pred(*It2) ) ++It2; Chris@16: } Chris@16: else Chris@16: { Chris@16: // Advance by one position Chris@16: ++It2; Chris@16: } Chris@16: Chris@16: return result_type( It, It2 ); Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: PredicateT m_Pred; Chris@16: token_compress_mode_type m_eCompress; Chris@16: }; Chris@16: Chris@16: // find range functor -----------------------------------------------// Chris@16: Chris@16: // find a range in the sequence ( functor ) Chris@16: /* Chris@16: This functor actually does not perform any find operation. Chris@16: It always returns given iterator range as a result. Chris@16: */ Chris@16: template Chris@16: struct range_finderF Chris@16: { Chris@16: typedef ForwardIterator1T input_iterator_type; Chris@16: typedef iterator_range result_type; Chris@16: Chris@16: // Construction Chris@16: range_finderF( Chris@16: input_iterator_type Begin, Chris@16: input_iterator_type End ) : m_Range(Begin, End) {} Chris@16: Chris@16: range_finderF(const iterator_range& Range) : Chris@16: m_Range(Range) {} Chris@16: Chris@16: // Operation Chris@16: template< typename ForwardIterator2T > Chris@16: iterator_range Chris@16: operator()( Chris@16: ForwardIterator2T, Chris@16: ForwardIterator2T ) const Chris@16: { Chris@16: #if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 ) Chris@16: return iterator_range(this->m_Range); Chris@16: #else Chris@16: return m_Range; Chris@16: #endif Chris@16: } Chris@16: Chris@16: private: Chris@16: iterator_range m_Range; Chris@16: }; Chris@16: Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace algorithm Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_STRING_FINDER_DETAIL_HPP