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