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