/src/boost/boost/multi_index/detail/ord_index_node.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright 2003-2020 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 | | * The internal implementation of red-black trees is based on that of SGI STL |
9 | | * stl_tree.h file: |
10 | | * |
11 | | * Copyright (c) 1996,1997 |
12 | | * Silicon Graphics Computer Systems, Inc. |
13 | | * |
14 | | * Permission to use, copy, modify, distribute and sell this software |
15 | | * and its documentation for any purpose is hereby granted without fee, |
16 | | * provided that the above copyright notice appear in all copies and |
17 | | * that both that copyright notice and this permission notice appear |
18 | | * in supporting documentation. Silicon Graphics makes no |
19 | | * representations about the suitability of this software for any |
20 | | * purpose. It is provided "as is" without express or implied warranty. |
21 | | * |
22 | | * |
23 | | * Copyright (c) 1994 |
24 | | * Hewlett-Packard Company |
25 | | * |
26 | | * Permission to use, copy, modify, distribute and sell this software |
27 | | * and its documentation for any purpose is hereby granted without fee, |
28 | | * provided that the above copyright notice appear in all copies and |
29 | | * that both that copyright notice and this permission notice appear |
30 | | * in supporting documentation. Hewlett-Packard Company makes no |
31 | | * representations about the suitability of this software for any |
32 | | * purpose. It is provided "as is" without express or implied warranty. |
33 | | * |
34 | | */ |
35 | | |
36 | | #ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP |
37 | | #define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP |
38 | | |
39 | | #if defined(_MSC_VER) |
40 | | #pragma once |
41 | | #endif |
42 | | |
43 | | #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
44 | | #include <cstddef> |
45 | | #include <boost/multi_index/detail/allocator_traits.hpp> |
46 | | #include <boost/multi_index/detail/raw_ptr.hpp> |
47 | | |
48 | | #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES) |
49 | | #include <boost/mpl/and.hpp> |
50 | | #include <boost/mpl/if.hpp> |
51 | | #include <boost/multi_index/detail/uintptr_type.hpp> |
52 | | #include <boost/type_traits/alignment_of.hpp> |
53 | | #include <boost/type_traits/is_same.hpp> |
54 | | #endif |
55 | | |
56 | | namespace boost{ |
57 | | |
58 | | namespace multi_index{ |
59 | | |
60 | | namespace detail{ |
61 | | |
62 | | /* definition of red-black nodes for ordered_index */ |
63 | | |
64 | | enum ordered_index_color{red=false,black=true}; |
65 | | enum ordered_index_side{to_left=false,to_right=true}; |
66 | | |
67 | | template<typename AugmentPolicy,typename Allocator> |
68 | | struct ordered_index_node_impl; /* fwd decl. */ |
69 | | |
70 | | template<typename AugmentPolicy,typename Allocator> |
71 | | struct ordered_index_node_traits |
72 | | { |
73 | | typedef typename rebind_alloc_for< |
74 | | Allocator, |
75 | | ordered_index_node_impl<AugmentPolicy,Allocator> |
76 | | >::type allocator; |
77 | | typedef allocator_traits<allocator> alloc_traits; |
78 | | typedef typename alloc_traits::pointer pointer; |
79 | | typedef typename alloc_traits::const_pointer const_pointer; |
80 | | typedef typename alloc_traits::difference_type difference_type; |
81 | | typedef typename alloc_traits::size_type size_type; |
82 | | }; |
83 | | |
84 | | template<typename AugmentPolicy,typename Allocator> |
85 | | struct ordered_index_node_std_base |
86 | | { |
87 | | typedef ordered_index_node_traits< |
88 | | AugmentPolicy,Allocator> node_traits; |
89 | | typedef typename node_traits::allocator node_allocator; |
90 | | typedef typename node_traits::pointer pointer; |
91 | | typedef typename node_traits::const_pointer const_pointer; |
92 | | typedef typename node_traits::difference_type difference_type; |
93 | | typedef typename node_traits::size_type size_type; |
94 | | typedef ordered_index_color& color_ref; |
95 | | typedef pointer& parent_ref; |
96 | | |
97 | | ordered_index_color& color(){return color_;} |
98 | | ordered_index_color color()const{return color_;} |
99 | | pointer& parent(){return parent_;} |
100 | | pointer parent()const{return parent_;} |
101 | | pointer& left(){return left_;} |
102 | | pointer left()const{return left_;} |
103 | | pointer& right(){return right_;} |
104 | | pointer right()const{return right_;} |
105 | | |
106 | | private: |
107 | | ordered_index_color color_; |
108 | | pointer parent_; |
109 | | pointer left_; |
110 | | pointer right_; |
111 | | }; |
112 | | |
113 | | #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES) |
114 | | /* If ordered_index_node_impl has even alignment, we can use the least |
115 | | * significant bit of one of the ordered_index_node_impl pointers to |
116 | | * store color information. This typically reduces the size of |
117 | | * ordered_index_node_impl by 25%. |
118 | | */ |
119 | | |
120 | | #if defined(BOOST_MSVC) |
121 | | /* This code casts pointers to an integer type that has been computed |
122 | | * to be large enough to hold the pointer, however the metaprogramming |
123 | | * logic is not always spotted by the VC++ code analyser that issues a |
124 | | * long list of warnings. |
125 | | */ |
126 | | |
127 | | #pragma warning(push) |
128 | | #pragma warning(disable:4312 4311) |
129 | | #endif |
130 | | |
131 | | template<typename AugmentPolicy,typename Allocator> |
132 | | struct ordered_index_node_compressed_base |
133 | | { |
134 | | typedef ordered_index_node_traits< |
135 | | AugmentPolicy,Allocator> node_traits; |
136 | | typedef ordered_index_node_impl< |
137 | | AugmentPolicy,Allocator>* pointer; |
138 | | typedef const ordered_index_node_impl< |
139 | | AugmentPolicy,Allocator>* const_pointer; |
140 | | typedef typename node_traits::difference_type difference_type; |
141 | | typedef typename node_traits::size_type size_type; |
142 | | |
143 | | struct color_ref |
144 | | { |
145 | 203k | color_ref(uintptr_type* r_):r(r_){} |
146 | | color_ref(const color_ref& x):r(x.r){} |
147 | | |
148 | | operator ordered_index_color()const |
149 | 46.7k | { |
150 | 46.7k | return ordered_index_color(*r&uintptr_type(1)); |
151 | 46.7k | } |
152 | | |
153 | | color_ref& operator=(ordered_index_color c) |
154 | 156k | { |
155 | 156k | *r&=~uintptr_type(1); |
156 | 156k | *r|=uintptr_type(c); |
157 | 156k | return *this; |
158 | 156k | } |
159 | | |
160 | | color_ref& operator=(const color_ref& x) |
161 | 1.45k | { |
162 | 1.45k | return operator=(x.operator ordered_index_color()); |
163 | 1.45k | } |
164 | | |
165 | | private: |
166 | | uintptr_type* r; |
167 | | }; |
168 | | |
169 | | struct parent_ref |
170 | | { |
171 | 511k | parent_ref(uintptr_type* r_):r(r_){} |
172 | 12.3k | parent_ref(const parent_ref& x):r(x.r){} |
173 | | |
174 | | operator pointer()const |
175 | 432k | { |
176 | 432k | return (pointer)(void*)(*r&~uintptr_type(1)); |
177 | 432k | } |
178 | | |
179 | | parent_ref& operator=(pointer p) |
180 | 135k | { |
181 | 135k | *r=((uintptr_type)(void*)p)|(*r&uintptr_type(1)); |
182 | 135k | return *this; |
183 | 135k | } |
184 | | |
185 | | parent_ref& operator=(const parent_ref& x) |
186 | 13.8k | { |
187 | 13.8k | return operator=(x.operator pointer()); |
188 | 13.8k | } |
189 | | |
190 | | pointer operator->()const |
191 | 202k | { |
192 | 202k | return operator pointer(); |
193 | 202k | } |
194 | | |
195 | | private: |
196 | | uintptr_type* r; |
197 | | }; |
198 | | |
199 | 203k | color_ref color(){return color_ref(&parentcolor_);} |
200 | | ordered_index_color color()const |
201 | | { |
202 | | return ordered_index_color(parentcolor_&uintptr_type(1)); |
203 | | } |
204 | | |
205 | 511k | parent_ref parent(){return parent_ref(&parentcolor_);} |
206 | | pointer parent()const |
207 | | { |
208 | | return (pointer)(void*)(parentcolor_&~uintptr_type(1)); |
209 | | } |
210 | | |
211 | 275k | pointer& left(){return left_;} |
212 | | pointer left()const{return left_;} |
213 | 254k | pointer& right(){return right_;} |
214 | | pointer right()const{return right_;} |
215 | | |
216 | | private: |
217 | | uintptr_type parentcolor_; |
218 | | pointer left_; |
219 | | pointer right_; |
220 | | }; |
221 | | #if defined(BOOST_MSVC) |
222 | | #pragma warning(pop) |
223 | | #endif |
224 | | #endif |
225 | | |
226 | | template<typename AugmentPolicy,typename Allocator> |
227 | | struct ordered_index_node_impl_base: |
228 | | |
229 | | #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES) |
230 | | AugmentPolicy::template augmented_node< |
231 | | typename mpl::if_c< |
232 | | !(has_uintptr_type::value)|| |
233 | | (alignment_of< |
234 | | ordered_index_node_compressed_base<AugmentPolicy,Allocator> |
235 | | >::value%2)|| |
236 | | !(is_same< |
237 | | typename ordered_index_node_traits<AugmentPolicy,Allocator>::pointer, |
238 | | ordered_index_node_impl<AugmentPolicy,Allocator>*>::value), |
239 | | ordered_index_node_std_base<AugmentPolicy,Allocator>, |
240 | | ordered_index_node_compressed_base<AugmentPolicy,Allocator> |
241 | | >::type |
242 | | >::type |
243 | | #else |
244 | | AugmentPolicy::template augmented_node< |
245 | | ordered_index_node_std_base<AugmentPolicy,Allocator> |
246 | | >::type |
247 | | #endif |
248 | | |
249 | | {}; |
250 | | |
251 | | template<typename AugmentPolicy,typename Allocator> |
252 | | struct ordered_index_node_impl: |
253 | | ordered_index_node_impl_base<AugmentPolicy,Allocator> |
254 | | { |
255 | | private: |
256 | | typedef ordered_index_node_impl_base<AugmentPolicy,Allocator> super; |
257 | | |
258 | | public: |
259 | | typedef typename super::color_ref color_ref; |
260 | | typedef typename super::parent_ref parent_ref; |
261 | | typedef typename super::pointer pointer; |
262 | | typedef typename super::const_pointer const_pointer; |
263 | | |
264 | | /* interoperability with bidir_node_iterator */ |
265 | | |
266 | | static void increment(pointer& x) |
267 | | { |
268 | | if(x->right()!=pointer(0)){ |
269 | | x=x->right(); |
270 | | while(x->left()!=pointer(0))x=x->left(); |
271 | | } |
272 | | else{ |
273 | | pointer y=x->parent(); |
274 | | while(x==y->right()){ |
275 | | x=y; |
276 | | y=y->parent(); |
277 | | } |
278 | | if(x->right()!=y)x=y; |
279 | | } |
280 | | } |
281 | | |
282 | | static void decrement(pointer& x) |
283 | | { |
284 | | if(x->color()==red&&x->parent()->parent()==x){ |
285 | | x=x->right(); |
286 | | } |
287 | | else if(x->left()!=pointer(0)){ |
288 | | pointer y=x->left(); |
289 | | while(y->right()!=pointer(0))y=y->right(); |
290 | | x=y; |
291 | | }else{ |
292 | | pointer y=x->parent(); |
293 | | while(x==y->left()){ |
294 | | x=y; |
295 | | y=y->parent(); |
296 | | } |
297 | | x=y; |
298 | | } |
299 | | } |
300 | | |
301 | | /* algorithmic stuff */ |
302 | | |
303 | | static void rotate_left(pointer x,parent_ref root) |
304 | 6.17k | { |
305 | 6.17k | pointer y=x->right(); |
306 | 6.17k | x->right()=y->left(); |
307 | 6.17k | if(y->left()!=pointer(0))y->left()->parent()=x; |
308 | 6.17k | y->parent()=x->parent(); |
309 | | |
310 | 6.17k | if(x==root) root=y; |
311 | 5.08k | else if(x==x->parent()->left())x->parent()->left()=y; |
312 | 1.59k | else x->parent()->right()=y; |
313 | 6.17k | y->left()=x; |
314 | 6.17k | x->parent()=y; |
315 | 6.17k | AugmentPolicy::rotate_left(x,y); |
316 | 6.17k | } |
317 | | |
318 | | static pointer minimum(pointer x) |
319 | 0 | { |
320 | 0 | while(x->left()!=pointer(0))x=x->left(); |
321 | 0 | return x; |
322 | 0 | } |
323 | | |
324 | | static pointer maximum(pointer x) |
325 | 0 | { |
326 | 0 | while(x->right()!=pointer(0))x=x->right(); |
327 | 0 | return x; |
328 | 0 | } |
329 | | |
330 | | static void rotate_right(pointer x,parent_ref root) |
331 | 6.17k | { |
332 | 6.17k | pointer y=x->left(); |
333 | 6.17k | x->left()=y->right(); |
334 | 6.17k | if(y->right()!=pointer(0))y->right()->parent()=x; |
335 | 6.17k | y->parent()=x->parent(); |
336 | | |
337 | 6.17k | if(x==root) root=y; |
338 | 5.11k | else if(x==x->parent()->right())x->parent()->right()=y; |
339 | 1.72k | else x->parent()->left()=y; |
340 | 6.17k | y->right()=x; |
341 | 6.17k | x->parent()=y; |
342 | 6.17k | AugmentPolicy::rotate_right(x,y); |
343 | 6.17k | } |
344 | | |
345 | | static void rebalance(pointer x,parent_ref root) |
346 | 19.3k | { |
347 | 19.3k | x->color()=red; |
348 | 34.0k | while(x!=root&&x->parent()->color()==red){ |
349 | 14.6k | if(x->parent()==x->parent()->parent()->left()){ |
350 | 7.38k | pointer y=x->parent()->parent()->right(); |
351 | 7.38k | if(y!=pointer(0)&&y->color()==red){ |
352 | 3.20k | x->parent()->color()=black; |
353 | 3.20k | y->color()=black; |
354 | 3.20k | x->parent()->parent()->color()=red; |
355 | 3.20k | x=x->parent()->parent(); |
356 | 3.20k | } |
357 | 4.17k | else{ |
358 | 4.17k | if(x==x->parent()->right()){ |
359 | 2.15k | x=x->parent(); |
360 | 2.15k | rotate_left(x,root); |
361 | 2.15k | } |
362 | 4.17k | x->parent()->color()=black; |
363 | 4.17k | x->parent()->parent()->color()=red; |
364 | 4.17k | rotate_right(x->parent()->parent(),root); |
365 | 4.17k | } |
366 | 7.38k | } |
367 | 7.31k | else{ |
368 | 7.31k | pointer y=x->parent()->parent()->left(); |
369 | 7.31k | if(y!=pointer(0)&&y->color()==red){ |
370 | 3.29k | x->parent()->color()=black; |
371 | 3.29k | y->color()=black; |
372 | 3.29k | x->parent()->parent()->color()=red; |
373 | 3.29k | x=x->parent()->parent(); |
374 | 3.29k | } |
375 | 4.01k | else{ |
376 | 4.01k | if(x==x->parent()->left()){ |
377 | 2.00k | x=x->parent(); |
378 | 2.00k | rotate_right(x,root); |
379 | 2.00k | } |
380 | 4.01k | x->parent()->color()=black; |
381 | 4.01k | x->parent()->parent()->color()=red; |
382 | 4.01k | rotate_left(x->parent()->parent(),root); |
383 | 4.01k | } |
384 | 7.31k | } |
385 | 14.6k | } |
386 | 19.3k | root->color()=black; |
387 | 19.3k | } |
388 | | |
389 | | static void link( |
390 | | pointer x,ordered_index_side side,pointer position,pointer header) |
391 | 19.3k | { |
392 | 19.3k | if(side==to_left){ |
393 | 11.1k | position->left()=x; /* also makes leftmost=x when parent==header */ |
394 | 11.1k | if(position==header){ |
395 | 2.84k | header->parent()=x; |
396 | 2.84k | header->right()=x; |
397 | 2.84k | } |
398 | 8.29k | else if(position==header->left()){ |
399 | 3.01k | header->left()=x; /* maintain leftmost pointing to min node */ |
400 | 3.01k | } |
401 | 11.1k | } |
402 | 8.17k | else{ |
403 | 8.17k | position->right()=x; |
404 | 8.17k | if(position==header->right()){ |
405 | 2.76k | header->right()=x; /* maintain rightmost pointing to max node */ |
406 | 2.76k | } |
407 | 8.17k | } |
408 | 19.3k | x->parent()=position; |
409 | 19.3k | x->left()=pointer(0); |
410 | 19.3k | x->right()=pointer(0); |
411 | 19.3k | AugmentPolicy::add(x,pointer(header->parent())); |
412 | 19.3k | ordered_index_node_impl::rebalance(x,header->parent()); |
413 | 19.3k | } |
414 | | |
415 | | static pointer rebalance_for_extract( |
416 | | pointer z,parent_ref root,pointer& leftmost,pointer& rightmost) |
417 | 5.28k | { |
418 | 5.28k | pointer y=z; |
419 | 5.28k | pointer x=pointer(0); |
420 | 5.28k | pointer x_parent=pointer(0); |
421 | 5.28k | if(y->left()==pointer(0)){ /* z has at most one non-null child. y==z. */ |
422 | 3.82k | x=y->right(); /* x might be null */ |
423 | 3.82k | } |
424 | 1.45k | else{ |
425 | 1.45k | if(y->right()==pointer(0)){ /* z has exactly one non-null child. y==z. */ |
426 | 0 | x=y->left(); /* x is not null */ |
427 | 0 | } |
428 | 1.45k | else{ /* z has two non-null children. Set y to */ |
429 | 1.45k | y=y->right(); /* z's successor. x might be null. */ |
430 | 1.45k | while(y->left()!=pointer(0))y=y->left(); |
431 | 1.45k | x=y->right(); |
432 | 1.45k | } |
433 | 1.45k | } |
434 | 5.28k | AugmentPolicy::remove(y,pointer(root)); |
435 | 5.28k | if(y!=z){ |
436 | 1.45k | AugmentPolicy::copy(z,y); |
437 | 1.45k | z->left()->parent()=y; /* relink y in place of z. y is z's successor */ |
438 | 1.45k | y->left()=z->left(); |
439 | 1.45k | if(y!=z->right()){ |
440 | 0 | x_parent=y->parent(); |
441 | 0 | if(x!=pointer(0))x->parent()=y->parent(); |
442 | 0 | y->parent()->left()=x; /* y must be a child of left */ |
443 | 0 | y->right()=z->right(); |
444 | 0 | z->right()->parent()=y; |
445 | 0 | } |
446 | 1.45k | else{ |
447 | 1.45k | x_parent=y; |
448 | 1.45k | } |
449 | | |
450 | 1.45k | if(root==z) root=y; |
451 | 882 | else if(z->parent()->left()==z)z->parent()->left()=y; |
452 | 293 | else z->parent()->right()=y; |
453 | 1.45k | y->parent()=z->parent(); |
454 | 1.45k | ordered_index_color c=y->color(); |
455 | 1.45k | y->color()=z->color(); |
456 | 1.45k | z->color()=c; |
457 | 1.45k | y=z; /* y now points to node to be actually deleted */ |
458 | 1.45k | } |
459 | 3.82k | else{ /* y==z */ |
460 | 3.82k | x_parent=y->parent(); |
461 | 3.82k | if(x!=pointer(0))x->parent()=y->parent(); |
462 | 3.82k | if(root==z){ |
463 | 1.18k | root=x; |
464 | 1.18k | } |
465 | 2.64k | else{ |
466 | 2.64k | if(z->parent()->left()==z)z->parent()->left()=x; |
467 | 688 | else z->parent()->right()=x; |
468 | 2.64k | } |
469 | 3.82k | if(leftmost==z){ |
470 | 2.79k | if(z->right()==pointer(0)){ /* z->left() must be null also */ |
471 | 2.79k | leftmost=z->parent(); |
472 | 2.79k | } |
473 | 0 | else{ |
474 | 0 | leftmost=minimum(x); /* makes leftmost==header if z==root */ |
475 | 0 | } |
476 | 2.79k | } |
477 | 3.82k | if(rightmost==z){ |
478 | 1.86k | if(z->left()==pointer(0)){ /* z->right() must be null also */ |
479 | 1.86k | rightmost=z->parent(); |
480 | 1.86k | } |
481 | 0 | else{ /* x==z->left() */ |
482 | 0 | rightmost=maximum(x); /* makes rightmost==header if z==root */ |
483 | 0 | } |
484 | 1.86k | } |
485 | 3.82k | } |
486 | 5.28k | if(y->color()!=red){ |
487 | 1.18k | while(x!=root&&(x==pointer(0)|| x->color()==black)){ |
488 | 0 | if(x==x_parent->left()){ |
489 | 0 | pointer w=x_parent->right(); |
490 | 0 | if(w->color()==red){ |
491 | 0 | w->color()=black; |
492 | 0 | x_parent->color()=red; |
493 | 0 | rotate_left(x_parent,root); |
494 | 0 | w=x_parent->right(); |
495 | 0 | } |
496 | 0 | if((w->left()==pointer(0)||w->left()->color()==black) && |
497 | 0 | (w->right()==pointer(0)||w->right()->color()==black)){ |
498 | 0 | w->color()=red; |
499 | 0 | x=x_parent; |
500 | 0 | x_parent=x_parent->parent(); |
501 | 0 | } |
502 | 0 | else{ |
503 | 0 | if(w->right()==pointer(0 ) |
504 | 0 | || w->right()->color()==black){ |
505 | 0 | if(w->left()!=pointer(0)) w->left()->color()=black; |
506 | 0 | w->color()=red; |
507 | 0 | rotate_right(w,root); |
508 | 0 | w=x_parent->right(); |
509 | 0 | } |
510 | 0 | w->color()=x_parent->color(); |
511 | 0 | x_parent->color()=black; |
512 | 0 | if(w->right()!=pointer(0))w->right()->color()=black; |
513 | 0 | rotate_left(x_parent,root); |
514 | 0 | break; |
515 | 0 | } |
516 | 0 | } |
517 | 0 | else{ /* same as above,with right <-> left */ |
518 | 0 | pointer w=x_parent->left(); |
519 | 0 | if(w->color()==red){ |
520 | 0 | w->color()=black; |
521 | 0 | x_parent->color()=red; |
522 | 0 | rotate_right(x_parent,root); |
523 | 0 | w=x_parent->left(); |
524 | 0 | } |
525 | 0 | if((w->right()==pointer(0)||w->right()->color()==black) && |
526 | 0 | (w->left()==pointer(0)||w->left()->color()==black)){ |
527 | 0 | w->color()=red; |
528 | 0 | x=x_parent; |
529 | 0 | x_parent=x_parent->parent(); |
530 | 0 | } |
531 | 0 | else{ |
532 | 0 | if(w->left()==pointer(0)||w->left()->color()==black){ |
533 | 0 | if(w->right()!=pointer(0))w->right()->color()=black; |
534 | 0 | w->color()=red; |
535 | 0 | rotate_left(w,root); |
536 | 0 | w=x_parent->left(); |
537 | 0 | } |
538 | 0 | w->color()=x_parent->color(); |
539 | 0 | x_parent->color()=black; |
540 | 0 | if(w->left()!=pointer(0))w->left()->color()=black; |
541 | 0 | rotate_right(x_parent,root); |
542 | 0 | break; |
543 | 0 | } |
544 | 0 | } |
545 | 0 | } |
546 | 1.18k | if(x!=pointer(0))x->color()=black; |
547 | 1.18k | } |
548 | 5.28k | return y; |
549 | 5.28k | } |
550 | | |
551 | | static void restore(pointer x,pointer position,pointer header) |
552 | | { |
553 | | if(position->left()==pointer(0)||position->left()==header){ |
554 | | link(x,to_left,position,header); |
555 | | } |
556 | | else{ |
557 | | decrement(position); |
558 | | link(x,to_right,position,header); |
559 | | } |
560 | | } |
561 | | |
562 | | #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) |
563 | | /* invariant stuff */ |
564 | | |
565 | | static std::size_t black_count(pointer node,pointer root) |
566 | | { |
567 | | if(node==pointer(0))return 0; |
568 | | std::size_t sum=0; |
569 | | for(;;){ |
570 | | if(node->color()==black)++sum; |
571 | | if(node==root)break; |
572 | | node=node->parent(); |
573 | | } |
574 | | return sum; |
575 | | } |
576 | | #endif |
577 | | }; |
578 | | |
579 | | template<typename AugmentPolicy,typename Super> |
580 | | struct ordered_index_node_trampoline: |
581 | | ordered_index_node_impl< |
582 | | AugmentPolicy, |
583 | | typename rebind_alloc_for< |
584 | | typename Super::allocator_type, |
585 | | char |
586 | | >::type |
587 | | > |
588 | | { |
589 | | typedef ordered_index_node_impl< |
590 | | AugmentPolicy, |
591 | | typename rebind_alloc_for< |
592 | | typename Super::allocator_type, |
593 | | char |
594 | | >::type |
595 | | > impl_type; |
596 | | }; |
597 | | |
598 | | template<typename AugmentPolicy,typename Super> |
599 | | struct ordered_index_node: |
600 | | Super,ordered_index_node_trampoline<AugmentPolicy,Super> |
601 | | { |
602 | | private: |
603 | | typedef ordered_index_node_trampoline<AugmentPolicy,Super> trampoline; |
604 | | |
605 | | public: |
606 | | typedef typename trampoline::impl_type impl_type; |
607 | | typedef typename trampoline::color_ref impl_color_ref; |
608 | | typedef typename trampoline::parent_ref impl_parent_ref; |
609 | | typedef typename trampoline::pointer impl_pointer; |
610 | | typedef typename trampoline::const_pointer const_impl_pointer; |
611 | | typedef typename trampoline::difference_type difference_type; |
612 | | typedef typename trampoline::size_type size_type; |
613 | | |
614 | 79.0k | impl_color_ref color(){return trampoline::color();} |
615 | | ordered_index_color color()const{return trampoline::color();} |
616 | 180k | impl_parent_ref parent(){return trampoline::parent();} |
617 | | impl_pointer parent()const{return trampoline::parent();} |
618 | 145k | impl_pointer& left(){return trampoline::left();} |
619 | | impl_pointer left()const{return trampoline::left();} |
620 | 146k | impl_pointer& right(){return trampoline::right();} |
621 | | impl_pointer right()const{return trampoline::right();} |
622 | | |
623 | | impl_pointer impl() |
624 | 221k | { |
625 | 221k | return static_cast<impl_pointer>( |
626 | 221k | static_cast<impl_type*>(static_cast<trampoline*>(this))); |
627 | 221k | } |
628 | | |
629 | | const_impl_pointer impl()const |
630 | | { |
631 | | return static_cast<const_impl_pointer>( |
632 | | static_cast<const impl_type*>(static_cast<const trampoline*>(this))); |
633 | | } |
634 | | |
635 | | static ordered_index_node* from_impl(impl_pointer x) |
636 | 219k | { |
637 | 219k | return |
638 | 219k | static_cast<ordered_index_node*>( |
639 | 219k | static_cast<trampoline*>( |
640 | 219k | raw_ptr<impl_type*>(x))); |
641 | 219k | } |
642 | | |
643 | | static const ordered_index_node* from_impl(const_impl_pointer x) |
644 | | { |
645 | | return |
646 | | static_cast<const ordered_index_node*>( |
647 | | static_cast<const trampoline*>( |
648 | | raw_ptr<const impl_type*>(x))); |
649 | | } |
650 | | |
651 | | /* interoperability with bidir_node_iterator */ |
652 | | |
653 | | static void increment(ordered_index_node*& x) |
654 | | { |
655 | | impl_pointer xi=x->impl(); |
656 | | trampoline::increment(xi); |
657 | | x=from_impl(xi); |
658 | | } |
659 | | |
660 | | static void decrement(ordered_index_node*& x) |
661 | | { |
662 | | impl_pointer xi=x->impl(); |
663 | | trampoline::decrement(xi); |
664 | | x=from_impl(xi); |
665 | | } |
666 | | }; |
667 | | |
668 | | } /* namespace multi_index::detail */ |
669 | | |
670 | | } /* namespace multi_index */ |
671 | | |
672 | | } /* namespace boost */ |
673 | | |
674 | | #endif |