00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #ifndef GNU_LIBSTDCXX_TR1_HASHTABLE_
00055 #define GNU_LIBSTDCXX_TR1_HASHTABLE_
00056
00057 #include <utility>
00058 #include <iterator>
00059 #include <cstddef>
00060 #include <cstdlib>
00061 #include <cmath>
00062 #include <bits/functexcept.h>
00063 #include <tr1/type_traits>
00064
00065
00066
00067
00068 namespace Internal
00069 {
00070 template<bool Flag, typename IfTrue, typename IfFalse>
00071 struct IF;
00072
00073 template<typename IfTrue, typename IfFalse>
00074 struct IF<true, IfTrue, IfFalse>
00075 { typedef IfTrue type; };
00076
00077 template <typename IfTrue, typename IfFalse>
00078 struct IF<false, IfTrue, IfFalse>
00079 { typedef IfFalse type; };
00080
00081
00082
00083 template<class Iterator>
00084 inline typename std::iterator_traits<Iterator>::difference_type
00085 distance_fw(Iterator first, Iterator last, std::input_iterator_tag)
00086 { return 0; }
00087
00088 template<class Iterator>
00089 inline typename std::iterator_traits<Iterator>::difference_type
00090 distance_fw(Iterator first, Iterator last, std::forward_iterator_tag)
00091 { return std::distance(first, last); }
00092
00093 template<class Iterator>
00094 inline typename std::iterator_traits<Iterator>::difference_type
00095 distance_fw(Iterator first, Iterator last)
00096 {
00097 typedef typename std::iterator_traits<Iterator>::iterator_category tag;
00098 return distance_fw(first, last, tag());
00099 }
00100
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 namespace Internal
00113 {
00114 template<typename Value, bool cache_hash_code>
00115 struct hash_node;
00116
00117 template<typename Value>
00118 struct hash_node<Value, true>
00119 {
00120 Value m_v;
00121 std::size_t hash_code;
00122 hash_node* m_next;
00123 };
00124
00125 template<typename Value>
00126 struct hash_node<Value, false>
00127 {
00128 Value m_v;
00129 hash_node* m_next;
00130 };
00131
00132
00133
00134
00135 template<typename Value, bool cache>
00136 struct node_iterator_base
00137 {
00138 node_iterator_base(hash_node<Value, cache>* p)
00139 : m_cur(p) { }
00140
00141 void
00142 incr()
00143 { m_cur = m_cur->m_next; }
00144
00145 hash_node<Value, cache>* m_cur;
00146 };
00147
00148 template<typename Value, bool cache>
00149 inline bool
00150 operator==(const node_iterator_base<Value, cache>& x,
00151 const node_iterator_base<Value, cache>& y)
00152 { return x.m_cur == y.m_cur; }
00153
00154 template<typename Value, bool cache>
00155 inline bool
00156 operator!=(const node_iterator_base<Value, cache>& x,
00157 const node_iterator_base<Value, cache>& y)
00158 { return x.m_cur != y.m_cur; }
00159
00160 template<typename Value, bool constant_iterators, bool cache>
00161 struct node_iterator
00162 : public node_iterator_base<Value, cache>
00163 {
00164 typedef Value value_type;
00165 typedef typename IF<constant_iterators, const Value*, Value*>::type
00166 pointer;
00167 typedef typename IF<constant_iterators, const Value&, Value&>::type
00168 reference;
00169 typedef std::ptrdiff_t difference_type;
00170 typedef std::forward_iterator_tag iterator_category;
00171
00172 node_iterator()
00173 : node_iterator_base<Value, cache>(0) { }
00174
00175 explicit
00176 node_iterator(hash_node<Value, cache>* p)
00177 : node_iterator_base<Value, cache>(p) { }
00178
00179 reference
00180 operator*() const
00181 { return this->m_cur->m_v; }
00182
00183 pointer
00184 operator->() const
00185 { return &this->m_cur->m_v; }
00186
00187 node_iterator&
00188 operator++()
00189 {
00190 this->incr();
00191 return *this;
00192 }
00193
00194 node_iterator
00195 operator++(int)
00196 {
00197 node_iterator tmp(*this);
00198 this->incr();
00199 return tmp;
00200 }
00201 };
00202
00203 template<typename Value, bool constant_iterators, bool cache>
00204 struct node_const_iterator
00205 : public node_iterator_base<Value, cache>
00206 {
00207 typedef Value value_type;
00208 typedef const Value* pointer;
00209 typedef const Value& reference;
00210 typedef std::ptrdiff_t difference_type;
00211 typedef std::forward_iterator_tag iterator_category;
00212
00213 node_const_iterator()
00214 : node_iterator_base<Value, cache>(0) { }
00215
00216 explicit
00217 node_const_iterator(hash_node<Value, cache>* p)
00218 : node_iterator_base<Value, cache>(p) { }
00219
00220 node_const_iterator(const node_iterator<Value, constant_iterators,
00221 cache>& x)
00222 : node_iterator_base<Value, cache>(x.m_cur) { }
00223
00224 reference
00225 operator*() const
00226 { return this->m_cur->m_v; }
00227
00228 pointer
00229 operator->() const
00230 { return &this->m_cur->m_v; }
00231
00232 node_const_iterator&
00233 operator++()
00234 {
00235 this->incr();
00236 return *this;
00237 }
00238
00239 node_const_iterator
00240 operator++(int)
00241 {
00242 node_const_iterator tmp(*this);
00243 this->incr();
00244 return tmp;
00245 }
00246 };
00247
00248 template<typename Value, bool cache>
00249 struct hashtable_iterator_base
00250 {
00251 hashtable_iterator_base(hash_node<Value, cache>* node,
00252 hash_node<Value, cache>** bucket)
00253 : m_cur_node(node), m_cur_bucket(bucket) { }
00254
00255 void
00256 incr()
00257 {
00258 m_cur_node = m_cur_node->m_next;
00259 if (!m_cur_node)
00260 m_incr_bucket();
00261 }
00262
00263 void
00264 m_incr_bucket();
00265
00266 hash_node<Value, cache>* m_cur_node;
00267 hash_node<Value, cache>** m_cur_bucket;
00268 };
00269
00270
00271
00272 template<typename Value, bool cache>
00273 void
00274 hashtable_iterator_base<Value, cache>::
00275 m_incr_bucket()
00276 {
00277 ++m_cur_bucket;
00278
00279
00280 while (!*m_cur_bucket)
00281 ++m_cur_bucket;
00282 m_cur_node = *m_cur_bucket;
00283 }
00284
00285 template<typename Value, bool cache>
00286 inline bool
00287 operator==(const hashtable_iterator_base<Value, cache>& x,
00288 const hashtable_iterator_base<Value, cache>& y)
00289 { return x.m_cur_node == y.m_cur_node; }
00290
00291 template<typename Value, bool cache>
00292 inline bool
00293 operator!=(const hashtable_iterator_base<Value, cache>& x,
00294 const hashtable_iterator_base<Value, cache>& y)
00295 { return x.m_cur_node != y.m_cur_node; }
00296
00297 template<typename Value, bool constant_iterators, bool cache>
00298 struct hashtable_iterator
00299 : public hashtable_iterator_base<Value, cache>
00300 {
00301 typedef Value value_type;
00302 typedef typename IF<constant_iterators, const Value*, Value*>::type
00303 pointer;
00304 typedef typename IF<constant_iterators, const Value&, Value&>::type
00305 reference;
00306 typedef std::ptrdiff_t difference_type;
00307 typedef std::forward_iterator_tag iterator_category;
00308
00309 hashtable_iterator()
00310 : hashtable_iterator_base<Value, cache>(0, 0) { }
00311
00312 hashtable_iterator(hash_node<Value, cache>* p,
00313 hash_node<Value, cache>** b)
00314 : hashtable_iterator_base<Value, cache>(p, b) { }
00315
00316 explicit
00317 hashtable_iterator(hash_node<Value, cache>** b)
00318 : hashtable_iterator_base<Value, cache>(*b, b) { }
00319
00320 reference
00321 operator*() const
00322 { return this->m_cur_node->m_v; }
00323
00324 pointer
00325 operator->() const
00326 { return &this->m_cur_node->m_v; }
00327
00328 hashtable_iterator&
00329 operator++()
00330 {
00331 this->incr();
00332 return *this;
00333 }
00334
00335 hashtable_iterator
00336 operator++(int)
00337 {
00338 hashtable_iterator tmp(*this);
00339 this->incr();
00340 return tmp;
00341 }
00342 };
00343
00344 template<typename Value, bool constant_iterators, bool cache>
00345 struct hashtable_const_iterator
00346 : public hashtable_iterator_base<Value, cache>
00347 {
00348 typedef Value value_type;
00349 typedef const Value* pointer;
00350 typedef const Value& reference;
00351 typedef std::ptrdiff_t difference_type;
00352 typedef std::forward_iterator_tag iterator_category;
00353
00354 hashtable_const_iterator()
00355 : hashtable_iterator_base<Value, cache>(0, 0) { }
00356
00357 hashtable_const_iterator(hash_node<Value, cache>* p,
00358 hash_node<Value, cache>** b)
00359 : hashtable_iterator_base<Value, cache>(p, b) { }
00360
00361 explicit
00362 hashtable_const_iterator(hash_node<Value, cache>** b)
00363 : hashtable_iterator_base<Value, cache>(*b, b) { }
00364
00365 hashtable_const_iterator(const hashtable_iterator<Value,
00366 constant_iterators, cache>& x)
00367 : hashtable_iterator_base<Value, cache>(x.m_cur_node, x.m_cur_bucket) { }
00368
00369 reference
00370 operator*() const
00371 { return this->m_cur_node->m_v; }
00372
00373 pointer
00374 operator->() const
00375 { return &this->m_cur_node->m_v; }
00376
00377 hashtable_const_iterator&
00378 operator++()
00379 {
00380 this->incr();
00381 return *this;
00382 }
00383
00384 hashtable_const_iterator
00385 operator++(int)
00386 {
00387 hashtable_const_iterator tmp(*this);
00388 this->incr();
00389 return tmp;
00390 }
00391 };
00392 }
00393
00394
00395
00396
00397
00398 namespace Internal
00399 {
00400
00401 template<typename T>
00402 struct identity
00403 {
00404 const T&
00405 operator()(const T& t) const
00406 { return t; }
00407 };
00408
00409 template<typename Pair>
00410 struct extract1st
00411 {
00412 const typename Pair::first_type&
00413 operator()(const Pair& p) const
00414 { return p.first; }
00415 };
00416
00417
00418
00419 struct mod_range_hashing
00420 {
00421 typedef std::size_t first_argument_type;
00422 typedef std::size_t second_argument_type;
00423 typedef std::size_t result_type;
00424
00425 result_type
00426 operator()(first_argument_type r, second_argument_type N) const
00427 { return r % N; }
00428 };
00429
00430
00431
00432
00433
00434
00435 struct default_ranged_hash { };
00436
00437
00438
00439 struct prime_rehash_policy
00440 {
00441 prime_rehash_policy(float z = 1.0);
00442
00443 float
00444 max_load_factor() const;
00445
00446
00447 std::size_t
00448 next_bkt(std::size_t n) const;
00449
00450
00451 std::size_t
00452 bkt_for_elements(std::size_t n) const;
00453
00454
00455
00456
00457
00458 std::pair<bool, std::size_t>
00459 need_rehash(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const;
00460
00461 float m_max_load_factor;
00462 float m_growth_factor;
00463 mutable std::size_t m_next_resize;
00464 };
00465
00466
00467
00468
00469
00470
00471
00472
00473 struct lt
00474 {
00475 template<typename X, typename Y>
00476 bool
00477 operator()(X x, Y y)
00478 { return x < y; }
00479 };
00480
00481 template<int ulongsize = sizeof(unsigned long)>
00482 struct X
00483 {
00484 static const int n_primes = ulongsize != 8 ? 256 : 256 + 48;
00485 static const unsigned long primes[256 + 48 + 1];
00486 };
00487
00488 template<int ulongsize>
00489 const int X<ulongsize>::n_primes;
00490
00491 template<int ulongsize>
00492 const unsigned long X<ulongsize>::primes[256 + 48 + 1] =
00493 {
00494 2ul, 3ul, 5ul, 7ul, 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul,
00495 37ul, 41ul, 43ul, 47ul, 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul,
00496 83ul, 89ul, 97ul, 103ul, 109ul, 113ul, 127ul, 137ul, 139ul, 149ul,
00497 157ul, 167ul, 179ul, 193ul, 199ul, 211ul, 227ul, 241ul, 257ul,
00498 277ul, 293ul, 313ul, 337ul, 359ul, 383ul, 409ul, 439ul, 467ul,
00499 503ul, 541ul, 577ul, 619ul, 661ul, 709ul, 761ul, 823ul, 887ul,
00500 953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul, 1493ul, 1613ul,
00501 1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul, 2753ul, 2971ul,
00502 3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul, 5087ul, 5503ul,
00503 5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul, 9497ul, 10273ul,
00504 11113ul, 12011ul, 12983ul, 14033ul, 15173ul, 16411ul, 17749ul,
00505 19183ul, 20753ul, 22447ul, 24281ul, 26267ul, 28411ul, 30727ul,
00506 33223ul, 35933ul, 38873ul, 42043ul, 45481ul, 49201ul, 53201ul,
00507 57557ul, 62233ul, 67307ul, 72817ul, 78779ul, 85229ul, 92203ul,
00508 99733ul, 107897ul, 116731ul, 126271ul, 136607ul, 147793ul,
00509 159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul,
00510 256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul,
00511 410857ul, 444487ul, 480881ul, 520241ul, 562841ul, 608903ul,
00512 658753ul, 712697ul, 771049ul, 834181ul, 902483ul, 976369ul,
00513 1056323ul, 1142821ul, 1236397ul, 1337629ul, 1447153ul, 1565659ul,
00514 1693859ul, 1832561ul, 1982627ul, 2144977ul, 2320627ul, 2510653ul,
00515 2716249ul, 2938679ul, 3179303ul, 3439651ul, 3721303ul, 4026031ul,
00516 4355707ul, 4712381ul, 5098259ul, 5515729ul, 5967347ul, 6456007ul,
00517 6984629ul, 7556579ul, 8175383ul, 8844859ul, 9569143ul, 10352717ul,
00518 11200489ul, 12117689ul, 13109983ul, 14183539ul, 15345007ul,
00519 16601593ul, 17961079ul, 19431899ul, 21023161ul, 22744717ul,
00520 24607243ul, 26622317ul, 28802401ul, 31160981ul, 33712729ul,
00521 36473443ul, 39460231ul, 42691603ul, 46187573ul, 49969847ul,
00522 54061849ul, 58488943ul, 63278561ul, 68460391ul, 74066549ul,
00523 80131819ul, 86693767ul, 93793069ul, 101473717ul, 109783337ul,
00524 118773397ul, 128499677ul, 139022417ul, 150406843ul, 162723577ul,
00525 176048909ul, 190465427ul, 206062531ul, 222936881ul, 241193053ul,
00526 260944219ul, 282312799ul, 305431229ul, 330442829ul, 357502601ul,
00527 386778277ul, 418451333ul, 452718089ul, 489790921ul, 529899637ul,
00528 573292817ul, 620239453ul, 671030513ul, 725980837ul, 785430967ul,
00529 849749479ul, 919334987ul, 994618837ul, 1076067617ul, 1164186217ul,
00530 1259520799ul, 1362662261ul, 1474249943ul, 1594975441ul,
00531 1725587117ul, 1866894511ul, 2019773507ul, 2185171673ul,
00532 2364114217ul, 2557710269ul, 2767159799ul, 2993761039ul,
00533 3238918481ul, 3504151727ul, 3791104843ul, 4101556399ul,
00534 4294967291ul,
00535
00536
00537 ulongsize != 8 ? 4294967291ul : (unsigned long)6442450933ull,
00538 (unsigned long)8589934583ull,
00539 (unsigned long)12884901857ull, (unsigned long)17179869143ull,
00540 (unsigned long)25769803693ull, (unsigned long)34359738337ull,
00541 (unsigned long)51539607367ull, (unsigned long)68719476731ull,
00542 (unsigned long)103079215087ull, (unsigned long)137438953447ull,
00543 (unsigned long)206158430123ull, (unsigned long)274877906899ull,
00544 (unsigned long)412316860387ull, (unsigned long)549755813881ull,
00545 (unsigned long)824633720731ull, (unsigned long)1099511627689ull,
00546 (unsigned long)1649267441579ull, (unsigned long)2199023255531ull,
00547 (unsigned long)3298534883309ull, (unsigned long)4398046511093ull,
00548 (unsigned long)6597069766607ull, (unsigned long)8796093022151ull,
00549 (unsigned long)13194139533241ull, (unsigned long)17592186044399ull,
00550 (unsigned long)26388279066581ull, (unsigned long)35184372088777ull,
00551 (unsigned long)52776558133177ull, (unsigned long)70368744177643ull,
00552 (unsigned long)105553116266399ull, (unsigned long)140737488355213ull,
00553 (unsigned long)211106232532861ull, (unsigned long)281474976710597ull,
00554 (unsigned long)562949953421231ull, (unsigned long)1125899906842597ull,
00555 (unsigned long)2251799813685119ull, (unsigned long)4503599627370449ull,
00556 (unsigned long)9007199254740881ull, (unsigned long)18014398509481951ull,
00557 (unsigned long)36028797018963913ull, (unsigned long)72057594037927931ull,
00558 (unsigned long)144115188075855859ull,
00559 (unsigned long)288230376151711717ull,
00560 (unsigned long)576460752303423433ull,
00561 (unsigned long)1152921504606846883ull,
00562 (unsigned long)2305843009213693951ull,
00563 (unsigned long)4611686018427387847ull,
00564 (unsigned long)9223372036854775783ull,
00565 (unsigned long)18446744073709551557ull,
00566 (unsigned long)18446744073709551557ull
00567 };
00568
00569 inline
00570 prime_rehash_policy::
00571 prime_rehash_policy(float z)
00572 : m_max_load_factor(z), m_growth_factor(2.f), m_next_resize(0)
00573 { }
00574
00575 inline float
00576 prime_rehash_policy::
00577 max_load_factor() const
00578 { return m_max_load_factor; }
00579
00580
00581 inline std::size_t
00582 prime_rehash_policy::
00583 next_bkt(std::size_t n) const
00584 {
00585 const unsigned long* const last = X<>::primes + X<>::n_primes;
00586 const unsigned long* p = std::lower_bound(X<>::primes, last, n);
00587 m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00588 return *p;
00589 }
00590
00591
00592
00593 inline std::size_t
00594 prime_rehash_policy::
00595 bkt_for_elements(std::size_t n) const
00596 {
00597 const unsigned long* const last = X<>::primes + X<>::n_primes;
00598 const float min_bkts = n / m_max_load_factor;
00599 const unsigned long* p = std::lower_bound(X<>::primes, last,
00600 min_bkts, lt());
00601 m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00602 return *p;
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 inline std::pair<bool, std::size_t>
00615 prime_rehash_policy::
00616 need_rehash(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const
00617 {
00618 if (n_elt + n_ins > m_next_resize)
00619 {
00620 float min_bkts = (float(n_ins) + float(n_elt)) / m_max_load_factor;
00621 if (min_bkts > n_bkt)
00622 {
00623 min_bkts = std::max(min_bkts, m_growth_factor * n_bkt);
00624 const unsigned long* const last = X<>::primes + X<>::n_primes;
00625 const unsigned long* p = std::lower_bound(X<>::primes, last,
00626 min_bkts, lt());
00627 m_next_resize =
00628 static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00629 return std::make_pair(true, *p);
00630 }
00631 else
00632 {
00633 m_next_resize =
00634 static_cast<std::size_t>(std::ceil(n_bkt * m_max_load_factor));
00635 return std::make_pair(false, 0);
00636 }
00637 }
00638 else
00639 return std::make_pair(false, 0);
00640 }
00641
00642 }
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 namespace Internal
00654 {
00655
00656
00657
00658
00659
00660
00661 template<typename K, typename V, typename Ex, bool unique, typename Hashtable>
00662 struct map_base { };
00663
00664 template<typename K, typename Pair, typename Hashtable>
00665 struct map_base<K, Pair, extract1st<Pair>, false, Hashtable>
00666 {
00667 typedef typename Pair::second_type mapped_type;
00668 };
00669
00670 template<typename K, typename Pair, typename Hashtable>
00671 struct map_base<K, Pair, extract1st<Pair>, true, Hashtable>
00672 {
00673 typedef typename Pair::second_type mapped_type;
00674
00675 mapped_type&
00676 operator[](const K& k);
00677 };
00678
00679 template<typename K, typename Pair, typename Hashtable>
00680 typename map_base<K, Pair, extract1st<Pair>, true, Hashtable>::mapped_type&
00681 map_base<K, Pair, extract1st<Pair>, true, Hashtable>::
00682 operator[](const K& k)
00683 {
00684 Hashtable* h = static_cast<Hashtable*>(this);
00685 typename Hashtable::hash_code_t code = h->m_hash_code(k);
00686 std::size_t n = h->bucket_index(k, code, h->bucket_count());
00687
00688 typename Hashtable::node* p = h->m_find_node(h->m_buckets[n], k, code);
00689 if (!p)
00690 return h->m_insert_bucket(std::make_pair(k, mapped_type()),
00691 n, code)->second;
00692 return (p->m_v).second;
00693 }
00694
00695
00696
00697 template<typename RehashPolicy, typename Hashtable>
00698 struct rehash_base { };
00699
00700 template<typename Hashtable>
00701 struct rehash_base<prime_rehash_policy, Hashtable>
00702 {
00703 float
00704 max_load_factor() const
00705 {
00706 const Hashtable* This = static_cast<const Hashtable*>(this);
00707 return This->rehash_policy().max_load_factor();
00708 }
00709
00710 void
00711 max_load_factor(float z)
00712 {
00713 Hashtable* This = static_cast<Hashtable*>(this);
00714 This->rehash_policy(prime_rehash_policy(z));
00715 }
00716 };
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 template<typename Key, typename Value,
00732 typename ExtractKey, typename Equal,
00733 typename H1, typename H2, typename H,
00734 bool cache_hash_code>
00735 struct hash_code_base;
00736
00737
00738
00739 template<typename Key, typename Value,
00740 typename ExtractKey, typename Equal,
00741 typename H1, typename H2, typename H>
00742 struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, false>
00743 {
00744 protected:
00745 hash_code_base(const ExtractKey& ex, const Equal& eq,
00746 const H1&, const H2&, const H& h)
00747 : m_extract(ex), m_eq(eq), m_ranged_hash(h) { }
00748
00749 typedef void* hash_code_t;
00750
00751 hash_code_t
00752 m_hash_code(const Key& k) const
00753 { return 0; }
00754
00755 std::size_t
00756 bucket_index(const Key& k, hash_code_t, std::size_t N) const
00757 { return m_ranged_hash(k, N); }
00758
00759 std::size_t
00760 bucket_index(const hash_node<Value, false>* p, std::size_t N) const
00761 { return m_ranged_hash(m_extract(p->m_v), N); }
00762
00763 bool
00764 compare(const Key& k, hash_code_t, hash_node<Value, false>* n) const
00765 { return m_eq(k, m_extract(n->m_v)); }
00766
00767 void
00768 store_code(hash_node<Value, false>*, hash_code_t) const
00769 { }
00770
00771 void
00772 copy_code(hash_node<Value, false>*, const hash_node<Value, false>*) const
00773 { }
00774
00775 void
00776 m_swap(hash_code_base& x)
00777 {
00778 std::swap(m_extract, x.m_extract);
00779 std::swap(m_eq, x.m_eq);
00780 std::swap(m_ranged_hash, x.m_ranged_hash);
00781 }
00782
00783 protected:
00784 ExtractKey m_extract;
00785 Equal m_eq;
00786 H m_ranged_hash;
00787 };
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 template<typename Key, typename Value,
00799 typename ExtractKey, typename Equal,
00800 typename H1, typename H2, typename H>
00801 struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, true>;
00802
00803
00804
00805
00806
00807
00808 template<typename Key, typename Value,
00809 typename ExtractKey, typename Equal,
00810 typename H1, typename H2>
00811 struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2,
00812 default_ranged_hash, false>
00813 {
00814 typedef H1 hasher;
00815
00816 hasher
00817 hash_function() const
00818 { return m_h1; }
00819
00820 protected:
00821 hash_code_base(const ExtractKey& ex, const Equal& eq,
00822 const H1& h1, const H2& h2, const default_ranged_hash&)
00823 : m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { }
00824
00825 typedef std::size_t hash_code_t;
00826
00827 hash_code_t
00828 m_hash_code(const Key& k) const
00829 { return m_h1(k); }
00830
00831 std::size_t
00832 bucket_index(const Key&, hash_code_t c, std::size_t N) const
00833 { return m_h2(c, N); }
00834
00835 std::size_t
00836 bucket_index(const hash_node<Value, false>* p, std::size_t N) const
00837 { return m_h2(m_h1(m_extract(p->m_v)), N); }
00838
00839 bool
00840 compare(const Key& k, hash_code_t, hash_node<Value, false>* n) const
00841 { return m_eq(k, m_extract(n->m_v)); }
00842
00843 void
00844 store_code(hash_node<Value, false>*, hash_code_t) const
00845 { }
00846
00847 void
00848 copy_code(hash_node<Value, false>*, const hash_node<Value, false>*) const
00849 { }
00850
00851 void
00852 m_swap(hash_code_base& x)
00853 {
00854 std::swap(m_extract, x.m_extract);
00855 std::swap(m_eq, x.m_eq);
00856 std::swap(m_h1, x.m_h1);
00857 std::swap(m_h2, x.m_h2);
00858 }
00859
00860 protected:
00861 ExtractKey m_extract;
00862 Equal m_eq;
00863 H1 m_h1;
00864 H2 m_h2;
00865 };
00866
00867
00868
00869
00870 template<typename Key, typename Value,
00871 typename ExtractKey, typename Equal,
00872 typename H1, typename H2>
00873 struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2,
00874 default_ranged_hash, true>
00875 {
00876 typedef H1 hasher;
00877
00878 hasher
00879 hash_function() const
00880 { return m_h1; }
00881
00882 protected:
00883 hash_code_base(const ExtractKey& ex, const Equal& eq,
00884 const H1& h1, const H2& h2, const default_ranged_hash&)
00885 : m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { }
00886
00887 typedef std::size_t hash_code_t;
00888
00889 hash_code_t
00890 m_hash_code(const Key& k) const
00891 { return m_h1(k); }
00892
00893 std::size_t
00894 bucket_index(const Key&, hash_code_t c, std::size_t N) const
00895 { return m_h2(c, N); }
00896
00897 std::size_t
00898 bucket_index(const hash_node<Value, true>* p, std::size_t N) const
00899 { return m_h2(p->hash_code, N); }
00900
00901 bool
00902 compare(const Key& k, hash_code_t c, hash_node<Value, true>* n) const
00903 { return c == n->hash_code && m_eq(k, m_extract(n->m_v)); }
00904
00905 void
00906 store_code(hash_node<Value, true>* n, hash_code_t c) const
00907 { n->hash_code = c; }
00908
00909 void
00910 copy_code(hash_node<Value, true>* to,
00911 const hash_node<Value, true>* from) const
00912 { to->hash_code = from->hash_code; }
00913
00914 void
00915 m_swap(hash_code_base& x)
00916 {
00917 std::swap(m_extract, x.m_extract);
00918 std::swap(m_eq, x.m_eq);
00919 std::swap(m_h1, x.m_h1);
00920 std::swap(m_h2, x.m_h2);
00921 }
00922
00923 protected:
00924 ExtractKey m_extract;
00925 Equal m_eq;
00926 H1 m_h1;
00927 H2 m_h2;
00928 };
00929
00930 }
00931
00932 namespace std
00933 {
00934 namespace tr1
00935 {
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993 template<typename Key, typename Value,
00994 typename Allocator,
00995 typename ExtractKey, typename Equal,
00996 typename H1, typename H2,
00997 typename H, typename RehashPolicy,
00998 bool cache_hash_code,
00999 bool constant_iterators,
01000 bool unique_keys>
01001 class hashtable
01002 : public Internal::rehash_base<RehashPolicy,
01003 hashtable<Key, Value, Allocator, ExtractKey,
01004 Equal, H1, H2, H, RehashPolicy,
01005 cache_hash_code, constant_iterators,
01006 unique_keys> >,
01007 public Internal::hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H,
01008 cache_hash_code>,
01009 public Internal::map_base<Key, Value, ExtractKey, unique_keys,
01010 hashtable<Key, Value, Allocator, ExtractKey,
01011 Equal, H1, H2, H, RehashPolicy,
01012 cache_hash_code, constant_iterators,
01013 unique_keys> >
01014 {
01015 public:
01016 typedef Allocator allocator_type;
01017 typedef Value value_type;
01018 typedef Key key_type;
01019 typedef Equal key_equal;
01020
01021
01022 typedef typename Allocator::difference_type difference_type;
01023 typedef typename Allocator::size_type size_type;
01024 typedef typename Allocator::reference reference;
01025 typedef typename Allocator::const_reference const_reference;
01026
01027 typedef Internal::node_iterator<value_type, constant_iterators,
01028 cache_hash_code>
01029 local_iterator;
01030 typedef Internal::node_const_iterator<value_type, constant_iterators,
01031 cache_hash_code>
01032 const_local_iterator;
01033
01034 typedef Internal::hashtable_iterator<value_type, constant_iterators,
01035 cache_hash_code>
01036 iterator;
01037 typedef Internal::hashtable_const_iterator<value_type, constant_iterators,
01038 cache_hash_code>
01039 const_iterator;
01040
01041 template<typename K, typename Pair, typename Hashtable>
01042 friend struct Internal::map_base;
01043
01044 private:
01045 typedef Internal::hash_node<Value, cache_hash_code> node;
01046 typedef typename Allocator::template rebind<node>::other
01047 node_allocator_t;
01048 typedef typename Allocator::template rebind<node*>::other
01049 bucket_allocator_t;
01050
01051 private:
01052 node_allocator_t m_node_allocator;
01053 node** m_buckets;
01054 size_type m_bucket_count;
01055 size_type m_element_count;
01056 RehashPolicy m_rehash_policy;
01057
01058 node*
01059 m_allocate_node(const value_type& v);
01060
01061 void
01062 m_deallocate_node(node* n);
01063
01064 void
01065 m_deallocate_nodes(node**, size_type);
01066
01067 node**
01068 m_allocate_buckets(size_type n);
01069
01070 void
01071 m_deallocate_buckets(node**, size_type n);
01072
01073 public:
01074 hashtable(size_type bucket_hint,
01075 const H1&, const H2&, const H&,
01076 const Equal&, const ExtractKey&,
01077 const allocator_type&);
01078
01079 template<typename InIter>
01080 hashtable(InIter first, InIter last,
01081 size_type bucket_hint,
01082 const H1&, const H2&, const H&,
01083 const Equal&, const ExtractKey&,
01084 const allocator_type&);
01085
01086 hashtable(const hashtable&);
01087
01088 hashtable&
01089 operator=(const hashtable&);
01090
01091 ~hashtable();
01092
01093 void swap(hashtable&);
01094
01095 public:
01096 iterator
01097 begin()
01098 {
01099 iterator i(m_buckets);
01100 if (!i.m_cur_node)
01101 i.m_incr_bucket();
01102 return i;
01103 }
01104
01105 const_iterator
01106 begin() const
01107 {
01108 const_iterator i(m_buckets);
01109 if (!i.m_cur_node)
01110 i.m_incr_bucket();
01111 return i;
01112 }
01113
01114 iterator
01115 end()
01116 { return iterator(m_buckets + m_bucket_count); }
01117
01118 const_iterator
01119 end() const
01120 { return const_iterator(m_buckets + m_bucket_count); }
01121
01122 size_type
01123 size() const
01124 { return m_element_count; }
01125
01126 bool
01127 empty() const
01128 { return size() == 0; }
01129
01130 allocator_type
01131 get_allocator() const
01132 { return m_node_allocator; }
01133
01134 size_type
01135 max_size() const
01136 { return m_node_allocator.max_size(); }
01137
01138 public:
01139 key_equal
01140 key_eq() const
01141 { return this->m_eq; }
01142
01143
01144
01145 public:
01146 size_type
01147 bucket_count() const
01148 { return m_bucket_count; }
01149
01150 size_type
01151 max_bucket_count() const
01152 { return max_size(); }
01153
01154 size_type
01155 bucket_size(size_type n) const
01156 { return std::distance(begin(n), end(n)); }
01157
01158 size_type
01159 bucket(const key_type& k) const
01160 {
01161 return this->bucket_index(k, this->m_hash_code(k),
01162 this->m_bucket_count);
01163 }
01164
01165 local_iterator
01166 begin(size_type n)
01167 { return local_iterator(m_buckets[n]); }
01168
01169 local_iterator
01170 end(size_type)
01171 { return local_iterator(0); }
01172
01173 const_local_iterator
01174 begin(size_type n) const
01175 { return const_local_iterator(m_buckets[n]); }
01176
01177 const_local_iterator
01178 end(size_type) const
01179 { return const_local_iterator(0); }
01180
01181 float
01182 load_factor() const
01183 {
01184 return static_cast<float>(size()) / static_cast<float>(bucket_count());
01185 }
01186
01187
01188
01189
01190 const RehashPolicy&
01191 rehash_policy() const
01192 { return m_rehash_policy; }
01193
01194 void
01195 rehash_policy(const RehashPolicy&);
01196
01197 public:
01198 iterator
01199 find(const key_type& k);
01200
01201 const_iterator
01202 find(const key_type& k) const;
01203
01204 size_type
01205 count(const key_type& k) const;
01206
01207 std::pair<iterator, iterator>
01208 equal_range(const key_type& k);
01209
01210 std::pair<const_iterator, const_iterator>
01211 equal_range(const key_type& k) const;
01212
01213 private:
01214
01215
01216
01217
01218 typedef typename Internal::IF<unique_keys,
01219 std::pair<iterator, bool>, iterator>::type
01220 Insert_Return_Type;
01221
01222 typedef typename Internal::IF<unique_keys,
01223 Internal::extract1st<Insert_Return_Type>,
01224 Internal::identity<Insert_Return_Type>
01225 >::type
01226 Insert_Conv_Type;
01227
01228 node*
01229 m_find_node(node*, const key_type&,
01230 typename hashtable::hash_code_t) const;
01231
01232 iterator
01233 m_insert_bucket(const value_type&, size_type,
01234 typename hashtable::hash_code_t);
01235
01236 std::pair<iterator, bool>
01237 m_insert(const value_type&, std::tr1::true_type);
01238
01239 iterator
01240 m_insert(const value_type&, std::tr1::false_type);
01241
01242 void
01243 m_erase_node(node*, node**);
01244
01245 public:
01246 Insert_Return_Type
01247 insert(const value_type& v)
01248 { return m_insert(v, std::tr1::integral_constant<bool, unique_keys>()); }
01249
01250 iterator
01251 insert(iterator, const value_type& v)
01252 { return iterator(Insert_Conv_Type()(this->insert(v))); }
01253
01254 const_iterator
01255 insert(const_iterator, const value_type& v)
01256 { return const_iterator(Insert_Conv_Type()(this->insert(v))); }
01257
01258 template<typename InIter>
01259 void
01260 insert(InIter first, InIter last);
01261
01262 iterator
01263 erase(iterator);
01264
01265 const_iterator
01266 erase(const_iterator);
01267
01268 size_type
01269 erase(const key_type&);
01270
01271 iterator
01272 erase(iterator, iterator);
01273
01274 const_iterator
01275 erase(const_iterator, const_iterator);
01276
01277 void
01278 clear();
01279
01280 public:
01281
01282 void rehash(size_type n);
01283
01284 private:
01285
01286 void m_rehash(size_type n);
01287 };
01288
01289
01290
01291
01292 template<typename K, typename V,
01293 typename A, typename Ex, typename Eq,
01294 typename H1, typename H2, typename H, typename RP,
01295 bool c, bool ci, bool u>
01296 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node*
01297 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01298 m_allocate_node(const value_type& v)
01299 {
01300 node* n = m_node_allocator.allocate(1);
01301 try
01302 {
01303 get_allocator().construct(&n->m_v, v);
01304 n->m_next = 0;
01305 return n;
01306 }
01307 catch(...)
01308 {
01309 m_node_allocator.deallocate(n, 1);
01310 __throw_exception_again;
01311 }
01312 }
01313
01314 template<typename K, typename V,
01315 typename A, typename Ex, typename Eq,
01316 typename H1, typename H2, typename H, typename RP,
01317 bool c, bool ci, bool u>
01318 void
01319 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01320 m_deallocate_node(node* n)
01321 {
01322 get_allocator().destroy(&n->m_v);
01323 m_node_allocator.deallocate(n, 1);
01324 }
01325
01326 template<typename K, typename V,
01327 typename A, typename Ex, typename Eq,
01328 typename H1, typename H2, typename H, typename RP,
01329 bool c, bool ci, bool u>
01330 void
01331 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01332 m_deallocate_nodes(node** array, size_type n)
01333 {
01334 for (size_type i = 0; i < n; ++i)
01335 {
01336 node* p = array[i];
01337 while (p)
01338 {
01339 node* tmp = p;
01340 p = p->m_next;
01341 m_deallocate_node(tmp);
01342 }
01343 array[i] = 0;
01344 }
01345 }
01346
01347 template<typename K, typename V,
01348 typename A, typename Ex, typename Eq,
01349 typename H1, typename H2, typename H, typename RP,
01350 bool c, bool ci, bool u>
01351 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node**
01352 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01353 m_allocate_buckets(size_type n)
01354 {
01355 bucket_allocator_t alloc(m_node_allocator);
01356
01357
01358
01359 node** p = alloc.allocate(n + 1);
01360 std::fill(p, p + n, (node*) 0);
01361 p[n] = reinterpret_cast<node*>(0x1000);
01362 return p;
01363 }
01364
01365 template<typename K, typename V,
01366 typename A, typename Ex, typename Eq,
01367 typename H1, typename H2, typename H, typename RP,
01368 bool c, bool ci, bool u>
01369 void
01370 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01371 m_deallocate_buckets(node** p, size_type n)
01372 {
01373 bucket_allocator_t alloc(m_node_allocator);
01374 alloc.deallocate(p, n + 1);
01375 }
01376
01377 template<typename K, typename V,
01378 typename A, typename Ex, typename Eq,
01379 typename H1, typename H2, typename H, typename RP,
01380 bool c, bool ci, bool u>
01381 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01382 hashtable(size_type bucket_hint,
01383 const H1& h1, const H2& h2, const H& h,
01384 const Eq& eq, const Ex& exk,
01385 const allocator_type& a)
01386 : Internal::rehash_base<RP, hashtable>(),
01387 Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(exk, eq, h1, h2, h),
01388 Internal::map_base<K, V, Ex, u, hashtable>(),
01389 m_node_allocator(a),
01390 m_bucket_count(0),
01391 m_element_count(0),
01392 m_rehash_policy()
01393 {
01394 m_bucket_count = m_rehash_policy.next_bkt(bucket_hint);
01395 m_buckets = m_allocate_buckets(m_bucket_count);
01396 }
01397
01398 template<typename K, typename V,
01399 typename A, typename Ex, typename Eq,
01400 typename H1, typename H2, typename H, typename RP,
01401 bool c, bool ci, bool u>
01402 template<typename InIter>
01403 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01404 hashtable(InIter f, InIter l,
01405 size_type bucket_hint,
01406 const H1& h1, const H2& h2, const H& h,
01407 const Eq& eq, const Ex& exk,
01408 const allocator_type& a)
01409 : Internal::rehash_base<RP, hashtable>(),
01410 Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(exk, eq,
01411 h1, h2, h),
01412 Internal::map_base<K, V, Ex, u, hashtable>(),
01413 m_node_allocator(a),
01414 m_bucket_count(0),
01415 m_element_count(0),
01416 m_rehash_policy()
01417 {
01418 m_bucket_count = std::max(m_rehash_policy.next_bkt(bucket_hint),
01419 m_rehash_policy.
01420 bkt_for_elements(Internal::
01421 distance_fw(f, l)));
01422 m_buckets = m_allocate_buckets(m_bucket_count);
01423 try
01424 {
01425 for (; f != l; ++f)
01426 this->insert(*f);
01427 }
01428 catch(...)
01429 {
01430 clear();
01431 m_deallocate_buckets(m_buckets, m_bucket_count);
01432 __throw_exception_again;
01433 }
01434 }
01435
01436 template<typename K, typename V,
01437 typename A, typename Ex, typename Eq,
01438 typename H1, typename H2, typename H, typename RP,
01439 bool c, bool ci, bool u>
01440 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01441 hashtable(const hashtable& ht)
01442 : Internal::rehash_base<RP, hashtable>(ht),
01443 Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(ht),
01444 Internal::map_base<K, V, Ex, u, hashtable>(ht),
01445 m_node_allocator(ht.get_allocator()),
01446 m_bucket_count(ht.m_bucket_count),
01447 m_element_count(ht.m_element_count),
01448 m_rehash_policy(ht.m_rehash_policy)
01449 {
01450 m_buckets = m_allocate_buckets(m_bucket_count);
01451 try
01452 {
01453 for (size_type i = 0; i < ht.m_bucket_count; ++i)
01454 {
01455 node* n = ht.m_buckets[i];
01456 node** tail = m_buckets + i;
01457 while (n)
01458 {
01459 *tail = m_allocate_node(n->m_v);
01460 this->copy_code(*tail, n);
01461 tail = &((*tail)->m_next);
01462 n = n->m_next;
01463 }
01464 }
01465 }
01466 catch(...)
01467 {
01468 clear();
01469 m_deallocate_buckets(m_buckets, m_bucket_count);
01470 __throw_exception_again;
01471 }
01472 }
01473
01474 template<typename K, typename V,
01475 typename A, typename Ex, typename Eq,
01476 typename H1, typename H2, typename H, typename RP,
01477 bool c, bool ci, bool u>
01478 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>&
01479 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01480 operator=(const hashtable& ht)
01481 {
01482 hashtable tmp(ht);
01483 this->swap(tmp);
01484 return *this;
01485 }
01486
01487 template<typename K, typename V,
01488 typename A, typename Ex, typename Eq,
01489 typename H1, typename H2, typename H, typename RP,
01490 bool c, bool ci, bool u>
01491 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01492 ~hashtable()
01493 {
01494 clear();
01495 m_deallocate_buckets(m_buckets, m_bucket_count);
01496 }
01497
01498 template<typename K, typename V,
01499 typename A, typename Ex, typename Eq,
01500 typename H1, typename H2, typename H, typename RP,
01501 bool c, bool ci, bool u>
01502 void
01503 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01504 swap(hashtable& x)
01505 {
01506
01507
01508
01509 Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>::m_swap(x);
01510
01511
01512
01513 std::swap(m_rehash_policy, x.m_rehash_policy);
01514 std::swap(m_buckets, x.m_buckets);
01515 std::swap(m_bucket_count, x.m_bucket_count);
01516 std::swap(m_element_count, x.m_element_count);
01517 }
01518
01519 template<typename K, typename V,
01520 typename A, typename Ex, typename Eq,
01521 typename H1, typename H2, typename H, typename RP,
01522 bool c, bool ci, bool u>
01523 void
01524 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01525 rehash_policy(const RP& pol)
01526 {
01527 m_rehash_policy = pol;
01528 size_type n_bkt = pol.bkt_for_elements(m_element_count);
01529 if (n_bkt > m_bucket_count)
01530 m_rehash(n_bkt);
01531 }
01532
01533 template<typename K, typename V,
01534 typename A, typename Ex, typename Eq,
01535 typename H1, typename H2, typename H, typename RP,
01536 bool c, bool ci, bool u>
01537 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01538 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01539 find(const key_type& k)
01540 {
01541 typename hashtable::hash_code_t code = this->m_hash_code(k);
01542 std::size_t n = this->bucket_index(k, code, this->bucket_count());
01543 node* p = m_find_node(m_buckets[n], k, code);
01544 return p ? iterator(p, m_buckets + n) : this->end();
01545 }
01546
01547 template<typename K, typename V,
01548 typename A, typename Ex, typename Eq,
01549 typename H1, typename H2, typename H, typename RP,
01550 bool c, bool ci, bool u>
01551 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator
01552 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01553 find(const key_type& k) const
01554 {
01555 typename hashtable::hash_code_t code = this->m_hash_code(k);
01556 std::size_t n = this->bucket_index(k, code, this->bucket_count());
01557 node* p = m_find_node(m_buckets[n], k, code);
01558 return p ? const_iterator(p, m_buckets + n) : this->end();
01559 }
01560
01561 template<typename K, typename V,
01562 typename A, typename Ex, typename Eq,
01563 typename H1, typename H2, typename H, typename RP,
01564 bool c, bool ci, bool u>
01565 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::size_type
01566 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01567 count(const key_type& k) const
01568 {
01569 typename hashtable::hash_code_t code = this->m_hash_code(k);
01570 std::size_t n = this->bucket_index(k, code, this->bucket_count());
01571 std::size_t result = 0;
01572 for (node* p = m_buckets[n]; p; p = p->m_next)
01573 if (this->compare(k, code, p))
01574 ++result;
01575 return result;
01576 }
01577
01578 template<typename K, typename V,
01579 typename A, typename Ex, typename Eq,
01580 typename H1, typename H2, typename H, typename RP,
01581 bool c, bool ci, bool u>
01582 std::pair<typename hashtable<K, V, A, Ex, Eq, H1,
01583 H2, H, RP, c, ci, u>::iterator,
01584 typename hashtable<K, V, A, Ex, Eq, H1,
01585 H2, H, RP, c, ci, u>::iterator>
01586 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01587 equal_range(const key_type& k)
01588 {
01589 typename hashtable::hash_code_t code = this->m_hash_code(k);
01590 std::size_t n = this->bucket_index(k, code, this->bucket_count());
01591 node** head = m_buckets + n;
01592 node* p = m_find_node(*head, k, code);
01593
01594 if (p)
01595 {
01596 node* p1 = p->m_next;
01597 for (; p1; p1 = p1->m_next)
01598 if (!this->compare(k, code, p1))
01599 break;
01600
01601 iterator first(p, head);
01602 iterator last(p1, head);
01603 if (!p1)
01604 last.m_incr_bucket();
01605 return std::make_pair(first, last);
01606 }
01607 else
01608 return std::make_pair(this->end(), this->end());
01609 }
01610
01611 template<typename K, typename V,
01612 typename A, typename Ex, typename Eq,
01613 typename H1, typename H2, typename H, typename RP,
01614 bool c, bool ci, bool u>
01615 std::pair<typename hashtable<K, V, A, Ex, Eq, H1,
01616 H2, H, RP, c, ci, u>::const_iterator,
01617 typename hashtable<K, V, A, Ex, Eq, H1,
01618 H2, H, RP, c, ci, u>::const_iterator>
01619 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01620 equal_range(const key_type& k) const
01621 {
01622 typename hashtable::hash_code_t code = this->m_hash_code(k);
01623 std::size_t n = this->bucket_index(k, code, this->bucket_count());
01624 node** head = m_buckets + n;
01625 node* p = m_find_node(*head, k, code);
01626
01627 if (p)
01628 {
01629 node* p1 = p->m_next;
01630 for (; p1; p1 = p1->m_next)
01631 if (!this->compare(k, code, p1))
01632 break;
01633
01634 const_iterator first(p, head);
01635 const_iterator last(p1, head);
01636 if (!p1)
01637 last.m_incr_bucket();
01638 return std::make_pair(first, last);
01639 }
01640 else
01641 return std::make_pair(this->end(), this->end());
01642 }
01643
01644
01645
01646 template<typename K, typename V,
01647 typename A, typename Ex, typename Eq,
01648 typename H1, typename H2, typename H, typename RP,
01649 bool c, bool ci, bool u>
01650 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node*
01651 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01652 m_find_node(node* p, const key_type& k,
01653 typename hashtable::hash_code_t code) const
01654 {
01655 for (; p; p = p->m_next)
01656 if (this->compare(k, code, p))
01657 return p;
01658 return false;
01659 }
01660
01661
01662 template<typename K, typename V,
01663 typename A, typename Ex, typename Eq,
01664 typename H1, typename H2, typename H, typename RP,
01665 bool c, bool ci, bool u>
01666 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01667 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01668 m_insert_bucket(const value_type& v, size_type n,
01669 typename hashtable::hash_code_t code)
01670 {
01671 std::pair<bool, std::size_t> do_rehash
01672 = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
01673
01674
01675
01676 node* new_node = m_allocate_node(v);
01677
01678 try
01679 {
01680 if (do_rehash.first)
01681 {
01682 const key_type& k = this->m_extract(v);
01683 n = this->bucket_index(k, code, do_rehash.second);
01684 m_rehash(do_rehash.second);
01685 }
01686
01687 new_node->m_next = m_buckets[n];
01688 this->store_code(new_node, code);
01689 m_buckets[n] = new_node;
01690 ++m_element_count;
01691 return iterator(new_node, m_buckets + n);
01692 }
01693 catch(...)
01694 {
01695 m_deallocate_node(new_node);
01696 __throw_exception_again;
01697 }
01698 }
01699
01700
01701 template<typename K, typename V,
01702 typename A, typename Ex, typename Eq,
01703 typename H1, typename H2, typename H, typename RP,
01704 bool c, bool ci, bool u>
01705 std::pair<typename hashtable<K, V, A, Ex, Eq, H1,
01706 H2, H, RP, c, ci, u>::iterator, bool>
01707 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01708 m_insert(const value_type& v, std::tr1::true_type)
01709 {
01710 const key_type& k = this->m_extract(v);
01711 typename hashtable::hash_code_t code = this->m_hash_code(k);
01712 size_type n = this->bucket_index(k, code, m_bucket_count);
01713
01714 if (node* p = m_find_node(m_buckets[n], k, code))
01715 return std::make_pair(iterator(p, m_buckets + n), false);
01716 return std::make_pair(m_insert_bucket(v, n, code), true);
01717 }
01718
01719
01720 template<typename K, typename V,
01721 typename A, typename Ex, typename Eq,
01722 typename H1, typename H2, typename H, typename RP,
01723 bool c, bool ci, bool u>
01724 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01725 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01726 m_insert(const value_type& v, std::tr1::false_type)
01727 {
01728 std::pair<bool, std::size_t> do_rehash
01729 = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
01730 if (do_rehash.first)
01731 m_rehash(do_rehash.second);
01732
01733 const key_type& k = this->m_extract(v);
01734 typename hashtable::hash_code_t code = this->m_hash_code(k);
01735 size_type n = this->bucket_index(k, code, m_bucket_count);
01736
01737
01738 node* prev = m_find_node(m_buckets[n], k, code);
01739 node* new_node = m_allocate_node(v);
01740
01741 if (prev)
01742 {
01743 new_node->m_next = prev->m_next;
01744 prev->m_next = new_node;
01745 }
01746 else
01747 {
01748 new_node->m_next = m_buckets[n];
01749 m_buckets[n] = new_node;
01750 }
01751 this->store_code(new_node, code);
01752
01753 ++m_element_count;
01754 return iterator(new_node, m_buckets + n);
01755 }
01756
01757
01758 template<typename K, typename V,
01759 typename A, typename Ex, typename Eq,
01760 typename H1, typename H2, typename H, typename RP,
01761 bool c, bool ci, bool u>
01762 void
01763 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01764 m_erase_node(node* p, node** b)
01765 {
01766 node* cur = *b;
01767 if (cur == p)
01768 *b = cur->m_next;
01769 else
01770 {
01771 node* next = cur->m_next;
01772 while (next != p)
01773 {
01774 cur = next;
01775 next = cur->m_next;
01776 }
01777 cur->m_next = next->m_next;
01778 }
01779
01780 m_deallocate_node(p);
01781 --m_element_count;
01782 }
01783
01784 template<typename K, typename V,
01785 typename A, typename Ex, typename Eq,
01786 typename H1, typename H2, typename H, typename RP,
01787 bool c, bool ci, bool u>
01788 template<typename InIter>
01789 void
01790 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01791 insert(InIter first, InIter last)
01792 {
01793 size_type n_elt = Internal::distance_fw(first, last);
01794 std::pair<bool, std::size_t> do_rehash
01795 = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, n_elt);
01796 if (do_rehash.first)
01797 m_rehash(do_rehash.second);
01798
01799 for (; first != last; ++first)
01800 this->insert(*first);
01801 }
01802
01803 template<typename K, typename V,
01804 typename A, typename Ex, typename Eq,
01805 typename H1, typename H2, typename H, typename RP,
01806 bool c, bool ci, bool u>
01807 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01808 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01809 erase(iterator it)
01810 {
01811 iterator result = it;
01812 ++result;
01813 m_erase_node(it.m_cur_node, it.m_cur_bucket);
01814 return result;
01815 }
01816
01817 template<typename K, typename V,
01818 typename A, typename Ex, typename Eq,
01819 typename H1, typename H2, typename H, typename RP,
01820 bool c, bool ci, bool u>
01821 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator
01822 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01823 erase(const_iterator it)
01824 {
01825 const_iterator result = it;
01826 ++result;
01827 m_erase_node(it.m_cur_node, it.m_cur_bucket);
01828 return result;
01829 }
01830
01831 template<typename K, typename V,
01832 typename A, typename Ex, typename Eq,
01833 typename H1, typename H2, typename H, typename RP,
01834 bool c, bool ci, bool u>
01835 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::size_type
01836 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01837 erase(const key_type& k)
01838 {
01839 typename hashtable::hash_code_t code = this->m_hash_code(k);
01840 size_type n = this->bucket_index(k, code, m_bucket_count);
01841 size_type result = 0;
01842
01843 node** slot = m_buckets + n;
01844 while (*slot && !this->compare(k, code, *slot))
01845 slot = &((*slot)->m_next);
01846
01847 while (*slot && this->compare(k, code, *slot))
01848 {
01849 node* p = *slot;
01850 *slot = p->m_next;
01851 m_deallocate_node(p);
01852 --m_element_count;
01853 ++result;
01854 }
01855
01856 return result;
01857 }
01858
01859
01860
01861
01862 template<typename K, typename V,
01863 typename A, typename Ex, typename Eq,
01864 typename H1, typename H2, typename H, typename RP,
01865 bool c, bool ci, bool u>
01866 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01867 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01868 erase(iterator first, iterator last)
01869 {
01870 while (first != last)
01871 first = this->erase(first);
01872 return last;
01873 }
01874
01875 template<typename K, typename V,
01876 typename A, typename Ex, typename Eq,
01877 typename H1, typename H2, typename H, typename RP,
01878 bool c, bool ci, bool u>
01879 typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator
01880 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01881 erase(const_iterator first, const_iterator last)
01882 {
01883 while (first != last)
01884 first = this->erase(first);
01885 return last;
01886 }
01887
01888 template<typename K, typename V,
01889 typename A, typename Ex, typename Eq,
01890 typename H1, typename H2, typename H, typename RP,
01891 bool c, bool ci, bool u>
01892 void
01893 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01894 clear()
01895 {
01896 m_deallocate_nodes(m_buckets, m_bucket_count);
01897 m_element_count = 0;
01898 }
01899
01900 template<typename K, typename V,
01901 typename A, typename Ex, typename Eq,
01902 typename H1, typename H2, typename H, typename RP,
01903 bool c, bool ci, bool u>
01904 void
01905 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01906 rehash(size_type n)
01907 {
01908 m_rehash(std::max(m_rehash_policy.next_bkt(n),
01909 m_rehash_policy.bkt_for_elements(m_element_count
01910 + 1)));
01911 }
01912
01913 template<typename K, typename V,
01914 typename A, typename Ex, typename Eq,
01915 typename H1, typename H2, typename H, typename RP,
01916 bool c, bool ci, bool u>
01917 void
01918 hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01919 m_rehash(size_type n)
01920 {
01921 node** new_array = m_allocate_buckets(n);
01922 try
01923 {
01924 for (size_type i = 0; i < m_bucket_count; ++i)
01925 while (node* p = m_buckets[i])
01926 {
01927 size_type new_index = this->bucket_index(p, n);
01928 m_buckets[i] = p->m_next;
01929 p->m_next = new_array[new_index];
01930 new_array[new_index] = p;
01931 }
01932 m_deallocate_buckets(m_buckets, m_bucket_count);
01933 m_bucket_count = n;
01934 m_buckets = new_array;
01935 }
01936 catch(...)
01937 {
01938
01939
01940
01941
01942 m_deallocate_nodes(new_array, n);
01943 m_deallocate_buckets(new_array, n);
01944 m_deallocate_nodes(m_buckets, m_bucket_count);
01945 m_element_count = 0;
01946 __throw_exception_again;
01947 }
01948 }
01949 }
01950 }
01951
01952 #endif
01953