// 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 #ifdef BOOST_MSVC #pragma warning( push ) #pragma warning( disable : 4355 ) #endif #include #include #include #include #include #include namespace boost { namespace range_detail { template< class Iter, class Pred, bool default_pass > class skip_iterator : public boost::iterator_adaptor< skip_iterator, Iter, BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type, boost::forward_traversal_tag, BOOST_DEDUCED_TYPENAME std::iterator_traits::reference, BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type > , private Pred { private: typedef boost::iterator_adaptor< skip_iterator, Iter, BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type, boost::forward_traversal_tag, BOOST_DEDUCED_TYPENAME std::iterator_traits::reference, BOOST_DEDUCED_TYPENAME std::iterator_traits::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) { move_to_next_valid(); } template skip_iterator( const skip_iterator& other ) : base_t(other.base()) , pred_t(other) , m_last(other.m_last) {} void move_to_next_valid() { iter_t& it = this->base_reference(); pred_t& bi_pred = *this; if (it != m_last) { if (default_pass) { iter_t nxt = ::boost::next(it); while (nxt != m_last && !bi_pred(*it, *nxt)) { ++it; ++nxt; } } else { iter_t nxt = ::boost::next(it); for(; nxt != m_last; ++it, ++nxt) { if (bi_pred(*it, *nxt)) { break; } } if (nxt == m_last) { it = m_last; } } } } void increment() { iter_t& it = this->base_reference(); BOOST_ASSERT( it != m_last ); ++it; move_to_next_valid(); } iter_t m_last; }; template< class P, class R, bool default_pass > struct adjacent_filter_range : iterator_range< skip_iterator< BOOST_DEDUCED_TYPENAME range_iterator::type, P, default_pass > > { private: typedef skip_iterator< BOOST_DEDUCED_TYPENAME range_iterator::type, P, default_pass > skip_iter; typedef iterator_range base_range; typedef BOOST_DEDUCED_TYPENAME range_iterator::type raw_iterator; public: adjacent_filter_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)) { } private: P m_pred; R* m_range; }; template< class T > struct adjacent_holder : holder { adjacent_holder( T r ) : holder(r) { } }; template< class T > struct adjacent_excl_holder : holder { adjacent_excl_holder( T r ) : holder(r) { } }; template< class ForwardRng, class BinPredicate > inline adjacent_filter_range operator|( ForwardRng& r, const adjacent_holder& f ) { return adjacent_filter_range( f.val, r ); } template< class ForwardRng, class BinPredicate > inline adjacent_filter_range operator|( const ForwardRng& r, const adjacent_holder& f ) { return adjacent_filter_range( f.val, r ); } template< class ForwardRng, class BinPredicate > inline adjacent_filter_range operator|( ForwardRng& r, const adjacent_excl_holder& f ) { return adjacent_filter_range( f.val, r ); } template< class ForwardRng, class BinPredicate > inline adjacent_filter_range operator|( const ForwardRng& r, const adjacent_excl_holder& f ) { return adjacent_filter_range( 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_filter_range; namespace adaptors { namespace { const range_detail::forwarder adjacent_filtered = range_detail::forwarder(); const range_detail::forwarder adjacent_filtered_excl = range_detail::forwarder(); } template inline adjacent_filter_range adjacent_filter(ForwardRng& rng, BinPredicate filter_pred) { return adjacent_filter_range(filter_pred, rng); } template inline adjacent_filter_range adjacent_filter(const ForwardRng& rng, BinPredicate filter_pred) { return adjacent_filter_range(filter_pred, rng); } } // 'adaptors' } #ifdef BOOST_MSVC #pragma warning( pop ) #endif #endif