218 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
/* Copyright 2003-2015 Joaquin M Lopez Munoz.
 | 
						|
 * 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_SEQ_INDEX_NODE_HPP
 | 
						|
#define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_NODE_HPP
 | 
						|
 | 
						|
#if defined(_MSC_VER)
 | 
						|
#pragma once
 | 
						|
#endif
 | 
						|
 | 
						|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
 | 
						|
#include <algorithm>
 | 
						|
#include <boost/detail/allocator_utilities.hpp>
 | 
						|
#include <boost/multi_index/detail/raw_ptr.hpp>
 | 
						|
 | 
						|
namespace boost{
 | 
						|
 | 
						|
namespace multi_index{
 | 
						|
 | 
						|
namespace detail{
 | 
						|
 | 
						|
/* doubly-linked node for use by sequenced_index */
 | 
						|
 | 
						|
template<typename Allocator>
 | 
						|
struct sequenced_index_node_impl
 | 
						|
{
 | 
						|
  typedef typename
 | 
						|
  boost::detail::allocator::rebind_to<
 | 
						|
    Allocator,sequenced_index_node_impl
 | 
						|
  >::type::pointer                      pointer;
 | 
						|
  typedef typename
 | 
						|
  boost::detail::allocator::rebind_to<
 | 
						|
    Allocator,sequenced_index_node_impl
 | 
						|
  >::type::const_pointer                const_pointer;
 | 
						|
 | 
						|
  pointer& prior(){return prior_;}
 | 
						|
  pointer  prior()const{return prior_;}
 | 
						|
  pointer& next(){return next_;}
 | 
						|
  pointer  next()const{return next_;}
 | 
						|
 | 
						|
  /* interoperability with bidir_node_iterator */
 | 
						|
 | 
						|
  static void increment(pointer& x){x=x->next();}
 | 
						|
  static void decrement(pointer& x){x=x->prior();}
 | 
						|
 | 
						|
  /* algorithmic stuff */
 | 
						|
 | 
						|
  static void link(pointer x,pointer header)
 | 
						|
  {
 | 
						|
    x->prior()=header->prior();
 | 
						|
    x->next()=header;
 | 
						|
    x->prior()->next()=x->next()->prior()=x;
 | 
						|
  };
 | 
						|
 | 
						|
  static void unlink(pointer x)
 | 
						|
  {
 | 
						|
    x->prior()->next()=x->next();
 | 
						|
    x->next()->prior()=x->prior();
 | 
						|
  }
 | 
						|
 | 
						|
  static void relink(pointer position,pointer x)
 | 
						|
  {
 | 
						|
    unlink(x);
 | 
						|
    x->prior()=position->prior();
 | 
						|
    x->next()=position;
 | 
						|
    x->prior()->next()=x->next()->prior()=x;
 | 
						|
  }
 | 
						|
 | 
						|
  static void relink(pointer position,pointer x,pointer y)
 | 
						|
  {
 | 
						|
    /* position is assumed not to be in [x,y) */
 | 
						|
 | 
						|
    if(x!=y){
 | 
						|
      pointer z=y->prior();
 | 
						|
      x->prior()->next()=y;
 | 
						|
      y->prior()=x->prior();
 | 
						|
      x->prior()=position->prior();
 | 
						|
      z->next()=position;
 | 
						|
      x->prior()->next()=x;
 | 
						|
      z->next()->prior()=z;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  static void reverse(pointer header)
 | 
						|
  {
 | 
						|
    pointer x=header;
 | 
						|
    do{
 | 
						|
      pointer y=x->next();
 | 
						|
      std::swap(x->prior(),x->next());
 | 
						|
      x=y;
 | 
						|
    }while(x!=header);
 | 
						|
  }
 | 
						|
 | 
						|
  static void swap(pointer x,pointer y)
 | 
						|
  {
 | 
						|
    /* This swap function does not exchange the header nodes,
 | 
						|
     * but rather their pointers. This is *not* used for implementing
 | 
						|
     * sequenced_index::swap.
 | 
						|
     */
 | 
						|
 | 
						|
    if(x->next()!=x){
 | 
						|
      if(y->next()!=y){
 | 
						|
        std::swap(x->next(),y->next());
 | 
						|
        std::swap(x->prior(),y->prior());
 | 
						|
        x->next()->prior()=x->prior()->next()=x;
 | 
						|
        y->next()->prior()=y->prior()->next()=y;
 | 
						|
      }
 | 
						|
      else{
 | 
						|
        y->next()=x->next();
 | 
						|
        y->prior()=x->prior();
 | 
						|
        x->next()=x->prior()=x;
 | 
						|
        y->next()->prior()=y->prior()->next()=y;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else if(y->next()!=y){
 | 
						|
      x->next()=y->next();
 | 
						|
      x->prior()=y->prior();
 | 
						|
      y->next()=y->prior()=y;
 | 
						|
      x->next()->prior()=x->prior()->next()=x;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  pointer prior_;
 | 
						|
  pointer next_;
 | 
						|
};
 | 
						|
 | 
						|
template<typename Super>
 | 
						|
struct sequenced_index_node_trampoline:
 | 
						|
  sequenced_index_node_impl<
 | 
						|
    typename boost::detail::allocator::rebind_to<
 | 
						|
      typename Super::allocator_type,
 | 
						|
      char
 | 
						|
    >::type
 | 
						|
  >
 | 
						|
{
 | 
						|
  typedef sequenced_index_node_impl<
 | 
						|
    typename boost::detail::allocator::rebind_to<
 | 
						|
      typename Super::allocator_type,
 | 
						|
      char
 | 
						|
    >::type
 | 
						|
  > impl_type;
 | 
						|
};
 | 
						|
 | 
						|
template<typename Super>
 | 
						|
struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
 | 
						|
{
 | 
						|
private:
 | 
						|
  typedef sequenced_index_node_trampoline<Super> trampoline;
 | 
						|
 | 
						|
public:
 | 
						|
  typedef typename trampoline::impl_type         impl_type;
 | 
						|
  typedef typename trampoline::pointer           impl_pointer;
 | 
						|
  typedef typename trampoline::const_pointer     const_impl_pointer;
 | 
						|
 | 
						|
  impl_pointer& prior(){return trampoline::prior();}
 | 
						|
  impl_pointer  prior()const{return trampoline::prior();}
 | 
						|
  impl_pointer& next(){return trampoline::next();}
 | 
						|
  impl_pointer  next()const{return trampoline::next();}
 | 
						|
 | 
						|
  impl_pointer impl()
 | 
						|
  {
 | 
						|
    return static_cast<impl_pointer>(
 | 
						|
      static_cast<impl_type*>(static_cast<trampoline*>(this)));
 | 
						|
  }
 | 
						|
 | 
						|
  const_impl_pointer impl()const
 | 
						|
  {
 | 
						|
    return static_cast<const_impl_pointer>(
 | 
						|
      static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
 | 
						|
  }
 | 
						|
 | 
						|
  static sequenced_index_node* from_impl(impl_pointer x)
 | 
						|
  {
 | 
						|
    return
 | 
						|
      static_cast<sequenced_index_node*>(
 | 
						|
        static_cast<trampoline*>(
 | 
						|
          raw_ptr<impl_type*>(x)));
 | 
						|
  }
 | 
						|
 | 
						|
  static const sequenced_index_node* from_impl(const_impl_pointer x)
 | 
						|
  {
 | 
						|
    return
 | 
						|
      static_cast<const sequenced_index_node*>(
 | 
						|
        static_cast<const trampoline*>(
 | 
						|
          raw_ptr<const impl_type*>(x)));
 | 
						|
  }
 | 
						|
 | 
						|
  /* interoperability with bidir_node_iterator */
 | 
						|
 | 
						|
  static void increment(sequenced_index_node*& x)
 | 
						|
  {
 | 
						|
    impl_pointer xi=x->impl();
 | 
						|
    trampoline::increment(xi);
 | 
						|
    x=from_impl(xi);
 | 
						|
  }
 | 
						|
 | 
						|
  static void decrement(sequenced_index_node*& x)
 | 
						|
  {
 | 
						|
    impl_pointer xi=x->impl();
 | 
						|
    trampoline::decrement(xi);
 | 
						|
    x=from_impl(xi);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
} /* namespace multi_index::detail */
 | 
						|
 | 
						|
} /* namespace multi_index */
 | 
						|
 | 
						|
} /* namespace boost */
 | 
						|
 | 
						|
#endif
 |