1 /* Copyright 2003-2018 Joaquin M Lopez Munoz.
2  * Distributed under the Boost Software License, Version 1.0.
3  * (See accompanying file LICENSE_1_0.txt or copy at
4  * http://www.boost.org/LICENSE_1_0.txt)
5  *
6  * See http://www.boost.org/libs/multi_index for library home page.
7  */
8 
9 #ifndef BOOST_MULTI_INDEX_DETAIL_DUPLICATES_ITERATOR_HPP
10 #define BOOST_MULTI_INDEX_DETAIL_DUPLICATES_ITERATOR_HPP
11 
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15 
16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
17 #include <iterator>
18 
19 namespace boost{
20 
21 namespace multi_index{
22 
23 namespace detail{
24 
25 /* duplicates_operator is given a range of ordered elements and
26  * passes only over those which are duplicated.
27  */
28 
29 template<typename Node,typename Predicate>
30 class duplicates_iterator
31 {
32 public:
33   typedef typename Node::value_type        value_type;
34   typedef typename Node::difference_type   difference_type;
35   typedef const typename Node::value_type* pointer;
36   typedef const typename Node::value_type& reference;
37   typedef std::forward_iterator_tag        iterator_category;
38 
duplicates_iterator(Node * node_,Node * end_,Predicate pred_)39   duplicates_iterator(Node* node_,Node* end_,Predicate pred_):
40     node(node_),begin_chunk(0),end(end_),pred(pred_)
41   {
42     advance();
43   }
44 
duplicates_iterator(Node * end_,Predicate pred_)45   duplicates_iterator(Node* end_,Predicate pred_):
46     node(end_),begin_chunk(end_),end(end_),pred(pred_)
47   {
48   }
49 
operator *() const50   reference operator*()const
51   {
52     return node->value();
53   }
54 
operator ->() const55   pointer operator->()const
56   {
57     return &node->value();
58   }
59 
operator ++()60   duplicates_iterator& operator++()
61   {
62     Node::increment(node);
63     sync();
64     return *this;
65   }
66 
operator ++(int)67   duplicates_iterator operator++(int)
68   {
69     duplicates_iterator tmp(*this);
70     ++(*this);
71     return tmp;
72   }
73 
get_node() const74   Node* get_node()const{return node;}
75 
76 private:
sync()77   void sync()
78   {
79     if(node!=end&&pred(begin_chunk->value(),node->value()))advance();
80   }
81 
advance()82   void advance()
83   {
84     for(Node* node2=node;node!=end;node=node2){
85       Node::increment(node2);
86       if(node2!=end&&!pred(node->value(),node2->value()))break;
87     }
88     begin_chunk=node;
89   }
90 
91   Node*     node;
92   Node*     begin_chunk;
93   Node*     end;
94   Predicate pred;
95 };
96 
97 template<typename Node,typename Predicate>
operator ==(const duplicates_iterator<Node,Predicate> & x,const duplicates_iterator<Node,Predicate> & y)98 bool operator==(
99   const duplicates_iterator<Node,Predicate>& x,
100   const duplicates_iterator<Node,Predicate>& y)
101 {
102   return x.get_node()==y.get_node();
103 }
104 
105 template<typename Node,typename Predicate>
operator !=(const duplicates_iterator<Node,Predicate> & x,const duplicates_iterator<Node,Predicate> & y)106 bool operator!=(
107   const duplicates_iterator<Node,Predicate>& x,
108   const duplicates_iterator<Node,Predicate>& y)
109 {
110   return !(x==y);
111 }
112 
113 } /* namespace multi_index::detail */
114 
115 } /* namespace multi_index */
116 
117 } /* namespace boost */
118 
119 #endif
120