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
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
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 #ifndef _SPARSEHASHTABLE_H_
00092 #define _SPARSEHASHTABLE_H_
00093
00094 #ifndef SPARSEHASH_STAT_UPDATE
00095 #define SPARSEHASH_STAT_UPDATE(x) ((void) 0)
00096 #endif
00097
00098
00099
00100
00101
00102 #define JUMP_(key, num_probes) ( num_probes )
00103
00104
00105
00106
00107
00108 #if defined(Q_OS_WIN)
00109 #include "sparseconfig_windows.h"
00110 #else
00111 #include "sparseconfig.h"
00112 #endif
00113 #include <assert.h>
00114 #include <algorithm>
00115 #include <iterator>
00116 #include <utility>
00117 #include <google/sparsetable>
00118
00119 _START_GOOGLE_NAMESPACE_
00120
00121 using STL_NAMESPACE::pair;
00122
00123
00124
00125
00126
00127 template <class Value, class Key, class HashFcn,
00128 class ExtractKey, class EqualKey, class Alloc>
00129 class sparse_hashtable;
00130
00131 template <class V, class K, class HF, class ExK, class EqK, class A>
00132 struct sparse_hashtable_iterator;
00133
00134 template <class V, class K, class HF, class ExK, class EqK, class A>
00135 struct sparse_hashtable_const_iterator;
00136
00137
00138
00139 template <class V, class K, class HF, class ExK, class EqK, class A>
00140 struct sparse_hashtable_iterator {
00141 public:
00142 typedef sparse_hashtable_iterator<V,K,HF,ExK,EqK,A> iterator;
00143 typedef sparse_hashtable_const_iterator<V,K,HF,ExK,EqK,A> const_iterator;
00144 typedef typename sparsetable<V>::nonempty_iterator st_iterator;
00145
00146 typedef STL_NAMESPACE::forward_iterator_tag iterator_category;
00147 typedef V value_type;
00148 typedef ptrdiff_t difference_type;
00149 typedef size_t size_type;
00150 typedef V& reference;
00151 typedef V* pointer;
00152
00153
00154 sparse_hashtable_iterator(const sparse_hashtable<V,K,HF,ExK,EqK,A> *h,
00155 st_iterator it, st_iterator it_end)
00156 : ht(h), pos(it), end(it_end) { advance_past_deleted(); }
00157 sparse_hashtable_iterator() { }
00158
00159
00160
00161
00162 reference operator*() const { return *pos; }
00163 pointer operator->() const { return &(operator*()); }
00164
00165
00166
00167 void advance_past_deleted() {
00168 while ( pos != end && ht->test_deleted(*this) )
00169 ++pos;
00170 }
00171 iterator& operator++() {
00172 assert(pos != end); ++pos; advance_past_deleted(); return *this;
00173 }
00174 iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
00175
00176
00177 bool operator==(const iterator& it) const { return pos == it.pos; }
00178 bool operator!=(const iterator& it) const { return pos != it.pos; }
00179
00180
00181
00182 const sparse_hashtable<V,K,HF,ExK,EqK,A> *ht;
00183 st_iterator pos, end;
00184 };
00185
00186
00187 template <class V, class K, class HF, class ExK, class EqK, class A>
00188 struct sparse_hashtable_const_iterator {
00189 public:
00190 typedef sparse_hashtable_iterator<V,K,HF,ExK,EqK,A> iterator;
00191 typedef sparse_hashtable_const_iterator<V,K,HF,ExK,EqK,A> const_iterator;
00192 typedef typename sparsetable<V>::const_nonempty_iterator st_iterator;
00193
00194 typedef STL_NAMESPACE::forward_iterator_tag iterator_category;
00195 typedef V value_type;
00196 typedef ptrdiff_t difference_type;
00197 typedef size_t size_type;
00198 typedef const V& reference;
00199 typedef const V* pointer;
00200
00201
00202 sparse_hashtable_const_iterator(const sparse_hashtable<V,K,HF,ExK,EqK,A> *h,
00203 st_iterator it, st_iterator it_end)
00204 : ht(h), pos(it), end(it_end) { advance_past_deleted(); }
00205
00206 sparse_hashtable_const_iterator() { }
00207 sparse_hashtable_const_iterator(const iterator &it)
00208 : ht(it.ht), pos(it.pos), end(it.end) { }
00209
00210
00211
00212
00213 reference operator*() const { return *pos; }
00214 pointer operator->() const { return &(operator*()); }
00215
00216
00217
00218 void advance_past_deleted() {
00219 while ( pos != end && ht->test_deleted(*this) )
00220 ++pos;
00221 }
00222 const_iterator& operator++() {
00223 assert(pos != end); ++pos; advance_past_deleted(); return *this;
00224 }
00225 const_iterator operator++(int) { const_iterator tmp(*this); ++*this; return tmp; }
00226
00227
00228 bool operator==(const const_iterator& it) const { return pos == it.pos; }
00229 bool operator!=(const const_iterator& it) const { return pos != it.pos; }
00230
00231
00232
00233 const sparse_hashtable<V,K,HF,ExK,EqK,A> *ht;
00234 st_iterator pos, end;
00235 };
00236
00237
00238 template <class V, class K, class HF, class ExK, class EqK, class A>
00239 struct sparse_hashtable_destructive_iterator {
00240 public:
00241 typedef sparse_hashtable_destructive_iterator<V,K,HF,ExK,EqK,A> iterator;
00242 typedef typename sparsetable<V>::destructive_iterator st_iterator;
00243
00244 typedef STL_NAMESPACE::forward_iterator_tag iterator_category;
00245 typedef V value_type;
00246 typedef ptrdiff_t difference_type;
00247 typedef size_t size_type;
00248 typedef V& reference;
00249 typedef V* pointer;
00250
00251
00252 sparse_hashtable_destructive_iterator(const
00253 sparse_hashtable<V,K,HF,ExK,EqK,A> *h,
00254 st_iterator it, st_iterator it_end)
00255 : ht(h), pos(it), end(it_end) { advance_past_deleted(); }
00256 sparse_hashtable_destructive_iterator() { }
00257
00258
00259
00260
00261 reference operator*() const { return *pos; }
00262 pointer operator->() const { return &(operator*()); }
00263
00264
00265
00266 void advance_past_deleted() {
00267 while ( pos != end && ht->test_deleted(*this) )
00268 ++pos;
00269 }
00270 iterator& operator++() {
00271 assert(pos != end); ++pos; advance_past_deleted(); return *this;
00272 }
00273 iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
00274
00275
00276 bool operator==(const iterator& it) const { return pos == it.pos; }
00277 bool operator!=(const iterator& it) const { return pos != it.pos; }
00278
00279
00280
00281 const sparse_hashtable<V,K,HF,ExK,EqK,A> *ht;
00282 st_iterator pos, end;
00283 };
00284
00285
00286 template <class Value, class Key, class HashFcn,
00287 class ExtractKey, class EqualKey, class Alloc>
00288 class sparse_hashtable {
00289 public:
00290 typedef Key key_type;
00291 typedef Value value_type;
00292 typedef HashFcn hasher;
00293 typedef EqualKey key_equal;
00294
00295 typedef size_t size_type;
00296 typedef ptrdiff_t difference_type;
00297 typedef value_type* pointer;
00298 typedef const value_type* const_pointer;
00299 typedef value_type& reference;
00300 typedef const value_type& const_reference;
00301 typedef sparse_hashtable_iterator<Value, Key, HashFcn,
00302 ExtractKey, EqualKey, Alloc>
00303 iterator;
00304
00305 typedef sparse_hashtable_const_iterator<Value, Key, HashFcn,
00306 ExtractKey, EqualKey, Alloc>
00307 const_iterator;
00308
00309 typedef sparse_hashtable_destructive_iterator<Value, Key, HashFcn,
00310 ExtractKey, EqualKey, Alloc>
00311 destructive_iterator;
00312
00313
00314
00315 static const float HT_OCCUPANCY_FLT;
00316
00317
00318
00319 static const float HT_EMPTY_FLT;
00320
00321
00322
00323
00324
00325 static const size_t HT_MIN_BUCKETS = 32;
00326
00327
00328
00329 iterator begin() { return iterator(this, table.nonempty_begin(),
00330 table.nonempty_end()); }
00331 iterator end() { return iterator(this, table.nonempty_end(),
00332 table.nonempty_end()); }
00333 const_iterator begin() const { return const_iterator(this,
00334 table.nonempty_begin(),
00335 table.nonempty_end()); }
00336 const_iterator end() const { return const_iterator(this,
00337 table.nonempty_end(),
00338 table.nonempty_end()); }
00339
00340
00341 destructive_iterator destructive_begin() {
00342 return destructive_iterator(this, table.destructive_begin(),
00343 table.destructive_end());
00344 }
00345 destructive_iterator destructive_end() {
00346 return destructive_iterator(this, table.destructive_end(),
00347 table.destructive_end());
00348 }
00349
00350
00351
00352 hasher hash_funct() const { return hash; }
00353 key_equal key_eq() const { return equals; }
00354
00355
00356
00357
00358
00359
00360 private:
00361 void set_value(value_type* dst, const value_type src) {
00362 dst->~value_type();
00363 new(dst) value_type(src);
00364 }
00365
00366
00367
00368
00369
00370 enum MoveDontCopyT {MoveDontCopy, MoveDontGrow};
00371
00372
00373
00374
00375
00376
00377
00378
00379 private:
00380 void squash_deleted() {
00381 if ( num_deleted ) {
00382 sparse_hashtable tmp(MoveDontGrow, *this);
00383 swap(tmp);
00384 }
00385 assert(num_deleted == 0);
00386 }
00387
00388 public:
00389 void set_deleted_key(const value_type &val) {
00390
00391 squash_deleted();
00392 use_deleted = true;
00393 set_value(&delval, val);
00394 }
00395 void clear_deleted_key() {
00396 squash_deleted();
00397 use_deleted = false;
00398 }
00399
00400
00401
00402 bool test_deleted(size_type bucknum) const {
00403
00404
00405 return (use_deleted && num_deleted > 0 && table.test(bucknum) &&
00406 equals(get_key(delval), get_key(table.get(bucknum))));
00407 }
00408 bool test_deleted(const iterator &it) const {
00409 return (use_deleted && num_deleted > 0 &&
00410 equals(get_key(delval), get_key(*it)));
00411 }
00412 bool test_deleted(const const_iterator &it) const {
00413 return (use_deleted && num_deleted > 0 &&
00414 equals(get_key(delval), get_key(*it)));
00415 }
00416 bool test_deleted(const destructive_iterator &it) const {
00417 return (use_deleted && num_deleted > 0 &&
00418 equals(get_key(delval), get_key(*it)));
00419 }
00420
00421
00422 bool set_deleted(const_iterator &it) {
00423 assert(use_deleted);
00424 bool retval = !test_deleted(it);
00425
00426 set_value(const_cast<value_type*>(&(*it)), delval);
00427 return retval;
00428 }
00429
00430 bool clear_deleted(const_iterator &it) {
00431 assert(use_deleted);
00432
00433 return test_deleted(it);
00434 }
00435
00436
00437
00438 size_type size() const { return table.num_nonempty() - num_deleted; }
00439
00440 size_type max_size() const { return (size_type(-1) >> 1U) + 1; }
00441 bool empty() const { return size() == 0; }
00442 size_type bucket_count() const { return table.size(); }
00443 size_type max_bucket_count() const { return max_size(); }
00444
00445 private:
00446
00447 static const size_type ILLEGAL_BUCKET = size_type(-1);
00448
00449 private:
00450
00451
00452 size_type min_size(size_type num_elts, size_type min_buckets_wanted) {
00453 size_type sz = HT_MIN_BUCKETS;
00454 while ( sz < min_buckets_wanted || num_elts >= sz * HT_OCCUPANCY_FLT )
00455 sz *= 2;
00456 return sz;
00457 }
00458
00459
00460 void maybe_shrink() {
00461 assert(table.num_nonempty() >= num_deleted);
00462 assert((bucket_count() & (bucket_count()-1)) == 0);
00463 assert(bucket_count() >= HT_MIN_BUCKETS);
00464
00465 if ( (table.num_nonempty()-num_deleted) <= shrink_threshold &&
00466 bucket_count() > HT_MIN_BUCKETS ) {
00467 size_type sz = bucket_count() / 2;
00468 while ( sz > HT_MIN_BUCKETS &&
00469 (table.num_nonempty() - num_deleted) <= sz * HT_EMPTY_FLT )
00470 sz /= 2;
00471 sparse_hashtable tmp(MoveDontCopy, *this, sz);
00472 swap(tmp);
00473 }
00474 consider_shrink = false;
00475 }
00476
00477
00478
00479 void resize_delta(size_type delta, size_type min_buckets_wanted = 0) {
00480 if ( consider_shrink )
00481 maybe_shrink();
00482 if ( bucket_count() > min_buckets_wanted &&
00483 (table.num_nonempty() + delta) <= enlarge_threshold )
00484 return;
00485
00486
00487
00488
00489
00490
00491
00492 const size_type needed_size = min_size(table.num_nonempty() + delta,
00493 min_buckets_wanted);
00494 if ( needed_size > bucket_count() ) {
00495 const size_type resize_to = min_size(table.num_nonempty() - num_deleted
00496 + delta, min_buckets_wanted);
00497 sparse_hashtable tmp(MoveDontCopy, *this, resize_to);
00498 swap(tmp);
00499 }
00500 }
00501
00502
00503 void copy_from(const sparse_hashtable &ht, size_type min_buckets_wanted = 0) {
00504 clear();
00505
00506
00507 const size_type resize_to = min_size(ht.size(), min_buckets_wanted);
00508 if ( resize_to > bucket_count() ) {
00509 table.resize(resize_to);
00510 reset_thresholds();
00511 }
00512
00513
00514
00515
00516 assert( (bucket_count() & (bucket_count()-1)) == 0);
00517 for ( const_iterator it = ht.begin(); it != ht.end(); ++it ) {
00518 size_type num_probes = 0;
00519 size_type bucknum;
00520 const size_type bucket_count_minus_one = bucket_count() - 1;
00521 for (bucknum = hash(get_key(*it)) & bucket_count_minus_one;
00522 table.test(bucknum);
00523 bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one) {
00524 ++num_probes;
00525 assert(num_probes < bucket_count());
00526 }
00527 table.set(bucknum, *it);
00528 }
00529 }
00530
00531
00532
00533
00534 void move_from(MoveDontCopyT mover, sparse_hashtable &ht,
00535 size_type min_buckets_wanted = 0) {
00536 clear();
00537
00538
00539 size_t resize_to;
00540 if ( mover == MoveDontGrow )
00541 resize_to = ht.bucket_count();
00542 else
00543 resize_to = min_size(ht.size(), min_buckets_wanted);
00544 if ( resize_to > bucket_count() ) {
00545 table.resize(resize_to);
00546 reset_thresholds();
00547 }
00548
00549
00550
00551
00552 assert( (bucket_count() & (bucket_count()-1)) == 0);
00553
00554 for ( destructive_iterator it = ht.destructive_begin();
00555 it != ht.destructive_end(); ++it ) {
00556 size_type num_probes = 0;
00557 size_type bucknum;
00558 for ( bucknum = hash(get_key(*it)) & (bucket_count()-1);
00559 table.test(bucknum);
00560 bucknum = (bucknum + JUMP_(key, num_probes)) & (bucket_count()-1) ) {
00561 ++num_probes;
00562 assert(num_probes < bucket_count());
00563 }
00564 table.set(bucknum, *it);
00565 }
00566 }
00567
00568
00569
00570 public:
00571
00572
00573
00574 void resize(size_type req_elements) {
00575 if ( consider_shrink || req_elements == 0 )
00576 maybe_shrink();
00577 if ( req_elements > table.num_nonempty() )
00578 resize_delta(req_elements - table.num_nonempty(), 0);
00579 }
00580
00581
00582
00583
00584
00585
00586 explicit sparse_hashtable(size_type n = 0,
00587 const HashFcn& hf = HashFcn(),
00588 const EqualKey& eql = EqualKey(),
00589 const ExtractKey& ext = ExtractKey())
00590 : hash(hf), equals(eql), get_key(ext), num_deleted(0),
00591 use_deleted(false), delval(), table(min_size(0, n)) {
00592 reset_thresholds();
00593 }
00594
00595
00596
00597
00598
00599 sparse_hashtable(const sparse_hashtable& ht, size_type min_buckets_wanted = 0)
00600 : hash(ht.hash), equals(ht.equals), get_key(ht.get_key),
00601 num_deleted(0), use_deleted(ht.use_deleted), delval(ht.delval), table() {
00602 reset_thresholds();
00603 copy_from(ht, min_buckets_wanted);
00604 }
00605 sparse_hashtable(MoveDontCopyT mover, sparse_hashtable& ht,
00606 size_type min_buckets_wanted=0)
00607 : hash(ht.hash), equals(ht.equals), get_key(ht.get_key),
00608 num_deleted(0), use_deleted(ht.use_deleted), delval(ht.delval), table() {
00609 reset_thresholds();
00610 move_from(mover, ht, min_buckets_wanted);
00611 }
00612
00613 sparse_hashtable& operator= (const sparse_hashtable& ht) {
00614 if (&ht == this) return *this;
00615 clear();
00616 hash = ht.hash;
00617 equals = ht.equals;
00618 get_key = ht.get_key;
00619 use_deleted = ht.use_deleted;
00620 set_value(&delval, ht.delval);
00621 copy_from(ht);
00622 return *this;
00623 }
00624
00625
00626 void swap(sparse_hashtable& ht) {
00627 STL_NAMESPACE::swap(hash, ht.hash);
00628 STL_NAMESPACE::swap(equals, ht.equals);
00629 STL_NAMESPACE::swap(get_key, ht.get_key);
00630 STL_NAMESPACE::swap(num_deleted, ht.num_deleted);
00631 STL_NAMESPACE::swap(use_deleted, ht.use_deleted);
00632 { value_type tmp;
00633 set_value(&tmp, delval);
00634 set_value(&delval, ht.delval);
00635 set_value(&ht.delval, tmp);
00636 }
00637 table.swap(ht.table);
00638 reset_thresholds();
00639 ht.reset_thresholds();
00640 }
00641
00642
00643 void clear() {
00644 table.clear();
00645 reset_thresholds();
00646 num_deleted = 0;
00647 }
00648
00649
00650
00651 private:
00652
00653
00654
00655
00656
00657 pair<size_type, size_type> find_position(const key_type &key) const {
00658 size_type num_probes = 0;
00659 const size_type bucket_count_minus_one = bucket_count() - 1;
00660 size_type bucknum = hash(key) & bucket_count_minus_one;
00661 size_type insert_pos = ILLEGAL_BUCKET;
00662 SPARSEHASH_STAT_UPDATE(total_lookups += 1);
00663 while ( 1 ) {
00664 if ( !table.test(bucknum) ) {
00665 SPARSEHASH_STAT_UPDATE(total_probes += num_probes);
00666 if ( insert_pos == ILLEGAL_BUCKET )
00667 return pair<size_type,size_type>(ILLEGAL_BUCKET, bucknum);
00668 else
00669 return pair<size_type,size_type>(ILLEGAL_BUCKET, insert_pos);
00670
00671 } else if ( test_deleted(bucknum) ) {
00672 if ( insert_pos == ILLEGAL_BUCKET )
00673 insert_pos = bucknum;
00674
00675 } else if ( equals(key, get_key(table.get(bucknum))) ) {
00676 SPARSEHASH_STAT_UPDATE(total_probes += num_probes);
00677 return pair<size_type,size_type>(bucknum, ILLEGAL_BUCKET);
00678 }
00679 ++num_probes;
00680 bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one;
00681 assert(num_probes < bucket_count());
00682 }
00683 }
00684
00685 public:
00686 iterator find(const key_type& key) {
00687 if ( size() == 0 ) return end();
00688 pair<size_type, size_type> pos = find_position(key);
00689 if ( pos.first == ILLEGAL_BUCKET )
00690 return end();
00691 else
00692 return iterator(this, table.get_iter(pos.first), table.nonempty_end());
00693 }
00694
00695 const_iterator find(const key_type& key) const {
00696 if ( size() == 0 ) return end();
00697 pair<size_type, size_type> pos = find_position(key);
00698 if ( pos.first == ILLEGAL_BUCKET )
00699 return end();
00700 else
00701 return const_iterator(this,
00702 table.get_iter(pos.first), table.nonempty_end());
00703 }
00704
00705
00706 size_type count(const key_type &key) const {
00707 pair<size_type, size_type> pos = find_position(key);
00708 return pos.first == ILLEGAL_BUCKET ? 0 : 1;
00709 }
00710
00711
00712 pair<iterator,iterator> equal_range(const key_type& key) {
00713 const iterator pos = find(key);
00714 return pair<iterator,iterator>(pos, pos);
00715 }
00716 pair<const_iterator,const_iterator> equal_range(const key_type& key) const {
00717 const const_iterator pos = find(key);
00718 return pair<iterator,iterator>(pos, pos);
00719 }
00720
00721
00722
00723 private:
00724
00725 pair<iterator, bool> insert_noresize(const value_type& obj) {
00726 const pair<size_type,size_type> pos = find_position(get_key(obj));
00727 if ( pos.first != ILLEGAL_BUCKET) {
00728 return pair<iterator,bool>(iterator(this, table.get_iter(pos.first),
00729 table.nonempty_end()),
00730 false);
00731 } else {
00732 if ( test_deleted(pos.second) ) {
00733
00734 assert(num_deleted > 0);
00735 --num_deleted;
00736 }
00737 table.set(pos.second, obj);
00738 return pair<iterator,bool>(iterator(this, table.get_iter(pos.second),
00739 table.nonempty_end()),
00740 true);
00741 }
00742 }
00743
00744 public:
00745
00746 pair<iterator, bool> insert(const value_type& obj) {
00747 resize_delta(1);
00748 return insert_noresize(obj);
00749 }
00750
00751
00752 template <class InputIterator>
00753 void insert(InputIterator f, InputIterator l) {
00754
00755 insert(f, l, typename STL_NAMESPACE::iterator_traits<InputIterator>::iterator_category());
00756 }
00757
00758
00759 template <class ForwardIterator>
00760 void insert(ForwardIterator f, ForwardIterator l,
00761 STL_NAMESPACE::forward_iterator_tag) {
00762 size_type n = STL_NAMESPACE::distance(f, l);
00763 resize_delta(n);
00764 for ( ; n > 0; --n, ++f)
00765 insert_noresize(*f);
00766 }
00767
00768
00769 template <class InputIterator>
00770 void insert(InputIterator f, InputIterator l,
00771 STL_NAMESPACE::input_iterator_tag) {
00772 for ( ; f != l; ++f)
00773 insert(*f);
00774 }
00775
00776
00777
00778 size_type erase(const key_type& key) {
00779 const_iterator pos = find(key);
00780 if ( pos != end() ) {
00781 assert(!test_deleted(pos));
00782 set_deleted(pos);
00783 ++num_deleted;
00784 consider_shrink = true;
00785 return 1;
00786 } else {
00787 return 0;
00788 }
00789 }
00790
00791
00792
00793
00794 void erase(const_iterator pos) {
00795 if ( pos == end() ) return;
00796 if ( set_deleted(pos) ) {
00797 ++num_deleted;
00798 consider_shrink = true;
00799 }
00800 }
00801
00802 void erase(const_iterator f, const_iterator l) {
00803 for ( ; f != l; ++f) {
00804 if ( set_deleted(f) )
00805 ++num_deleted;
00806 }
00807 consider_shrink = true;
00808 }
00809
00810
00811
00812 bool operator==(const sparse_hashtable& ht) const {
00813
00814
00815 return ( num_deleted == ht.num_deleted && table == ht.table );
00816 }
00817 bool operator!=(const sparse_hashtable& ht) const {
00818 return !(*this == ht);
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828 bool write_metadata(FILE *fp) {
00829 squash_deleted();
00830 return table.write_metadata(fp);
00831 }
00832
00833 bool read_metadata(FILE *fp) {
00834 num_deleted = 0;
00835 bool result = table.read_metadata(fp);
00836 reset_thresholds();
00837 return result;
00838 }
00839
00840
00841 bool write_nopointer_data(FILE *fp) {
00842 return table.write_nopointer_data(fp);
00843 }
00844
00845
00846 bool read_nopointer_data(FILE *fp) {
00847 return table.read_nopointer_data(fp);
00848 }
00849
00850 private:
00851
00852 hasher hash;
00853 key_equal equals;
00854 ExtractKey get_key;
00855 size_type num_deleted;
00856 bool use_deleted;
00857 value_type delval;
00858 sparsetable<value_type> table;
00859 size_type shrink_threshold;
00860 size_type enlarge_threshold;
00861 bool consider_shrink;
00862
00863 void reset_thresholds() {
00864 enlarge_threshold = static_cast<size_type>(table.size()*HT_OCCUPANCY_FLT);
00865 shrink_threshold = static_cast<size_type>(table.size()*HT_EMPTY_FLT);
00866 consider_shrink = false;
00867 }
00868 };
00869
00870
00871 template <class V, class K, class HF, class ExK, class EqK, class A>
00872 inline void swap(sparse_hashtable<V,K,HF,ExK,EqK,A> &x,
00873 sparse_hashtable<V,K,HF,ExK,EqK,A> &y) {
00874 x.swap(y);
00875 }
00876
00877 #undef JUMP_
00878
00879 template <class V, class K, class HF, class ExK, class EqK, class A>
00880 const typename sparse_hashtable<V,K,HF,ExK,EqK,A>::size_type
00881 sparse_hashtable<V,K,HF,ExK,EqK,A>::ILLEGAL_BUCKET;
00882
00883
00884
00885 template <class V, class K, class HF, class ExK, class EqK, class A>
00886 const float sparse_hashtable<V,K,HF,ExK,EqK,A>::HT_OCCUPANCY_FLT = 0.8f;
00887
00888
00889
00890 template <class V, class K, class HF, class ExK, class EqK, class A>
00891 const float sparse_hashtable<V,K,HF,ExK,EqK,A>::HT_EMPTY_FLT = 0.4f *
00892 sparse_hashtable<V,K,HF,ExK,EqK,A>::HT_OCCUPANCY_FLT;
00893
00894 _END_GOOGLE_NAMESPACE_
00895
00896 #endif