seq_index_node.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* Copyright 2003-2008 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_NODE_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_NODE_HPP
  10. #if defined(_MSC_VER)&&(_MSC_VER>=1200)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <algorithm>
  15. #include <boost/detail/allocator_utilities.hpp>
  16. #include <boost/multi_index/detail/prevent_eti.hpp>
  17. namespace boost{
  18. namespace multi_index{
  19. namespace detail{
  20. /* doubly-linked node for use by sequenced_index */
  21. template<typename Allocator>
  22. struct sequenced_index_node_impl
  23. {
  24. typedef typename prevent_eti<
  25. Allocator,
  26. typename boost::detail::allocator::rebind_to<
  27. Allocator,sequenced_index_node_impl
  28. >::type
  29. >::type::pointer pointer;
  30. typedef typename prevent_eti<
  31. Allocator,
  32. typename boost::detail::allocator::rebind_to<
  33. Allocator,sequenced_index_node_impl
  34. >::type
  35. >::type::const_pointer const_pointer;
  36. pointer& prior(){return prior_;}
  37. pointer prior()const{return prior_;}
  38. pointer& next(){return next_;}
  39. pointer next()const{return next_;}
  40. /* interoperability with bidir_node_iterator */
  41. static void increment(pointer& x){x=x->next();}
  42. static void decrement(pointer& x){x=x->prior();}
  43. /* algorithmic stuff */
  44. static void link(pointer x,pointer header)
  45. {
  46. x->prior()=header->prior();
  47. x->next()=header;
  48. x->prior()->next()=x->next()->prior()=x;
  49. };
  50. static void unlink(pointer x)
  51. {
  52. x->prior()->next()=x->next();
  53. x->next()->prior()=x->prior();
  54. }
  55. static void relink(pointer position,pointer x)
  56. {
  57. unlink(x);
  58. x->prior()=position->prior();
  59. x->next()=position;
  60. x->prior()->next()=x->next()->prior()=x;
  61. }
  62. static void relink(pointer position,pointer x,pointer y)
  63. {
  64. /* position is assumed not to be in [x,y) */
  65. if(x!=y){
  66. pointer z=y->prior();
  67. x->prior()->next()=y;
  68. y->prior()=x->prior();
  69. x->prior()=position->prior();
  70. z->next()=position;
  71. x->prior()->next()=x;
  72. z->next()->prior()=z;
  73. }
  74. }
  75. static void reverse(pointer header)
  76. {
  77. pointer x=header;
  78. do{
  79. pointer y=x->next();
  80. std::swap(x->prior(),x->next());
  81. x=y;
  82. }while(x!=header);
  83. }
  84. static void swap(pointer x,pointer y)
  85. {
  86. /* This swap function does not exchange the header nodes,
  87. * but rather their pointers. This is *not* used for implementing
  88. * sequenced_index::swap.
  89. */
  90. if(x->next()!=x){
  91. if(y->next()!=y){
  92. std::swap(x->next(),y->next());
  93. std::swap(x->prior(),y->prior());
  94. x->next()->prior()=x->prior()->next()=x;
  95. y->next()->prior()=y->prior()->next()=y;
  96. }
  97. else{
  98. y->next()=x->next();
  99. y->prior()=x->prior();
  100. x->next()=x->prior()=x;
  101. y->next()->prior()=y->prior()->next()=y;
  102. }
  103. }
  104. else if(y->next()!=y){
  105. x->next()=y->next();
  106. x->prior()=y->prior();
  107. y->next()=y->prior()=y;
  108. x->next()->prior()=x->prior()->next()=x;
  109. }
  110. }
  111. private:
  112. pointer prior_;
  113. pointer next_;
  114. };
  115. template<typename Super>
  116. struct sequenced_index_node_trampoline:
  117. prevent_eti<
  118. Super,
  119. sequenced_index_node_impl<
  120. typename boost::detail::allocator::rebind_to<
  121. typename Super::allocator_type,
  122. char
  123. >::type
  124. >
  125. >::type
  126. {
  127. typedef typename prevent_eti<
  128. Super,
  129. sequenced_index_node_impl<
  130. typename boost::detail::allocator::rebind_to<
  131. typename Super::allocator_type,
  132. char
  133. >::type
  134. >
  135. >::type impl_type;
  136. };
  137. template<typename Super>
  138. struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
  139. {
  140. private:
  141. typedef sequenced_index_node_trampoline<Super> trampoline;
  142. public:
  143. typedef typename trampoline::impl_type impl_type;
  144. typedef typename trampoline::pointer impl_pointer;
  145. typedef typename trampoline::const_pointer const_impl_pointer;
  146. impl_pointer& prior(){return trampoline::prior();}
  147. impl_pointer prior()const{return trampoline::prior();}
  148. impl_pointer& next(){return trampoline::next();}
  149. impl_pointer next()const{return trampoline::next();}
  150. impl_pointer impl()
  151. {
  152. return static_cast<impl_pointer>(
  153. static_cast<impl_type*>(static_cast<trampoline*>(this)));
  154. }
  155. const_impl_pointer impl()const
  156. {
  157. return static_cast<const_impl_pointer>(
  158. static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
  159. }
  160. static sequenced_index_node* from_impl(impl_pointer x)
  161. {
  162. return static_cast<sequenced_index_node*>(
  163. static_cast<trampoline*>(&*x));
  164. }
  165. static const sequenced_index_node* from_impl(const_impl_pointer x)
  166. {
  167. return static_cast<const sequenced_index_node*>(
  168. static_cast<const trampoline*>(&*x));
  169. }
  170. /* interoperability with bidir_node_iterator */
  171. static void increment(sequenced_index_node*& x)
  172. {
  173. impl_pointer xi=x->impl();
  174. trampoline::increment(xi);
  175. x=from_impl(xi);
  176. }
  177. static void decrement(sequenced_index_node*& x)
  178. {
  179. impl_pointer xi=x->impl();
  180. trampoline::decrement(xi);
  181. x=from_impl(xi);
  182. }
  183. };
  184. } /* namespace multi_index::detail */
  185. } /* namespace multi_index */
  186. } /* namespace boost */
  187. #endif