annotate DEPENDENCIES/generic/include/boost/unordered/detail/equivalent.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1
Chris@16 2 // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
Chris@16 3 // Copyright (C) 2005-2011 Daniel James
Chris@16 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6
Chris@16 7 #ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
Chris@16 8 #define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
Chris@16 9
Chris@101 10 #include <boost/config.hpp>
Chris@101 11 #if defined(BOOST_HAS_PRAGMA_ONCE)
Chris@101 12 #pragma once
Chris@16 13 #endif
Chris@16 14
Chris@16 15 #include <boost/unordered/detail/table.hpp>
Chris@16 16 #include <boost/unordered/detail/extract_key.hpp>
Chris@16 17
Chris@16 18 namespace boost { namespace unordered { namespace detail {
Chris@16 19
Chris@16 20 template <typename A, typename T> struct grouped_node;
Chris@16 21 template <typename T> struct grouped_ptr_node;
Chris@16 22 template <typename Types> struct grouped_table_impl;
Chris@16 23
Chris@16 24 template <typename A, typename T>
Chris@16 25 struct grouped_node :
Chris@16 26 boost::unordered::detail::value_base<T>
Chris@16 27 {
Chris@16 28 typedef typename ::boost::unordered::detail::rebind_wrap<
Chris@16 29 A, grouped_node<A, T> >::type allocator;
Chris@16 30 typedef typename ::boost::unordered::detail::
Chris@16 31 allocator_traits<allocator>::pointer node_pointer;
Chris@16 32 typedef node_pointer link_pointer;
Chris@16 33
Chris@16 34 link_pointer next_;
Chris@16 35 node_pointer group_prev_;
Chris@16 36 std::size_t hash_;
Chris@16 37
Chris@16 38 grouped_node() :
Chris@16 39 next_(),
Chris@16 40 group_prev_(),
Chris@16 41 hash_(0)
Chris@16 42 {}
Chris@16 43
Chris@16 44 void init(node_pointer self)
Chris@16 45 {
Chris@16 46 group_prev_ = self;
Chris@16 47 }
Chris@16 48
Chris@16 49 private:
Chris@16 50 grouped_node& operator=(grouped_node const&);
Chris@16 51 };
Chris@16 52
Chris@16 53 template <typename T>
Chris@16 54 struct grouped_ptr_node :
Chris@16 55 boost::unordered::detail::ptr_bucket
Chris@16 56 {
Chris@101 57 typedef T value_type;
Chris@16 58 typedef boost::unordered::detail::ptr_bucket bucket_base;
Chris@16 59 typedef grouped_ptr_node<T>* node_pointer;
Chris@16 60 typedef ptr_bucket* link_pointer;
Chris@16 61
Chris@16 62 node_pointer group_prev_;
Chris@16 63 std::size_t hash_;
Chris@101 64 boost::unordered::detail::value_base<T> value_base_;
Chris@16 65
Chris@16 66 grouped_ptr_node() :
Chris@16 67 bucket_base(),
Chris@16 68 group_prev_(0),
Chris@16 69 hash_(0)
Chris@16 70 {}
Chris@16 71
Chris@16 72 void init(node_pointer self)
Chris@16 73 {
Chris@16 74 group_prev_ = self;
Chris@16 75 }
Chris@16 76
Chris@101 77 void* address() { return value_base_.address(); }
Chris@101 78 value_type& value() { return value_base_.value(); }
Chris@101 79 value_type* value_ptr() { return value_base_.value_ptr(); }
Chris@101 80
Chris@16 81 private:
Chris@16 82 grouped_ptr_node& operator=(grouped_ptr_node const&);
Chris@16 83 };
Chris@16 84
Chris@16 85 // If the allocator uses raw pointers use grouped_ptr_node
Chris@16 86 // Otherwise use grouped_node.
Chris@16 87
Chris@16 88 template <typename A, typename T, typename NodePtr, typename BucketPtr>
Chris@16 89 struct pick_grouped_node2
Chris@16 90 {
Chris@16 91 typedef boost::unordered::detail::grouped_node<A, T> node;
Chris@16 92
Chris@16 93 typedef typename boost::unordered::detail::allocator_traits<
Chris@16 94 typename boost::unordered::detail::rebind_wrap<A, node>::type
Chris@16 95 >::pointer node_pointer;
Chris@16 96
Chris@16 97 typedef boost::unordered::detail::bucket<node_pointer> bucket;
Chris@16 98 typedef node_pointer link_pointer;
Chris@16 99 };
Chris@16 100
Chris@16 101 template <typename A, typename T>
Chris@16 102 struct pick_grouped_node2<A, T,
Chris@16 103 boost::unordered::detail::grouped_ptr_node<T>*,
Chris@16 104 boost::unordered::detail::ptr_bucket*>
Chris@16 105 {
Chris@16 106 typedef boost::unordered::detail::grouped_ptr_node<T> node;
Chris@16 107 typedef boost::unordered::detail::ptr_bucket bucket;
Chris@16 108 typedef bucket* link_pointer;
Chris@16 109 };
Chris@16 110
Chris@16 111 template <typename A, typename T>
Chris@16 112 struct pick_grouped_node
Chris@16 113 {
Chris@16 114 typedef boost::unordered::detail::allocator_traits<
Chris@16 115 typename boost::unordered::detail::rebind_wrap<A,
Chris@16 116 boost::unordered::detail::grouped_ptr_node<T> >::type
Chris@16 117 > tentative_node_traits;
Chris@16 118
Chris@16 119 typedef boost::unordered::detail::allocator_traits<
Chris@16 120 typename boost::unordered::detail::rebind_wrap<A,
Chris@16 121 boost::unordered::detail::ptr_bucket >::type
Chris@16 122 > tentative_bucket_traits;
Chris@16 123
Chris@16 124 typedef pick_grouped_node2<A, T,
Chris@16 125 typename tentative_node_traits::pointer,
Chris@16 126 typename tentative_bucket_traits::pointer> pick;
Chris@16 127
Chris@16 128 typedef typename pick::node node;
Chris@16 129 typedef typename pick::bucket bucket;
Chris@16 130 typedef typename pick::link_pointer link_pointer;
Chris@16 131 };
Chris@16 132
Chris@16 133 template <typename A, typename T, typename H, typename P>
Chris@16 134 struct multiset
Chris@16 135 {
Chris@16 136 typedef boost::unordered::detail::multiset<A, T, H, P> types;
Chris@16 137
Chris@16 138 typedef A allocator;
Chris@16 139 typedef T value_type;
Chris@16 140 typedef H hasher;
Chris@16 141 typedef P key_equal;
Chris@16 142 typedef T key_type;
Chris@16 143
Chris@16 144 typedef boost::unordered::detail::allocator_traits<allocator> traits;
Chris@16 145 typedef boost::unordered::detail::pick_grouped_node<allocator,
Chris@16 146 value_type> pick;
Chris@16 147 typedef typename pick::node node;
Chris@16 148 typedef typename pick::bucket bucket;
Chris@16 149 typedef typename pick::link_pointer link_pointer;
Chris@16 150
Chris@16 151 typedef boost::unordered::detail::grouped_table_impl<types> table;
Chris@16 152 typedef boost::unordered::detail::set_extractor<value_type> extractor;
Chris@16 153
Chris@101 154 typedef typename boost::unordered::detail::pick_policy<T>::type policy;
Chris@16 155 };
Chris@16 156
Chris@16 157 template <typename A, typename K, typename M, typename H, typename P>
Chris@16 158 struct multimap
Chris@16 159 {
Chris@16 160 typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
Chris@16 161
Chris@16 162 typedef A allocator;
Chris@16 163 typedef std::pair<K const, M> value_type;
Chris@16 164 typedef H hasher;
Chris@16 165 typedef P key_equal;
Chris@16 166 typedef K key_type;
Chris@16 167
Chris@16 168 typedef boost::unordered::detail::allocator_traits<allocator> traits;
Chris@16 169 typedef boost::unordered::detail::pick_grouped_node<allocator,
Chris@16 170 value_type> pick;
Chris@16 171 typedef typename pick::node node;
Chris@16 172 typedef typename pick::bucket bucket;
Chris@16 173 typedef typename pick::link_pointer link_pointer;
Chris@16 174
Chris@16 175 typedef boost::unordered::detail::grouped_table_impl<types> table;
Chris@16 176 typedef boost::unordered::detail::map_extractor<key_type, value_type>
Chris@16 177 extractor;
Chris@16 178
Chris@101 179 typedef typename boost::unordered::detail::pick_policy<K>::type policy;
Chris@16 180 };
Chris@16 181
Chris@16 182 template <typename Types>
Chris@16 183 struct grouped_table_impl : boost::unordered::detail::table<Types>
Chris@16 184 {
Chris@16 185 typedef boost::unordered::detail::table<Types> table;
Chris@16 186 typedef typename table::value_type value_type;
Chris@16 187 typedef typename table::bucket bucket;
Chris@16 188 typedef typename table::policy policy;
Chris@16 189 typedef typename table::node_pointer node_pointer;
Chris@16 190 typedef typename table::node_allocator node_allocator;
Chris@16 191 typedef typename table::node_allocator_traits node_allocator_traits;
Chris@16 192 typedef typename table::bucket_pointer bucket_pointer;
Chris@16 193 typedef typename table::link_pointer link_pointer;
Chris@16 194 typedef typename table::hasher hasher;
Chris@16 195 typedef typename table::key_equal key_equal;
Chris@16 196 typedef typename table::key_type key_type;
Chris@16 197 typedef typename table::node_constructor node_constructor;
Chris@16 198 typedef typename table::extractor extractor;
Chris@16 199 typedef typename table::iterator iterator;
Chris@16 200 typedef typename table::c_iterator c_iterator;
Chris@16 201
Chris@16 202 // Constructors
Chris@16 203
Chris@16 204 grouped_table_impl(std::size_t n,
Chris@16 205 hasher const& hf,
Chris@16 206 key_equal const& eq,
Chris@16 207 node_allocator const& a)
Chris@16 208 : table(n, hf, eq, a)
Chris@16 209 {}
Chris@16 210
Chris@16 211 grouped_table_impl(grouped_table_impl const& x)
Chris@16 212 : table(x, node_allocator_traits::
Chris@16 213 select_on_container_copy_construction(x.node_alloc()))
Chris@16 214 {
Chris@16 215 this->init(x);
Chris@16 216 }
Chris@16 217
Chris@16 218 grouped_table_impl(grouped_table_impl const& x,
Chris@16 219 node_allocator const& a)
Chris@16 220 : table(x, a)
Chris@16 221 {
Chris@16 222 this->init(x);
Chris@16 223 }
Chris@16 224
Chris@16 225 grouped_table_impl(grouped_table_impl& x,
Chris@16 226 boost::unordered::detail::move_tag m)
Chris@16 227 : table(x, m)
Chris@16 228 {}
Chris@16 229
Chris@16 230 grouped_table_impl(grouped_table_impl& x,
Chris@16 231 node_allocator const& a,
Chris@16 232 boost::unordered::detail::move_tag m)
Chris@16 233 : table(x, a, m)
Chris@16 234 {
Chris@16 235 this->move_init(x);
Chris@16 236 }
Chris@16 237
Chris@16 238 // Accessors
Chris@16 239
Chris@16 240 template <class Key, class Pred>
Chris@16 241 iterator find_node_impl(
Chris@16 242 std::size_t key_hash,
Chris@16 243 Key const& k,
Chris@16 244 Pred const& eq) const
Chris@16 245 {
Chris@16 246 std::size_t bucket_index = this->hash_to_bucket(key_hash);
Chris@16 247 iterator n = this->begin(bucket_index);
Chris@16 248
Chris@16 249 for (;;)
Chris@16 250 {
Chris@16 251 if (!n.node_) return n;
Chris@16 252
Chris@16 253 std::size_t node_hash = n.node_->hash_;
Chris@16 254 if (key_hash == node_hash)
Chris@16 255 {
Chris@16 256 if (eq(k, this->get_key(*n)))
Chris@16 257 return n;
Chris@16 258 }
Chris@16 259 else
Chris@16 260 {
Chris@16 261 if (this->hash_to_bucket(node_hash) != bucket_index)
Chris@16 262 return iterator();
Chris@16 263 }
Chris@16 264
Chris@16 265 n = iterator(n.node_->group_prev_->next_);
Chris@16 266 }
Chris@16 267 }
Chris@16 268
Chris@16 269 std::size_t count(key_type const& k) const
Chris@16 270 {
Chris@16 271 iterator n = this->find_node(k);
Chris@16 272 if (!n.node_) return 0;
Chris@16 273
Chris@16 274 std::size_t x = 0;
Chris@16 275 node_pointer it = n.node_;
Chris@16 276 do {
Chris@16 277 it = it->group_prev_;
Chris@16 278 ++x;
Chris@16 279 } while(it != n.node_);
Chris@16 280
Chris@16 281 return x;
Chris@16 282 }
Chris@16 283
Chris@16 284 std::pair<iterator, iterator>
Chris@16 285 equal_range(key_type const& k) const
Chris@16 286 {
Chris@16 287 iterator n = this->find_node(k);
Chris@16 288 return std::make_pair(
Chris@16 289 n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
Chris@16 290 }
Chris@16 291
Chris@16 292 // Equality
Chris@16 293
Chris@16 294 bool equals(grouped_table_impl const& other) const
Chris@16 295 {
Chris@16 296 if(this->size_ != other.size_) return false;
Chris@16 297
Chris@16 298 for(iterator n1 = this->begin(); n1.node_;)
Chris@16 299 {
Chris@16 300 iterator n2 = other.find_matching_node(n1);
Chris@16 301 if (!n2.node_) return false;
Chris@16 302 iterator end1(n1.node_->group_prev_->next_);
Chris@16 303 iterator end2(n2.node_->group_prev_->next_);
Chris@16 304 if (!group_equals(n1, end1, n2, end2)) return false;
Chris@16 305 n1 = end1;
Chris@16 306 }
Chris@16 307
Chris@16 308 return true;
Chris@16 309 }
Chris@16 310
Chris@16 311 static bool group_equals(iterator n1, iterator end1,
Chris@16 312 iterator n2, iterator end2)
Chris@16 313 {
Chris@16 314 for(;;)
Chris@16 315 {
Chris@16 316 if (*n1 != *n2) break;
Chris@16 317
Chris@16 318 ++n1;
Chris@16 319 ++n2;
Chris@16 320
Chris@16 321 if (n1 == end1) return n2 == end2;
Chris@16 322 if (n2 == end2) return false;
Chris@16 323 }
Chris@16 324
Chris@16 325 for(iterator n1a = n1, n2a = n2;;)
Chris@16 326 {
Chris@16 327 ++n1a;
Chris@16 328 ++n2a;
Chris@16 329
Chris@16 330 if (n1a == end1)
Chris@16 331 {
Chris@16 332 if (n2a == end2) break;
Chris@16 333 else return false;
Chris@16 334 }
Chris@16 335
Chris@16 336 if (n2a == end2) return false;
Chris@16 337 }
Chris@16 338
Chris@16 339 iterator start = n1;
Chris@16 340 for(;n1 != end1; ++n1)
Chris@16 341 {
Chris@16 342 value_type const& v = *n1;
Chris@16 343 if (find(start, n1, v)) continue;
Chris@16 344 std::size_t matches = count_equal(n2, end2, v);
Chris@16 345 if (!matches) return false;
Chris@16 346 iterator next = n1;
Chris@16 347 ++next;
Chris@16 348 if (matches != 1 + count_equal(next, end1, v)) return false;
Chris@16 349 }
Chris@16 350
Chris@16 351 return true;
Chris@16 352 }
Chris@16 353
Chris@16 354 static bool find(iterator n, iterator end, value_type const& v)
Chris@16 355 {
Chris@16 356 for(;n != end; ++n)
Chris@16 357 if (*n == v)
Chris@16 358 return true;
Chris@16 359 return false;
Chris@16 360 }
Chris@16 361
Chris@16 362 static std::size_t count_equal(iterator n, iterator end,
Chris@16 363 value_type const& v)
Chris@16 364 {
Chris@16 365 std::size_t count = 0;
Chris@16 366 for(;n != end; ++n)
Chris@16 367 if (*n == v) ++count;
Chris@16 368 return count;
Chris@16 369 }
Chris@16 370
Chris@16 371 // Emplace/Insert
Chris@16 372
Chris@16 373 static inline void add_after_node(
Chris@16 374 node_pointer n,
Chris@16 375 node_pointer pos)
Chris@16 376 {
Chris@16 377 n->next_ = pos->group_prev_->next_;
Chris@16 378 n->group_prev_ = pos->group_prev_;
Chris@16 379 pos->group_prev_->next_ = n;
Chris@16 380 pos->group_prev_ = n;
Chris@16 381 }
Chris@16 382
Chris@16 383 inline iterator add_node(
Chris@16 384 node_constructor& a,
Chris@16 385 std::size_t key_hash,
Chris@16 386 iterator pos)
Chris@16 387 {
Chris@16 388 node_pointer n = a.release();
Chris@16 389 n->hash_ = key_hash;
Chris@16 390 if (pos.node_) {
Chris@16 391 this->add_after_node(n, pos.node_);
Chris@16 392 if (n->next_) {
Chris@16 393 std::size_t next_bucket = this->hash_to_bucket(
Chris@16 394 static_cast<node_pointer>(n->next_)->hash_);
Chris@16 395 if (next_bucket != this->hash_to_bucket(key_hash)) {
Chris@16 396 this->get_bucket(next_bucket)->next_ = n;
Chris@16 397 }
Chris@16 398 }
Chris@16 399 }
Chris@16 400 else {
Chris@16 401 bucket_pointer b = this->get_bucket(
Chris@16 402 this->hash_to_bucket(key_hash));
Chris@16 403
Chris@16 404 if (!b->next_)
Chris@16 405 {
Chris@16 406 link_pointer start_node = this->get_previous_start();
Chris@16 407
Chris@16 408 if (start_node->next_) {
Chris@16 409 this->get_bucket(this->hash_to_bucket(
Chris@16 410 static_cast<node_pointer>(start_node->next_)->hash_
Chris@16 411 ))->next_ = n;
Chris@16 412 }
Chris@16 413
Chris@16 414 b->next_ = start_node;
Chris@16 415 n->next_ = start_node->next_;
Chris@16 416 start_node->next_ = n;
Chris@16 417 }
Chris@16 418 else
Chris@16 419 {
Chris@16 420 n->next_ = b->next_->next_;
Chris@16 421 b->next_->next_ = n;
Chris@16 422 }
Chris@16 423 }
Chris@16 424 ++this->size_;
Chris@16 425 return iterator(n);
Chris@16 426 }
Chris@16 427
Chris@16 428 iterator emplace_impl(node_constructor& a)
Chris@16 429 {
Chris@16 430 key_type const& k = this->get_key(a.value());
Chris@16 431 std::size_t key_hash = this->hash(k);
Chris@16 432 iterator position = this->find_node(key_hash, k);
Chris@16 433
Chris@16 434 // reserve has basic exception safety if the hash function
Chris@16 435 // throws, strong otherwise.
Chris@16 436 this->reserve_for_insert(this->size_ + 1);
Chris@16 437 return this->add_node(a, key_hash, position);
Chris@16 438 }
Chris@16 439
Chris@16 440 void emplace_impl_no_rehash(node_constructor& a)
Chris@16 441 {
Chris@16 442 key_type const& k = this->get_key(a.value());
Chris@16 443 std::size_t key_hash = this->hash(k);
Chris@16 444 this->add_node(a, key_hash, this->find_node(key_hash, k));
Chris@16 445 }
Chris@16 446
Chris@16 447 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@16 448 # if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@16 449 iterator emplace(boost::unordered::detail::emplace_args1<
Chris@16 450 boost::unordered::detail::please_ignore_this_overload> const&)
Chris@16 451 {
Chris@16 452 BOOST_ASSERT(false);
Chris@16 453 return iterator();
Chris@16 454 }
Chris@16 455 # else
Chris@16 456 iterator emplace(
Chris@16 457 boost::unordered::detail::please_ignore_this_overload const&)
Chris@16 458 {
Chris@16 459 BOOST_ASSERT(false);
Chris@16 460 return iterator();
Chris@16 461 }
Chris@16 462 # endif
Chris@16 463 #endif
Chris@16 464
Chris@16 465 template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
Chris@16 466 iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
Chris@16 467 {
Chris@16 468 node_constructor a(this->node_alloc());
Chris@16 469 a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
Chris@16 470
Chris@16 471 return iterator(emplace_impl(a));
Chris@16 472 }
Chris@16 473
Chris@16 474 ////////////////////////////////////////////////////////////////////////
Chris@16 475 // Insert range methods
Chris@16 476
Chris@16 477 // if hash function throws, or inserting > 1 element, basic exception
Chris@16 478 // safety. Strong otherwise
Chris@16 479 template <class I>
Chris@16 480 typename boost::unordered::detail::enable_if_forward<I, void>::type
Chris@16 481 insert_range(I i, I j)
Chris@16 482 {
Chris@16 483 if(i == j) return;
Chris@16 484
Chris@16 485 std::size_t distance = boost::unordered::detail::distance(i, j);
Chris@16 486 if(distance == 1) {
Chris@16 487 node_constructor a(this->node_alloc());
Chris@16 488 a.construct_with_value2(*i);
Chris@16 489 emplace_impl(a);
Chris@16 490 }
Chris@16 491 else {
Chris@16 492 // Only require basic exception safety here
Chris@16 493 this->reserve_for_insert(this->size_ + distance);
Chris@16 494
Chris@16 495 node_constructor a(this->node_alloc());
Chris@16 496 for (; i != j; ++i) {
Chris@16 497 a.construct_with_value2(*i);
Chris@16 498 emplace_impl_no_rehash(a);
Chris@16 499 }
Chris@16 500 }
Chris@16 501 }
Chris@16 502
Chris@16 503 template <class I>
Chris@16 504 typename boost::unordered::detail::disable_if_forward<I, void>::type
Chris@16 505 insert_range(I i, I j)
Chris@16 506 {
Chris@16 507 node_constructor a(this->node_alloc());
Chris@16 508 for (; i != j; ++i) {
Chris@16 509 a.construct_with_value2(*i);
Chris@16 510 emplace_impl(a);
Chris@16 511 }
Chris@16 512 }
Chris@16 513
Chris@16 514 ////////////////////////////////////////////////////////////////////////
Chris@16 515 // Erase
Chris@16 516 //
Chris@16 517 // no throw
Chris@16 518
Chris@16 519 std::size_t erase_key(key_type const& k)
Chris@16 520 {
Chris@16 521 if(!this->size_) return 0;
Chris@16 522
Chris@16 523 std::size_t key_hash = this->hash(k);
Chris@16 524 std::size_t bucket_index = this->hash_to_bucket(key_hash);
Chris@16 525 link_pointer prev = this->get_previous_start(bucket_index);
Chris@16 526 if (!prev) return 0;
Chris@16 527
Chris@16 528 for (;;)
Chris@16 529 {
Chris@16 530 if (!prev->next_) return 0;
Chris@16 531 std::size_t node_hash =
Chris@16 532 static_cast<node_pointer>(prev->next_)->hash_;
Chris@16 533 if (this->hash_to_bucket(node_hash) != bucket_index)
Chris@16 534 return 0;
Chris@16 535 if (node_hash == key_hash &&
Chris@16 536 this->key_eq()(k, this->get_key(
Chris@16 537 static_cast<node_pointer>(prev->next_)->value())))
Chris@16 538 break;
Chris@16 539 prev = static_cast<node_pointer>(prev->next_)->group_prev_;
Chris@16 540 }
Chris@16 541
Chris@16 542 node_pointer first_node = static_cast<node_pointer>(prev->next_);
Chris@16 543 link_pointer end = first_node->group_prev_->next_;
Chris@16 544
Chris@101 545 std::size_t deleted_count = this->delete_nodes(prev, end);
Chris@16 546 this->fix_bucket(bucket_index, prev);
Chris@101 547 return deleted_count;
Chris@16 548 }
Chris@16 549
Chris@16 550 iterator erase(c_iterator r)
Chris@16 551 {
Chris@16 552 BOOST_ASSERT(r.node_);
Chris@16 553 iterator next(r.node_);
Chris@16 554 ++next;
Chris@16 555 erase_nodes(r.node_, next.node_);
Chris@16 556 return next;
Chris@16 557 }
Chris@16 558
Chris@16 559 iterator erase_range(c_iterator r1, c_iterator r2)
Chris@16 560 {
Chris@16 561 if (r1 == r2) return iterator(r2.node_);
Chris@16 562 erase_nodes(r1.node_, r2.node_);
Chris@16 563 return iterator(r2.node_);
Chris@16 564 }
Chris@16 565
Chris@101 566 link_pointer erase_nodes(node_pointer i, node_pointer j)
Chris@16 567 {
Chris@101 568 std::size_t bucket_index = this->hash_to_bucket(i->hash_);
Chris@16 569
Chris@101 570 // Split the groups containing 'i' and 'j'.
Chris@101 571 // And get the pointer to the node before i while
Chris@16 572 // we're at it.
Chris@101 573 link_pointer prev = split_groups(i, j);
Chris@16 574
Chris@101 575 // If we don't have a 'prev' it means that i is at the
Chris@16 576 // beginning of a block, so search through the blocks in the
Chris@16 577 // same bucket.
Chris@16 578 if (!prev) {
Chris@16 579 prev = this->get_previous_start(bucket_index);
Chris@101 580 while (prev->next_ != i)
Chris@16 581 prev = static_cast<node_pointer>(prev->next_)->group_prev_;
Chris@16 582 }
Chris@16 583
Chris@16 584 // Delete the nodes.
Chris@16 585 do {
Chris@16 586 link_pointer group_end =
Chris@16 587 static_cast<node_pointer>(prev->next_)->group_prev_->next_;
Chris@16 588 this->delete_nodes(prev, group_end);
Chris@16 589 bucket_index = this->fix_bucket(bucket_index, prev);
Chris@101 590 } while(prev->next_ != j);
Chris@16 591
Chris@16 592 return prev;
Chris@16 593 }
Chris@16 594
Chris@101 595 static link_pointer split_groups(node_pointer i, node_pointer j)
Chris@16 596 {
Chris@101 597 node_pointer prev = i->group_prev_;
Chris@101 598 if (prev->next_ != i) prev = node_pointer();
Chris@16 599
Chris@101 600 if (j) {
Chris@101 601 node_pointer first = j;
Chris@101 602 while (first != i && first->group_prev_->next_ == first) {
Chris@16 603 first = first->group_prev_;
Chris@16 604 }
Chris@16 605
Chris@101 606 boost::swap(first->group_prev_, j->group_prev_);
Chris@101 607 if (first == i) return prev;
Chris@16 608 }
Chris@16 609
Chris@16 610 if (prev) {
Chris@16 611 node_pointer first = prev;
Chris@16 612 while (first->group_prev_->next_ == first) {
Chris@16 613 first = first->group_prev_;
Chris@16 614 }
Chris@101 615 boost::swap(first->group_prev_, i->group_prev_);
Chris@16 616 }
Chris@16 617
Chris@16 618 return prev;
Chris@16 619 }
Chris@16 620
Chris@16 621 ////////////////////////////////////////////////////////////////////////
Chris@16 622 // fill_buckets
Chris@16 623
Chris@16 624 template <class NodeCreator>
Chris@16 625 static void fill_buckets(iterator n, table& dst,
Chris@16 626 NodeCreator& creator)
Chris@16 627 {
Chris@16 628 link_pointer prev = dst.get_previous_start();
Chris@16 629
Chris@16 630 while (n.node_) {
Chris@16 631 std::size_t key_hash = n.node_->hash_;
Chris@16 632 iterator group_end(n.node_->group_prev_->next_);
Chris@16 633
Chris@16 634 node_pointer first_node = creator.create(*n);
Chris@16 635 node_pointer end = first_node;
Chris@16 636 first_node->hash_ = key_hash;
Chris@16 637 prev->next_ = first_node;
Chris@16 638 ++dst.size_;
Chris@16 639
Chris@16 640 for (++n; n != group_end; ++n)
Chris@16 641 {
Chris@16 642 end = creator.create(*n);
Chris@16 643 end->hash_ = key_hash;
Chris@16 644 add_after_node(end, first_node);
Chris@16 645 ++dst.size_;
Chris@16 646 }
Chris@16 647
Chris@16 648 prev = place_in_bucket(dst, prev, end);
Chris@16 649 }
Chris@16 650 }
Chris@16 651
Chris@16 652 // strong otherwise exception safety
Chris@16 653 void rehash_impl(std::size_t num_buckets)
Chris@16 654 {
Chris@16 655 BOOST_ASSERT(this->buckets_);
Chris@16 656
Chris@16 657 this->create_buckets(num_buckets);
Chris@16 658 link_pointer prev = this->get_previous_start();
Chris@16 659 while (prev->next_)
Chris@16 660 prev = place_in_bucket(*this, prev,
Chris@16 661 static_cast<node_pointer>(prev->next_)->group_prev_);
Chris@16 662 }
Chris@16 663
Chris@16 664 // Iterate through the nodes placing them in the correct buckets.
Chris@16 665 // pre: prev->next_ is not null.
Chris@16 666 static link_pointer place_in_bucket(table& dst,
Chris@16 667 link_pointer prev, node_pointer end)
Chris@16 668 {
Chris@16 669 bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(end->hash_));
Chris@16 670
Chris@16 671 if (!b->next_) {
Chris@16 672 b->next_ = prev;
Chris@16 673 return end;
Chris@16 674 }
Chris@16 675 else {
Chris@16 676 link_pointer next = end->next_;
Chris@16 677 end->next_ = b->next_->next_;
Chris@16 678 b->next_->next_ = prev->next_;
Chris@16 679 prev->next_ = next;
Chris@16 680 return prev;
Chris@16 681 }
Chris@16 682 }
Chris@16 683 };
Chris@16 684 }}}
Chris@16 685
Chris@16 686 #endif