33 #include <agrum/tools/core/hashTable.h> 42 template <
typename Key,
typename Val,
typename Alloc >
43 template <
typename OtherAlloc >
44 void HashTableList< Key, Val, Alloc >::copy__(
45 const HashTableList< Key, Val, OtherAlloc >& from) {
46 Bucket *ptr, *old_ptr{
nullptr}, *new_elt{
nullptr};
52 for (ptr = from.deb_list__; ptr !=
nullptr; ptr = ptr->next) {
56 new_elt = alloc_bucket__->allocate(1);
59 alloc_bucket__->construct(new_elt, *ptr);
61 alloc_bucket__->deallocate(new_elt, 1);
66 new_elt->prev = old_ptr;
68 if (old_ptr !=
nullptr)
69 old_ptr->next = new_elt;
76 if (old_ptr !=
nullptr) old_ptr->next =
nullptr;
80 nb_elements__ = from.nb_elements__;
85 for (; deb_list__ !=
nullptr; deb_list__ = new_elt) {
86 new_elt = deb_list__->next;
87 alloc_bucket__->destroy(deb_list__);
88 alloc_bucket__->deallocate(deb_list__, 1);
98 template <
typename Key,
typename Val,
typename Alloc >
99 INLINE HashTableBucket< Key, Val >*
100 HashTableList< Key, Val, Alloc >::bucket(
const Key& key)
const {
101 for (Bucket* ptr = deb_list__; ptr !=
nullptr; ptr = ptr->next)
102 if (ptr->key() == key)
return ptr;
107 template <
typename Key,
typename Val,
typename Alloc >
109 HashTableList< Key, Val, Alloc >::erase(HashTableBucket< Key, Val >* ptr) {
111 if (ptr ==
nullptr) {
112 GUM_ERROR(NullElement,
"trying to erase a nullptr bucket");
116 if (ptr->prev !=
nullptr)
117 ptr->prev->next = ptr->next;
119 deb_list__ = ptr->next;
121 if (ptr->next !=
nullptr)
122 ptr->next->prev = ptr->prev;
124 end_list__ = ptr->prev;
127 alloc_bucket__->destroy(ptr);
128 alloc_bucket__->deallocate(ptr, 1);
133 template <
typename Key,
typename Val,
typename Alloc >
134 INLINE HashTableList< Key, Val, Alloc >::HashTableList(
135 typename HashTableList< Key, Val, Alloc >::BucketAllocator*
136 allocator)
noexcept :
137 alloc_bucket__{allocator} {}
139 template <
typename Key,
typename Val,
typename Alloc >
140 INLINE HashTableList< Key, Val, Alloc >::HashTableList(
141 const HashTableList< Key, Val, Alloc >& from) :
142 alloc_bucket__{from.alloc_bucket__} {
146 template <
typename Key,
typename Val,
typename Alloc >
147 INLINE HashTableList< Key, Val, Alloc >::HashTableList(
148 HashTableList< Key, Val, Alloc >&& from)
noexcept :
149 deb_list__{from.deb_list__},
150 end_list__{from.end_list__}, nb_elements__{from.nb_elements__},
151 alloc_bucket__{from.alloc_bucket__} {
152 from.deb_list__ =
nullptr;
155 template <
typename Key,
typename Val,
typename Alloc >
156 INLINE HashTableList< Key, Val, Alloc >::~HashTableList() {
157 for (Bucket *next_ptr, *ptr = deb_list__; ptr !=
nullptr; ptr = next_ptr) {
158 next_ptr = ptr->next;
159 alloc_bucket__->destroy(ptr);
160 alloc_bucket__->deallocate(ptr, 1);
164 template <
typename Key,
typename Val,
typename Alloc >
165 INLINE
void HashTableList< Key, Val, Alloc >::clear() {
166 for (Bucket *next_ptr, *ptr = deb_list__; ptr !=
nullptr; ptr = next_ptr) {
167 next_ptr = ptr->next;
168 alloc_bucket__->destroy(ptr);
169 alloc_bucket__->deallocate(ptr, 1);
172 nb_elements__ = Size(0);
173 deb_list__ =
nullptr;
174 end_list__ =
nullptr;
177 template <
typename Key,
typename Val,
typename Alloc >
178 INLINE HashTableList< Key, Val, Alloc >&
179 HashTableList< Key, Val, Alloc >::operator=(
180 const HashTableList< Key, Val, Alloc >& from) {
190 template <
typename Key,
typename Val,
typename Alloc >
191 template <
typename OtherAlloc >
192 INLINE HashTableList< Key, Val, Alloc >&
193 HashTableList< Key, Val, Alloc >::operator=(
194 const HashTableList< Key, Val, OtherAlloc >& from) {
197 !=
reinterpret_cast<
const HashTableList< Key, Val, Alloc >* >(&from)) {
205 template <
typename Key,
typename Val,
typename Alloc >
206 INLINE HashTableList< Key, Val, Alloc >&
207 HashTableList< Key, Val, Alloc >::operator=(
208 HashTableList< Key, Val, Alloc >&& from)
noexcept {
211 deb_list__ = from.deb_list__;
212 end_list__ = from.end_list__;
213 nb_elements__ = from.nb_elements__;
214 from.deb_list__ =
nullptr;
220 template <
typename Key,
typename Val,
typename Alloc >
221 INLINE
void HashTableList< Key, Val, Alloc >::setAllocator(
222 typename HashTableList< Key, Val, Alloc >::BucketAllocator& alloc) {
223 alloc_bucket__ = &alloc;
226 template <
typename Key,
typename Val,
typename Alloc >
227 INLINE
typename HashTableList< Key, Val, Alloc >::value_type&
228 HashTableList< Key, Val, Alloc >::at(Size i) {
229 if (i >= nb_elements__) {
230 GUM_ERROR(NotFound,
"not enough elements in the chained list");
235 for (ptr = deb_list__; i; --i, ptr = ptr->next) {}
240 template <
typename Key,
typename Val,
typename Alloc >
241 INLINE
const typename HashTableList< Key, Val, Alloc >::value_type&
242 HashTableList< Key, Val, Alloc >::at(Size i)
const {
243 if (i >= nb_elements__) {
244 GUM_ERROR(NotFound,
"not enough elements in the chained list");
249 for (ptr = deb_list__; i; --i, ptr = ptr->next) {}
254 template <
typename Key,
typename Val,
typename Alloc >
255 INLINE
const typename HashTableList< Key, Val, Alloc >::mapped_type&
256 HashTableList< Key, Val, Alloc >::operator[](
const Key& key)
const {
257 for (Bucket* ptr = deb_list__; ptr !=
nullptr; ptr = ptr->next)
258 if (ptr->key() == key)
return ptr->val();
260 GUM_ERROR(NotFound,
"No element with the key <" << key <<
">");
263 template <
typename Key,
typename Val,
typename Alloc >
264 INLINE
typename HashTableList< Key, Val, Alloc >::mapped_type&
265 HashTableList< Key, Val, Alloc >::operator[](
const Key& key) {
266 for (Bucket* ptr = deb_list__; ptr !=
nullptr; ptr = ptr->next)
267 if (ptr->key() == key)
return ptr->val();
269 GUM_ERROR(NotFound,
"No element with the key <" << key <<
">");
272 template <
typename Key,
typename Val,
typename Alloc >
273 INLINE
bool HashTableList< Key, Val, Alloc >::exists(
const Key& key)
const {
274 for (Bucket* ptr = deb_list__; ptr !=
nullptr; ptr = ptr->next) {
275 if (ptr->key() == key) {
return true; }
281 template <
typename Key,
typename Val,
typename Alloc >
282 INLINE
bool HashTableList< Key, Val, Alloc >::empty()
const noexcept {
283 return (nb_elements__ == Size(0));
286 template <
typename Key,
typename Val,
typename Alloc >
287 INLINE
void HashTableList< Key, Val, Alloc >::insert(
288 HashTableBucket< Key, Val >* new_elt)
noexcept {
290 new_elt->prev =
nullptr;
291 new_elt->next = deb_list__;
293 if (deb_list__ !=
nullptr)
294 deb_list__->prev = new_elt;
296 end_list__ = new_elt;
298 deb_list__ = new_elt;
307 template <
typename Key,
typename Val,
typename Alloc >
308 template <
typename OtherAlloc >
309 void HashTable< Key, Val, Alloc >::copy__(
310 const HashTable< Key, Val, OtherAlloc >& table) {
313 GUM_ASSERT(table.size__ == size__);
316 for (Size i = 0; i < table.size__; ++i) {
318 nodes__[i] = table.nodes__[i];
322 for (Size j = 0; j < size__; ++j)
325 nb_elements__ = Size(0);
332 nb_elements__ = table.nb_elements__;
335 template <
typename Key,
typename Val,
typename Alloc >
336 INLINE
const typename HashTable< Key, Val, Alloc >::iterator&
337 HashTable< Key, Val, Alloc >::end4Statics() {
338 return *(
reinterpret_cast<
const iterator* >(
339 HashTableIteratorStaticEnd::end4Statics()));
342 template <
typename Key,
typename Val,
typename Alloc >
343 INLINE
const typename HashTable< Key, Val, Alloc >::const_iterator&
344 HashTable< Key, Val, Alloc >::constEnd4Statics() {
345 return *(
reinterpret_cast<
const const_iterator* >(
346 HashTableIteratorStaticEnd::constEnd4Statics()));
349 template <
typename Key,
typename Val,
typename Alloc >
350 INLINE
const typename HashTable< Key, Val, Alloc >::iterator_safe&
351 HashTable< Key, Val, Alloc >::endSafe4Statics() {
352 return *(
reinterpret_cast<
const iterator_safe* >(
353 HashTableIteratorStaticEnd::endSafe4Statics()));
356 template <
typename Key,
typename Val,
typename Alloc >
357 INLINE
const typename HashTable< Key, Val, Alloc >::const_iterator_safe&
358 HashTable< Key, Val, Alloc >::constEndSafe4Statics() {
359 return *(
reinterpret_cast<
const const_iterator_safe* >(
360 HashTableIteratorStaticEnd::constEndSafe4Statics()));
363 template <
typename Key,
typename Val,
typename Alloc >
364 INLINE
void HashTable< Key, Val, Alloc >::create__(Size size) {
366 nodes__.resize(size);
368 for (
auto& list: nodes__) {
369 list.setAllocator(alloc__);
373 hash_func__.resize(size);
380 template <
typename Key,
typename Val,
typename Alloc >
381 HashTable< Key, Val, Alloc >::HashTable(Size size_param,
383 bool key_uniqueness_pol) :
385 size__{Size(1) << hashTableLog2__(std::max(Size(2), size_param))},
386 resize_policy__{resize_pol}, key_uniqueness_policy__{key_uniqueness_pol} {
388 GUM_CONSTRUCTOR(HashTable);
394 template <
typename Key,
typename Val,
typename Alloc >
395 HashTable< Key, Val, Alloc >::HashTable(
396 std::initializer_list< std::pair< Key, Val > > list) :
398 size__{Size(1) << hashTableLog2__(
399 std::max< Size >(Size(2), Size(list.size()) / 2))} {
401 GUM_CONSTRUCTOR(HashTable);
407 for (
const auto& elt: list) {
412 template <
typename Key,
typename Val,
typename Alloc >
413 HashTable< Key, Val, Alloc >::HashTable(
414 const HashTable< Key, Val, Alloc >& table) :
415 size__{table.size__},
416 resize_policy__{table.resize_policy__},
417 key_uniqueness_policy__{table.key_uniqueness_policy__},
418 begin_index__{table.begin_index__} {
420 GUM_CONS_CPY(HashTable);
429 template <
typename Key,
typename Val,
typename Alloc >
430 template <
typename OtherAlloc >
431 HashTable< Key, Val, Alloc >::HashTable(
432 const HashTable< Key, Val, OtherAlloc >& table) :
433 size__{table.size__},
434 resize_policy__{table.resize_policy__},
435 key_uniqueness_policy__{table.key_uniqueness_policy__},
436 begin_index__{table.begin_index__} {
438 GUM_CONS_CPY(HashTable);
447 template <
typename Key,
typename Val,
typename Alloc >
448 HashTable< Key, Val, Alloc >::HashTable(HashTable< Key, Val, Alloc >&& table) :
449 nodes__(std::move(table.nodes__)), size__{table.size__},
450 nb_elements__{table.nb_elements__}, hash_func__{table.hash_func__},
451 resize_policy__{table.resize_policy__},
452 key_uniqueness_policy__{table.key_uniqueness_policy__},
453 begin_index__{table.begin_index__},
454 safe_iterators__(std::move(table.safe_iterators__)),
455 alloc__(std::move(table.alloc__)) {
458 GUM_CONS_MOV(HashTable);
461 template <
typename Key,
typename Val,
typename Alloc >
462 INLINE
void HashTable< Key, Val, Alloc >::clearIterators__() {
463 const Size len = safe_iterators__.size();
464 for (Size i = Size(0); i < len; ++i)
465 safe_iterators__[i]->clear();
468 template <
typename Key,
typename Val,
typename Alloc >
469 INLINE
void HashTable< Key, Val, Alloc >::clear() {
475 for (Size i = Size(0); i < size__; ++i)
478 nb_elements__ = Size(0);
479 begin_index__ = std::numeric_limits< Size >::max();
482 template <
typename Key,
typename Val,
typename Alloc >
483 INLINE HashTable< Key, Val, Alloc >::~HashTable() {
485 GUM_DESTRUCTOR(HashTable);
492 template <
typename Key,
typename Val,
typename Alloc >
493 HashTable< Key, Val, Alloc >& HashTable< Key, Val, Alloc >::operator=(
494 const HashTable< Key, Val, Alloc >& from) {
498 GUM_OP_CPY(HashTable);
507 if (size__ != from.size__) {
508 nodes__.resize(from.size__);
510 for (Size i = Size(0); i < from.size__; ++i) {
511 nodes__[i].setAllocator(alloc__);
514 size__ = from.size__;
518 hash_func__.resize(size__);
521 resize_policy__ = from.resize_policy__;
522 key_uniqueness_policy__ = from.key_uniqueness_policy__;
523 begin_index__ = from.begin_index__;
532 template <
typename Key,
typename Val,
typename Alloc >
533 template <
typename OtherAlloc >
534 HashTable< Key, Val, Alloc >& HashTable< Key, Val, Alloc >::operator=(
535 const HashTable< Key, Val, OtherAlloc >& from) {
537 if (
this !=
reinterpret_cast<
const HashTable< Key, Val, Alloc >* >(&from)) {
539 GUM_OP_CPY(HashTable);
548 if (size__ != from.size__) {
549 nodes__.resize(from.size__);
551 for (Size i = 0; i < from.size__; ++i) {
552 nodes__[i].setAllocator(alloc__);
555 size__ = from.size__;
559 hash_func__.resize(size__);
562 resize_policy__ = from.resize_policy__;
563 key_uniqueness_policy__ = from.key_uniqueness_policy__;
564 begin_index__ = from.begin_index__;
573 template <
typename Key,
typename Val,
typename Alloc >
574 HashTable< Key, Val, Alloc >& HashTable< Key, Val, Alloc >::operator=(
575 HashTable< Key, Val, Alloc >&& table) {
577 if (
this != &table) {
579 GUM_OP_MOV(HashTable);
585 nodes__ = std::move(table.nodes__);
586 safe_iterators__ = std::move(table.safe_iterators__);
587 alloc__ = std::move(table.alloc__);
588 size__ = table.size__;
589 nb_elements__ = table.nb_elements__;
590 hash_func__ = table.hash_func__;
591 resize_policy__ = table.resize_policy__;
592 key_uniqueness_policy__ = table.key_uniqueness_policy__;
593 begin_index__ = table.begin_index__;
602 template <
typename Key,
typename Val,
typename Alloc >
603 INLINE
const typename HashTable< Key, Val, Alloc >::iterator&
604 HashTable< Key, Val, Alloc >::end()
noexcept {
608 return *(
reinterpret_cast<
const iterator* >(
609 HashTableIteratorStaticEnd::HashTableIterEnd__));
612 template <
typename Key,
typename Val,
typename Alloc >
613 INLINE
const typename HashTable< Key, Val, Alloc >::const_iterator&
614 HashTable< Key, Val, Alloc >::end()
const noexcept {
618 return *(
reinterpret_cast<
const const_iterator* >(
619 HashTableIteratorStaticEnd::HashTableIterEnd__));
622 template <
typename Key,
typename Val,
typename Alloc >
623 INLINE
const typename HashTable< Key, Val, Alloc >::const_iterator&
624 HashTable< Key, Val, Alloc >::cend()
const noexcept {
628 return *(
reinterpret_cast<
const const_iterator* >(
629 HashTableIteratorStaticEnd::HashTableIterEnd__));
632 template <
typename Key,
typename Val,
typename Alloc >
633 INLINE
typename HashTable< Key, Val, Alloc >::iterator
634 HashTable< Key, Val, Alloc >::begin() {
636 if (nb_elements__ == Size(0))
637 return iterator{end()};
639 return iterator{*
this};
642 template <
typename Key,
typename Val,
typename Alloc >
643 INLINE
typename HashTable< Key, Val, Alloc >::const_iterator
644 HashTable< Key, Val, Alloc >::begin()
const {
646 if (nb_elements__ == Size(0))
647 return const_iterator{end()};
649 return const_iterator{*
this};
652 template <
typename Key,
typename Val,
typename Alloc >
653 INLINE
typename HashTable< Key, Val, Alloc >::const_iterator
654 HashTable< Key, Val, Alloc >::cbegin()
const {
656 if (nb_elements__ == Size(0))
657 return const_iterator{cend()};
659 return const_iterator{*
this};
662 template <
typename Key,
typename Val,
typename Alloc >
663 INLINE
const typename HashTable< Key, Val, Alloc >::iterator_safe&
664 HashTable< Key, Val, Alloc >::endSafe()
noexcept {
668 return *(
reinterpret_cast<
const iterator_safe* >(
669 HashTableIteratorStaticEnd::HashTableIterEndSafe__));
672 template <
typename Key,
typename Val,
typename Alloc >
673 INLINE
const typename HashTable< Key, Val, Alloc >::const_iterator_safe&
674 HashTable< Key, Val, Alloc >::endSafe()
const noexcept {
678 return *(
reinterpret_cast<
const const_iterator_safe* >(
679 HashTableIteratorStaticEnd::HashTableIterEndSafe__));
682 template <
typename Key,
typename Val,
typename Alloc >
683 INLINE
const typename HashTable< Key, Val, Alloc >::const_iterator_safe&
684 HashTable< Key, Val, Alloc >::cendSafe()
const noexcept {
688 return *(
reinterpret_cast<
const const_iterator_safe* >(
689 HashTableIteratorStaticEnd::HashTableIterEndSafe__));
692 template <
typename Key,
typename Val,
typename Alloc >
693 INLINE
typename HashTable< Key, Val, Alloc >::iterator_safe
694 HashTable< Key, Val, Alloc >::beginSafe() {
696 if (nb_elements__ == Size(0))
697 return iterator_safe{endSafe()};
699 return iterator_safe{*
this};
702 template <
typename Key,
typename Val,
typename Alloc >
703 INLINE
typename HashTable< Key, Val, Alloc >::const_iterator_safe
704 HashTable< Key, Val, Alloc >::beginSafe()
const {
706 if (nb_elements__ == Size(0))
707 return const_iterator_safe{endSafe()};
709 return const_iterator_safe{*
this};
712 template <
typename Key,
typename Val,
typename Alloc >
713 INLINE
typename HashTable< Key, Val, Alloc >::const_iterator_safe
714 HashTable< Key, Val, Alloc >::cbeginSafe()
const {
716 if (nb_elements__ == Size(0))
717 return const_iterator_safe{cendSafe()};
719 return const_iterator_safe{*
this};
722 template <
typename Key,
typename Val,
typename Alloc >
723 INLINE Val& HashTable< Key, Val, Alloc >::operator[](
const Key& key) {
724 return nodes__[hash_func__(key)][key];
727 template <
typename Key,
typename Val,
typename Alloc >
729 HashTable< Key, Val, Alloc >::operator[](
const Key& key)
const {
730 return nodes__[hash_func__(key)][key];
733 template <
typename Key,
typename Val,
typename Alloc >
734 INLINE Size HashTable< Key, Val, Alloc >::size()
const noexcept {
735 return nb_elements__;
738 template <
typename Key,
typename Val,
typename Alloc >
739 INLINE Size HashTable< Key, Val, Alloc >::capacity()
const noexcept {
743 template <
typename Key,
typename Val,
typename Alloc >
744 INLINE
bool HashTable< Key, Val, Alloc >::exists(
const Key& key)
const {
745 return nodes__[hash_func__(key)].exists(key);
748 template <
typename Key,
typename Val,
typename Alloc >
749 INLINE
void HashTable< Key, Val, Alloc >::setResizePolicy(
750 const bool new_policy)
noexcept {
751 resize_policy__ = new_policy;
754 template <
typename Key,
typename Val,
typename Alloc >
755 INLINE
bool HashTable< Key, Val, Alloc >::resizePolicy()
const noexcept {
756 return resize_policy__;
759 template <
typename Key,
typename Val,
typename Alloc >
760 INLINE
void HashTable< Key, Val, Alloc >::setKeyUniquenessPolicy(
761 const bool new_policy)
noexcept {
762 key_uniqueness_policy__ = new_policy;
765 template <
typename Key,
typename Val,
typename Alloc >
766 INLINE
bool HashTable< Key, Val, Alloc >::keyUniquenessPolicy()
const noexcept {
767 return key_uniqueness_policy__;
770 template <
typename Key,
typename Val,
typename Alloc >
771 void HashTable< Key, Val, Alloc >::resize(Size new_size) {
773 new_size = std::max(Size(2), new_size);
777 int log_size = hashTableLog2__(new_size);
778 new_size = Size(1) << log_size;
783 if (new_size != size__) {
788 <= new_size * HashTableConst::default_mean_val_by_slot)) {
790 std::vector< HashTableList< Key, Val, Alloc > > new_nodes(new_size);
792 for (
auto& list: new_nodes) {
793 list.setAllocator(alloc__);
797 hash_func__.resize(new_size);
803 for (Size i = Size(0); i < size__; ++i) {
804 while ((bucket = nodes__[i].deb_list__) !=
nullptr) {
806 new_hashed_key = hash_func__(bucket->key());
810 nodes__[i].deb_list__ = bucket->next;
813 new_nodes[new_hashed_key].insert(bucket);
819 begin_index__ = std::numeric_limits< Size >::max();
822 std::swap(nodes__, new_nodes);
825 for (
auto iter: safe_iterators__) {
827 iter->index__ = hash_func__(iter->bucket__->key());
829 iter->next_bucket__ =
nullptr;
837 template <
typename Key,
typename Val,
typename Alloc >
839 HashTable< Key, Val, Alloc >::insert__(HashTableBucket< Key, Val >* bucket) {
840 Size hash_key = hash_func__(bucket->key());
843 if (key_uniqueness_policy__ && nodes__[hash_key].exists(bucket->key())) {
845 Key k = bucket->key();
846 alloc__.destroy(bucket);
847 alloc__.deallocate(bucket, 1);
848 GUM_ERROR(DuplicateElement,
849 "the hashtable contains an element with the same key (" << k
856 && (nb_elements__ >= size__ * HashTableConst::default_mean_val_by_slot)) {
858 hash_key = hash_func__(bucket->key());
862 nodes__[hash_key].insert(bucket);
870 if (begin_index__ < hash_key) { begin_index__ = hash_key; }
873 template <
typename Key,
typename Val,
typename Alloc >
874 INLINE
typename HashTable< Key, Val, Alloc >::value_type&
875 HashTable< Key, Val, Alloc >::insert(
const Key& thekey,
const Val& theval) {
876 Bucket* bucket = alloc__.allocate(1);
879 alloc__.construct(bucket, thekey, theval);
881 alloc__.deallocate(bucket, 1);
886 return bucket->elt();
889 template <
typename Key,
typename Val,
typename Alloc >
890 INLINE
typename HashTable< Key, Val, Alloc >::value_type&
891 HashTable< Key, Val, Alloc >::insert(Key&& thekey, Val&& theval) {
892 Bucket* bucket = alloc__.allocate(1);
895 alloc__.construct(bucket, std::move(thekey), std::move(theval));
897 alloc__.deallocate(bucket, 1);
902 return bucket->elt();
905 template <
typename Key,
typename Val,
typename Alloc >
906 INLINE
typename HashTable< Key, Val, Alloc >::value_type&
907 HashTable< Key, Val, Alloc >::insert(
const std::pair< Key, Val >& elt) {
908 Bucket* bucket = alloc__.allocate(1);
911 alloc__.construct(bucket,
reinterpret_cast<
const value_type& >(elt));
913 alloc__.deallocate(bucket, 1);
918 return bucket->elt();
921 template <
typename Key,
typename Val,
typename Alloc >
922 INLINE
typename HashTable< Key, Val, Alloc >::value_type&
923 HashTable< Key, Val, Alloc >::insert(std::pair< Key, Val >&& elt) {
924 Bucket* bucket = alloc__.allocate(1);
927 alloc__.construct(bucket, std::move(
reinterpret_cast< value_type& >(elt)));
929 alloc__.deallocate(bucket, 1);
934 return bucket->elt();
937 template <
typename Key,
typename Val,
typename Alloc >
938 template <
typename... Args >
939 INLINE
typename HashTable< Key, Val, Alloc >::value_type&
940 HashTable< Key, Val, Alloc >::emplace(Args&&... args) {
941 Bucket* bucket = alloc__.allocate(1);
944 alloc__.construct(bucket,
945 HashTableBucket< Key, Val >::Emplace::EMPLACE,
946 std::forward< Args >(args)...);
948 alloc__.deallocate(bucket, 1);
953 return bucket->elt();
956 template <
typename Key,
typename Val,
typename Alloc >
957 INLINE
typename HashTable< Key, Val, Alloc >::mapped_type&
958 HashTable< Key, Val, Alloc >::getWithDefault(
const Key& key,
959 const Val& default_value) {
960 Bucket* bucket = nodes__[hash_func__(key)].bucket(key);
962 if (bucket ==
nullptr)
963 return insert(key, default_value).second;
965 return bucket->val();
968 template <
typename Key,
typename Val,
typename Alloc >
969 INLINE
typename HashTable< Key, Val, Alloc >::mapped_type&
970 HashTable< Key, Val, Alloc >::getWithDefault(Key&& key, Val&& default_value) {
971 Bucket* bucket = nodes__[hash_func__(key)].bucket(key);
973 if (bucket ==
nullptr)
974 return insert(std::move(key), std::move(default_value)).second;
976 return bucket->val();
979 template <
typename Key,
typename Val,
typename Alloc >
980 INLINE
void HashTable< Key, Val, Alloc >::set(
const Key& key,
const Val& value) {
981 Bucket* bucket = nodes__[hash_func__(key)].bucket(key);
983 if (bucket ==
nullptr)
986 bucket->val() = value;
989 template <
typename Key,
typename Val,
typename Alloc >
990 void HashTable< Key, Val, Alloc >::erase__(HashTableBucket< Key, Val >* bucket,
992 if (bucket ==
nullptr)
return;
995 for (
auto iter: safe_iterators__) {
996 if (iter->bucket__ == bucket) {
998 iter->next_bucket__ = iter->bucket__;
999 iter->bucket__ =
nullptr;
1000 }
else if (iter->next_bucket__ == bucket) {
1001 iter->bucket__ = bucket;
1003 iter->next_bucket__ = iter->bucket__;
1004 iter->bucket__ =
nullptr;
1009 nodes__[index].erase(bucket);
1013 if ((index == begin_index__) && nodes__[index].empty()) {
1014 begin_index__ = std::numeric_limits< Size >::max();
1018 template <
typename Key,
typename Val,
typename Alloc >
1019 INLINE
void HashTable< Key, Val, Alloc >::erase(
const Key& key) {
1021 Size hash = hash_func__(key);
1024 HashTableBucket< Key, Val >* bucket = nodes__[hash].bucket(key);
1026 erase__(bucket, hash);
1029 template <
typename Key,
typename Val,
typename Alloc >
1030 INLINE
void HashTable< Key, Val, Alloc >::erase(
const iterator_safe& iter) {
1031 erase__(iter.getBucket__(), iter.getIndex__());
1034 template <
typename Key,
typename Val,
typename Alloc >
1036 HashTable< Key, Val, Alloc >::erase(
const const_iterator_safe& iter) {
1037 erase__(iter.getBucket__(), iter.getIndex__());
1040 template <
typename Key,
typename Val,
typename Alloc >
1041 INLINE
void HashTable< Key, Val, Alloc >::eraseByVal(
const Val& val) {
1042 for (
auto iter = cbegin(); iter != cend(); ++iter)
1043 if (iter.bucket__->val() == val) {
1044 erase__(iter.getBucket__(), iter.getIndex__());
1049 template <
typename Key,
typename Val,
typename Alloc >
1050 INLINE
void HashTable< Key, Val, Alloc >::reset(
const Key& key) {
1054 template <
typename Key,
typename Val,
typename Alloc >
1055 INLINE
const Key& HashTable< Key, Val, Alloc >::keyByVal(
const Val& val)
const {
1056 for (
auto iter = begin(); iter != end(); ++iter)
1057 if (iter.bucket__->val() == val)
return iter.key();
1059 GUM_ERROR(NotFound,
"not enough elements in the chained list");
1062 template <
typename Key,
typename Val,
typename Alloc >
1063 INLINE
const Key& HashTable< Key, Val, Alloc >::key(
const Key& key)
const {
1065 Bucket* bucket = nodes__[hash_func__(key)].bucket(key);
1067 if (bucket ==
nullptr) {
1068 GUM_ERROR(NotFound,
"key does not belong to the hashtable");
1071 return bucket->key();
1074 template <
typename Key,
typename Val,
typename Alloc >
1075 void HashTable< Key, Val, Alloc >::eraseAllVal(
const Val& val) {
1076 for (
auto iterAll = cbeginSafe(); iterAll != cendSafe(); ++iterAll) {
1077 if (iterAll.bucket__->val() == val) {
1078 erase__(iterAll.bucket__, iterAll.index__);
1083 template <
typename Key,
typename Val,
typename Alloc >
1084 INLINE
bool HashTable< Key, Val, Alloc >::empty()
const noexcept {
1085 return (nb_elements__ == Size(0));
1088 template <
typename Key,
typename Val,
typename Alloc >
1089 template <
typename Mount,
typename OtherAlloc >
1090 HashTable< Key, Mount, OtherAlloc >
1091 INLINE HashTable< Key, Val, Alloc >::map(Mount (*f)(Val),
1094 bool key_uniqueness_pol)
const {
1099 if (size == 0) size = std::max(Size(2), nb_elements__ / 2);
1102 HashTable< Key, Mount, OtherAlloc > table(size,
1104 key_uniqueness_pol);
1107 for (
auto iter = begin(); iter != end(); ++iter) {
1108 table.insert(iter.key(), f(iter.val()));
1114 template <
typename Key,
typename Val,
typename Alloc >
1115 template <
typename Mount,
typename OtherAlloc >
1116 HashTable< Key, Mount, OtherAlloc >
1117 INLINE HashTable< Key, Val, Alloc >::map(Mount (*f)(Val&),
1120 bool key_uniqueness_pol)
const {
1125 if (size == Size(0)) size = std::max(Size(2), nb_elements__ / 2);
1128 HashTable< Key, Mount, OtherAlloc > table(size,
1130 key_uniqueness_pol);
1133 for (
auto iter = begin(); iter != end(); ++iter) {
1134 table.insert(iter.key(), f(
const_cast< Val& >(iter.val())));
1140 template <
typename Key,
typename Val,
typename Alloc >
1141 template <
typename Mount,
typename OtherAlloc >
1142 HashTable< Key, Mount, OtherAlloc >
1143 INLINE HashTable< Key, Val, Alloc >::map(Mount (*f)(
const Val&),
1146 bool key_uniqueness_pol)
const {
1151 if (size == Size(0)) size = std::max(Size(2), nb_elements__ / 2);
1154 HashTable< Key, Mount, OtherAlloc > table(size,
1156 key_uniqueness_pol);
1159 for (
auto iter = begin(); iter != end(); ++iter) {
1160 table.insert(iter.key(), f(iter.val()));
1166 template <
typename Key,
typename Val,
typename Alloc >
1167 template <
typename Mount,
typename OtherAlloc >
1168 HashTable< Key, Mount, OtherAlloc >
1169 INLINE HashTable< Key, Val, Alloc >::map(
const Mount& val,
1172 bool key_uniqueness_pol)
const {
1177 if (size == Size(0)) size = std::max(Size(2), nb_elements__ / 2);
1180 HashTable< Key, Mount, OtherAlloc > table(size,
1182 key_uniqueness_pol);
1185 for (
auto iter = begin(); iter != end(); ++iter) {
1186 table.insert(iter.key(), val);
1192 template <
typename Key,
typename Val,
typename Alloc >
1193 template <
typename OtherAlloc >
1194 bool HashTable< Key, Val, Alloc >::operator==(
1195 const HashTable< Key, Val, OtherAlloc >& from)
const {
1197 if (from.nb_elements__ != nb_elements__)
return false;
1200 for (
auto iter = begin(); iter != end(); ++iter) {
1202 if (iter.val() != from[iter.key()])
return false;
1203 }
catch (NotFound&) {
return false; }
1209 template <
typename Key,
typename Val,
typename Alloc >
1210 template <
typename OtherAlloc >
1211 INLINE
bool HashTable< Key, Val, Alloc >::operator!=(
1212 const HashTable< Key, Val, OtherAlloc >& from)
const {
1213 return !operator==(from);
1216 template <
typename Key,
typename Val,
typename Alloc >
1217 std::ostream& operator<<(std::ostream& stream,
1218 const HashTableList< Key, Val, Alloc >& list) {
1222 for (HashTableBucket< Key, Val >* ptr = list.deb_list__; ptr;
1223 ptr = ptr->list.next, deja =
true) {
1224 if (deja) stream <<
" , ";
1226 stream << ptr->key() <<
"=>" << ptr->val();
1234 template <
typename Key,
typename Val,
typename Alloc >
1235 std::ostream& operator<<(std::ostream& stream,
1236 const HashTableList< Key*, Val, Alloc >& list) {
1240 for (HashTableBucket< Key, Val >* ptr = list.deb_list__; ptr;
1241 ptr = ptr->list.next, deja =
true) {
1242 if (deja) stream <<
" , ";
1244 stream << ptr->key() <<
"=>" << ptr->val();
1252 template <
typename Key,
typename Val,
typename Alloc >
1253 std::ostream& operator<<(std::ostream& stream,
1254 const HashTable< Key, Val, Alloc >& table) {
1258 for (Size i = Size(0); i < table.size__; ++i)
1259 for (
auto ptr = table.nodes__[i].deb_list__; ptr; ptr = ptr->next) {
1260 if (deja) stream <<
" , ";
1262 stream << ptr->key() <<
"=>" << ptr->val();
1272 template <
typename Key,
typename Val,
typename Alloc >
1273 std::ostream& operator<<(std::ostream& stream,
1274 const HashTable< Key*, Val, Alloc >& table) {
1278 for (Size i = Size(0); i < table.size__; ++i)
1279 for (
auto ptr = table.nodes__[i].deb_list__; ptr; ptr = ptr->next) {
1280 if (deja) stream <<
" , ";
1282 stream << ptr->key() <<
"=>" << ptr->val();
1296 template <
typename Key,
typename Val >
1298 HashTableConstIteratorSafe< Key, Val >::insertIntoSafeList__()
const {
1299 table__->safe_iterators__.push_back(
1300 const_cast< HashTableConstIteratorSafe< Key, Val >* >(
this));
1303 template <
typename Key,
typename Val >
1305 HashTableConstIteratorSafe< Key, Val >::removeFromSafeList__()
const {
1306 if (table__ ==
nullptr)
return;
1309 std::vector< HashTableConstIteratorSafe< Key, Val >* >& iter_vect
1310 = table__->safe_iterators__;
1312 auto len = iter_vect.size();
1313 for (Size i = Size(0); i < len; ++i) {
1314 if (iter_vect[i] ==
this) {
1315 iter_vect.erase(iter_vect.begin() + i);
1321 template <
typename Key,
typename Val >
1322 INLINE HashTableConstIteratorSafe< Key, Val >::HashTableConstIteratorSafe() {
1324 GUM_CONSTRUCTOR(HashTableConstIteratorSafe);
1327 template <
typename Key,
typename Val >
1328 template <
typename Alloc >
1329 INLINE HashTableConstIteratorSafe< Key, Val >::HashTableConstIteratorSafe(
1330 const HashTable< Key, Val, Alloc >& tab) :
1331 table__{
reinterpret_cast<
const HashTable< Key, Val >* >(&tab)} {
1333 GUM_CONSTRUCTOR(HashTableConstIteratorSafe);
1336 insertIntoSafeList__();
1338 if (table__->nb_elements__) {
1339 if (table__->begin_index__ != std::numeric_limits< Size >::max()) {
1340 index__ = table__->begin_index__;
1341 bucket__ = table__->nodes__[index__].end_list__;
1344 for (Size i = table__->size__ - Size(1);; --i) {
1346 if (table__->nodes__[i].nb_elements__) {
1348 bucket__ = table__->nodes__[index__].end_list__;
1349 table__->begin_index__ = index__;
1357 template <
typename Key,
typename Val >
1358 template <
typename Alloc >
1359 HashTableConstIteratorSafe< Key, Val >::HashTableConstIteratorSafe(
1360 const HashTable< Key, Val, Alloc >& tab,
1362 table__{
reinterpret_cast<
const HashTable< Key, Val >* >(&tab)} {
1366 if ((ind_elt == Size(0))
1367 && (table__->begin_index__ != std::numeric_limits< Size >::max())) {
1368 index__ = table__->begin_index__;
1369 bucket__ = table__->nodes__[index__].end_list__;
1373 if (ind_elt < (table__->nb_elements__ >> 1)) {
1375 for (i = table__->size__ - 1;; --i) {
1377 if (table__->nodes__[i].nb_elements__) {
1378 if (ind_elt >= table__->nodes__[i].nb_elements__)
1379 ind_elt -= table__->nodes__[i].nb_elements__;
1381 for (bucket__ = table__->nodes__[i].end_list__; ind_elt;
1382 --ind_elt, bucket__ = bucket__->prev) {}
1392 if (ind_elt >= table__->nb_elements__) {
1393 GUM_ERROR(UndefinedIteratorValue,
1394 "Not enough elements in the hashtable");
1398 for (i = 0, ind_elt = table__->nb_elements__ - ind_elt - 1;; ++i) {
1399 if (table__->nodes__[i].nb_elements__) {
1400 if (ind_elt >= table__->nodes__[i].nb_elements__)
1401 ind_elt -= table__->nodes__[i].nb_elements__;
1403 for (bucket__ = table__->nodes__[i].deb_list__; ind_elt;
1404 --ind_elt, bucket__ = bucket__->next) {}
1415 GUM_CONSTRUCTOR(HashTableConstIteratorSafe);
1418 insertIntoSafeList__();
1421 template <
typename Key,
typename Val >
1422 INLINE HashTableConstIteratorSafe< Key, Val >::HashTableConstIteratorSafe(
1423 const HashTableConstIteratorSafe< Key, Val >& from) :
1424 table__{from.table__},
1425 index__{from.index__}, bucket__{from.bucket__}, next_bucket__{
1426 from.next_bucket__} {
1428 if (table__ !=
nullptr) { insertIntoSafeList__(); }
1431 GUM_CONS_CPY(HashTableConstIteratorSafe);
1434 template <
typename Key,
typename Val >
1435 INLINE HashTableConstIteratorSafe< Key, Val >::HashTableConstIteratorSafe(
1436 const HashTableConstIterator< Key, Val >& from) :
1437 table__{from.table__},
1438 index__{from.index__}, bucket__{from.bucket__} {
1440 if (table__ !=
nullptr) { insertIntoSafeList__(); }
1443 GUM_CONS_CPY(HashTableConstIteratorSafe);
1446 template <
typename Key,
typename Val >
1447 INLINE HashTableConstIteratorSafe< Key, Val >::HashTableConstIteratorSafe(
1448 HashTableConstIteratorSafe< Key, Val >&& from) :
1449 table__{from.table__},
1450 index__{from.index__}, bucket__{from.bucket__}, next_bucket__{
1451 from.next_bucket__} {
1452 GUM_CONS_MOV(HashTableConstIteratorSafe);
1456 if (table__ !=
nullptr) {
1457 std::vector< HashTableConstIteratorSafe< Key, Val >* >& vect
1458 = table__->safe_iterators__;
1460 for (
auto ptr = vect.rbegin(); ptr != vect.rend(); ++ptr) {
1461 if (*ptr == &from) {
1463 from.table__ =
nullptr;
1470 template <
typename Key,
typename Val >
1472 HashTableConstIteratorSafe< Key,
1473 Val >::~HashTableConstIteratorSafe()
noexcept {
1475 GUM_DESTRUCTOR(HashTableConstIteratorSafe);
1478 removeFromSafeList__();
1481 template <
typename Key,
typename Val >
1482 HashTableConstIteratorSafe< Key, Val >&
1483 HashTableConstIteratorSafe< Key, Val >::operator=(
1484 const HashTableConstIteratorSafe< Key, Val >& from) {
1492 if (table__ != from.table__) {
1494 removeFromSafeList__();
1496 table__ = from.table__;
1499 if (table__) { insertIntoSafeList__(); }
1502 index__ = from.index__;
1503 bucket__ = from.bucket__;
1504 next_bucket__ = from.next_bucket__;
1509 template <
typename Key,
typename Val >
1510 HashTableConstIteratorSafe< Key, Val >&
1511 HashTableConstIteratorSafe< Key, Val >::operator=(
1512 const HashTableConstIterator< Key, Val >& from) {
1520 if (table__ != from.table__) {
1522 removeFromSafeList__();
1524 table__ = from.table__;
1527 if (table__) { insertIntoSafeList__(); }
1530 index__ = from.index__;
1531 bucket__ = from.bucket__;
1532 next_bucket__ =
nullptr;
1537 template <
typename Key,
typename Val >
1538 INLINE HashTableConstIteratorSafe< Key, Val >&
1539 HashTableConstIteratorSafe< Key, Val >::operator=(
1540 HashTableConstIteratorSafe< Key, Val >&& from)
noexcept {
1548 if (table__ != from.table__) {
1550 removeFromSafeList__();
1552 if (from.table__ !=
nullptr) {
1554 std::vector< HashTableConstIteratorSafe< Key, Val >* >& vect
1555 = from.table__->safe_iterators__;
1557 for (
auto ptr = vect.rbegin(); ptr != vect.rend(); ++ptr) {
1558 if (*ptr == &from) {
1565 table__ = from.table__;
1566 from.table__ =
nullptr;
1569 index__ = from.index__;
1570 bucket__ = from.bucket__;
1571 next_bucket__ = from.next_bucket__;
1576 template <
typename Key,
typename Val >
1577 INLINE
const typename HashTableConstIteratorSafe< Key, Val >::key_type&
1578 HashTableConstIteratorSafe< Key, Val >::key()
const {
1579 if (bucket__ !=
nullptr)
1580 return bucket__->key();
1582 GUM_ERROR(UndefinedIteratorValue,
"Accessing a nullptr object");
1586 template <
typename Key,
typename Val >
1587 INLINE
const typename HashTableConstIteratorSafe< Key, Val >::mapped_type&
1588 HashTableConstIteratorSafe< Key, Val >::val()
const {
1589 if (bucket__ !=
nullptr)
1590 return bucket__->val();
1592 GUM_ERROR(UndefinedIteratorValue,
"Accessing a nullptr object");
1596 template <
typename Key,
typename Val >
1597 INLINE
void HashTableConstIteratorSafe< Key, Val >::clear()
noexcept {
1599 removeFromSafeList__();
1604 next_bucket__ =
nullptr;
1610 template <
typename Key,
typename Val >
1611 HashTableConstIteratorSafe< Key, Val >&
1612 HashTableConstIteratorSafe< Key, Val >::operator++()
noexcept {
1614 if (bucket__ ==
nullptr) {
1620 bucket__ = next_bucket__;
1621 next_bucket__ =
nullptr;
1627 if (bucket__->prev) {
1628 bucket__ = bucket__->prev;
1638 if (index__ == Size(0)) {
1648 if (index__ > Size(0)) {
1649 for (Size i = index__ - Size(1); i > Size(0); --i) {
1650 if (table__->nodes__[i].nb_elements__) {
1652 bucket__ = table__->nodes__[i].end_list__;
1658 if (table__->nodes__[0].nb_elements__)
1659 bucket__ = table__->nodes__[0].end_list__;
1671 template <
typename Key,
typename Val >
1672 HashTableConstIteratorSafe< Key, Val >&
1673 HashTableConstIteratorSafe< Key, Val >::operator+=(Size nb)
noexcept {
1674 if ((nb == Size(0)) || (table__ ==
nullptr))
return *
this;
1677 if (bucket__ ==
nullptr) {
1683 bucket__ = next_bucket__;
1684 next_bucket__ =
nullptr;
1690 for (; nb && bucket__ !=
nullptr; --nb, bucket__ = bucket__->prev) {}
1692 if (bucket__ !=
nullptr)
return *
this;
1698 for (; index__ < table__->size__
1699 && nb >= table__->nodes__[index__].nb_elements__;
1700 nb -= table__->nodes__[index__].nb_elements__, --index__) {}
1706 if (index__ >= table__->size__) {
1711 for (bucket__ = table__->nodes__[index__].end_list__; nb;
1712 --nb, bucket__ = bucket__->prev) {}
1717 template <
typename Key,
typename Val >
1718 INLINE HashTableConstIteratorSafe< Key, Val >
1719 HashTableConstIteratorSafe< Key, Val >::operator+(Size nb)
const {
1720 return HashTableConstIteratorSafe< Key, Val >{*
this} += nb;
1723 template <
typename Key,
typename Val >
1724 INLINE
bool HashTableConstIteratorSafe< Key, Val >::operator!=(
1725 const HashTableConstIteratorSafe< Key, Val >& from)
const noexcept {
1726 return ((bucket__ != from.bucket__) || (index__ != from.index__));
1729 template <
typename Key,
typename Val >
1730 INLINE
bool HashTableConstIteratorSafe< Key, Val >::operator==(
1731 const HashTableConstIteratorSafe< Key, Val >& from)
const noexcept {
1732 return ((bucket__ == from.bucket__) && (index__ == from.index__));
1735 template <
typename Key,
typename Val >
1736 INLINE
const typename HashTableConstIteratorSafe< Key, Val >::value_type&
1737 HashTableConstIteratorSafe< Key, Val >::operator*()
const {
1739 return bucket__->elt();
1741 GUM_ERROR(UndefinedIteratorValue,
"Accessing a nullptr object");
1745 template <
typename Key,
typename Val >
1746 INLINE HashTableBucket< Key, Val >*
1747 HashTableConstIteratorSafe< Key, Val >::getBucket__()
const noexcept {
1751 template <
typename Key,
typename Val >
1752 INLINE Size HashTableConstIteratorSafe< Key, Val >::getIndex__()
const noexcept {
1760 template <
typename Key,
typename Val >
1761 INLINE HashTableIteratorSafe< Key, Val >::HashTableIteratorSafe() :
1762 HashTableConstIteratorSafe< Key, Val >() {
1763 GUM_CONSTRUCTOR(HashTableIteratorSafe);
1766 template <
typename Key,
typename Val >
1767 template <
typename Alloc >
1768 INLINE HashTableIteratorSafe< Key, Val >::HashTableIteratorSafe(
1769 const HashTable< Key, Val, Alloc >& tab) :
1770 HashTableConstIteratorSafe< Key, Val >(tab) {
1771 GUM_CONSTRUCTOR(HashTableIteratorSafe);
1774 template <
typename Key,
typename Val >
1775 template <
typename Alloc >
1776 INLINE HashTableIteratorSafe< Key, Val >::HashTableIteratorSafe(
1777 const HashTable< Key, Val, Alloc >& tab,
1779 HashTableConstIteratorSafe< Key, Val >(tab, ind_elt) {
1780 GUM_CONSTRUCTOR(HashTableIteratorSafe);
1783 template <
typename Key,
typename Val >
1784 INLINE HashTableIteratorSafe< Key, Val >::HashTableIteratorSafe(
1785 const HashTableIteratorSafe< Key, Val >& from) :
1786 HashTableConstIteratorSafe< Key, Val >(from) {
1787 GUM_CONS_CPY(HashTableIteratorSafe);
1790 template <
typename Key,
typename Val >
1791 INLINE HashTableIteratorSafe< Key, Val >::HashTableIteratorSafe(
1792 const HashTableIterator< Key, Val >& from) :
1793 HashTableConstIteratorSafe< Key, Val >(from) {
1794 GUM_CONS_CPY(HashTableIteratorSafe);
1797 template <
typename Key,
typename Val >
1798 INLINE HashTableIteratorSafe< Key, Val >::HashTableIteratorSafe(
1799 HashTableIteratorSafe< Key, Val >&& from)
noexcept :
1800 HashTableConstIteratorSafe< Key, Val >(std::move(from)) {
1801 GUM_CONS_MOV(HashTableIteratorSafe);
1804 template <
typename Key,
typename Val >
1805 INLINE HashTableIteratorSafe< Key, Val >::~HashTableIteratorSafe()
noexcept {
1806 GUM_DESTRUCTOR(HashTableIteratorSafe);
1809 template <
typename Key,
typename Val >
1810 INLINE
typename HashTableIteratorSafe< Key, Val >::mapped_type&
1811 HashTableIteratorSafe< Key, Val >::val() {
1812 return const_cast< Val& >(HashTableConstIteratorSafe< Key, Val >::val());
1815 template <
typename Key,
typename Val >
1816 INLINE HashTableIteratorSafe< Key, Val >&
1817 HashTableIteratorSafe< Key, Val >::operator=(
1818 const HashTableIteratorSafe< Key, Val >& from) {
1819 GUM_OP_CPY(HashTableIteratorSafe);
1820 HashTableConstIteratorSafe< Key, Val >::operator=(from);
1824 template <
typename Key,
typename Val >
1825 INLINE HashTableIteratorSafe< Key, Val >&
1826 HashTableIteratorSafe< Key, Val >::operator=(
1827 const HashTableIterator< Key, Val >& from) {
1828 GUM_OP_CPY(HashTableIteratorSafe);
1829 HashTableConstIteratorSafe< Key, Val >::operator=(from);
1833 template <
typename Key,
typename Val >
1834 INLINE HashTableIteratorSafe< Key, Val >&
1835 HashTableIteratorSafe< Key, Val >::operator=(
1836 HashTableIteratorSafe< Key, Val >&& from)
noexcept {
1837 HashTableConstIteratorSafe< Key, Val >::operator=(std::move(from));
1841 template <
typename Key,
typename Val >
1842 INLINE HashTableIteratorSafe< Key, Val >&
1843 HashTableIteratorSafe< Key, Val >::operator++()
noexcept {
1844 HashTableConstIteratorSafe< Key, Val >::operator++();
1848 template <
typename Key,
typename Val >
1849 INLINE HashTableIteratorSafe< Key, Val >&
1850 HashTableIteratorSafe< Key, Val >::operator+=(Size nb)
noexcept {
1851 HashTableConstIteratorSafe< Key, Val >::operator+=(nb);
1855 template <
typename Key,
typename Val >
1856 INLINE HashTableIteratorSafe< Key, Val >
1857 HashTableIteratorSafe< Key, Val >::operator+(Size nb)
const {
1858 HashTableIteratorSafe< Key, Val > iter{*
this};
1863 template <
typename Key,
typename Val >
1864 INLINE
bool HashTableIteratorSafe< Key, Val >::operator!=(
1865 const HashTableIteratorSafe< Key, Val >& from)
const noexcept {
1866 return HashTableConstIteratorSafe< Key, Val >::operator!=(from);
1869 template <
typename Key,
typename Val >
1870 INLINE
bool HashTableIteratorSafe< Key, Val >::operator==(
1871 const HashTableIteratorSafe< Key, Val >& from)
const noexcept {
1872 return HashTableConstIteratorSafe< Key, Val >::operator==(from);
1875 template <
typename Key,
typename Val >
1876 INLINE
typename HashTableIteratorSafe< Key, Val >::value_type&
1877 HashTableIteratorSafe< Key, Val >::operator*() {
1878 return const_cast< Val& >(HashTableConstIteratorSafe< Key, Val >::operator*());
1881 template <
typename Key,
typename Val >
1882 INLINE
const typename HashTableIteratorSafe< Key, Val >::value_type&
1883 HashTableIteratorSafe< Key, Val >::operator*()
const {
1884 return HashTableConstIteratorSafe< Key, Val >::operator*();
1891 template <
typename Key,
typename Val >
1892 INLINE HashTableConstIterator< Key, Val >::HashTableConstIterator()
noexcept {
1893 GUM_CONSTRUCTOR(HashTableConstIterator);
1896 template <
typename Key,
typename Val >
1897 template <
typename Alloc >
1898 INLINE HashTableConstIterator< Key, Val >::HashTableConstIterator(
1899 const HashTable< Key, Val, Alloc >& tab)
noexcept :
1900 table__{
reinterpret_cast<
const HashTable< Key, Val >* >(&tab)} {
1902 GUM_CONSTRUCTOR(HashTableConstIterator);
1904 if (table__->nb_elements__) {
1905 if (table__->begin_index__ != std::numeric_limits< Size >::max()) {
1906 index__ = table__->begin_index__;
1907 bucket__ = table__->nodes__[index__].end_list__;
1910 for (Size i = table__->size__ - Size(1);; --i) {
1912 if (table__->nodes__[i].nb_elements__) {
1914 bucket__ = table__->nodes__[index__].end_list__;
1915 table__->begin_index__ = index__;
1923 template <
typename Key,
typename Val >
1924 template <
typename Alloc >
1925 HashTableConstIterator< Key, Val >::HashTableConstIterator(
1926 const HashTable< Key, Val, Alloc >& tab,
1928 table__{
reinterpret_cast<
const HashTable< Key, Val >* >(&tab)} {
1932 if ((ind_elt == Size(0))
1933 && (table__->begin_index__ != std::numeric_limits< Size >::max())) {
1934 index__ = table__->begin_index__;
1935 bucket__ = table__->nodes__[index__].end_list__;
1939 if (ind_elt < (table__->nb_elements__ >> 1)) {
1941 for (i = table__->size__ - 1;; --i) {
1943 if (table__->nodes__[i].nb_elements__) {
1944 if (ind_elt >= table__->nodes__[i].nb_elements__)
1945 ind_elt -= table__->nodes__[i].nb_elements__;
1947 for (bucket__ = table__->nodes__[i].end_list__; ind_elt;
1948 --ind_elt, bucket__ = bucket__->prev) {}
1958 if (ind_elt >= table__->nb_elements__) {
1959 GUM_ERROR(UndefinedIteratorValue,
1960 "Not enough elements in the hashtable");
1964 for (i = 0, ind_elt = table__->nb_elements__ - ind_elt - 1;; ++i) {
1965 if (table__->nodes__[i].nb_elements__) {
1966 if (ind_elt >= table__->nodes__[i].nb_elements__)
1967 ind_elt -= table__->nodes__[i].nb_elements__;
1969 for (bucket__ = table__->nodes__[i].deb_list__; ind_elt;
1970 --ind_elt, bucket__ = bucket__->next) {}
1981 GUM_CONSTRUCTOR(HashTableConstIterator);
1984 template <
typename Key,
typename Val >
1985 INLINE HashTableConstIterator< Key, Val >::HashTableConstIterator(
1986 const HashTableConstIterator< Key, Val >& from)
noexcept :
1987 table__{from.table__},
1988 index__{from.index__}, bucket__{from.bucket__} {
1989 GUM_CONS_CPY(HashTableConstIterator);
1992 template <
typename Key,
typename Val >
1993 INLINE HashTableConstIterator< Key, Val >::HashTableConstIterator(
1994 HashTableConstIterator< Key, Val >&& from)
noexcept :
1995 table__{from.table__},
1996 index__{from.index__}, bucket__{from.bucket__} {
1997 GUM_CONS_MOV(HashTableConstIterator);
2000 template <
typename Key,
typename Val >
2001 INLINE HashTableConstIterator< Key, Val >::~HashTableConstIterator()
noexcept {
2003 GUM_DESTRUCTOR(HashTableConstIterator);
2006 template <
typename Key,
typename Val >
2007 INLINE HashTableConstIterator< Key, Val >&
2008 HashTableConstIterator< Key, Val >::operator=(
2009 const HashTableConstIterator< Key, Val >& from)
noexcept {
2013 table__ = from.table__;
2014 index__ = from.index__;
2015 bucket__ = from.bucket__;
2020 template <
typename Key,
typename Val >
2021 INLINE HashTableConstIterator< Key, Val >&
2022 HashTableConstIterator< Key, Val >::operator=(
2023 HashTableConstIterator< Key, Val >&& from)
noexcept {
2027 table__ = from.table__;
2028 index__ = from.index__;
2029 bucket__ = from.bucket__;
2034 template <
typename Key,
typename Val >
2035 INLINE
const typename HashTableConstIterator< Key, Val >::key_type&
2036 HashTableConstIterator< Key, Val >::key()
const {
2038 return bucket__->pair.first;
2040 GUM_ERROR(UndefinedIteratorValue,
"Accessing a nullptr object");
2044 template <
typename Key,
typename Val >
2045 INLINE
const typename HashTableConstIterator< Key, Val >::mapped_type&
2046 HashTableConstIterator< Key, Val >::val()
const {
2048 return bucket__->val();
2050 GUM_ERROR(UndefinedIteratorValue,
"Accessing a nullptr object");
2054 template <
typename Key,
typename Val >
2055 INLINE
void HashTableConstIterator< Key, Val >::clear()
noexcept {
2061 template <
typename Key,
typename Val >
2062 HashTableConstIterator< Key, Val >&
2063 HashTableConstIterator< Key, Val >::operator++()
noexcept {
2065 if (bucket__ ==
nullptr)
return *
this;
2069 if (bucket__->prev) {
2070 bucket__ = bucket__->prev;
2079 if (index__ == Size(0)) {
2089 for (Size i = index__ - Size(1); i; --i) {
2090 if (table__->nodes__[i].nb_elements__) {
2092 bucket__ = table__->nodes__[i].end_list__;
2097 if (table__->nodes__[0].nb_elements__)
2098 bucket__ = table__->nodes__[0].end_list__;
2109 template <
typename Key,
typename Val >
2110 HashTableConstIterator< Key, Val >&
2111 HashTableConstIterator< Key, Val >::operator+=(Size nb)
noexcept {
2112 if ((nb == 0) || (table__ ==
nullptr) || (bucket__ ==
nullptr))
return *
this;
2116 for (; nb && bucket__ !=
nullptr; --nb, bucket__ = bucket__->prev) {}
2118 if (bucket__ !=
nullptr)
return *
this;
2124 for (; index__ < table__->size__
2125 && nb >= table__->nodes__[index__].nb_elements__;
2126 nb -= table__->nodes__[index__].nb_elements__, --index__) {}
2132 if (index__ >= table__->size__) {
2137 for (bucket__ = table__->nodes__[index__].end_list__; nb;
2138 --nb, bucket__ = bucket__->prev) {}
2143 template <
typename Key,
typename Val >
2144 INLINE HashTableConstIterator< Key, Val >
2145 HashTableConstIterator< Key, Val >::operator+(Size nb)
const noexcept {
2146 return HashTableConstIterator< Key, Val >{*
this} += nb;
2149 template <
typename Key,
typename Val >
2150 INLINE
bool HashTableConstIterator< Key, Val >::operator!=(
2151 const HashTableConstIterator< Key, Val >& from)
const noexcept {
2152 return (bucket__ != from.bucket__);
2155 template <
typename Key,
typename Val >
2156 INLINE
bool HashTableConstIterator< Key, Val >::operator==(
2157 const HashTableConstIterator< Key, Val >& from)
const noexcept {
2158 return (bucket__ == from.bucket__);
2161 template <
typename Key,
typename Val >
2162 INLINE
const typename HashTableConstIterator< Key, Val >::value_type&
2163 HashTableConstIterator< Key, Val >::operator*()
const {
2165 return bucket__->elt();
2167 GUM_ERROR(UndefinedIteratorValue,
"Accessing a nullptr object");
2171 template <
typename Key,
typename Val >
2172 INLINE
typename HashTable< Key, Val >::Bucket*
2173 HashTableConstIterator< Key, Val >::getBucket__()
const noexcept {
2177 template <
typename Key,
typename Val >
2178 INLINE Size HashTableConstIterator< Key, Val >::getIndex__()
const noexcept {
2186 template <
typename Key,
typename Val >
2187 INLINE HashTableIterator< Key, Val >::HashTableIterator()
noexcept :
2188 HashTableConstIterator< Key, Val >() {
2189 GUM_CONSTRUCTOR(HashTableIterator);
2192 template <
typename Key,
typename Val >
2193 template <
typename Alloc >
2194 INLINE HashTableIterator< Key, Val >::HashTableIterator(
2195 const HashTable< Key, Val, Alloc >& tab)
noexcept :
2196 HashTableConstIterator< Key, Val >(tab) {
2197 GUM_CONSTRUCTOR(HashTableIterator);
2200 template <
typename Key,
typename Val >
2201 template <
typename Alloc >
2202 INLINE HashTableIterator< Key, Val >::HashTableIterator(
2203 const HashTable< Key, Val, Alloc >& tab,
2205 HashTableConstIterator< Key, Val >(tab, ind_elt) {
2206 GUM_CONSTRUCTOR(HashTableIterator);
2209 template <
typename Key,
typename Val >
2210 INLINE HashTableIterator< Key, Val >::HashTableIterator(
2211 const HashTableIterator< Key, Val >& from)
noexcept :
2212 HashTableConstIterator< Key, Val >(from) {
2213 GUM_CONS_CPY(HashTableIterator);
2216 template <
typename Key,
typename Val >
2217 INLINE HashTableIterator< Key, Val >::HashTableIterator(
2218 HashTableIterator< Key, Val >&& from)
noexcept :
2219 HashTableConstIterator< Key, Val >(std::move(from)) {
2220 GUM_CONS_MOV(HashTableIterator);
2223 template <
typename Key,
typename Val >
2224 INLINE HashTableIterator< Key, Val >::~HashTableIterator()
noexcept {
2225 GUM_DESTRUCTOR(HashTableIterator);
2228 template <
typename Key,
typename Val >
2229 INLINE
typename HashTableIterator< Key, Val >::mapped_type&
2230 HashTableIterator< Key, Val >::val() {
2232 return this->bucket__->val();
2234 GUM_ERROR(UndefinedIteratorValue,
"Accessing a nullptr object");
2238 template <
typename Key,
typename Val >
2239 INLINE HashTableIterator< Key, Val >& HashTableIterator< Key, Val >::operator=(
2240 const HashTableIterator< Key, Val >& from)
noexcept {
2241 HashTableConstIterator< Key, Val >::operator=(from);
2245 template <
typename Key,
typename Val >
2246 INLINE HashTableIterator< Key, Val >& HashTableIterator< Key, Val >::operator=(
2247 HashTableIterator< Key, Val >&& from)
noexcept {
2248 HashTableConstIterator< Key, Val >::operator=(std::move(from));
2252 template <
typename Key,
typename Val >
2253 INLINE HashTableIterator< Key, Val >&
2254 HashTableIterator< Key, Val >::operator++()
noexcept {
2255 HashTableConstIterator< Key, Val >::operator++();
2259 template <
typename Key,
typename Val >
2260 INLINE HashTableIterator< Key, Val >&
2261 HashTableIterator< Key, Val >::operator+=(Size nb)
noexcept {
2262 HashTableConstIterator< Key, Val >::operator+=(nb);
2266 template <
typename Key,
typename Val >
2267 INLINE HashTableIterator< Key, Val >
2268 HashTableIterator< Key, Val >::operator+(Size nb)
const noexcept {
2269 HashTableIterator< Key, Val > iter{*
this};
2274 template <
typename Key,
typename Val >
2275 INLINE
bool HashTableIterator< Key, Val >::operator!=(
2276 const HashTableIterator< Key, Val >& from)
const noexcept {
2277 return HashTableConstIterator< Key, Val >::operator!=(from);
2280 template <
typename Key,
typename Val >
2281 INLINE
bool HashTableIterator< Key, Val >::operator==(
2282 const HashTableIterator< Key, Val >& from)
const noexcept {
2283 return HashTableConstIterator< Key, Val >::operator==(from);
2286 template <
typename Key,
typename Val >
2287 INLINE
typename HashTableIterator< Key, Val >::value_type&
2288 HashTableIterator< Key, Val >::operator*() {
2289 return const_cast< value_type& >(
2290 HashTableConstIterator< Key, Val >::operator*());
2293 template <
typename Key,
typename Val >
2294 INLINE
const typename HashTableIterator< Key, Val >::value_type&
2295 HashTableIterator< Key, Val >::operator*()
const {
2296 return HashTableConstIterator< Key, Val >::operator*();