132 typedef ETL_OR_STD::pair<const TKey, T> value_type;
134 typedef TKey key_type;
135 typedef T mapped_type;
136 typedef THash hasher;
137 typedef TKeyEqual key_equal;
138 typedef value_type& reference;
139 typedef const value_type& const_reference;
141 typedef value_type&& rvalue_reference;
143 typedef value_type* pointer;
144 typedef const value_type* const_pointer;
145 typedef size_t size_type;
150 typedef key_type&& rvalue_key_reference;
152 typedef mapped_type& mapped_reference;
153 typedef const mapped_type& const_mapped_reference;
159 struct node_t :
public link_t
161 node_t(const_reference key_value_pair_)
162 : key_value_pair(key_value_pair_)
166 value_type key_value_pair;
169 friend bool operator ==(
const node_t& lhs,
const node_t& rhs)
171 return (lhs.key_value_pair.first == rhs.key_value_pair.first) &&
172 (lhs.key_value_pair.second == rhs.key_value_pair.second);
175 friend bool operator !=(
const node_t& lhs,
const node_t& rhs)
177 return !(lhs == rhs);
188 typedef typename bucket_t::iterator local_iterator;
189 typedef typename bucket_t::const_iterator const_local_iterator;
196 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, T>::value_type value_type;
197 typedef typename iunordered_map::key_type key_type;
198 typedef typename iunordered_map::mapped_type mapped_type;
199 typedef typename iunordered_map::hasher hasher;
200 typedef typename iunordered_map::key_equal key_equal;
201 typedef typename iunordered_map::reference reference;
202 typedef typename iunordered_map::const_reference const_reference;
203 typedef typename iunordered_map::pointer pointer;
204 typedef typename iunordered_map::const_pointer const_pointer;
205 typedef typename iunordered_map::size_type size_type;
207 friend class iunordered_map;
208 friend class const_iterator;
216 iterator(
const iterator& other)
217 : pbuckets_end(other.pbuckets_end)
218 , pbucket(other.pbucket)
224 iterator& operator ++()
229 if (inode == pbucket->end())
233 while ((pbucket != pbuckets_end) && (pbucket->empty()))
239 if (pbucket != pbuckets_end)
241 inode = pbucket->begin();
249 iterator operator ++(
int)
251 iterator temp(*
this);
257 iterator& operator =(
const iterator& other)
259 pbuckets_end = other.pbuckets_end;
260 pbucket = other.pbucket;
266 reference operator *()
const
268 return inode->key_value_pair;
272 pointer operator &()
const
274 return &(inode->key_value_pair);
278 pointer operator ->()
const
280 return &(inode->key_value_pair);
284 friend bool operator == (
const iterator& lhs,
const iterator& rhs)
286 return lhs.compare(rhs);
290 friend bool operator != (
const iterator& lhs,
const iterator& rhs)
292 return !(lhs == rhs);
298 iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
299 : pbuckets_end(pbuckets_end_)
306 bool compare(
const iterator& rhs)
const
308 return rhs.inode == inode;
312 bucket_t& get_bucket()
318 bucket_t* get_bucket_list_iterator()
324 local_iterator get_local_iterator()
329 bucket_t* pbuckets_end;
331 local_iterator inode;
335 class const_iterator :
public etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>
339 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>::value_type value_type;
340 typedef typename iunordered_map::key_type key_type;
341 typedef typename iunordered_map::mapped_type mapped_type;
342 typedef typename iunordered_map::hasher hasher;
343 typedef typename iunordered_map::key_equal key_equal;
344 typedef typename iunordered_map::reference reference;
345 typedef typename iunordered_map::const_reference const_reference;
346 typedef typename iunordered_map::pointer pointer;
347 typedef typename iunordered_map::const_pointer const_pointer;
348 typedef typename iunordered_map::size_type size_type;
350 friend class iunordered_map;
351 friend class iterator;
360 : pbuckets_end(other.pbuckets_end)
361 , pbucket(other.pbucket)
367 const_iterator(
const const_iterator& other)
368 : pbuckets_end(other.pbuckets_end)
369 , pbucket(other.pbucket)
375 const_iterator& operator ++()
380 if (inode == pbucket->end())
384 while ((pbucket != pbuckets_end) && (pbucket->empty()))
390 if (pbucket != pbuckets_end)
392 inode = pbucket->begin();
400 const_iterator operator ++(
int)
402 const_iterator temp(*
this);
408 const_iterator& operator =(
const const_iterator& other)
410 pbuckets_end = other.pbuckets_end;
411 pbucket = other.pbucket;
417 const_reference operator *()
const
419 return inode->key_value_pair;
423 const_pointer operator &()
const
425 return &(inode->key_value_pair);
429 const_pointer operator ->()
const
431 return &(inode->key_value_pair);
435 friend bool operator == (
const const_iterator& lhs,
const const_iterator& rhs)
437 return lhs.compare(rhs);
441 friend bool operator != (
const const_iterator& lhs,
const const_iterator& rhs)
443 return !(lhs == rhs);
449 const_iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
450 : pbuckets_end(pbuckets_end_)
457 bool compare(
const const_iterator& rhs)
const
459 return rhs.inode == inode;
463 bucket_t& get_bucket()
469 bucket_t* get_bucket_list_iterator()
475 local_iterator get_local_iterator()
480 bucket_t* pbuckets_end;
482 local_iterator inode;
485 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
493 return iterator((pbuckets + number_of_buckets), first, first->begin());
502 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
511 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
520 return pbuckets[i].begin();
527 const_local_iterator
begin(
size_t i)
const
529 return pbuckets[i].cbegin();
536 const_local_iterator
cbegin(
size_t i)
const
538 return pbuckets[i].cbegin();
547 return iterator((pbuckets + number_of_buckets), last, last->end());
554 const_iterator
end()
const
556 return const_iterator((pbuckets + number_of_buckets), last, last->end());
565 return const_iterator((pbuckets + number_of_buckets), last, last->end());
572 local_iterator
end(
size_t i)
574 return pbuckets[i].end();
581 const_local_iterator
end(
size_t i)
const
583 return pbuckets[i].cend();
590 const_local_iterator
cend(
size_t i)
const
592 return pbuckets[i].cend();
601 return key_hash_function(key) % number_of_buckets;
609 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
612 return key_hash_function(key) % number_of_buckets;
622 size_t index = bucket(key);
624 return etl::distance(pbuckets[index].
begin(), pbuckets[index].
end());
632 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
635 size_t index = bucket(key);
637 return etl::distance(pbuckets[index].
begin(), pbuckets[index].
end());
647 return number_of_buckets;
656 return number_of_buckets;
665 mapped_reference
operator [](rvalue_key_reference key)
671 local_iterator inode = pbucket->begin();
674 while (inode != pbucket->end())
677 if (key_equal_function(key, inode->key_value_pair.first))
680 return inode->key_value_pair.second;
690 node_t* node = allocate_data_node();
692 ::new ((
void*)
etl::addressof(node->key_value_pair.first)) key_type(etl::move(key));
693 ::new ((
void*)etl::
addressof(node->key_value_pair.second)) mapped_type();
694 ETL_INCREMENT_DEBUG_COUNT;
696 pbucket->insert_after(pbucket->before_begin(), *node);
698 adjust_first_last_markers_after_insert(pbucket);
700 return pbucket->
begin()->key_value_pair.second;
715 local_iterator inode = pbucket->
begin();
718 while (inode != pbucket->
end())
721 if (key_equal_function(key, inode->key_value_pair.first))
724 return inode->key_value_pair.second;
734 node_t* node = allocate_data_node();
736 ::new ((
void*)
etl::addressof(node->key_value_pair.first)) key_type(key);
737 ::new ((
void*)
etl::addressof(node->key_value_pair.second)) mapped_type();
738 ETL_INCREMENT_DEBUG_COUNT;
742 adjust_first_last_markers_after_insert(pbucket);
744 return pbucket->
begin()->key_value_pair.second;
753 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
760 local_iterator inode = pbucket->begin();
763 while (inode != pbucket->end())
766 if (key_equal_function(key, inode->key_value_pair.first))
769 return inode->key_value_pair.second;
779 node_t* node = allocate_data_node();
781 ::new ((
void*)
etl::addressof(node->key_value_pair.first)) key_type(key);
782 ::new ((
void*)etl::
addressof(node->key_value_pair.second)) mapped_type();
783 ETL_INCREMENT_DEBUG_COUNT;
785 pbucket->insert_after(pbucket->before_begin(), *node);
787 adjust_first_last_markers_after_insert(pbucket);
789 return pbucket->
begin()->key_value_pair.second;
805 local_iterator inode = pbucket->
begin();
808 while (inode != pbucket->
end())
811 if (key_equal_function(key, inode->key_value_pair.first))
814 return inode->key_value_pair.second;
825 return begin()->second;
840 local_iterator inode = pbucket->
begin();
843 while (inode != pbucket->
end())
846 if (key_equal_function(key, inode->key_value_pair.first))
849 return inode->key_value_pair.second;
860 return begin()->second;
870 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
871 mapped_reference
at(
const K& key)
877 local_iterator inode = pbucket->begin();
880 while (inode != pbucket->end())
883 if (key_equal_function(key, inode->key_value_pair.first))
886 return inode->key_value_pair.second;
895 ETL_ASSERT(
false, ETL_ERROR(unordered_map_out_of_range));
897 return begin()->second;
908 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
909 const_mapped_reference
at(
const K& key)
const
915 local_iterator inode = pbucket->begin();
918 while (inode != pbucket->end())
921 if (key_equal_function(key, inode->key_value_pair.first))
924 return inode->key_value_pair.second;
933 ETL_ASSERT(
false, ETL_ERROR(unordered_map_out_of_range));
935 return begin()->second;
946 template <
typename TIterator>
947 void assign(TIterator first_, TIterator last_)
949#if ETL_IS_DEBUG_BUILD
950 difference_type d = etl::distance(first_, last_);
957 while (first_ != last_)
969 ETL_OR_STD::pair<iterator, bool>
insert(const_reference key_value_pair)
971 ETL_OR_STD::pair<iterator, bool> result(
end(),
false);
975 const key_type& key = key_value_pair.first;
981 bucket_t* pbucket = pbuckets + index;
982 bucket_t& bucket = *pbucket;
988 node_t* node = allocate_data_node();
990 ::new ((
void*)
etl::addressof(node->key_value_pair)) value_type(key_value_pair);
991 ETL_INCREMENT_DEBUG_COUNT;
996 adjust_first_last_markers_after_insert(pbucket);
998 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->
begin());
999 result.second =
true;
1005 local_iterator inode = bucket.
begin();
1007 while (inode != bucket.
end())
1010 if (key_equal_function(inode->key_value_pair.first, key))
1020 if (inode == bucket.
end())
1023 node_t* node = allocate_data_node();
1025 ::new ((
void*)
etl::addressof(node->key_value_pair)) value_type(key_value_pair);
1026 ETL_INCREMENT_DEBUG_COUNT;
1030 adjust_first_last_markers_after_insert(&bucket);
1033 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
1034 result.second =
true;
1047 ETL_OR_STD::pair<iterator, bool>
insert(rvalue_reference key_value_pair)
1049 ETL_OR_STD::pair<iterator, bool> result(
end(),
false);
1053 const key_type& key = key_value_pair.first;
1059 bucket_t* pbucket = pbuckets + index;
1060 bucket_t& bucket = *pbucket;
1066 node_t* node = allocate_data_node();
1069 ETL_INCREMENT_DEBUG_COUNT;
1072 bucket.insert_after(bucket.before_begin(), *node);
1074 adjust_first_last_markers_after_insert(pbucket);
1076 result.first =
iterator((pbuckets + number_of_buckets), pbucket, pbucket->
begin());
1077 result.second = true;
1082 local_iterator inode_previous = bucket.before_begin();
1083 local_iterator inode = bucket.begin();
1085 while (inode != bucket.end())
1088 if (key_equal_function(inode->key_value_pair.first, key))
1098 if (inode == bucket.end())
1101 node_t* node = allocate_data_node();
1103 ::new ((
void*)
etl::addressof(node->key_value_pair)) value_type(
etl::move(key_value_pair));
1104 ETL_INCREMENT_DEBUG_COUNT;
1107 bucket.insert_after(inode_previous, *node);
1108 adjust_first_last_markers_after_insert(&bucket);
1111 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
1112 result.second = true;
1126 iterator
insert(const_iterator, const_reference key_value_pair)
1128 return insert(key_value_pair).first;
1140 return insert(etl::move(key_value_pair)).first;
1151 template <
class TIterator>
1152 void insert(TIterator first_, TIterator last_)
1154 while (first_ != last_)
1171 bucket_t& bucket = pbuckets[index];
1174 local_iterator icurrent = bucket.
begin();
1177 while ((icurrent != bucket.
end()) && (!key_equal_function(icurrent->key_value_pair.first, key)))
1184 if (icurrent != bucket.
end())
1186 delete_data_node(iprevious, icurrent, bucket);
1199 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1200 size_t erase(
const K& key)
1205 bucket_t& bucket = pbuckets[index];
1208 local_iterator icurrent = bucket.begin();
1211 while ((icurrent != bucket.end()) && (!key_equal_function(icurrent->key_value_pair.first, key)))
1218 if (icurrent != bucket.end())
1220 delete_data_node(iprevious, icurrent, bucket);
1235 iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
1238 bucket_t& bucket = ielement.get_bucket();
1240 local_iterator icurrent = ielement.get_local_iterator();
1243 while (iprevious->etl_next != &*icurrent)
1248 delete_data_node(iprevious, icurrent, bucket);
1260 iterator
erase(const_iterator first_, const_iterator last_)
1263 if ((first_ ==
begin()) && (last_ ==
end()))
1270 bucket_t* pbucket = first_.get_bucket_list_iterator();
1271 bucket_t* pend_bucket = last_.get_bucket_list_iterator();
1273 local_iterator icurrent = first_.get_local_iterator();
1274 local_iterator iend = last_.get_local_iterator();
1277 while (iprevious->etl_next != &*icurrent)
1283 iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious);
1286 while ((icurrent != iend) || (pbucket != pend_bucket))
1288 icurrent = delete_data_node(iprevious, icurrent, *pbucket);
1291 if ((icurrent != iend) || (pbucket != pend_bucket))
1294 if ((icurrent == pbucket->
end()))
1300 }
while (pbucket->
empty());
1303 icurrent = pbucket->
begin();
1308 return ++ibefore_erased;
1326 return (
find(key) ==
end()) ? 0 : 1;
1335 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1336 size_t count(
const K& key)
const
1338 return (
find(key) ==
end()) ? 0 : 1;
1351 bucket_t* pbucket = pbuckets + index;
1352 bucket_t& bucket = *pbucket;
1355 if (!bucket.
empty())
1358 local_iterator inode = bucket.
begin();
1359 local_iterator iend = bucket.
end();
1361 while (inode != iend)
1364 if (key_equal_function(key, inode->key_value_pair.first))
1366 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1385 bucket_t* pbucket = pbuckets + index;
1386 bucket_t& bucket = *pbucket;
1389 if (!bucket.
empty())
1392 local_iterator inode = bucket.
begin();
1393 local_iterator iend = bucket.
end();
1395 while (inode != iend)
1398 if (key_equal_function(key, inode->key_value_pair.first))
1400 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1416 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1421 bucket_t* pbucket = pbuckets + index;
1422 bucket_t& bucket = *pbucket;
1425 if (!bucket.empty())
1428 local_iterator inode = bucket.begin();
1429 local_iterator iend = bucket.end();
1431 while (inode != iend)
1434 if (key_equal_function(key, inode->key_value_pair.first))
1436 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1453 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1458 bucket_t* pbucket = pbuckets + index;
1459 bucket_t& bucket = *pbucket;
1462 if (!bucket.empty())
1465 local_iterator inode = bucket.begin();
1466 local_iterator iend = bucket.end();
1468 while (inode != iend)
1471 if (key_equal_function(key, inode->key_value_pair.first))
1473 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1494 iterator f =
find(key);
1502 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1515 const_iterator f =
find(key);
1516 const_iterator l = f;
1523 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1535 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1536 ETL_OR_STD::pair<iterator, iterator>
equal_range(
const K& key)
1546 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1559 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1560 ETL_OR_STD::pair<const_iterator, const_iterator>
equal_range(
const K& key)
const
1570 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1579 return pnodepool->size();
1587 return pnodepool->max_size();
1595 return pnodepool->max_size();
1603 return pnodepool->empty();
1611 return pnodepool->full();
1620 return pnodepool->available();
1638 return key_hash_function;
1647 return key_equal_function;
1659 key_equal_function = rhs.
key_eq();
1675 key_hash_function = rhs.hash_function();
1676 key_equal_function = rhs.key_eq();
1677 this->move(rhs.begin(), rhs.end());
1696 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1708 iunordered_map(pool_t& node_pool_, bucket_t* pbuckets_,
size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
1709 : pnodepool(&node_pool_)
1710 , pbuckets(pbuckets_)
1711 , number_of_buckets(number_of_buckets_)
1714 , key_hash_function(key_hash_function_)
1715 , key_equal_function(key_equal_function_)
1727 for (
size_t i = 0UL; i < number_of_buckets; ++i)
1729 bucket_t& bucket = pbuckets[i];
1731 if (!bucket.
empty())
1734 local_iterator it = bucket.
begin();
1736 while (it != bucket.
end())
1739 it->key_value_pair.~value_type();
1740 ETL_DECREMENT_DEBUG_COUNT;
1751 pnodepool->release_all();
1779 node_t* allocate_data_node()
1782 return (pnodepool->*func)();
1788 void adjust_first_last_markers_after_insert(bucket_t* pbucket)
1797 if (pbucket < first)
1801 else if (pbucket > last)
1811 void adjust_first_last_markers_after_erase(bucket_t* pbucket)
1820 if (pbucket == first)
1823 while (first->empty())
1828 else if (pbucket == last)
1832 bucket_t* pend = last;
1836 while (pbucket != pend)
1838 if (!pbucket->empty())
1852 local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket)
1854 local_iterator inext = bucket.erase_after(iprevious);
1855 icurrent->key_value_pair.~value_type();
1856 pnodepool->release(&*icurrent);
1857 adjust_first_last_markers_after_erase(&bucket);
1858 ETL_DECREMENT_DEBUG_COUNT;
1873 const size_t number_of_buckets;
1880 hasher key_hash_function;
1883 key_equal key_equal_function;
1886 ETL_DECLARE_DEBUG_COUNT;
1891#if defined(ETL_POLYMORPHIC_UNORDERED_MAP) || defined(ETL_POLYMORPHIC_CONTAINERS)