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 |