133 typedef ETL_OR_STD::pair<const TKey, T> value_type;
135 typedef TKey key_type;
136 typedef T mapped_type;
137 typedef THash hasher;
138 typedef TKeyEqual key_equal;
139 typedef value_type& reference;
140 typedef const value_type& const_reference;
142 typedef value_type&& rvalue_reference;
144 typedef value_type* pointer;
145 typedef const value_type* const_pointer;
146 typedef size_t size_type;
151 typedef key_type&& rvalue_key_reference;
153 typedef mapped_type& mapped_reference;
154 typedef const mapped_type& const_mapped_reference;
160 struct node_t :
public link_t
162 node_t(const_reference key_value_pair_)
163 : key_value_pair(key_value_pair_)
167 value_type key_value_pair;
170 friend bool operator==(
const node_t& lhs,
const node_t& rhs)
172 return (lhs.key_value_pair.first == rhs.key_value_pair.first) && (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;
214 iterator(
const iterator& other)
215 : pbuckets_end(other.pbuckets_end)
216 , pbucket(other.pbucket)
222 iterator& operator++()
227 if (inode == pbucket->end())
231 while ((pbucket != pbuckets_end) && (pbucket->empty()))
237 if (pbucket != pbuckets_end)
239 inode = pbucket->begin();
247 iterator operator++(
int)
249 iterator temp(*
this);
255 iterator& operator=(
const iterator& other)
257 pbuckets_end = other.pbuckets_end;
258 pbucket = other.pbucket;
264 reference operator*()
const
266 return inode->key_value_pair;
270 pointer operator&()
const
272 return &(inode->key_value_pair);
276 pointer operator->()
const
278 return &(inode->key_value_pair);
282 friend bool operator==(
const iterator& lhs,
const iterator& rhs)
284 return lhs.compare(rhs);
288 friend bool operator!=(
const iterator& lhs,
const iterator& rhs)
290 return !(lhs == rhs);
296 iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
297 : pbuckets_end(pbuckets_end_)
304 bool compare(
const iterator& rhs)
const
306 return rhs.inode == inode;
310 bucket_t& get_bucket()
316 bucket_t* get_bucket_list_iterator()
322 local_iterator get_local_iterator()
327 bucket_t* pbuckets_end;
329 local_iterator inode;
333 class const_iterator :
public etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>
337 typedef typename etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>::value_type value_type;
338 typedef typename iunordered_map::key_type key_type;
339 typedef typename iunordered_map::mapped_type mapped_type;
340 typedef typename iunordered_map::hasher hasher;
341 typedef typename iunordered_map::key_equal key_equal;
342 typedef typename iunordered_map::reference reference;
343 typedef typename iunordered_map::const_reference const_reference;
344 typedef typename iunordered_map::pointer pointer;
345 typedef typename iunordered_map::const_pointer const_pointer;
346 typedef typename iunordered_map::size_type size_type;
348 friend class iunordered_map;
349 friend class iterator;
356 : pbuckets_end(other.pbuckets_end)
357 , pbucket(other.pbucket)
363 const_iterator(
const const_iterator& other)
364 : pbuckets_end(other.pbuckets_end)
365 , pbucket(other.pbucket)
371 const_iterator& operator++()
376 if (inode == pbucket->end())
380 while ((pbucket != pbuckets_end) && (pbucket->empty()))
386 if (pbucket != pbuckets_end)
388 inode = pbucket->begin();
396 const_iterator operator++(
int)
398 const_iterator temp(*
this);
404 const_iterator& operator=(
const const_iterator& other)
406 pbuckets_end = other.pbuckets_end;
407 pbucket = other.pbucket;
413 const_reference operator*()
const
415 return inode->key_value_pair;
419 const_pointer operator&()
const
421 return &(inode->key_value_pair);
425 const_pointer operator->()
const
427 return &(inode->key_value_pair);
431 friend bool operator==(
const const_iterator& lhs,
const const_iterator& rhs)
433 return lhs.compare(rhs);
437 friend bool operator!=(
const const_iterator& lhs,
const const_iterator& rhs)
439 return !(lhs == rhs);
445 const_iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
446 : pbuckets_end(pbuckets_end_)
453 bool compare(
const const_iterator& rhs)
const
455 return rhs.inode == inode;
459 bucket_t& get_bucket()
465 bucket_t* get_bucket_list_iterator()
471 local_iterator get_local_iterator()
476 bucket_t* pbuckets_end;
478 local_iterator inode;
481 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
489 return iterator((pbuckets + number_of_buckets), first, first->begin());
498 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
507 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
516 return pbuckets[i].begin();
523 const_local_iterator
begin(
size_t i)
const
525 return pbuckets[i].cbegin();
532 const_local_iterator
cbegin(
size_t i)
const
534 return pbuckets[i].cbegin();
543 return iterator((pbuckets + number_of_buckets), last, last->end());
550 const_iterator
end()
const
552 return const_iterator((pbuckets + number_of_buckets), last, last->end());
561 return const_iterator((pbuckets + number_of_buckets), last, last->end());
568 local_iterator
end(
size_t i)
570 return pbuckets[i].end();
577 const_local_iterator
end(
size_t i)
const
579 return pbuckets[i].cend();
586 const_local_iterator
cend(
size_t i)
const
588 return pbuckets[i].cend();
597 return key_hash_function(key) % number_of_buckets;
605 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
608 return key_hash_function(key) % number_of_buckets;
618 size_t index = bucket(key);
620 return etl::distance(pbuckets[index].
begin(), pbuckets[index].
end());
628 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
631 size_t index = bucket(key);
633 return etl::distance(pbuckets[index].
begin(), pbuckets[index].
end());
643 return number_of_buckets;
652 return number_of_buckets;
661 mapped_reference
operator[](rvalue_key_reference key)
667 local_iterator inode = pbucket->begin();
670 while (inode != pbucket->end())
673 if (key_equal_function(key, inode->key_value_pair.first))
676 return inode->key_value_pair.second;
686 node_t* node = allocate_data_node();
688 ::new ((
void*)
etl::addressof(node->key_value_pair.first)) key_type(etl::move(key));
689 ::new ((
void*)etl::
addressof(node->key_value_pair.second)) mapped_type();
690 ETL_INCREMENT_DEBUG_COUNT;
692 pbucket->insert_after(pbucket->before_begin(), *node);
694 adjust_first_last_markers_after_insert(pbucket);
696 return pbucket->
begin()->key_value_pair.second;
711 local_iterator inode = pbucket->
begin();
714 while (inode != pbucket->
end())
717 if (key_equal_function(key, inode->key_value_pair.first))
720 return inode->key_value_pair.second;
730 node_t* node = allocate_data_node();
732 ::new ((
void*)
etl::addressof(node->key_value_pair.first)) key_type(key);
733 ::new ((
void*)
etl::addressof(node->key_value_pair.second)) mapped_type();
734 ETL_INCREMENT_DEBUG_COUNT;
738 adjust_first_last_markers_after_insert(pbucket);
740 return pbucket->
begin()->key_value_pair.second;
749 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
756 local_iterator inode = pbucket->begin();
759 while (inode != pbucket->end())
762 if (key_equal_function(key, inode->key_value_pair.first))
765 return inode->key_value_pair.second;
775 node_t* node = allocate_data_node();
777 ::new ((
void*)
etl::addressof(node->key_value_pair.first)) key_type(key);
778 ::new ((
void*)etl::
addressof(node->key_value_pair.second)) mapped_type();
779 ETL_INCREMENT_DEBUG_COUNT;
781 pbucket->insert_after(pbucket->before_begin(), *node);
783 adjust_first_last_markers_after_insert(pbucket);
785 return pbucket->
begin()->key_value_pair.second;
802 local_iterator inode = pbucket->
begin();
805 while (inode != pbucket->
end())
808 if (key_equal_function(key, inode->key_value_pair.first))
811 return inode->key_value_pair.second;
822 return begin()->second;
838 local_iterator inode = pbucket->
begin();
841 while (inode != pbucket->
end())
844 if (key_equal_function(key, inode->key_value_pair.first))
847 return inode->key_value_pair.second;
858 return begin()->second;
869 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
870 mapped_reference
at(
const K& key)
876 local_iterator inode = pbucket->begin();
879 while (inode != pbucket->end())
882 if (key_equal_function(key, inode->key_value_pair.first))
885 return inode->key_value_pair.second;
894 ETL_ASSERT(
false, ETL_ERROR(unordered_map_out_of_range));
896 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;
947 template <
typename TIterator>
948 void assign(TIterator first_, TIterator last_)
950#if ETL_IS_DEBUG_BUILD
951 difference_type d = etl::distance(first_, last_);
958 while (first_ != last_)
971 ETL_OR_STD::pair<iterator, bool>
insert(const_reference key_value_pair)
973 ETL_OR_STD::pair<iterator, bool> result(
end(),
false);
977 const key_type& key = key_value_pair.first;
983 bucket_t* pbucket = pbuckets + index;
984 bucket_t& bucket = *pbucket;
990 node_t* node = allocate_data_node();
992 ::new ((
void*)
etl::addressof(node->key_value_pair)) value_type(key_value_pair);
993 ETL_INCREMENT_DEBUG_COUNT;
998 adjust_first_last_markers_after_insert(pbucket);
1000 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->
begin());
1001 result.second =
true;
1007 local_iterator inode = bucket.
begin();
1009 while (inode != bucket.
end())
1012 if (key_equal_function(inode->key_value_pair.first, key))
1022 if (inode == bucket.
end())
1025 node_t* node = allocate_data_node();
1027 ::new ((
void*)
etl::addressof(node->key_value_pair)) value_type(key_value_pair);
1028 ETL_INCREMENT_DEBUG_COUNT;
1032 adjust_first_last_markers_after_insert(&bucket);
1035 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
1036 result.second =
true;
1050 ETL_OR_STD::pair<iterator, bool>
insert(rvalue_reference key_value_pair)
1052 ETL_OR_STD::pair<iterator, bool> result(
end(),
false);
1056 const key_type& key = key_value_pair.first;
1062 bucket_t* pbucket = pbuckets + index;
1063 bucket_t& bucket = *pbucket;
1069 node_t* node = allocate_data_node();
1072 ETL_INCREMENT_DEBUG_COUNT;
1075 bucket.insert_after(bucket.before_begin(), *node);
1077 adjust_first_last_markers_after_insert(pbucket);
1079 result.first =
iterator((pbuckets + number_of_buckets), pbucket, pbucket->
begin());
1080 result.second = true;
1085 local_iterator inode_previous = bucket.before_begin();
1086 local_iterator inode = bucket.begin();
1088 while (inode != bucket.end())
1091 if (key_equal_function(inode->key_value_pair.first, key))
1101 if (inode == bucket.end())
1104 node_t* node = allocate_data_node();
1106 ::new ((
void*)
etl::addressof(node->key_value_pair)) value_type(
etl::move(key_value_pair));
1107 ETL_INCREMENT_DEBUG_COUNT;
1110 bucket.insert_after(inode_previous, *node);
1111 adjust_first_last_markers_after_insert(&bucket);
1114 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
1115 result.second = true;
1130 iterator
insert(const_iterator, const_reference key_value_pair)
1132 return insert(key_value_pair).first;
1145 return insert(etl::move(key_value_pair)).first;
1157 template <
class TIterator>
1158 void insert(TIterator first_, TIterator last_)
1160 while (first_ != last_)
1177 bucket_t& bucket = pbuckets[index];
1180 local_iterator icurrent = bucket.
begin();
1183 while ((icurrent != bucket.
end()) && (!key_equal_function(icurrent->key_value_pair.first, key)))
1190 if (icurrent != bucket.
end())
1192 delete_data_node(iprevious, icurrent, bucket);
1205 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1206 size_t erase(
const K& key)
1211 bucket_t& bucket = pbuckets[index];
1214 local_iterator icurrent = bucket.begin();
1217 while ((icurrent != bucket.end()) && (!key_equal_function(icurrent->key_value_pair.first, key)))
1224 if (icurrent != bucket.end())
1226 delete_data_node(iprevious, icurrent, bucket);
1241 iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
1244 bucket_t& bucket = ielement.get_bucket();
1246 local_iterator icurrent = ielement.get_local_iterator();
1249 while (iprevious->etl_next != &*icurrent)
1254 delete_data_node(iprevious, icurrent, bucket);
1266 iterator
erase(const_iterator first_, const_iterator last_)
1269 if ((first_ ==
begin()) && (last_ ==
end()))
1276 bucket_t* pbucket = first_.get_bucket_list_iterator();
1277 bucket_t* pend_bucket = last_.get_bucket_list_iterator();
1279 local_iterator icurrent = first_.get_local_iterator();
1280 local_iterator iend = last_.get_local_iterator();
1284 while (iprevious->etl_next != &*icurrent)
1290 iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious);
1293 while ((icurrent != iend) || (pbucket != pend_bucket))
1295 icurrent = delete_data_node(iprevious, icurrent, *pbucket);
1298 if ((icurrent != iend) || (pbucket != pend_bucket))
1301 if ((icurrent == pbucket->
end()))
1306 }
while (pbucket->
empty());
1309 icurrent = pbucket->
begin();
1314 return ++ibefore_erased;
1332 return (
find(key) ==
end()) ? 0 : 1;
1341 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1342 size_t count(
const K& key)
const
1344 return (
find(key) ==
end()) ? 0 : 1;
1357 bucket_t* pbucket = pbuckets + index;
1358 bucket_t& bucket = *pbucket;
1361 if (!bucket.
empty())
1364 local_iterator inode = bucket.
begin();
1365 local_iterator iend = bucket.
end();
1367 while (inode != iend)
1370 if (key_equal_function(key, inode->key_value_pair.first))
1372 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1391 bucket_t* pbucket = pbuckets + index;
1392 bucket_t& bucket = *pbucket;
1395 if (!bucket.
empty())
1398 local_iterator inode = bucket.
begin();
1399 local_iterator iend = bucket.
end();
1401 while (inode != iend)
1404 if (key_equal_function(key, inode->key_value_pair.first))
1406 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1422 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1427 bucket_t* pbucket = pbuckets + index;
1428 bucket_t& bucket = *pbucket;
1431 if (!bucket.empty())
1434 local_iterator inode = bucket.begin();
1435 local_iterator iend = bucket.end();
1437 while (inode != iend)
1440 if (key_equal_function(key, inode->key_value_pair.first))
1442 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1459 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1464 bucket_t* pbucket = pbuckets + index;
1465 bucket_t& bucket = *pbucket;
1468 if (!bucket.empty())
1471 local_iterator inode = bucket.begin();
1472 local_iterator iend = bucket.end();
1474 while (inode != iend)
1477 if (key_equal_function(key, inode->key_value_pair.first))
1479 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1501 iterator f =
find(key);
1509 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1523 const_iterator f =
find(key);
1524 const_iterator l = f;
1531 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1544 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1545 ETL_OR_STD::pair<iterator, iterator>
equal_range(
const K& key)
1555 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1569 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1570 ETL_OR_STD::pair<const_iterator, const_iterator>
equal_range(
const K& key)
const
1580 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1589 return pnodepool->size();
1597 return pnodepool->max_size();
1605 return pnodepool->max_size();
1613 return pnodepool->empty();
1621 return pnodepool->full();
1630 return pnodepool->available();
1648 return key_hash_function;
1657 return key_equal_function;
1669 key_equal_function = rhs.
key_eq();
1685 key_hash_function = rhs.hash_function();
1686 key_equal_function = rhs.key_eq();
1687 this->move(rhs.begin(), rhs.end());
1706 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value,
int> = 0>
1718 iunordered_map(pool_t& node_pool_, bucket_t* pbuckets_,
size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
1719 : pnodepool(&node_pool_)
1720 , pbuckets(pbuckets_)
1721 , number_of_buckets(number_of_buckets_)
1724 , key_hash_function(key_hash_function_)
1725 , key_equal_function(key_equal_function_)
1737 for (
size_t i = 0UL; i < number_of_buckets; ++i)
1739 bucket_t& bucket = pbuckets[i];
1741 if (!bucket.
empty())
1744 local_iterator it = bucket.
begin();
1746 while (it != bucket.
end())
1749 it->key_value_pair.~value_type();
1750 ETL_DECREMENT_DEBUG_COUNT;
1761 pnodepool->release_all();
1789 node_t* allocate_data_node()
1792 return (pnodepool->*func)();
1798 void adjust_first_last_markers_after_insert(bucket_t* pbucket)
1807 if (pbucket < first)
1811 else if (pbucket > last)
1821 void adjust_first_last_markers_after_erase(bucket_t* pbucket)
1830 if (pbucket == first)
1834 while (first->empty())
1839 else if (pbucket == last)
1844 bucket_t* pend = last;
1848 while (pbucket != pend)
1850 if (!pbucket->empty())
1864 local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket)
1866 local_iterator inext = bucket.erase_after(iprevious);
1867 icurrent->key_value_pair.~value_type();
1868 pnodepool->release(&*icurrent);
1869 adjust_first_last_markers_after_erase(&bucket);
1870 ETL_DECREMENT_DEBUG_COUNT;
1885 const size_t number_of_buckets;
1892 hasher key_hash_function;
1895 key_equal key_equal_function;
1898 ETL_DECLARE_DEBUG_COUNT;
1903#if defined(ETL_POLYMORPHIC_UNORDERED_MAP) || defined(ETL_POLYMORPHIC_CONTAINERS)