seq_index_node.hpp 5.5 KB

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