90 #ifndef _DENSEHASHTABLE_H_ 91 #define _DENSEHASHTABLE_H_ 97 #define JUMP_(key, num_probes) ( num_probes ) 100 #include <stk_util/util/sparseconfig.h> 111 #include <stk_util/util/libc_allocator_with_realloc.h> 112 #include <stk_util/util/hashtable-common.h> 113 #include <stk_util/util/type_traits_google.h> 115 _START_GOOGLE_NAMESPACE_
117 using STL_NAMESPACE::pair;
136 template <
class Value,
class Key,
class HashFcn,
137 class ExtractKey,
class SetKey,
class EqualKey,
class Alloc>
138 class dense_hashtable;
140 template <
class V,
class K,
class HF,
class ExK,
class SetK,
class EqK,
class A>
141 struct dense_hashtable_iterator;
143 template <
class V,
class K,
class HF,
class ExK,
class SetK,
class EqK,
class A>
144 struct dense_hashtable_const_iterator;
147 template <
class V,
class K,
class HF,
class ExK,
class SetK,
class EqK,
class A>
148 struct dense_hashtable_iterator {
150 typedef typename A::template rebind<V>::other value_alloc_type;
153 typedef dense_hashtable_iterator<V,K,HF,ExK,SetK,EqK,A> iterator;
154 typedef dense_hashtable_const_iterator<V,K,HF,ExK,SetK,EqK,A> const_iterator;
156 typedef STL_NAMESPACE::forward_iterator_tag iterator_category;
157 typedef V value_type;
158 typedef typename value_alloc_type::difference_type difference_type;
159 typedef typename value_alloc_type::size_type size_type;
160 typedef typename value_alloc_type::reference reference;
161 typedef typename value_alloc_type::pointer pointer;
164 dense_hashtable_iterator(
const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *h,
165 pointer it, pointer it_end,
bool advance)
166 : ht(h), pos(it), end(it_end) {
167 if (advance) advance_past_empty_and_deleted();
169 dense_hashtable_iterator() { }
174 reference operator*()
const {
return *pos; }
175 pointer operator->()
const {
return &(operator*()); }
179 void advance_past_empty_and_deleted() {
180 while ( pos != end && (ht->test_empty(*
this) || ht->test_deleted(*
this)) )
183 iterator& operator++() {
184 assert(pos != end); ++pos; advance_past_empty_and_deleted();
return *
this;
186 iterator operator++(
int) { iterator tmp(*
this); ++*
this;
return tmp; }
189 bool operator==(
const iterator& it)
const {
return pos == it.pos; }
190 bool operator!=(
const iterator& it)
const {
return pos != it.pos; }
194 const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *ht;
200 template <
class V,
class K,
class HF,
class ExK,
class SetK,
class EqK,
class A>
201 struct dense_hashtable_const_iterator {
203 typedef typename A::template rebind<V>::other value_alloc_type;
206 typedef dense_hashtable_iterator<V,K,HF,ExK,SetK,EqK,A> iterator;
207 typedef dense_hashtable_const_iterator<V,K,HF,ExK,SetK,EqK,A> const_iterator;
209 typedef STL_NAMESPACE::forward_iterator_tag iterator_category;
210 typedef V value_type;
211 typedef typename value_alloc_type::difference_type difference_type;
212 typedef typename value_alloc_type::size_type size_type;
213 typedef typename value_alloc_type::const_reference reference;
214 typedef typename value_alloc_type::const_pointer pointer;
217 dense_hashtable_const_iterator(
218 const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *h,
219 pointer it, pointer it_end,
bool advance)
220 : ht(h), pos(it), end(it_end) {
221 if (advance) advance_past_empty_and_deleted();
223 dense_hashtable_const_iterator()
224 : ht(NULL), pos(pointer()), end(pointer()) { }
226 dense_hashtable_const_iterator(
const iterator &it)
227 : ht(it.ht), pos(it.pos), end(it.end) { }
232 reference operator*()
const {
return *pos; }
233 pointer operator->()
const {
return &(operator*()); }
237 void advance_past_empty_and_deleted() {
238 while ( pos != end && (ht->test_empty(*
this) || ht->test_deleted(*
this)) )
241 const_iterator& operator++() {
242 assert(pos != end); ++pos; advance_past_empty_and_deleted();
return *
this;
244 const_iterator operator++(
int) { const_iterator tmp(*
this); ++*
this;
return tmp; }
247 bool operator==(
const const_iterator& it)
const {
return pos == it.pos; }
248 bool operator!=(
const const_iterator& it)
const {
return pos != it.pos; }
252 const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *ht;
256 template <
class Value,
class Key,
class HashFcn,
257 class ExtractKey,
class SetKey,
class EqualKey,
class Alloc>
258 class dense_hashtable {
260 typedef typename Alloc::template rebind<Value>::other value_alloc_type;
263 typedef Key key_type;
264 typedef Value value_type;
265 typedef HashFcn hasher;
266 typedef EqualKey key_equal;
267 typedef Alloc allocator_type;
269 typedef typename value_alloc_type::size_type size_type;
270 typedef typename value_alloc_type::difference_type difference_type;
271 typedef typename value_alloc_type::reference reference;
272 typedef typename value_alloc_type::const_reference const_reference;
273 typedef typename value_alloc_type::pointer pointer;
274 typedef typename value_alloc_type::const_pointer const_pointer;
275 typedef dense_hashtable_iterator<Value, Key, HashFcn,
276 ExtractKey, SetKey, EqualKey, Alloc>
279 typedef dense_hashtable_const_iterator<Value, Key, HashFcn,
280 ExtractKey, SetKey, EqualKey, Alloc>
284 typedef iterator local_iterator;
285 typedef const_iterator const_local_iterator;
290 static const int HT_OCCUPANCY_PCT;
295 static const int HT_EMPTY_PCT;
301 static const size_type HT_MIN_BUCKETS = 4;
306 static const size_type HT_DEFAULT_STARTING_BUCKETS = 32;
309 iterator begin() {
return iterator(
this, table,
310 table + num_buckets,
true); }
311 iterator end() {
return iterator(
this, table + num_buckets,
312 table + num_buckets,
true); }
313 const_iterator begin()
const {
return const_iterator(
this, table,
314 table+num_buckets,
true);}
315 const_iterator end()
const {
return const_iterator(
this, table + num_buckets,
316 table+num_buckets,
true);}
320 local_iterator begin(size_type i) {
321 return local_iterator(
this, table + i, table + i+1,
false);
323 local_iterator end(size_type i) {
324 local_iterator it = begin(i);
325 if (!test_empty(i) && !test_deleted(i))
329 const_local_iterator begin(size_type i)
const {
330 return const_local_iterator(
this, table + i, table + i+1,
false);
332 const_local_iterator end(size_type i)
const {
333 const_local_iterator it = begin(i);
334 if (!test_empty(i) && !test_deleted(i))
340 hasher hash_funct()
const {
return settings; }
341 key_equal key_eq()
const {
return key_info; }
342 allocator_type get_allocator()
const {
343 return allocator_type(val_info);
347 int num_table_copies()
const {
return settings.num_ht_copies(); }
354 void set_value(pointer dst, const_reference src) {
356 new(dst) value_type(src);
359 void destroy_buckets(size_type first, size_type last) {
360 for ( ; first != last; ++first)
361 table[first].~value_type();
371 void squash_deleted() {
373 dense_hashtable tmp(*
this);
376 assert(num_deleted == 0);
379 bool test_deleted_key(
const key_type& key)
const {
383 assert(settings.use_deleted() || num_deleted == 0);
384 return num_deleted > 0 && equals(key_info.delkey, key);
388 void set_deleted_key(
const key_type &key) {
391 assert((!settings.use_empty() || !equals(key, get_key(val_info.emptyval)))
392 &&
"Passed the empty-key to set_deleted_key");
395 settings.set_use_deleted(
true);
396 key_info.delkey = key;
398 void clear_deleted_key() {
400 settings.set_use_deleted(
false);
402 key_type deleted_key()
const {
403 assert(settings.use_deleted()
404 &&
"Must set deleted key before calling deleted_key");
405 return key_info.delkey;
410 bool test_deleted(size_type bucknum)
const {
411 return test_deleted_key(get_key(table[bucknum]));
413 bool test_deleted(
const iterator &it)
const {
414 return test_deleted_key(get_key(*it));
416 bool test_deleted(
const const_iterator &it)
const {
417 return test_deleted_key(get_key(*it));
422 bool set_deleted(iterator &it) {
423 assert(settings.use_deleted());
424 bool retval = !test_deleted(it);
426 set_key(&(*it), key_info.delkey);
430 bool clear_deleted(iterator &it) {
431 assert(settings.use_deleted());
433 return test_deleted(it);
441 bool set_deleted(const_iterator &it) {
442 assert(settings.use_deleted());
443 bool retval = !test_deleted(it);
444 set_key(const_cast<pointer>(&(*it)), key_info.delkey);
448 bool clear_deleted(const_iterator &it) {
449 assert(settings.use_deleted());
450 return test_deleted(it);
462 bool test_empty(size_type bucknum)
const {
463 assert(settings.use_empty());
464 return equals(get_key(val_info.emptyval), get_key(table[bucknum]));
466 bool test_empty(
const iterator &it)
const {
467 assert(settings.use_empty());
468 return equals(get_key(val_info.emptyval), get_key(*it));
470 bool test_empty(
const const_iterator &it)
const {
471 assert(settings.use_empty());
472 return equals(get_key(val_info.emptyval), get_key(*it));
476 void fill_range_with_empty(pointer table_start, pointer table_end) {
477 STL_NAMESPACE::uninitialized_fill(table_start, table_end, val_info.emptyval);
483 void set_empty_key(const_reference val) {
485 assert(!settings.use_empty() &&
"Calling set_empty_key multiple times");
488 assert((!settings.use_deleted() || !equals(get_key(val), key_info.delkey))
489 &&
"Setting the empty key the same as the deleted key");
490 settings.set_use_empty(
true);
491 set_value(&val_info.emptyval, val);
495 table = val_info.allocate(num_buckets);
497 fill_range_with_empty(table, table + num_buckets);
500 value_type empty_key()
const {
501 assert(settings.use_empty());
502 return val_info.emptyval;
507 size_type size()
const {
return num_elements - num_deleted; }
508 size_type max_size()
const {
return val_info.max_size(); }
509 bool empty()
const {
return size() == 0; }
510 size_type bucket_count()
const {
return num_buckets; }
511 size_type max_bucket_count()
const {
return max_size(); }
512 size_type nonempty_bucket_count()
const {
return num_elements; }
515 size_type bucket_size(size_type i)
const {
516 return begin(i) == end(i) ? 0 : 1;
521 static const size_type ILLEGAL_BUCKET = size_type(-1);
526 bool maybe_shrink() {
527 assert(num_elements >= num_deleted);
528 assert((bucket_count() & (bucket_count()-1)) == 0);
529 assert(bucket_count() >= HT_MIN_BUCKETS);
537 const size_type num_remain = num_elements - num_deleted;
538 const size_type shrink_threshold = settings.shrink_threshold();
539 if (shrink_threshold > 0 && num_remain < shrink_threshold &&
540 bucket_count() > HT_DEFAULT_STARTING_BUCKETS) {
541 const float shrink_factor = settings.shrink_factor();
542 size_type sz = bucket_count() / 2;
543 while (sz > HT_DEFAULT_STARTING_BUCKETS &&
544 num_remain < sz * shrink_factor) {
547 dense_hashtable tmp(*
this, sz);
551 settings.set_consider_shrink(
false);
558 bool resize_delta(size_type delta) {
559 bool did_resize =
false;
560 if ( settings.consider_shrink() ) {
561 if ( maybe_shrink() )
564 if (num_elements >= (STL_NAMESPACE::numeric_limits<size_type>::max)() - delta)
565 throw std::length_error(
"resize overflow");
566 if ( bucket_count() >= HT_MIN_BUCKETS &&
567 (num_elements + delta) <= settings.enlarge_threshold() )
576 const size_type needed_size = settings.min_buckets(num_elements + delta, 0);
577 if ( needed_size <= bucket_count() )
580 size_type resize_to =
581 settings.min_buckets(num_elements - num_deleted + delta, bucket_count());
583 if (resize_to < needed_size &&
584 resize_to < (STL_NAMESPACE::numeric_limits<size_type>::max)() / 2) {
592 const size_type target =
593 static_cast<size_type
>(settings.shrink_size(resize_to*2));
594 if (num_elements - num_deleted + delta >= target) {
599 dense_hashtable tmp(*
this, resize_to);
605 void resize_table(size_type , size_type new_size,
607 table = val_info.realloc_or_die(table, new_size);
610 void resize_table(size_type old_size, size_type new_size, false_type) {
611 val_info.deallocate(table, old_size);
612 table = val_info.allocate(new_size);
616 void copy_from(
const dense_hashtable &ht, size_type min_buckets_wanted) {
617 clear_to_size(settings.min_buckets(ht.size(), min_buckets_wanted));
622 assert((bucket_count() & (bucket_count()-1)) == 0);
623 for ( const_iterator it = ht.begin(); it != ht.end(); ++it ) {
624 size_type num_probes = 0;
626 const size_type bucket_count_minus_one = bucket_count() - 1;
627 for (bucknum = hash(get_key(*it)) & bucket_count_minus_one;
628 !test_empty(bucknum);
629 bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one) {
631 assert(num_probes < bucket_count()
632 &&
"Hashtable is full: an error in key_equal<> or hash<>");
634 set_value(&table[bucknum], *it);
637 settings.inc_num_ht_copies();
645 void resize(size_type req_elements) {
646 if ( settings.consider_shrink() || req_elements == 0 )
648 if ( req_elements > num_elements )
649 resize_delta(req_elements - num_elements);
656 void get_resizing_parameters(
float* shrink,
float* grow)
const {
657 *shrink = settings.shrink_factor();
658 *grow = settings.enlarge_factor();
660 void set_resizing_parameters(
float shrink,
float grow) {
661 settings.set_resizing_parameters(shrink, grow);
662 settings.reset_thresholds(bucket_count());
669 explicit dense_hashtable(size_type expected_max_items_in_table = 0,
670 const HashFcn& hf = HashFcn(),
671 const EqualKey& eql = EqualKey(),
672 const ExtractKey& ext = ExtractKey(),
673 const SetKey&
set = SetKey(),
674 const Alloc& alloc = Alloc())
676 key_info(ext, set, eql),
679 num_buckets(expected_max_items_in_table == 0
680 ? HT_DEFAULT_STARTING_BUCKETS
681 : settings.min_buckets(expected_max_items_in_table, 0)),
682 val_info(alloc_impl<value_alloc_type>(alloc)),
686 settings.reset_thresholds(bucket_count());
691 dense_hashtable(
const dense_hashtable& ht,
692 size_type min_buckets_wanted = HT_DEFAULT_STARTING_BUCKETS)
693 : settings(ht.settings),
694 key_info(ht.key_info),
698 val_info(ht.val_info),
700 if (!ht.settings.use_empty()) {
703 num_buckets = settings.min_buckets(ht.size(), min_buckets_wanted);
704 settings.reset_thresholds(bucket_count());
707 settings.reset_thresholds(bucket_count());
708 copy_from(ht, min_buckets_wanted);
711 dense_hashtable& operator= (
const dense_hashtable& ht) {
712 if (&ht ==
this)
return *
this;
713 if (!ht.settings.use_empty()) {
715 dense_hashtable empty_table(ht);
716 this->swap(empty_table);
719 settings = ht.settings;
720 key_info = ht.key_info;
721 set_value(&val_info.emptyval, ht.val_info.emptyval);
723 copy_from(ht, HT_MIN_BUCKETS);
730 destroy_buckets(0, num_buckets);
731 val_info.deallocate(table, num_buckets);
736 void swap(dense_hashtable& ht) {
737 STL_NAMESPACE::swap(settings, ht.settings);
738 STL_NAMESPACE::swap(key_info, ht.key_info);
739 STL_NAMESPACE::swap(num_deleted, ht.num_deleted);
740 STL_NAMESPACE::swap(num_elements, ht.num_elements);
741 STL_NAMESPACE::swap(num_buckets, ht.num_buckets);
743 set_value(&tmp, val_info.emptyval);
744 set_value(&val_info.emptyval, ht.val_info.emptyval);
745 set_value(&ht.val_info.emptyval, tmp);
747 STL_NAMESPACE::swap(table, ht.table);
748 settings.reset_thresholds(bucket_count());
749 ht.settings.reset_thresholds(bucket_count());
754 void clear_to_size(size_type new_num_buckets) {
756 table = val_info.allocate(new_num_buckets);
758 destroy_buckets(0, num_buckets);
759 if (new_num_buckets != num_buckets) {
760 typedef integral_constant<bool,
761 is_same<value_alloc_type,
762 libc_allocator_with_realloc<value_type> >::value>
764 resize_table(num_buckets, new_num_buckets, realloc_ok());
768 fill_range_with_empty(table, table + new_num_buckets);
771 num_buckets = new_num_buckets;
772 settings.reset_thresholds(bucket_count());
780 const size_type new_num_buckets = settings.min_buckets(0, 0);
781 if (num_elements == 0 && new_num_buckets == num_buckets) {
784 clear_to_size(new_num_buckets);
790 void clear_no_resize() {
791 if (num_elements > 0) {
793 destroy_buckets(0, num_buckets);
794 fill_range_with_empty(table, table + num_buckets);
797 settings.reset_thresholds(bucket_count());
809 pair<size_type, size_type> find_position(
const key_type &key)
const {
810 size_type num_probes = 0;
811 const size_type bucket_count_minus_one = bucket_count() - 1;
812 size_type bucknum = hash(key) & bucket_count_minus_one;
813 size_type insert_pos = ILLEGAL_BUCKET;
815 if ( test_empty(bucknum) ) {
816 if ( insert_pos == ILLEGAL_BUCKET )
817 return pair<size_type,size_type>(ILLEGAL_BUCKET, bucknum);
819 return pair<size_type,size_type>(ILLEGAL_BUCKET, insert_pos);
821 }
else if ( test_deleted(bucknum) ) {
822 if ( insert_pos == ILLEGAL_BUCKET )
823 insert_pos = bucknum;
825 }
else if ( equals(key, get_key(table[bucknum])) ) {
826 return pair<size_type,size_type>(bucknum, ILLEGAL_BUCKET);
829 bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one;
830 assert(num_probes < bucket_count()
831 &&
"Hashtable is full: an error in key_equal<> or hash<>");
836 iterator
find(
const key_type& key) {
837 if ( size() == 0 )
return end();
838 pair<size_type, size_type> pos = find_position(key);
839 if ( pos.first == ILLEGAL_BUCKET )
842 return iterator(
this, table + pos.first, table + num_buckets,
false);
845 const_iterator
find(
const key_type& key)
const {
846 if ( size() == 0 )
return end();
847 pair<size_type, size_type> pos = find_position(key);
848 if ( pos.first == ILLEGAL_BUCKET )
851 return const_iterator(
this, table + pos.first, table+num_buckets,
false);
856 size_type bucket(
const key_type& key)
const {
857 pair<size_type, size_type> pos = find_position(key);
858 return pos.first == ILLEGAL_BUCKET ? pos.second : pos.first;
862 size_type
count(
const key_type &key)
const {
863 pair<size_type, size_type> pos = find_position(key);
864 return pos.first == ILLEGAL_BUCKET ? 0 : 1;
868 pair<iterator,iterator>
equal_range(
const key_type& key) {
869 iterator pos =
find(key);
871 return pair<iterator,iterator>(pos, pos);
873 const iterator startpos = pos++;
874 return pair<iterator,iterator>(startpos, pos);
877 pair<const_iterator,const_iterator>
equal_range(
const key_type& key)
const {
878 const_iterator pos =
find(key);
880 return pair<const_iterator,const_iterator>(pos, pos);
882 const const_iterator startpos = pos++;
883 return pair<const_iterator,const_iterator>(startpos, pos);
891 iterator insert_at(const_reference obj, size_type pos) {
892 if (size() >= max_size())
893 throw std::length_error(
"insert overflow");
894 if ( test_deleted(pos) ) {
896 const_iterator delpos(
this, table + pos, table + num_buckets,
false);
897 clear_deleted(delpos);
898 assert( num_deleted > 0);
903 set_value(&table[pos], obj);
904 return iterator(
this, table + pos, table + num_buckets,
false);
908 pair<iterator, bool> insert_noresize(const_reference obj) {
910 assert((!settings.use_empty() || !equals(get_key(obj),
911 get_key(val_info.emptyval)))
912 &&
"Inserting the empty key");
913 assert((!settings.use_deleted() || !equals(get_key(obj), key_info.delkey))
914 &&
"Inserting the deleted key");
915 const pair<size_type,size_type> pos = find_position(get_key(obj));
916 if ( pos.first != ILLEGAL_BUCKET) {
917 return pair<iterator,bool>(iterator(
this, table + pos.first,
918 table + num_buckets,
false),
921 return pair<iterator,bool>(insert_at(obj, pos.second),
true);
927 template <
class ForwardIterator>
928 void insert(ForwardIterator f, ForwardIterator l, STL_NAMESPACE::forward_iterator_tag) {
929 size_t dist = STL_NAMESPACE::distance(f, l);
930 if (dist >= (std::numeric_limits<size_type>::max)())
931 throw std::length_error(
"insert-range overflow");
932 resize_delta(static_cast<size_type>(dist));
933 for ( ; dist > 0; --dist, ++f) {
939 template <
class InputIterator>
940 void insert(InputIterator f, InputIterator l, STL_NAMESPACE::input_iterator_tag) {
947 pair<iterator, bool>
insert(const_reference obj) {
949 return insert_noresize(obj);
953 template <
class InputIterator>
954 void insert(InputIterator f, InputIterator l) {
956 insert(f, l,
typename STL_NAMESPACE::iterator_traits<InputIterator>::iterator_category());
961 template <
class DefaultValue>
962 value_type& find_or_insert(
const key_type& key) {
964 assert((!settings.use_empty() || !equals(key, get_key(val_info.emptyval)))
965 &&
"Inserting the empty key");
966 assert((!settings.use_deleted() || !equals(key, key_info.delkey))
967 &&
"Inserting the deleted key");
968 const pair<size_type,size_type> pos = find_position(key);
969 DefaultValue default_value;
970 if ( pos.first != ILLEGAL_BUCKET) {
971 return table[pos.first];
972 }
else if (resize_delta(1)) {
974 return *insert_noresize(default_value(key)).first;
976 return *insert_at(default_value(key), pos.second);
981 size_type erase(
const key_type& key) {
983 assert((!settings.use_empty() || !equals(key, get_key(val_info.emptyval)))
984 &&
"Erasing the empty key");
985 assert((!settings.use_deleted() || !equals(key, key_info.delkey))
986 &&
"Erasing the deleted key");
987 const_iterator pos =
find(key);
988 if ( pos != end() ) {
989 assert(!test_deleted(pos));
992 settings.set_consider_shrink(
true);
1000 void erase(iterator pos) {
1001 if ( pos == end() )
return;
1002 if ( set_deleted(pos) ) {
1004 settings.set_consider_shrink(
true);
1008 void erase(iterator f, iterator l) {
1009 for ( ; f != l; ++f) {
1010 if ( set_deleted(f) )
1013 settings.set_consider_shrink(
true);
1021 void erase(const_iterator pos) {
1022 if ( pos == end() )
return;
1023 if ( set_deleted(pos) ) {
1025 settings.set_consider_shrink(
true);
1028 void erase(const_iterator f, const_iterator l) {
1029 for ( ; f != l; ++f) {
1030 if ( set_deleted(f) )
1033 settings.set_consider_shrink(
true);
1038 bool operator==(
const dense_hashtable& ht)
const {
1039 if (size() != ht.size()) {
1041 }
else if (
this == &ht) {
1046 for ( const_iterator it = begin(); it != end(); ++it ) {
1047 const_iterator it2 = ht.find(get_key(*it));
1048 if ((it2 == ht.end()) || (*it != *it2)) {
1055 bool operator!=(
const dense_hashtable& ht)
const {
1056 return !(*
this == ht);
1066 bool write_metadata(FILE * ) {
1071 bool read_metadata(FILE* ) {
1073 assert(settings.use_empty() &&
"empty_key not set for read_metadata");
1074 if (table) val_info.deallocate(table, num_buckets);
1077 settings.reset_thresholds(bucket_count());
1078 table = val_info.allocate(num_buckets);
1080 fill_range_with_empty(table, table + num_buckets);
1082 for ( size_type i = 0; i < num_elements; ++i ) {
1093 bool write_nopointer_data(FILE *fp)
const {
1094 for ( const_iterator it = begin(); it != end(); ++it ) {
1096 if ( !fwrite(&*it,
sizeof(*it), 1, fp) )
return false;
1102 bool read_nopointer_data(FILE *fp) {
1103 for ( iterator it = begin(); it != end(); ++it ) {
1105 if ( !fread(reinterpret_cast<void*>(&(*it)),
sizeof(*it), 1, fp) )
1113 class alloc_impl :
public A {
1115 typedef typename A::pointer pointer;
1116 typedef typename A::size_type size_type;
1119 alloc_impl(
const A& a) : A(a) { }
1123 pointer realloc_or_die(pointer , size_type ) {
1124 fprintf(stderr,
"realloc_or_die is only supported for " 1125 "libc_allocator_with_realloc");
1134 class alloc_impl<libc_allocator_with_realloc<A> >
1135 :
public libc_allocator_with_realloc<A> {
1137 typedef typename libc_allocator_with_realloc<A>::pointer pointer;
1138 typedef typename libc_allocator_with_realloc<A>::size_type size_type;
1140 alloc_impl(
const libc_allocator_with_realloc<A>& a)
1141 : libc_allocator_with_realloc<A>(a) { }
1143 pointer realloc_or_die(pointer ptr, size_type n) {
1144 pointer retval = this->reallocate(ptr, n);
1145 if (retval == NULL) {
1149 fprintf(stderr,
"sparsehash: FATAL ERROR: failed to reallocate " 1150 "%lu elements for ptr %p",
1151 static_cast<unsigned long>(n), ptr);
1162 class ValInfo :
public alloc_impl<value_alloc_type> {
1164 typedef typename alloc_impl<value_alloc_type>::value_type value_type;
1166 ValInfo(
const alloc_impl<value_alloc_type>& a)
1167 : alloc_impl<value_alloc_type>(a), emptyval() { }
1168 ValInfo(
const ValInfo& v)
1169 : alloc_impl<value_alloc_type>(v), emptyval(v.emptyval) { }
1171 value_type emptyval;
1180 sh_hashtable_settings<key_type, hasher, size_type, HT_MIN_BUCKETS> {
1181 explicit Settings(
const hasher& hf)
1182 : sh_hashtable_settings<key_type, hasher, size_type, HT_MIN_BUCKETS>(
1183 hf, HT_OCCUPANCY_PCT / 100.0f, HT_EMPTY_PCT / 100.0f) {}
1187 class KeyInfo :
public ExtractKey,
public SetKey,
public key_equal {
1189 KeyInfo(
const ExtractKey& ek,
const SetKey& sk,
const key_equal& eq)
1196 typename ExtractKey::result_type get_key(const_reference v)
const {
1197 return ExtractKey::operator()(v);
1199 void set_key(pointer v,
const key_type& k)
const {
1200 SetKey::operator()(v, k);
1202 bool equals(
const key_type& a,
const key_type& b)
const {
1203 return key_equal::operator()(a, b);
1208 typename remove_const<key_type>::type delkey;
1212 size_type hash(
const key_type& v)
const {
1213 return settings.hash(v);
1215 bool equals(
const key_type& a,
const key_type& b)
const {
1216 return key_info.equals(a, b);
1218 typename ExtractKey::result_type get_key(const_reference v)
const {
1219 return key_info.get_key(v);
1221 void set_key(pointer v,
const key_type& k)
const {
1222 key_info.set_key(v, k);
1230 size_type num_deleted;
1231 size_type num_elements;
1232 size_type num_buckets;
1239 template <
class V,
class K,
class HF,
class ExK,
class SetK,
class EqK,
class A>
1240 inline void swap(dense_hashtable<V,K,HF,ExK,SetK,EqK,A> &x,
1241 dense_hashtable<V,K,HF,ExK,SetK,EqK,A> &y) {
1247 template <
class V,
class K,
class HF,
class ExK,
class SetK,
class EqK,
class A>
1248 const typename dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::size_type
1249 dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::ILLEGAL_BUCKET;
1256 template <
class V,
class K,
class HF,
class ExK,
class SetK,
class EqK,
class A>
1257 const int dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_OCCUPANCY_PCT = 50;
1261 template <
class V,
class K,
class HF,
class ExK,
class SetK,
class EqK,
class A>
1262 const int dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_EMPTY_PCT
1263 =
static_cast<int>(0.4 *
1264 dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_OCCUPANCY_PCT);
1266 _END_GOOGLE_NAMESPACE_
pair< ForwardIterator, ForwardIterator > equal_range(ForwardIterator first, ForwardIterator last, const T &value)
Part * find(const PartVector &parts, const std::string &name)
Find a part by name in a collection of parts.
bool insert(PartVector &v, Part &part)
Insert a part into a properly ordered collection of parts. Returns true if this is a new insertion...
eastl::iterator_traits< InputIterator >::difference_type count(InputIterator first, InputIterator last, const T &value)