1 | /* Copyright 2003-2013 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 <cstddef> |
18 | #include <iterator> |
19 | |
20 | namespace boost{ |
21 | |
22 | namespace multi_index{ |
23 | |
24 | namespace detail{ |
25 | |
26 | /* duplicates_operator is given a range of ordered elements and |
27 | * passes only over those which are duplicated. |
28 | */ |
29 | |
30 | template<typename Node,typename Predicate> |
31 | class duplicates_iterator |
32 | { |
33 | public: |
34 | typedef typename Node::value_type value_type; |
35 | typedef std::ptrdiff_t difference_type; |
36 | typedef const typename Node::value_type* pointer; |
37 | typedef const typename Node::value_type& reference; |
38 | typedef std::forward_iterator_tag iterator_category; |
39 | |
40 | duplicates_iterator(Node* node_,Node* end_,Predicate pred_): |
41 | node(node_),begin_chunk(0),end(end_),pred(pred_) |
42 | { |
43 | advance(); |
44 | } |
45 | |
46 | duplicates_iterator(Node* end_,Predicate pred_): |
47 | node(end_),begin_chunk(end_),end(end_),pred(pred_) |
48 | { |
49 | } |
50 | |
51 | reference operator*()const |
52 | { |
53 | return node->value(); |
54 | } |
55 | |
56 | pointer operator->()const |
57 | { |
58 | return &node->value(); |
59 | } |
60 | |
61 | duplicates_iterator& operator++() |
62 | { |
63 | Node::increment(node); |
64 | sync(); |
65 | return *this; |
66 | } |
67 | |
68 | duplicates_iterator operator++(int) |
69 | { |
70 | duplicates_iterator tmp(*this); |
71 | ++(*this); |
72 | return tmp; |
73 | } |
74 | |
75 | Node* get_node()const{return node;} |
76 | |
77 | private: |
78 | void sync() |
79 | { |
80 | if(node!=end&&pred(begin_chunk->value(),node->value()))advance(); |
81 | } |
82 | |
83 | void advance() |
84 | { |
85 | for(Node* node2=node;node!=end;node=node2){ |
86 | Node::increment(node2); |
87 | if(node2!=end&&!pred(node->value(),node2->value()))break; |
88 | } |
89 | begin_chunk=node; |
90 | } |
91 | |
92 | Node* node; |
93 | Node* begin_chunk; |
94 | Node* end; |
95 | Predicate pred; |
96 | }; |
97 | |
98 | template<typename Node,typename Predicate> |
99 | bool operator==( |
100 | const duplicates_iterator<Node,Predicate>& x, |
101 | const duplicates_iterator<Node,Predicate>& y) |
102 | { |
103 | return x.get_node()==y.get_node(); |
104 | } |
105 | |
106 | template<typename Node,typename Predicate> |
107 | bool operator!=( |
108 | const duplicates_iterator<Node,Predicate>& x, |
109 | const duplicates_iterator<Node,Predicate>& y) |
110 | { |
111 | return !(x==y); |
112 | } |
113 | |
114 | } /* namespace multi_index::detail */ |
115 | |
116 | } /* namespace multi_index */ |
117 | |
118 | } /* namespace boost */ |
119 | |
120 | #endif |
121 | |