williamr@2: /* Copyright 2003-2006 Joaquín M López Muñoz.
williamr@2:  * Distributed under the Boost Software License, Version 1.0.
williamr@2:  * (See accompanying file LICENSE_1_0.txt or copy at
williamr@2:  * http://www.boost.org/LICENSE_1_0.txt)
williamr@2:  *
williamr@2:  * See http://www.boost.org/libs/multi_index for library home page.
williamr@2:  */
williamr@2: 
williamr@2: #ifndef BOOST_MULTI_INDEX_DETAIL_DUPLICATES_ITERATOR_HPP
williamr@2: #define BOOST_MULTI_INDEX_DETAIL_DUPLICATES_ITERATOR_HPP
williamr@2: 
williamr@2: #if defined(_MSC_VER)&&(_MSC_VER>=1200)
williamr@2: #pragma once
williamr@2: #endif
williamr@2: 
williamr@2: #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
williamr@2: #include <cstddef>
williamr@2: #include <iterator>
williamr@2: 
williamr@2: namespace boost{
williamr@2: 
williamr@2: namespace multi_index{
williamr@2: 
williamr@2: namespace detail{
williamr@2: 
williamr@2: /* duplicates_operator is given a range of ordered elements and
williamr@2:  * passes only over those which are duplicated.
williamr@2:  */
williamr@2: 
williamr@2: template<typename Node,typename Predicate>
williamr@2: class duplicates_iterator
williamr@2: {
williamr@2: public:
williamr@2:   typedef typename Node::value_type        value_type;
williamr@2:   typedef std::ptrdiff_t                   difference_type;
williamr@2:   typedef const typename Node::value_type* pointer;
williamr@2:   typedef const typename Node::value_type& reference;
williamr@2:   typedef std::forward_iterator_tag        iterator_category;
williamr@2: 
williamr@2:   duplicates_iterator(Node* node_,Node* end_,Predicate pred_):
williamr@2:     node(node_),begin_chunk(0),end(end_),pred(pred_)
williamr@2:   {
williamr@2:     advance();
williamr@2:   }
williamr@2: 
williamr@2:   duplicates_iterator(Node* end_,Predicate pred_):
williamr@2:     node(end_),begin_chunk(end_),end(end_),pred(pred_)
williamr@2:   {
williamr@2:   }
williamr@2: 
williamr@2:   reference operator*()const
williamr@2:   {
williamr@2:     return node->value();
williamr@2:   }
williamr@2: 
williamr@2:   pointer operator->()const
williamr@2:   {
williamr@2:     return &node->value();
williamr@2:   }
williamr@2: 
williamr@2:   duplicates_iterator& operator++()
williamr@2:   {
williamr@2:     Node::increment(node);
williamr@2:     sync();
williamr@2:     return *this;
williamr@2:   }
williamr@2: 
williamr@2:   duplicates_iterator operator++(int)
williamr@2:   {
williamr@2:     duplicates_iterator tmp(*this);
williamr@2:     ++(*this);
williamr@2:     return tmp;
williamr@2:   }
williamr@2: 
williamr@2:   Node* get_node()const{return node;}
williamr@2: 
williamr@2: private:
williamr@2:   void sync()
williamr@2:   {
williamr@2:     if(node!=end&&pred(begin_chunk->value(),node->value()))advance();
williamr@2:   }
williamr@2: 
williamr@2:   void advance()
williamr@2:   {
williamr@2:     for(Node* node2=node;node!=end;node=node2){
williamr@2:       Node::increment(node2);
williamr@2:       if(node2!=end&&!pred(node->value(),node2->value()))break;
williamr@2:     }
williamr@2:     begin_chunk=node;
williamr@2:   }
williamr@2: 
williamr@2:   Node*     node;
williamr@2:   Node*     begin_chunk;
williamr@2:   Node*     end;
williamr@2:   Predicate pred;
williamr@2: };
williamr@2: 
williamr@2: template<typename Node,typename Predicate>
williamr@2: bool operator==(
williamr@2:   const duplicates_iterator<Node,Predicate>& x,
williamr@2:   const duplicates_iterator<Node,Predicate>& y)
williamr@2: {
williamr@2:   return x.get_node()==y.get_node();
williamr@2: }
williamr@2: 
williamr@2: template<typename Node,typename Predicate>
williamr@2: bool operator!=(
williamr@2:   const duplicates_iterator<Node,Predicate>& x,
williamr@2:   const duplicates_iterator<Node,Predicate>& y)
williamr@2: {
williamr@2:   return !(x==y);
williamr@2: }
williamr@2: 
williamr@2: } /* namespace multi_index::detail */
williamr@2: 
williamr@2: } /* namespace multi_index */
williamr@2: 
williamr@2: } /* namespace boost */
williamr@2: 
williamr@2: #endif