boost/algorithm/string/find_iterator.hpp
// Boost string_algo library find_iterator.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2004.
//
// 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_FIND_ITERATOR_HPP
#define BOOST_STRING_FIND_ITERATOR_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/detail/find_iterator.hpp>
/*! \file
Defines find iterator classes. Find iterator repeatedly applies a Finder
to the specified input string to search for matches. Dereferencing
the iterator yields the current match or a range between the last and the current
match depending on the iterator used.
*/
namespace boost {
namespace algorithm {
// find_iterator -----------------------------------------------//
//! find_iterator
/*!
Find iterator encapsulates a Finder and allows
for incremental searching in a string.
Each increment moves the iterator to the next match.
Find iterator is a readable forward traversal iterator.
Dereferencing the iterator yields an iterator_range delimiting
the current match.
*/
template<typename IteratorT>
class find_iterator :
public iterator_facade<
find_iterator<IteratorT>,
const iterator_range<IteratorT>,
forward_traversal_tag >,
private detail::find_iterator_base<IteratorT>
{
private:
// facade support
friend class ::boost::iterator_core_access;
private:
// typedefs
typedef detail::find_iterator_base<IteratorT> base_type;
typedef BOOST_STRING_TYPENAME
base_type::input_iterator_type input_iterator_type;
typedef BOOST_STRING_TYPENAME
base_type::match_type match_type;
public:
//! Default constructor
/*!
Construct null iterator. All null iterators are equal.
\post eof()==true
*/
find_iterator() {}
//! Copy constructor
/*!
Construct a copy of the find_iterator
*/
find_iterator( const find_iterator& Other ) :
base_type(Other),
m_Match(Other.m_Match),
m_End(Other.m_End) {}
//! Constructor
/*!
Construct new find_iterator for a given finder
and a range.
*/
template<typename FinderT>
find_iterator(
IteratorT Begin,
IteratorT End,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0),
m_Match(Begin,Begin),
m_End(End)
{
increment();
}
//! Constructor
/*!
Construct new find_iterator for a given finder
and a range.
*/
template<typename FinderT, typename RangeT>
find_iterator(
RangeT& Col,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0)
{
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col));
m_Match=::boost::make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col));
m_End=::boost::end(lit_col);
increment();
}
private:
// iterator operations
// dereference
const match_type& dereference() const
{
return m_Match;
}
// increment
void increment()
{
if(m_Match.begin() == m_Match.end())
m_Match=this->do_find(m_Match.end(),m_End);
else {
input_iterator_type last = m_Match.begin();
m_Match=this->do_find(++last,m_End);
}
}
// comparison
bool equal( const find_iterator& Other ) const
{
bool bEof=eof();
bool bOtherEof=Other.eof();
return bEof || bOtherEof ? bEof==bOtherEof :
(
m_Match==Other.m_Match &&
m_End==Other.m_End
);
}
public:
// operations
//! Eof check
/*!
Check the eof condition. Eof condition means that
there is nothing more to be searched i.e. find_iterator
is after the last match.
*/
bool eof() const
{
return
this->is_null() ||
(
m_Match.begin() == m_End &&
m_Match.end() == m_End
);
}
private:
// Attributes
match_type m_Match;
input_iterator_type m_End;
};
//! find iterator construction helper
/*!
* Construct a find iterator to iterate through the specified string
*/
template<typename RangeT, typename FinderT>
inline find_iterator<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
make_find_iterator(
RangeT& Collection,
FinderT Finder)
{
return find_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>(
Collection, Finder);
}
// split iterator -----------------------------------------------//
//! split_iterator
/*!
Split iterator encapsulates a Finder and allows
for incremental searching in a string.
Unlike the find iterator, split iterator iterates
through gaps between matches.
Find iterator is a readable forward traversal iterator.
Dereferencing the iterator yields an iterator_range delimiting
the current match.
*/
template<typename IteratorT>
class split_iterator :
public iterator_facade<
split_iterator<IteratorT>,
const iterator_range<IteratorT>,
forward_traversal_tag >,
private detail::find_iterator_base<IteratorT>
{
private:
// facade support
friend class ::boost::iterator_core_access;
private:
// typedefs
typedef detail::find_iterator_base<IteratorT> base_type;
typedef BOOST_STRING_TYPENAME
base_type::input_iterator_type input_iterator_type;
typedef BOOST_STRING_TYPENAME
base_type::match_type match_type;
public:
//! Default constructor
/*!
Construct null iterator. All null iterators are equal.
\post eof()==true
*/
split_iterator() {}
//! Copy constructor
/*!
Construct a copy of the split_iterator
*/
split_iterator( const split_iterator& Other ) :
base_type(Other),
m_Match(Other.m_Match),
m_Next(Other.m_Next),
m_End(Other.m_End),
m_bEof(Other.m_bEof)
{}
//! Constructor
/*!
Construct new split_iterator for a given finder
and a range.
*/
template<typename FinderT>
split_iterator(
IteratorT Begin,
IteratorT End,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0),
m_Match(Begin,Begin),
m_Next(Begin),
m_End(End),
m_bEof(false)
{
// force the correct behavior for empty sequences and yield at least one token
if(Begin!=End)
{
increment();
}
}
//! Constructor
/*!
Construct new split_iterator for a given finder
and a collection.
*/
template<typename FinderT, typename RangeT>
split_iterator(
RangeT& Col,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0),
m_bEof(false)
{
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col));
m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col));
m_Next=::boost::begin(lit_col);
m_End=::boost::end(lit_col);
// force the correct behavior for empty sequences and yield at least one token
if(m_Next!=m_End)
{
increment();
}
}
private:
// iterator operations
// dereference
const match_type& dereference() const
{
return m_Match;
}
// increment
void increment()
{
match_type FindMatch=this->do_find( m_Next, m_End );
if(FindMatch.begin()==m_End && FindMatch.end()==m_End)
{
if(m_Match.end()==m_End)
{
// Mark iterator as eof
m_bEof=true;
}
}
m_Match=match_type( m_Next, FindMatch.begin() );
m_Next=FindMatch.end();
}
// comparison
bool equal( const split_iterator& Other ) const
{
bool bEof=eof();
bool bOtherEof=Other.eof();
return bEof || bOtherEof ? bEof==bOtherEof :
(
m_Match==Other.m_Match &&
m_Next==Other.m_Next &&
m_End==Other.m_End
);
}
public:
// operations
//! Eof check
/*!
Check the eof condition. Eof condition means that
there is nothing more to be searched i.e. find_iterator
is after the last match.
*/
bool eof() const
{
return this->is_null() || m_bEof;
}
private:
// Attributes
match_type m_Match;
input_iterator_type m_Next;
input_iterator_type m_End;
bool m_bEof;
};
//! split iterator construction helper
/*!
* Construct a split iterator to iterate through the specified collection
*/
template<typename RangeT, typename FinderT>
inline split_iterator<
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
make_split_iterator(
RangeT& Collection,
FinderT Finder)
{
return split_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>(
Collection, Finder);
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::find_iterator;
using algorithm::make_find_iterator;
using algorithm::split_iterator;
using algorithm::make_split_iterator;
} // namespace boost
#endif // BOOST_STRING_FIND_ITERATOR_HPP