seq_index_node.hpp 5.3 KB

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