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
							 |