/* Copyright 2003-2005 Joaquín M López Muñoz.

 * Distributed under 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)

 *

 * See http://www.boost.org/libs/multi_index for library home page.

 */



#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_HPP

#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_HPP



#if defined(_MSC_VER)&&(_MSC_VER>=1200)

#pragma once

#endif



#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */

#include <boost/detail/workaround.hpp>

#include <boost/multi_index/detail/index_iterator_fwd.hpp>

#include <boost/multi_index/detail/index_proxy.hpp>

#include <boost/multi_index/detail/safe_mode.hpp>

#include <boost/operators.hpp>



#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)

#include <boost/serialization/nvp.hpp>

#include <boost/serialization/split_member.hpp>

#endif



namespace boost{



namespace multi_index{



namespace detail{



/* An iterator template for nodes of multi_index::detail::index.

 * Built with the aid boost::bidirectional_iterator_helper from

 * boost/operators.hpp.

 */



#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)

#if BOOST_WORKAROUND(BOOST_MSVC,<1300)

template<typename Node>

class index_iterator:

  public boost::bidirectional_iterator_helper<

    index_iterator<Node>,

    typename Node::value_type,

    std::ptrdiff_t,

    const typename Node::value_type*,

    const typename Node::value_type&>,

  public safe_iterator<index_proxy<Node> >

#else

template<typename Node,typename Container>

class index_iterator:

  public boost::bidirectional_iterator_helper<

    index_iterator<Node,Container>,

    typename Node::value_type,

    std::ptrdiff_t,

    const typename Node::value_type*,

    const typename Node::value_type&>,

  public safe_iterator<Container>

#endif

#else

template<typename Node>

class index_iterator:

  public boost::bidirectional_iterator_helper<

    index_iterator<Node>,

    typename Node::value_type,

    std::ptrdiff_t,

    const typename Node::value_type*,

    const typename Node::value_type&>

#endif



{

#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)

public:



#if BOOST_WORKAROUND(BOOST_MSVC,<1300)

  typedef index_proxy<Node> container_type;

#else

  typedef Container         container_type;

#endif



private:

  typedef safe_iterator<container_type> safe_super;



public:

  index_iterator():node(0){}

  index_iterator(Node* node_,container_type* cont_):

    safe_super(cont_),node(node_){}



  index_iterator& operator=(const index_iterator& x)

  {

    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);

    safe_super::operator=(x);

    node=x.node;

    return *this;

  }



#else

public:

  index_iterator(){}

  index_iterator(Node* node_):node(node_){}

#endif



  const typename Node::value_type& operator*()const

  {

    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);

    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);

    return node->value;

  }



  index_iterator& operator++()

  {

    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);

    BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);

    Node::increment(node);

    return *this;

  }



  index_iterator& operator--()

  {

    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);

    BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(*this);

    Node::decrement(node);

    return *this;

  }



  friend bool operator==(const index_iterator& x,const index_iterator& y)

  {

    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);

    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(y);

    BOOST_MULTI_INDEX_CHECK_SAME_OWNER(x,y);

    return x.node==y.node;

  }



  /* get_node is not to be used by the user */



  Node* get_node()const{return node;}



private:

  Node* node;



#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)

  /* serialization */



  friend class boost::serialization::access;



  BOOST_SERIALIZATION_SPLIT_MEMBER()



  typedef typename Node::base_type node_base_type;



  template<class Archive>

  void save(Archive& ar,const unsigned int version)const

  {

    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);

    node_base_type* bnode=node;

    ar<<serialization::make_nvp("pointer",bnode);

  }



  template<class Archive>

  void load(Archive& ar,const unsigned int version)

  {

    node_base_type* bnode;

    ar>>serialization::make_nvp("pointer",bnode);

    node=static_cast<Node*>(bnode);



#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)

    safe_super::uncheck();

#endif



  }

#endif

};



} /* namespace multi_index::detail */



} /* namespace multi_index */



} /* namespace boost */



#endif

