adjacent_filtered.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Boost.Range library
  2. //
  3. // Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
  4. // distribution is subject to the Boost Software License, Version
  5. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // For more information, see http://www.boost.org/libs/range/
  9. //
  10. #ifndef BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP
  11. #define BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP
  12. #include <boost/config.hpp>
  13. #ifdef BOOST_MSVC
  14. #pragma warning( push )
  15. #pragma warning( disable : 4355 )
  16. #endif
  17. #include <boost/range/adaptor/argument_fwd.hpp>
  18. #include <boost/range/iterator_range.hpp>
  19. #include <boost/range/begin.hpp>
  20. #include <boost/range/end.hpp>
  21. #include <boost/range/concepts.hpp>
  22. #include <boost/iterator/iterator_adaptor.hpp>
  23. #include <boost/next_prior.hpp>
  24. namespace boost
  25. {
  26. namespace range_detail
  27. {
  28. template< class Iter, class Pred, bool default_pass >
  29. class skip_iterator
  30. : public boost::iterator_adaptor<
  31. skip_iterator<Iter,Pred,default_pass>,
  32. Iter,
  33. BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type,
  34. boost::forward_traversal_tag,
  35. BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference,
  36. BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type
  37. >
  38. , private Pred
  39. {
  40. private:
  41. typedef boost::iterator_adaptor<
  42. skip_iterator<Iter,Pred,default_pass>,
  43. Iter,
  44. BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type,
  45. boost::forward_traversal_tag,
  46. BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference,
  47. BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type
  48. > base_t;
  49. public:
  50. typedef Pred pred_t;
  51. typedef Iter iter_t;
  52. skip_iterator() : m_last() {}
  53. skip_iterator(iter_t it, iter_t last, const Pred& pred)
  54. : base_t(it)
  55. , pred_t(pred)
  56. , m_last(last)
  57. {
  58. }
  59. template<class OtherIter>
  60. skip_iterator( const skip_iterator<OtherIter, pred_t, default_pass>& other )
  61. : base_t(other.base())
  62. , pred_t(other)
  63. , m_last(other.m_last)
  64. {
  65. }
  66. void increment()
  67. {
  68. iter_t& it = this->base_reference();
  69. BOOST_ASSERT( it != m_last );
  70. pred_t& bi_pred = *this;
  71. iter_t prev = it;
  72. ++it;
  73. if (it != m_last)
  74. {
  75. if (default_pass)
  76. {
  77. while (it != m_last && !bi_pred(*prev, *it))
  78. {
  79. ++it;
  80. ++prev;
  81. }
  82. }
  83. else
  84. {
  85. for (; it != m_last; ++it, ++prev)
  86. {
  87. if (bi_pred(*prev, *it))
  88. {
  89. break;
  90. }
  91. }
  92. }
  93. }
  94. }
  95. iter_t m_last;
  96. };
  97. template< class P, class R, bool default_pass >
  98. struct adjacent_filtered_range
  99. : iterator_range< skip_iterator<
  100. BOOST_DEDUCED_TYPENAME range_iterator<R>::type,
  101. P,
  102. default_pass
  103. >
  104. >
  105. {
  106. private:
  107. typedef skip_iterator<
  108. BOOST_DEDUCED_TYPENAME range_iterator<R>::type,
  109. P,
  110. default_pass
  111. >
  112. skip_iter;
  113. typedef iterator_range<skip_iter>
  114. base_range;
  115. typedef BOOST_DEDUCED_TYPENAME range_iterator<R>::type raw_iterator;
  116. public:
  117. adjacent_filtered_range( const P& p, R& r )
  118. : base_range(skip_iter(boost::begin(r), boost::end(r), p),
  119. skip_iter(boost::end(r), boost::end(r), p))
  120. {
  121. }
  122. };
  123. template< class T >
  124. struct adjacent_holder : holder<T>
  125. {
  126. adjacent_holder( T r ) : holder<T>(r)
  127. { }
  128. };
  129. template< class T >
  130. struct adjacent_excl_holder : holder<T>
  131. {
  132. adjacent_excl_holder( T r ) : holder<T>(r)
  133. { }
  134. };
  135. template< class ForwardRng, class BinPredicate >
  136. inline adjacent_filtered_range<BinPredicate, ForwardRng, true>
  137. operator|( ForwardRng& r,
  138. const adjacent_holder<BinPredicate>& f )
  139. {
  140. BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
  141. return adjacent_filtered_range<BinPredicate, ForwardRng, true>( f.val, r );
  142. }
  143. template< class ForwardRng, class BinPredicate >
  144. inline adjacent_filtered_range<BinPredicate, const ForwardRng, true>
  145. operator|( const ForwardRng& r,
  146. const adjacent_holder<BinPredicate>& f )
  147. {
  148. BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
  149. return adjacent_filtered_range<BinPredicate,
  150. const ForwardRng, true>( f.val, r );
  151. }
  152. template< class ForwardRng, class BinPredicate >
  153. inline adjacent_filtered_range<BinPredicate, ForwardRng, false>
  154. operator|( ForwardRng& r,
  155. const adjacent_excl_holder<BinPredicate>& f )
  156. {
  157. BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
  158. return adjacent_filtered_range<BinPredicate, ForwardRng, false>( f.val, r );
  159. }
  160. template< class ForwardRng, class BinPredicate >
  161. inline adjacent_filtered_range<BinPredicate, const ForwardRng, false>
  162. operator|( const ForwardRng& r,
  163. const adjacent_excl_holder<BinPredicate>& f )
  164. {
  165. BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
  166. return adjacent_filtered_range<BinPredicate,
  167. const ForwardRng, false>( f.val, r );
  168. }
  169. } // 'range_detail'
  170. // Bring adjacent_filter_range into the boost namespace so that users of
  171. // this library may specify the return type of the '|' operator and
  172. // adjacent_filter()
  173. using range_detail::adjacent_filtered_range;
  174. namespace adaptors
  175. {
  176. namespace
  177. {
  178. const range_detail::forwarder<range_detail::adjacent_holder>
  179. adjacent_filtered =
  180. range_detail::forwarder<range_detail::adjacent_holder>();
  181. const range_detail::forwarder<range_detail::adjacent_excl_holder>
  182. adjacent_filtered_excl =
  183. range_detail::forwarder<range_detail::adjacent_excl_holder>();
  184. }
  185. template<class ForwardRng, class BinPredicate>
  186. inline adjacent_filtered_range<BinPredicate, ForwardRng, true>
  187. adjacent_filter(ForwardRng& rng, BinPredicate filter_pred)
  188. {
  189. BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<ForwardRng>));
  190. return adjacent_filtered_range<BinPredicate, ForwardRng, true>(filter_pred, rng);
  191. }
  192. template<class ForwardRng, class BinPredicate>
  193. inline adjacent_filtered_range<BinPredicate, const ForwardRng, true>
  194. adjacent_filter(const ForwardRng& rng, BinPredicate filter_pred)
  195. {
  196. BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept<const ForwardRng>));
  197. return adjacent_filtered_range<BinPredicate, const ForwardRng, true>(filter_pred, rng);
  198. }
  199. } // 'adaptors'
  200. }
  201. #ifdef BOOST_MSVC
  202. #pragma warning( pop )
  203. #endif
  204. #endif