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