238 lines
8.2 KiB
Plaintext
238 lines
8.2 KiB
Plaintext
// Boost.Range library
|
|
//
|
|
// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
|
|
// distribution is subject to 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)
|
|
//
|
|
// For more information, see http://www.boost.org/libs/range/
|
|
//
|
|
|
|
#ifndef BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP
|
|
#define BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP
|
|
|
|
#include <boost/config.hpp>
|
|
#ifdef BOOST_MSVC
|
|
#pragma warning( push )
|
|
#pragma warning( disable : 4355 )
|
|
#endif
|
|
|
|
#include <boost/range/adaptor/argument_fwd.hpp>
|
|
#include <boost/range/iterator_range.hpp>
|
|
#include <boost/range/begin.hpp>
|
|
#include <boost/range/end.hpp>
|
|
#include <boost/range/concepts.hpp>
|
|
#include <boost/iterator/iterator_adaptor.hpp>
|
|
#include <boost/next_prior.hpp>
|
|
|
|
|
|
namespace boost
|
|
{
|
|
namespace range_detail
|
|
{
|
|
template< class Iter, class Pred, bool default_pass >
|
|
class skip_iterator
|
|
: public boost::iterator_adaptor<
|
|
skip_iterator<Iter,Pred,default_pass>,
|
|
Iter,
|
|
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type,
|
|
boost::forward_traversal_tag,
|
|
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference,
|
|
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type
|
|
>
|
|
, private Pred
|
|
{
|
|
private:
|
|
typedef boost::iterator_adaptor<
|
|
skip_iterator<Iter,Pred,default_pass>,
|
|
Iter,
|
|
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type,
|
|
boost::forward_traversal_tag,
|
|
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference,
|
|
BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type
|
|
> base_t;
|
|
|
|
public:
|
|
typedef Pred pred_t;
|
|
typedef Iter iter_t;
|
|
|
|
skip_iterator() : m_last() {}
|
|
|
|
skip_iterator(iter_t it, iter_t last, const Pred& pred)
|
|
: base_t(it)
|
|
, pred_t(pred)
|
|
, m_last(last)
|
|
{
|
|
}
|
|
|
|
template<class OtherIter>
|
|
skip_iterator( const skip_iterator<OtherIter, pred_t, default_pass>& other )
|
|
: base_t(other.base())
|
|
, pred_t(other)
|
|
, m_last(other.m_last)
|
|
{
|
|
}
|
|
|
|
void increment()
|
|
{
|
|
iter_t& it = this->base_reference();
|
|
BOOST_ASSERT( it != m_last );
|
|
pred_t& bi_pred = *this;
|
|
iter_t prev = it;
|
|
++it;
|
|
if (it != m_last)
|
|
{
|
|
if (default_pass)
|
|
{
|
|
while (it != m_last && !bi_pred(*prev, *it))
|
|
{
|
|
++it;
|
|
++prev;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (; it != m_last; ++it, ++prev)
|
|
{
|
|
if (bi_pred(*prev, *it))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
iter_t m_last;
|
|
};
|
|
|
|
template< class P, class R, bool default_pass >
|
|
struct adjacent_filtered_range
|
|
: iterator_range< skip_iterator<
|
|
BOOST_DEDUCED_TYPENAME range_iterator<R>::type,
|
|
P,
|
|
default_pass
|
|
>
|
|
>
|
|
{
|
|
private:
|
|
typedef skip_iterator<
|
|
BOOST_DEDUCED_TYPENAME range_iterator<R>::type,
|
|
P,
|
|
default_pass
|
|
>
|
|
skip_iter;
|
|
|
|
typedef iterator_range<skip_iter>
|
|
base_range;
|
|
|
|
typedef BOOST_DEDUCED_TYPENAME range_iterator<R>::type raw_iterator;
|
|
|
|
public:
|
|
adjacent_filtered_range( const P& p, R& r )
|
|
: base_range(skip_iter(boost::begin(r), boost::end(r), p),
|
|
skip_iter(boost::end(r), boost::end(r), p))
|
|
{
|
|
}
|
|
};
|
|
|
|
template< class T >
|
|
struct adjacent_holder : holder<T>
|
|
{
|
|
adjacent_holder( T r ) : holder<T>(r)
|
|
{ }
|
|
};
|
|
|
|
template< class T >
|
|
struct adjacent_excl_holder : holder<T>
|
|
{
|
|
adjacent_excl_holder( T r ) : holder<T>(r)
|
|
{ }
|
|
};
|
|
|
|
template< class ForwardRng, class BinPredicate >
|
|
inline adjacent_filtered_range<BinPredicate, ForwardRng, true>
|
|
operator|( ForwardRng& r,
|
|
const adjacent_holder<BinPredicate>& f )
|
|
{
|
|
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
|
|
|
|
return adjacent_filtered_range<BinPredicate, ForwardRng, true>( f.val, r );
|
|
}
|
|
|
|
template< class ForwardRng, class BinPredicate >
|
|
inline adjacent_filtered_range<BinPredicate, const ForwardRng, true>
|
|
operator|( const ForwardRng& r,
|
|
const adjacent_holder<BinPredicate>& f )
|
|
{
|
|
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
|
|
|
|
return adjacent_filtered_range<BinPredicate,
|
|
const ForwardRng, true>( f.val, r );
|
|
}
|
|
|
|
template< class ForwardRng, class BinPredicate >
|
|
inline adjacent_filtered_range<BinPredicate, ForwardRng, false>
|
|
operator|( ForwardRng& r,
|
|
const adjacent_excl_holder<BinPredicate>& f )
|
|
{
|
|
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
|
|
return adjacent_filtered_range<BinPredicate, ForwardRng, false>( f.val, r );
|
|
}
|
|
|
|
template< class ForwardRng, class BinPredicate >
|
|
inline adjacent_filtered_range<BinPredicate, ForwardRng, false>
|
|
operator|( const ForwardRng& r,
|
|
const adjacent_excl_holder<BinPredicate>& f )
|
|
{
|
|
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
|
|
return adjacent_filtered_range<BinPredicate,
|
|
const ForwardRng, false>( f.val, r );
|
|
}
|
|
|
|
} // 'range_detail'
|
|
|
|
// Bring adjacent_filter_range into the boost namespace so that users of
|
|
// this library may specify the return type of the '|' operator and
|
|
// adjacent_filter()
|
|
using range_detail::adjacent_filtered_range;
|
|
|
|
namespace adaptors
|
|
{
|
|
namespace
|
|
{
|
|
const range_detail::forwarder<range_detail::adjacent_holder>
|
|
adjacent_filtered =
|
|
range_detail::forwarder<range_detail::adjacent_holder>();
|
|
|
|
const range_detail::forwarder<range_detail::adjacent_excl_holder>
|
|
adjacent_filtered_excl =
|
|
range_detail::forwarder<range_detail::adjacent_excl_holder>();
|
|
}
|
|
|
|
template<class ForwardRng, class BinPredicate>
|
|
inline adjacent_filtered_range<BinPredicate, ForwardRng, true>
|
|
adjacent_filter(ForwardRng& rng, BinPredicate filter_pred)
|
|
{
|
|
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
|
|
return adjacent_filtered_range<BinPredicate, ForwardRng, true>(filter_pred, rng);
|
|
}
|
|
|
|
template<class ForwardRng, class BinPredicate>
|
|
inline adjacent_filtered_range<BinPredicate, const ForwardRng, true>
|
|
adjacent_filter(const ForwardRng& rng, BinPredicate filter_pred)
|
|
{
|
|
BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
|
|
return adjacent_filtered_range<BinPredicate, const ForwardRng, true>(filter_pred, rng);
|
|
}
|
|
|
|
} // 'adaptors'
|
|
|
|
}
|
|
|
|
#ifdef BOOST_MSVC
|
|
#pragma warning( pop )
|
|
#endif
|
|
|
|
#endif
|