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