annotate DEPENDENCIES/generic/include/boost/unordered/detail/unique.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +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_UNIQUE_HPP_INCLUDED
Chris@16 8 #define BOOST_UNORDERED_DETAIL_UNIQUE_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 #include <boost/throw_exception.hpp>
Chris@16 18 #include <stdexcept>
Chris@16 19
Chris@16 20 namespace boost { namespace unordered { namespace detail {
Chris@16 21
Chris@16 22 template <typename A, typename T> struct unique_node;
Chris@16 23 template <typename T> struct ptr_node;
Chris@16 24 template <typename Types> struct table_impl;
Chris@16 25
Chris@16 26 template <typename A, typename T>
Chris@16 27 struct unique_node :
Chris@16 28 boost::unordered::detail::value_base<T>
Chris@16 29 {
Chris@16 30 typedef typename ::boost::unordered::detail::rebind_wrap<
Chris@101 31 A, unique_node<A, T> >::type allocator;
Chris@101 32 typedef typename ::boost::unordered::detail::
Chris@101 33 allocator_traits<allocator>::pointer node_pointer;
Chris@16 34 typedef node_pointer link_pointer;
Chris@16 35
Chris@16 36 link_pointer next_;
Chris@16 37 std::size_t hash_;
Chris@16 38
Chris@16 39 unique_node() :
Chris@16 40 next_(),
Chris@16 41 hash_(0)
Chris@16 42 {}
Chris@16 43
Chris@16 44 void init(node_pointer)
Chris@16 45 {
Chris@16 46 }
Chris@16 47
Chris@16 48 private:
Chris@16 49 unique_node& operator=(unique_node const&);
Chris@16 50 };
Chris@16 51
Chris@16 52 template <typename T>
Chris@16 53 struct ptr_node :
Chris@16 54 boost::unordered::detail::ptr_bucket
Chris@16 55 {
Chris@101 56 typedef T value_type;
Chris@16 57 typedef boost::unordered::detail::ptr_bucket bucket_base;
Chris@16 58 typedef ptr_node<T>* node_pointer;
Chris@16 59 typedef ptr_bucket* link_pointer;
Chris@16 60
Chris@16 61 std::size_t hash_;
Chris@101 62 boost::unordered::detail::value_base<T> value_base_;
Chris@16 63
Chris@16 64 ptr_node() :
Chris@16 65 bucket_base(),
Chris@16 66 hash_(0)
Chris@16 67 {}
Chris@16 68
Chris@16 69 void init(node_pointer)
Chris@16 70 {
Chris@16 71 }
Chris@16 72
Chris@101 73 void* address() { return value_base_.address(); }
Chris@101 74 value_type& value() { return value_base_.value(); }
Chris@101 75 value_type* value_ptr() { return value_base_.value_ptr(); }
Chris@101 76
Chris@16 77 private:
Chris@16 78 ptr_node& operator=(ptr_node const&);
Chris@16 79 };
Chris@16 80
Chris@16 81 // If the allocator uses raw pointers use ptr_node
Chris@16 82 // Otherwise use node.
Chris@16 83
Chris@16 84 template <typename A, typename T, typename NodePtr, typename BucketPtr>
Chris@16 85 struct pick_node2
Chris@16 86 {
Chris@16 87 typedef boost::unordered::detail::unique_node<A, T> node;
Chris@16 88
Chris@16 89 typedef typename boost::unordered::detail::allocator_traits<
Chris@16 90 typename boost::unordered::detail::rebind_wrap<A, node>::type
Chris@16 91 >::pointer node_pointer;
Chris@16 92
Chris@16 93 typedef boost::unordered::detail::bucket<node_pointer> bucket;
Chris@16 94 typedef node_pointer link_pointer;
Chris@16 95 };
Chris@16 96
Chris@16 97 template <typename A, typename T>
Chris@16 98 struct pick_node2<A, T,
Chris@16 99 boost::unordered::detail::ptr_node<T>*,
Chris@16 100 boost::unordered::detail::ptr_bucket*>
Chris@16 101 {
Chris@16 102 typedef boost::unordered::detail::ptr_node<T> node;
Chris@16 103 typedef boost::unordered::detail::ptr_bucket bucket;
Chris@16 104 typedef bucket* link_pointer;
Chris@16 105 };
Chris@16 106
Chris@16 107 template <typename A, typename T>
Chris@16 108 struct pick_node
Chris@16 109 {
Chris@16 110 typedef boost::unordered::detail::allocator_traits<
Chris@16 111 typename boost::unordered::detail::rebind_wrap<A,
Chris@16 112 boost::unordered::detail::ptr_node<T> >::type
Chris@16 113 > tentative_node_traits;
Chris@16 114
Chris@16 115 typedef boost::unordered::detail::allocator_traits<
Chris@16 116 typename boost::unordered::detail::rebind_wrap<A,
Chris@16 117 boost::unordered::detail::ptr_bucket >::type
Chris@16 118 > tentative_bucket_traits;
Chris@16 119
Chris@16 120 typedef pick_node2<A, T,
Chris@16 121 typename tentative_node_traits::pointer,
Chris@16 122 typename tentative_bucket_traits::pointer> pick;
Chris@16 123
Chris@16 124 typedef typename pick::node node;
Chris@16 125 typedef typename pick::bucket bucket;
Chris@16 126 typedef typename pick::link_pointer link_pointer;
Chris@16 127 };
Chris@16 128
Chris@16 129 template <typename A, typename T, typename H, typename P>
Chris@16 130 struct set
Chris@16 131 {
Chris@16 132 typedef boost::unordered::detail::set<A, T, H, P> types;
Chris@16 133
Chris@16 134 typedef A allocator;
Chris@16 135 typedef T value_type;
Chris@16 136 typedef H hasher;
Chris@16 137 typedef P key_equal;
Chris@16 138 typedef T key_type;
Chris@16 139
Chris@16 140 typedef boost::unordered::detail::allocator_traits<allocator> traits;
Chris@16 141 typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
Chris@16 142 typedef typename pick::node node;
Chris@16 143 typedef typename pick::bucket bucket;
Chris@16 144 typedef typename pick::link_pointer link_pointer;
Chris@16 145
Chris@16 146 typedef boost::unordered::detail::table_impl<types> table;
Chris@16 147 typedef boost::unordered::detail::set_extractor<value_type> extractor;
Chris@16 148
Chris@101 149 typedef typename boost::unordered::detail::pick_policy<T>::type policy;
Chris@16 150 };
Chris@16 151
Chris@16 152 template <typename A, typename K, typename M, typename H, typename P>
Chris@16 153 struct map
Chris@16 154 {
Chris@16 155 typedef boost::unordered::detail::map<A, K, M, H, P> types;
Chris@16 156
Chris@16 157 typedef A allocator;
Chris@16 158 typedef std::pair<K const, M> value_type;
Chris@16 159 typedef H hasher;
Chris@16 160 typedef P key_equal;
Chris@16 161 typedef K key_type;
Chris@16 162
Chris@16 163 typedef boost::unordered::detail::allocator_traits<allocator>
Chris@16 164 traits;
Chris@16 165 typedef boost::unordered::detail::pick_node<allocator, value_type> pick;
Chris@16 166 typedef typename pick::node node;
Chris@16 167 typedef typename pick::bucket bucket;
Chris@16 168 typedef typename pick::link_pointer link_pointer;
Chris@16 169
Chris@16 170 typedef boost::unordered::detail::table_impl<types> table;
Chris@16 171 typedef boost::unordered::detail::map_extractor<key_type, value_type>
Chris@16 172 extractor;
Chris@16 173
Chris@101 174 typedef typename boost::unordered::detail::pick_policy<K>::type policy;
Chris@16 175 };
Chris@16 176
Chris@16 177 template <typename Types>
Chris@16 178 struct table_impl : boost::unordered::detail::table<Types>
Chris@16 179 {
Chris@16 180 typedef boost::unordered::detail::table<Types> table;
Chris@16 181 typedef typename table::value_type value_type;
Chris@16 182 typedef typename table::bucket bucket;
Chris@16 183 typedef typename table::policy policy;
Chris@16 184 typedef typename table::node_pointer node_pointer;
Chris@16 185 typedef typename table::node_allocator node_allocator;
Chris@16 186 typedef typename table::node_allocator_traits node_allocator_traits;
Chris@16 187 typedef typename table::bucket_pointer bucket_pointer;
Chris@16 188 typedef typename table::link_pointer link_pointer;
Chris@16 189 typedef typename table::hasher hasher;
Chris@16 190 typedef typename table::key_equal key_equal;
Chris@16 191 typedef typename table::key_type key_type;
Chris@16 192 typedef typename table::node_constructor node_constructor;
Chris@16 193 typedef typename table::extractor extractor;
Chris@16 194 typedef typename table::iterator iterator;
Chris@16 195 typedef typename table::c_iterator c_iterator;
Chris@16 196
Chris@16 197 typedef std::pair<iterator, bool> emplace_return;
Chris@16 198
Chris@16 199 // Constructors
Chris@16 200
Chris@16 201 table_impl(std::size_t n,
Chris@16 202 hasher const& hf,
Chris@16 203 key_equal const& eq,
Chris@16 204 node_allocator const& a)
Chris@16 205 : table(n, hf, eq, a)
Chris@16 206 {}
Chris@16 207
Chris@16 208 table_impl(table_impl const& x)
Chris@16 209 : table(x, node_allocator_traits::
Chris@16 210 select_on_container_copy_construction(x.node_alloc()))
Chris@16 211 {
Chris@16 212 this->init(x);
Chris@16 213 }
Chris@16 214
Chris@16 215 table_impl(table_impl const& x,
Chris@16 216 node_allocator const& a)
Chris@16 217 : table(x, a)
Chris@16 218 {
Chris@16 219 this->init(x);
Chris@16 220 }
Chris@16 221
Chris@16 222 table_impl(table_impl& x,
Chris@16 223 boost::unordered::detail::move_tag m)
Chris@16 224 : table(x, m)
Chris@16 225 {}
Chris@16 226
Chris@16 227 table_impl(table_impl& x,
Chris@16 228 node_allocator const& a,
Chris@16 229 boost::unordered::detail::move_tag m)
Chris@16 230 : table(x, a, m)
Chris@16 231 {
Chris@16 232 this->move_init(x);
Chris@16 233 }
Chris@16 234
Chris@16 235 // Accessors
Chris@16 236
Chris@16 237 template <class Key, class Pred>
Chris@16 238 iterator find_node_impl(
Chris@16 239 std::size_t key_hash,
Chris@16 240 Key const& k,
Chris@16 241 Pred const& eq) const
Chris@16 242 {
Chris@16 243 std::size_t bucket_index = this->hash_to_bucket(key_hash);
Chris@16 244 iterator n = this->begin(bucket_index);
Chris@16 245
Chris@16 246 for (;;)
Chris@16 247 {
Chris@16 248 if (!n.node_) return n;
Chris@16 249
Chris@16 250 std::size_t node_hash = n.node_->hash_;
Chris@16 251 if (key_hash == node_hash)
Chris@16 252 {
Chris@16 253 if (eq(k, this->get_key(*n)))
Chris@16 254 return n;
Chris@16 255 }
Chris@16 256 else
Chris@16 257 {
Chris@16 258 if (this->hash_to_bucket(node_hash) != bucket_index)
Chris@16 259 return iterator();
Chris@16 260 }
Chris@16 261
Chris@16 262 ++n;
Chris@16 263 }
Chris@16 264 }
Chris@16 265
Chris@16 266 std::size_t count(key_type const& k) const
Chris@16 267 {
Chris@16 268 return this->find_node(k).node_ ? 1 : 0;
Chris@16 269 }
Chris@16 270
Chris@16 271 value_type& at(key_type const& k) const
Chris@16 272 {
Chris@16 273 if (this->size_) {
Chris@16 274 iterator it = this->find_node(k);
Chris@16 275 if (it.node_) return *it;
Chris@16 276 }
Chris@16 277
Chris@16 278 boost::throw_exception(
Chris@16 279 std::out_of_range("Unable to find key in unordered_map."));
Chris@16 280 }
Chris@16 281
Chris@16 282 std::pair<iterator, iterator>
Chris@16 283 equal_range(key_type const& k) const
Chris@16 284 {
Chris@16 285 iterator n = this->find_node(k);
Chris@16 286 iterator n2 = n;
Chris@16 287 if (n2.node_) ++n2;
Chris@16 288 return std::make_pair(n, n2);
Chris@16 289 }
Chris@16 290
Chris@16 291 // equals
Chris@16 292
Chris@16 293 bool equals(table_impl const& other) const
Chris@16 294 {
Chris@16 295 if(this->size_ != other.size_) return false;
Chris@16 296
Chris@16 297 for(iterator n1 = this->begin(); n1.node_; ++n1)
Chris@16 298 {
Chris@16 299 iterator n2 = other.find_matching_node(n1);
Chris@16 300
Chris@16 301 if (!n2.node_ || *n1 != *n2)
Chris@16 302 return false;
Chris@16 303 }
Chris@16 304
Chris@16 305 return true;
Chris@16 306 }
Chris@16 307
Chris@16 308 // Emplace/Insert
Chris@16 309
Chris@16 310 inline iterator add_node(
Chris@16 311 node_constructor& a,
Chris@16 312 std::size_t key_hash)
Chris@16 313 {
Chris@16 314 node_pointer n = a.release();
Chris@16 315 n->hash_ = key_hash;
Chris@16 316
Chris@16 317 bucket_pointer b = this->get_bucket(this->hash_to_bucket(key_hash));
Chris@16 318
Chris@16 319 if (!b->next_)
Chris@16 320 {
Chris@16 321 link_pointer start_node = this->get_previous_start();
Chris@16 322
Chris@16 323 if (start_node->next_) {
Chris@16 324 this->get_bucket(this->hash_to_bucket(
Chris@16 325 static_cast<node_pointer>(start_node->next_)->hash_)
Chris@16 326 )->next_ = n;
Chris@16 327 }
Chris@16 328
Chris@16 329 b->next_ = start_node;
Chris@16 330 n->next_ = start_node->next_;
Chris@16 331 start_node->next_ = n;
Chris@16 332 }
Chris@16 333 else
Chris@16 334 {
Chris@16 335 n->next_ = b->next_->next_;
Chris@16 336 b->next_->next_ = n;
Chris@16 337 }
Chris@16 338
Chris@16 339 ++this->size_;
Chris@16 340 return iterator(n);
Chris@16 341 }
Chris@16 342
Chris@16 343 value_type& operator[](key_type const& k)
Chris@16 344 {
Chris@16 345 std::size_t key_hash = this->hash(k);
Chris@16 346 iterator pos = this->find_node(key_hash, k);
Chris@16 347
Chris@16 348 if (pos.node_) return *pos;
Chris@16 349
Chris@16 350 // Create the node before rehashing in case it throws an
Chris@16 351 // exception (need strong safety in such a case).
Chris@16 352 node_constructor a(this->node_alloc());
Chris@16 353 a.construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS3(
Chris@16 354 boost::unordered::piecewise_construct,
Chris@16 355 boost::make_tuple(k),
Chris@16 356 boost::make_tuple()));
Chris@16 357
Chris@16 358 this->reserve_for_insert(this->size_ + 1);
Chris@16 359 return *add_node(a, key_hash);
Chris@16 360 }
Chris@16 361
Chris@16 362 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
Chris@16 363 # if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@16 364 emplace_return emplace(boost::unordered::detail::emplace_args1<
Chris@16 365 boost::unordered::detail::please_ignore_this_overload> const&)
Chris@16 366 {
Chris@16 367 BOOST_ASSERT(false);
Chris@16 368 return emplace_return(this->begin(), false);
Chris@16 369 }
Chris@16 370 # else
Chris@16 371 emplace_return emplace(
Chris@16 372 boost::unordered::detail::please_ignore_this_overload const&)
Chris@16 373 {
Chris@16 374 BOOST_ASSERT(false);
Chris@16 375 return emplace_return(this->begin(), false);
Chris@16 376 }
Chris@16 377 # endif
Chris@16 378 #endif
Chris@16 379
Chris@16 380 template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
Chris@16 381 emplace_return emplace(BOOST_UNORDERED_EMPLACE_ARGS)
Chris@16 382 {
Chris@16 383 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@16 384 return emplace_impl(
Chris@16 385 extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
Chris@16 386 BOOST_UNORDERED_EMPLACE_FORWARD);
Chris@16 387 #else
Chris@16 388 return emplace_impl(
Chris@16 389 extractor::extract(args.a0, args.a1),
Chris@16 390 BOOST_UNORDERED_EMPLACE_FORWARD);
Chris@16 391 #endif
Chris@16 392 }
Chris@16 393
Chris@16 394 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
Chris@16 395 template <typename A0>
Chris@16 396 emplace_return emplace(
Chris@16 397 boost::unordered::detail::emplace_args1<A0> const& args)
Chris@16 398 {
Chris@16 399 return emplace_impl(extractor::extract(args.a0), args);
Chris@16 400 }
Chris@16 401 #endif
Chris@16 402
Chris@16 403 template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
Chris@16 404 emplace_return emplace_impl(key_type const& k,
Chris@16 405 BOOST_UNORDERED_EMPLACE_ARGS)
Chris@16 406 {
Chris@16 407 std::size_t key_hash = this->hash(k);
Chris@16 408 iterator pos = this->find_node(key_hash, k);
Chris@16 409
Chris@16 410 if (pos.node_) return emplace_return(pos, false);
Chris@16 411
Chris@16 412 // Create the node before rehashing in case it throws an
Chris@16 413 // exception (need strong safety in such a case).
Chris@16 414 node_constructor a(this->node_alloc());
Chris@16 415 a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
Chris@16 416
Chris@16 417 // reserve has basic exception safety if the hash function
Chris@16 418 // throws, strong otherwise.
Chris@16 419 this->reserve_for_insert(this->size_ + 1);
Chris@16 420 return emplace_return(this->add_node(a, key_hash), true);
Chris@16 421 }
Chris@16 422
Chris@16 423 emplace_return emplace_impl_with_node(node_constructor& a)
Chris@16 424 {
Chris@16 425 key_type const& k = this->get_key(a.value());
Chris@16 426 std::size_t key_hash = this->hash(k);
Chris@16 427 iterator pos = this->find_node(key_hash, k);
Chris@16 428
Chris@16 429 if (pos.node_) return emplace_return(pos, false);
Chris@16 430
Chris@16 431 // reserve has basic exception safety if the hash function
Chris@16 432 // throws, strong otherwise.
Chris@16 433 this->reserve_for_insert(this->size_ + 1);
Chris@16 434 return emplace_return(this->add_node(a, key_hash), true);
Chris@16 435 }
Chris@16 436
Chris@16 437 template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
Chris@16 438 emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
Chris@16 439 {
Chris@16 440 // Don't have a key, so construct the node first in order
Chris@16 441 // to be able to lookup the position.
Chris@16 442 node_constructor a(this->node_alloc());
Chris@16 443 a.construct_with_value(BOOST_UNORDERED_EMPLACE_FORWARD);
Chris@16 444 return emplace_impl_with_node(a);
Chris@16 445 }
Chris@16 446
Chris@16 447 ////////////////////////////////////////////////////////////////////////
Chris@16 448 // Insert range methods
Chris@16 449 //
Chris@16 450 // if hash function throws, or inserting > 1 element, basic exception
Chris@16 451 // safety strong otherwise
Chris@16 452
Chris@16 453 template <class InputIt>
Chris@16 454 void insert_range(InputIt i, InputIt j)
Chris@16 455 {
Chris@16 456 if(i != j)
Chris@16 457 return insert_range_impl(extractor::extract(*i), i, j);
Chris@16 458 }
Chris@16 459
Chris@16 460 template <class InputIt>
Chris@16 461 void insert_range_impl(key_type const& k, InputIt i, InputIt j)
Chris@16 462 {
Chris@16 463 node_constructor a(this->node_alloc());
Chris@16 464
Chris@16 465 insert_range_impl2(a, k, i, j);
Chris@16 466
Chris@16 467 while(++i != j) {
Chris@16 468 // Note: can't use get_key as '*i' might not be value_type - it
Chris@16 469 // could be a pair with first_types as key_type without const or
Chris@16 470 // a different second_type.
Chris@16 471 //
Chris@16 472 // TODO: Might be worth storing the value_type instead of the
Chris@16 473 // key here. Could be more efficient if '*i' is expensive. Could
Chris@16 474 // be less efficient if copying the full value_type is
Chris@16 475 // expensive.
Chris@16 476 insert_range_impl2(a, extractor::extract(*i), i, j);
Chris@16 477 }
Chris@16 478 }
Chris@16 479
Chris@16 480 template <class InputIt>
Chris@16 481 void insert_range_impl2(node_constructor& a, key_type const& k,
Chris@16 482 InputIt i, InputIt j)
Chris@16 483 {
Chris@16 484 // No side effects in this initial code
Chris@16 485 std::size_t key_hash = this->hash(k);
Chris@16 486 iterator pos = this->find_node(key_hash, k);
Chris@16 487
Chris@16 488 if (!pos.node_) {
Chris@16 489 a.construct_with_value2(*i);
Chris@16 490 if(this->size_ + 1 > this->max_load_)
Chris@16 491 this->reserve_for_insert(this->size_ +
Chris@16 492 boost::unordered::detail::insert_size(i, j));
Chris@16 493
Chris@16 494 // Nothing after this point can throw.
Chris@16 495 this->add_node(a, key_hash);
Chris@16 496 }
Chris@16 497 }
Chris@16 498
Chris@16 499 template <class InputIt>
Chris@16 500 void insert_range_impl(no_key, InputIt i, InputIt j)
Chris@16 501 {
Chris@16 502 node_constructor a(this->node_alloc());
Chris@16 503
Chris@16 504 do {
Chris@16 505 a.construct_with_value2(*i);
Chris@16 506 emplace_impl_with_node(a);
Chris@16 507 } while(++i != j);
Chris@16 508 }
Chris@16 509
Chris@16 510 ////////////////////////////////////////////////////////////////////////
Chris@16 511 // Erase
Chris@16 512 //
Chris@16 513 // no throw
Chris@16 514
Chris@16 515 std::size_t erase_key(key_type const& k)
Chris@16 516 {
Chris@16 517 if(!this->size_) return 0;
Chris@16 518
Chris@16 519 std::size_t key_hash = this->hash(k);
Chris@16 520 std::size_t bucket_index = this->hash_to_bucket(key_hash);
Chris@16 521 link_pointer prev = this->get_previous_start(bucket_index);
Chris@16 522 if (!prev) return 0;
Chris@16 523
Chris@16 524 for (;;)
Chris@16 525 {
Chris@16 526 if (!prev->next_) return 0;
Chris@16 527 std::size_t node_hash =
Chris@16 528 static_cast<node_pointer>(prev->next_)->hash_;
Chris@16 529 if (this->hash_to_bucket(node_hash) != bucket_index)
Chris@16 530 return 0;
Chris@16 531 if (node_hash == key_hash &&
Chris@16 532 this->key_eq()(k, this->get_key(
Chris@16 533 static_cast<node_pointer>(prev->next_)->value())))
Chris@16 534 break;
Chris@16 535 prev = prev->next_;
Chris@16 536 }
Chris@16 537
Chris@16 538 link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
Chris@16 539
Chris@101 540 std::size_t deleted_count = this->delete_nodes(prev, end);
Chris@16 541 this->fix_bucket(bucket_index, prev);
Chris@101 542 return deleted_count;
Chris@16 543 }
Chris@16 544
Chris@16 545 iterator erase(c_iterator r)
Chris@16 546 {
Chris@16 547 BOOST_ASSERT(r.node_);
Chris@16 548 iterator next(r.node_);
Chris@16 549 ++next;
Chris@16 550 erase_nodes(r.node_, next.node_);
Chris@16 551 return next;
Chris@16 552 }
Chris@16 553
Chris@16 554 iterator erase_range(c_iterator r1, c_iterator r2)
Chris@16 555 {
Chris@16 556 if (r1 == r2) return iterator(r2.node_);
Chris@16 557 erase_nodes(r1.node_, r2.node_);
Chris@16 558 return iterator(r2.node_);
Chris@16 559 }
Chris@16 560
Chris@101 561 void erase_nodes(node_pointer i, node_pointer j)
Chris@16 562 {
Chris@101 563 std::size_t bucket_index = this->hash_to_bucket(i->hash_);
Chris@16 564
Chris@101 565 // Find the node before i.
Chris@16 566 link_pointer prev = this->get_previous_start(bucket_index);
Chris@101 567 while(prev->next_ != i) prev = prev->next_;
Chris@16 568
Chris@16 569 // Delete the nodes.
Chris@16 570 do {
Chris@16 571 this->delete_node(prev);
Chris@16 572 bucket_index = this->fix_bucket(bucket_index, prev);
Chris@101 573 } while (prev->next_ != j);
Chris@16 574 }
Chris@16 575
Chris@16 576 ////////////////////////////////////////////////////////////////////////
Chris@16 577 // fill_buckets
Chris@16 578
Chris@16 579 template <class NodeCreator>
Chris@16 580 static void fill_buckets(iterator n, table& dst,
Chris@16 581 NodeCreator& creator)
Chris@16 582 {
Chris@16 583 link_pointer prev = dst.get_previous_start();
Chris@16 584
Chris@16 585 while (n.node_) {
Chris@16 586 node_pointer node = creator.create(*n);
Chris@16 587 node->hash_ = n.node_->hash_;
Chris@16 588 prev->next_ = node;
Chris@16 589 ++dst.size_;
Chris@16 590 ++n;
Chris@16 591
Chris@16 592 prev = place_in_bucket(dst, prev);
Chris@16 593 }
Chris@16 594 }
Chris@16 595
Chris@16 596 // strong otherwise exception safety
Chris@16 597 void rehash_impl(std::size_t num_buckets)
Chris@16 598 {
Chris@16 599 BOOST_ASSERT(this->buckets_);
Chris@16 600
Chris@16 601 this->create_buckets(num_buckets);
Chris@16 602 link_pointer prev = this->get_previous_start();
Chris@16 603 while (prev->next_)
Chris@16 604 prev = place_in_bucket(*this, prev);
Chris@16 605 }
Chris@16 606
Chris@16 607 // Iterate through the nodes placing them in the correct buckets.
Chris@16 608 // pre: prev->next_ is not null.
Chris@16 609 static link_pointer place_in_bucket(table& dst, link_pointer prev)
Chris@16 610 {
Chris@16 611 node_pointer n = static_cast<node_pointer>(prev->next_);
Chris@16 612 bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
Chris@16 613
Chris@16 614 if (!b->next_) {
Chris@16 615 b->next_ = prev;
Chris@16 616 return n;
Chris@16 617 }
Chris@16 618 else {
Chris@16 619 prev->next_ = n->next_;
Chris@16 620 n->next_ = b->next_->next_;
Chris@16 621 b->next_->next_ = n;
Chris@16 622 return prev;
Chris@16 623 }
Chris@16 624 }
Chris@16 625 };
Chris@16 626 }}}
Chris@16 627
Chris@16 628 #endif