Embedded Template Library 1.0
Loading...
Searching...
No Matches
unordered_map.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2016 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_UNORDERED_MAP_INCLUDED
32#define ETL_UNORDERED_MAP_INCLUDED
33
34#include "platform.h"
35#include "algorithm.h"
36#include "array.h"
37#include "debug_count.h"
38#include "error_handler.h"
39#include "exception.h"
40#include "functional.h"
41#include "hash.h"
42#include "initializer_list.h"
44#include "iterator.h"
45#include "nth_type.h"
46#include "nullptr.h"
47#include "parameter_type.h"
48#include "placement_new.h"
49#include "pool.h"
50#include "type_traits.h"
51#include "utility.h"
52#include "vector.h"
53
55
56#include <stddef.h>
57
58//*****************************************************************************
62//*****************************************************************************
63
64namespace etl
65{
66 //***************************************************************************
69 //***************************************************************************
70 class unordered_map_exception : public etl::exception
71 {
72 public:
73
74 unordered_map_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
75 : etl::exception(reason_, file_name_, line_number_)
76 {
77 }
78 };
79
80 //***************************************************************************
83 //***************************************************************************
84 class unordered_map_full : public etl::unordered_map_exception
85 {
86 public:
87
88 unordered_map_full(string_type file_name_, numeric_type line_number_)
89 : etl::unordered_map_exception(ETL_ERROR_TEXT("unordered_map:full", ETL_UNORDERED_MAP_FILE_ID"A"), file_name_, line_number_)
90 {
91 }
92 };
93
94 //***************************************************************************
97 //***************************************************************************
98 class unordered_map_out_of_range : public etl::unordered_map_exception
99 {
100 public:
101
102 unordered_map_out_of_range(string_type file_name_, numeric_type line_number_)
103 : etl::unordered_map_exception(ETL_ERROR_TEXT("unordered_map:range", ETL_UNORDERED_MAP_FILE_ID"B"), file_name_, line_number_)
104 {
105 }
106 };
107
108 //***************************************************************************
111 //***************************************************************************
112 class unordered_map_iterator : public etl::unordered_map_exception
113 {
114 public:
115
116 unordered_map_iterator(string_type file_name_, numeric_type line_number_)
117 : etl::unordered_map_exception(ETL_ERROR_TEXT("unordered_map:iterator", ETL_UNORDERED_MAP_FILE_ID"C"), file_name_, line_number_)
118 {
119 }
120 };
121
122 //***************************************************************************
127 //***************************************************************************
128 template <typename TKey, typename T, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey> >
130 {
131 public:
132
133 typedef ETL_OR_STD::pair<const TKey, T> value_type;
134
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;
141#if ETL_USING_CPP11
142 typedef value_type&& rvalue_reference;
143#endif
144 typedef value_type* pointer;
145 typedef const value_type* const_pointer;
146 typedef size_t size_type;
147
149 typedef const key_type& const_key_reference;
150#if ETL_USING_CPP11
151 typedef key_type&& rvalue_key_reference;
152#endif
153 typedef mapped_type& mapped_reference;
154 typedef const mapped_type& const_mapped_reference;
155
156 typedef etl::forward_link<0> link_t; // Default link.
157
158 // The nodes that store the elements.
159 // The nodes that store the elements.
160 struct node_t : public link_t
161 {
162 node_t(const_reference key_value_pair_)
163 : key_value_pair(key_value_pair_)
164 {
165 }
166
167 value_type key_value_pair;
168 };
169
170 friend bool operator==(const node_t& lhs, const node_t& rhs)
171 {
172 return (lhs.key_value_pair.first == rhs.key_value_pair.first) && (lhs.key_value_pair.second == rhs.key_value_pair.second);
173 }
174
175 friend bool operator!=(const node_t& lhs, const node_t& rhs)
176 {
177 return !(lhs == rhs);
178 }
179
180 protected:
181
183 typedef etl::ipool pool_t;
184
185 public:
186
187 // Local iterators iterate over one bucket.
188 typedef typename bucket_t::iterator local_iterator;
189 typedef typename bucket_t::const_iterator const_local_iterator;
190
191 //*********************************************************************
192 class iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, T>
193 {
194 public:
195
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;
206
207 friend class iunordered_map;
208 friend class const_iterator;
209
210 //*********************************
211 iterator() {}
212
213 //*********************************
214 iterator(const iterator& other)
215 : pbuckets_end(other.pbuckets_end)
216 , pbucket(other.pbucket)
217 , inode(other.inode)
218 {
219 }
220
221 //*********************************
222 iterator& operator++()
223 {
224 ++inode;
225
226 // The end of this node list?
227 if (inode == pbucket->end())
228 {
229 // Search for the next non-empty bucket.
230 ++pbucket;
231 while ((pbucket != pbuckets_end) && (pbucket->empty()))
232 {
233 ++pbucket;
234 }
235
236 // If not past the end, get the first node in the bucket.
237 if (pbucket != pbuckets_end)
238 {
239 inode = pbucket->begin();
240 }
241 }
242
243 return *this;
244 }
245
246 //*********************************
247 iterator operator++(int)
248 {
249 iterator temp(*this);
250 operator++();
251 return temp;
252 }
253
254 //*********************************
255 iterator& operator=(const iterator& other)
256 {
257 pbuckets_end = other.pbuckets_end;
258 pbucket = other.pbucket;
259 inode = other.inode;
260 return *this;
261 }
262
263 //*********************************
264 reference operator*() const
265 {
266 return inode->key_value_pair;
267 }
268
269 //*********************************
270 pointer operator&() const
271 {
272 return &(inode->key_value_pair);
273 }
274
275 //*********************************
276 pointer operator->() const
277 {
278 return &(inode->key_value_pair);
279 }
280
281 //*********************************
282 friend bool operator==(const iterator& lhs, const iterator& rhs)
283 {
284 return lhs.compare(rhs);
285 }
286
287 //*********************************
288 friend bool operator!=(const iterator& lhs, const iterator& rhs)
289 {
290 return !(lhs == rhs);
291 }
292
293 private:
294
295 //*********************************
296 iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
297 : pbuckets_end(pbuckets_end_)
298 , pbucket(pbucket_)
299 , inode(inode_)
300 {
301 }
302
303 //*********************************
304 bool compare(const iterator& rhs) const
305 {
306 return rhs.inode == inode;
307 }
308
309 //*********************************
310 bucket_t& get_bucket()
311 {
312 return *pbucket;
313 }
314
315 //*********************************
316 bucket_t* get_bucket_list_iterator()
317 {
318 return pbucket;
319 }
320
321 //*********************************
322 local_iterator get_local_iterator()
323 {
324 return inode;
325 }
326
327 bucket_t* pbuckets_end;
328 bucket_t* pbucket;
329 local_iterator inode;
330 };
331
332 //*********************************************************************
333 class const_iterator : public etl::iterator<ETL_OR_STD::forward_iterator_tag, const T>
334 {
335 public:
336
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;
347
348 friend class iunordered_map;
349 friend class iterator;
350
351 //*********************************
352 const_iterator() {}
353
354 //*********************************
355 const_iterator(const typename iunordered_map::iterator& other)
356 : pbuckets_end(other.pbuckets_end)
357 , pbucket(other.pbucket)
358 , inode(other.inode)
359 {
360 }
361
362 //*********************************
363 const_iterator(const const_iterator& other)
364 : pbuckets_end(other.pbuckets_end)
365 , pbucket(other.pbucket)
366 , inode(other.inode)
367 {
368 }
369
370 //*********************************
371 const_iterator& operator++()
372 {
373 ++inode;
374
375 // The end of this node list?
376 if (inode == pbucket->end())
377 {
378 // Search for the next non-empty bucket.
379 ++pbucket;
380 while ((pbucket != pbuckets_end) && (pbucket->empty()))
381 {
382 ++pbucket;
383 }
384
385 // If not past the end, get the first node in the bucket.
386 if (pbucket != pbuckets_end)
387 {
388 inode = pbucket->begin();
389 }
390 }
391
392 return *this;
393 }
394
395 //*********************************
396 const_iterator operator++(int)
397 {
398 const_iterator temp(*this);
399 operator++();
400 return temp;
401 }
402
403 //*********************************
404 const_iterator& operator=(const const_iterator& other)
405 {
406 pbuckets_end = other.pbuckets_end;
407 pbucket = other.pbucket;
408 inode = other.inode;
409 return *this;
410 }
411
412 //*********************************
413 const_reference operator*() const
414 {
415 return inode->key_value_pair;
416 }
417
418 //*********************************
419 const_pointer operator&() const
420 {
421 return &(inode->key_value_pair);
422 }
423
424 //*********************************
425 const_pointer operator->() const
426 {
427 return &(inode->key_value_pair);
428 }
429
430 //*********************************
431 friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
432 {
433 return lhs.compare(rhs);
434 }
435
436 //*********************************
437 friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
438 {
439 return !(lhs == rhs);
440 }
441
442 private:
443
444 //*********************************
445 const_iterator(bucket_t* pbuckets_end_, bucket_t* pbucket_, local_iterator inode_)
446 : pbuckets_end(pbuckets_end_)
447 , pbucket(pbucket_)
448 , inode(inode_)
449 {
450 }
451
452 //*********************************
453 bool compare(const const_iterator& rhs) const
454 {
455 return rhs.inode == inode;
456 }
457
458 //*********************************
459 bucket_t& get_bucket()
460 {
461 return *pbucket;
462 }
463
464 //*********************************
465 bucket_t* get_bucket_list_iterator()
466 {
467 return pbucket;
468 }
469
470 //*********************************
471 local_iterator get_local_iterator()
472 {
473 return inode;
474 }
475
476 bucket_t* pbuckets_end;
477 bucket_t* pbucket;
478 local_iterator inode;
479 };
480
481 typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
482
483 //*********************************************************************
486 //*********************************************************************
487 iterator begin()
488 {
489 return iterator((pbuckets + number_of_buckets), first, first->begin());
490 }
491
492 //*********************************************************************
495 //*********************************************************************
496 const_iterator begin() const
497 {
498 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
499 }
500
501 //*********************************************************************
504 //*********************************************************************
505 const_iterator cbegin() const
506 {
507 return const_iterator((pbuckets + number_of_buckets), first, first->begin());
508 }
509
510 //*********************************************************************
513 //*********************************************************************
514 local_iterator begin(size_t i)
515 {
516 return pbuckets[i].begin();
517 }
518
519 //*********************************************************************
522 //*********************************************************************
523 const_local_iterator begin(size_t i) const
524 {
525 return pbuckets[i].cbegin();
526 }
527
528 //*********************************************************************
531 //*********************************************************************
532 const_local_iterator cbegin(size_t i) const
533 {
534 return pbuckets[i].cbegin();
535 }
536
537 //*********************************************************************
540 //*********************************************************************
541 iterator end()
542 {
543 return iterator((pbuckets + number_of_buckets), last, last->end());
544 }
545
546 //*********************************************************************
549 //*********************************************************************
550 const_iterator end() const
551 {
552 return const_iterator((pbuckets + number_of_buckets), last, last->end());
553 }
554
555 //*********************************************************************
558 //*********************************************************************
559 const_iterator cend() const
560 {
561 return const_iterator((pbuckets + number_of_buckets), last, last->end());
562 }
563
564 //*********************************************************************
567 //*********************************************************************
568 local_iterator end(size_t i)
569 {
570 return pbuckets[i].end();
571 }
572
573 //*********************************************************************
576 //*********************************************************************
577 const_local_iterator end(size_t i) const
578 {
579 return pbuckets[i].cend();
580 }
581
582 //*********************************************************************
585 //*********************************************************************
586 const_local_iterator cend(size_t i) const
587 {
588 return pbuckets[i].cend();
589 }
590
591 //*********************************************************************
594 //*********************************************************************
596 {
597 return key_hash_function(key) % number_of_buckets;
598 }
599
600#if ETL_USING_CPP11
601 //*********************************************************************
604 //*********************************************************************
605 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
606 size_type get_bucket_index(const K& key) const
607 {
608 return key_hash_function(key) % number_of_buckets;
609 }
610#endif
611
612 //*********************************************************************
615 //*********************************************************************
616 size_type bucket_size(const_key_reference key) const
617 {
618 size_t index = bucket(key);
619
620 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
621 }
622
623#if ETL_USING_CPP11
624 //*********************************************************************
627 //*********************************************************************
628 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
629 size_type bucket_size(const K& key) const
630 {
631 size_t index = bucket(key);
632
633 return etl::distance(pbuckets[index].begin(), pbuckets[index].end());
634 }
635#endif
636
637 //*********************************************************************
640 //*********************************************************************
641 size_type max_bucket_count() const
642 {
643 return number_of_buckets;
644 }
645
646 //*********************************************************************
649 //*********************************************************************
650 size_type bucket_count() const
651 {
652 return number_of_buckets;
653 }
654
655#if ETL_USING_CPP11
656 //*********************************************************************
660 //*********************************************************************
661 mapped_reference operator[](rvalue_key_reference key)
662 {
663 // Find the bucket.
664 bucket_t* pbucket = pbuckets + get_bucket_index(key);
665
666 // Find the first node in the bucket.
667 local_iterator inode = pbucket->begin();
668
669 // Walk the list looking for the right one.
670 while (inode != pbucket->end())
671 {
672 // Equal keys?
673 if (key_equal_function(key, inode->key_value_pair.first))
674 {
675 // Found a match.
676 return inode->key_value_pair.second;
677 }
678 else
679 {
680 ++inode;
681 }
682 }
683
684 // Doesn't exist, so add a new one.
685 // Get a new node.
686 node_t* node = allocate_data_node();
687 node->clear();
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;
691
692 pbucket->insert_after(pbucket->before_begin(), *node);
693
694 adjust_first_last_markers_after_insert(pbucket);
695
696 return pbucket->begin()->key_value_pair.second;
697 }
698#endif
699
700 //*********************************************************************
704 //*********************************************************************
705 mapped_reference operator[](const_key_reference key)
706 {
707 // Find the bucket.
708 bucket_t* pbucket = pbuckets + get_bucket_index(key);
709
710 // Find the first node in the bucket.
711 local_iterator inode = pbucket->begin();
712
713 // Walk the list looking for the right one.
714 while (inode != pbucket->end())
715 {
716 // Equal keys?
717 if (key_equal_function(key, inode->key_value_pair.first))
718 {
719 // Found a match.
720 return inode->key_value_pair.second;
721 }
722 else
723 {
724 ++inode;
725 }
726 }
727
728 // Doesn't exist, so add a new one.
729 // Get a new node.
730 node_t* node = allocate_data_node();
731 node->clear();
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;
735
736 pbucket->insert_after(pbucket->before_begin(), *node);
737
738 adjust_first_last_markers_after_insert(pbucket);
739
740 return pbucket->begin()->key_value_pair.second;
741 }
742
743#if ETL_USING_CPP11
744 //*********************************************************************
748 //*********************************************************************
749 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
750 mapped_reference operator[](const K& key)
751 {
752 // Find the bucket.
753 bucket_t* pbucket = pbuckets + get_bucket_index(key);
754
755 // Find the first node in the bucket.
756 local_iterator inode = pbucket->begin();
757
758 // Walk the list looking for the right one.
759 while (inode != pbucket->end())
760 {
761 // Equal keys?
762 if (key_equal_function(key, inode->key_value_pair.first))
763 {
764 // Found a match.
765 return inode->key_value_pair.second;
766 }
767 else
768 {
769 ++inode;
770 }
771 }
772
773 // Doesn't exist, so add a new one.
774 // Get a new node.
775 node_t* node = allocate_data_node();
776 node->clear();
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;
780
781 pbucket->insert_after(pbucket->before_begin(), *node);
782
783 adjust_first_last_markers_after_insert(pbucket);
784
785 return pbucket->begin()->key_value_pair.second;
786 }
787#endif
788
789 //*********************************************************************
795 //*********************************************************************
796 mapped_reference at(const_key_reference key)
797 {
798 // Find the bucket.
799 bucket_t* pbucket = pbuckets + get_bucket_index(key);
800
801 // Find the first node in the bucket.
802 local_iterator inode = pbucket->begin();
803
804 // Walk the list looking for the right one.
805 while (inode != pbucket->end())
806 {
807 // Equal keys?
808 if (key_equal_function(key, inode->key_value_pair.first))
809 {
810 // Found a match.
811 return inode->key_value_pair.second;
812 }
813 else
814 {
815 ++inode;
816 }
817 }
818
819 // Doesn't exist.
820 ETL_ASSERT(false, ETL_ERROR(unordered_map_out_of_range));
821
822 return begin()->second;
823 }
824
825 //*********************************************************************
831 //*********************************************************************
832 const_mapped_reference at(const_key_reference key) const
833 {
834 // Find the bucket.
835 bucket_t* pbucket = pbuckets + get_bucket_index(key);
836
837 // Find the first node in the bucket.
838 local_iterator inode = pbucket->begin();
839
840 // Walk the list looking for the right one.
841 while (inode != pbucket->end())
842 {
843 // Equal keys?
844 if (key_equal_function(key, inode->key_value_pair.first))
845 {
846 // Found a match.
847 return inode->key_value_pair.second;
848 }
849 else
850 {
851 ++inode;
852 }
853 }
854
855 // Doesn't exist.
856 ETL_ASSERT(false, ETL_ERROR(unordered_map_out_of_range));
857
858 return begin()->second;
859 }
860
861#if ETL_USING_CPP11
862 //*********************************************************************
868 //*********************************************************************
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)
871 {
872 // Find the bucket.
873 bucket_t* pbucket = pbuckets + get_bucket_index(key);
874
875 // Find the first node in the bucket.
876 local_iterator inode = pbucket->begin();
877
878 // Walk the list looking for the right one.
879 while (inode != pbucket->end())
880 {
881 // Equal keys?
882 if (key_equal_function(key, inode->key_value_pair.first))
883 {
884 // Found a match.
885 return inode->key_value_pair.second;
886 }
887 else
888 {
889 ++inode;
890 }
891 }
892
893 // Doesn't exist.
894 ETL_ASSERT(false, ETL_ERROR(unordered_map_out_of_range));
895
896 return begin()->second;
897 }
898#endif
899
900#if ETL_USING_CPP11
901 //*********************************************************************
907 //*********************************************************************
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
910 {
911 // Find the bucket.
912 bucket_t* pbucket = pbuckets + get_bucket_index(key);
913
914 // Find the first node in the bucket.
915 local_iterator inode = pbucket->begin();
916
917 // Walk the list looking for the right one.
918 while (inode != pbucket->end())
919 {
920 // Equal keys?
921 if (key_equal_function(key, inode->key_value_pair.first))
922 {
923 // Found a match.
924 return inode->key_value_pair.second;
925 }
926 else
927 {
928 ++inode;
929 }
930 }
931
932 // Doesn't exist.
933 ETL_ASSERT(false, ETL_ERROR(unordered_map_out_of_range));
934
935 return begin()->second;
936 }
937#endif
938
939 //*********************************************************************
946 //*********************************************************************
947 template <typename TIterator>
948 void assign(TIterator first_, TIterator last_)
949 {
950#if ETL_IS_DEBUG_BUILD
951 difference_type d = etl::distance(first_, last_);
952 ETL_ASSERT(d >= 0, ETL_ERROR(unordered_map_iterator));
953 ETL_ASSERT(size_t(d) <= max_size(), ETL_ERROR(unordered_map_full));
954#endif
955
956 clear();
957
958 while (first_ != last_)
959 {
960 insert(*first_);
961 ++first_;
962 }
963 }
964
965 //*********************************************************************
970 //*********************************************************************
971 ETL_OR_STD::pair<iterator, bool> insert(const_reference key_value_pair)
972 {
973 ETL_OR_STD::pair<iterator, bool> result(end(), false);
974
975 ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full));
976
977 const key_type& key = key_value_pair.first;
978
979 // Get the hash index.
980 size_t index = get_bucket_index(key);
981
982 // Get the bucket & bucket iterator.
983 bucket_t* pbucket = pbuckets + index;
984 bucket_t& bucket = *pbucket;
985
986 // The first one in the bucket?
987 if (bucket.empty())
988 {
989 // Get a new node.
990 node_t* node = allocate_data_node();
991 node->clear();
992 ::new ((void*)etl::addressof(node->key_value_pair)) value_type(key_value_pair);
993 ETL_INCREMENT_DEBUG_COUNT;
994
995 // Just add the pointer to the bucket;
996 bucket.insert_after(bucket.before_begin(), *node);
997
998 adjust_first_last_markers_after_insert(pbucket);
999
1000 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
1001 result.second = true;
1002 }
1003 else
1004 {
1005 // Step though the bucket looking for a place to insert.
1006 local_iterator inode_previous = bucket.before_begin();
1007 local_iterator inode = bucket.begin();
1008
1009 while (inode != bucket.end())
1010 {
1011 // Do we already have this key?
1012 if (key_equal_function(inode->key_value_pair.first, key))
1013 {
1014 break;
1015 }
1016
1017 ++inode_previous;
1018 ++inode;
1019 }
1020
1021 // Not already there?
1022 if (inode == bucket.end())
1023 {
1024 // Get a new node.
1025 node_t* node = allocate_data_node();
1026 node->clear();
1027 ::new ((void*)etl::addressof(node->key_value_pair)) value_type(key_value_pair);
1028 ETL_INCREMENT_DEBUG_COUNT;
1029
1030 // Add the node to the end of the bucket;
1031 bucket.insert_after(inode_previous, *node);
1032 adjust_first_last_markers_after_insert(&bucket);
1033 ++inode_previous;
1034
1035 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
1036 result.second = true;
1037 }
1038 }
1039
1040 return result;
1041 }
1042
1043#if ETL_USING_CPP11
1044 //*********************************************************************
1049 //*********************************************************************
1050 ETL_OR_STD::pair<iterator, bool> insert(rvalue_reference key_value_pair)
1051 {
1052 ETL_OR_STD::pair<iterator, bool> result(end(), false);
1053
1054 ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full));
1055
1056 const key_type& key = key_value_pair.first;
1057
1058 // Get the hash index.
1059 size_t index = get_bucket_index(key);
1060
1061 // Get the bucket & bucket iterator.
1062 bucket_t* pbucket = pbuckets + index;
1063 bucket_t& bucket = *pbucket;
1064
1065 // The first one in the bucket?
1066 if (bucket.empty())
1067 {
1068 // Get a new node.
1069 node_t* node = allocate_data_node();
1070 node->clear();
1071 ::new ((void*)etl::addressof(node->key_value_pair)) value_type(etl::move(key_value_pair));
1072 ETL_INCREMENT_DEBUG_COUNT;
1073
1074 // Just add the pointer to the bucket;
1075 bucket.insert_after(bucket.before_begin(), *node);
1076
1077 adjust_first_last_markers_after_insert(pbucket);
1078
1079 result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
1080 result.second = true;
1081 }
1082 else
1083 {
1084 // Step though the bucket looking for a place to insert.
1085 local_iterator inode_previous = bucket.before_begin();
1086 local_iterator inode = bucket.begin();
1087
1088 while (inode != bucket.end())
1089 {
1090 // Do we already have this key?
1091 if (key_equal_function(inode->key_value_pair.first, key))
1092 {
1093 break;
1094 }
1095
1096 ++inode_previous;
1097 ++inode;
1098 }
1099
1100 // Not already there?
1101 if (inode == bucket.end())
1102 {
1103 // Get a new node.
1104 node_t* node = allocate_data_node();
1105 node->clear();
1106 ::new ((void*)etl::addressof(node->key_value_pair)) value_type(etl::move(key_value_pair));
1107 ETL_INCREMENT_DEBUG_COUNT;
1108
1109 // Add the node to the end of the bucket;
1110 bucket.insert_after(inode_previous, *node);
1111 adjust_first_last_markers_after_insert(&bucket);
1112 ++inode_previous;
1113
1114 result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
1115 result.second = true;
1116 }
1117 }
1118
1119 return result;
1120 }
1121#endif
1122
1123 //*********************************************************************
1129 //*********************************************************************
1130 iterator insert(const_iterator, const_reference key_value_pair)
1131 {
1132 return insert(key_value_pair).first;
1133 }
1134
1135#if ETL_USING_CPP11
1136 //*********************************************************************
1142 //*********************************************************************
1143 iterator insert(const_iterator, rvalue_reference key_value_pair)
1144 {
1145 return insert(etl::move(key_value_pair)).first;
1146 }
1147#endif
1148
1149 //*********************************************************************
1156 //*********************************************************************
1157 template <class TIterator>
1158 void insert(TIterator first_, TIterator last_)
1159 {
1160 while (first_ != last_)
1161 {
1162 insert(*first_);
1163 ++first_;
1164 }
1165 }
1166
1167 //*********************************************************************
1171 //*********************************************************************
1173 {
1174 size_t n = 0UL;
1175 size_t index = get_bucket_index(key);
1176
1177 bucket_t& bucket = pbuckets[index];
1178
1179 local_iterator iprevious = bucket.before_begin();
1180 local_iterator icurrent = bucket.begin();
1181
1182 // Search for the key, if we have it.
1183 while ((icurrent != bucket.end()) && (!key_equal_function(icurrent->key_value_pair.first, key)))
1184 {
1185 ++iprevious;
1186 ++icurrent;
1187 }
1188
1189 // Did we find it?
1190 if (icurrent != bucket.end())
1191 {
1192 delete_data_node(iprevious, icurrent, bucket);
1193 n = 1;
1194 }
1195
1196 return n;
1197 }
1198
1199#if ETL_USING_CPP11
1200 //*********************************************************************
1204 //*********************************************************************
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)
1207 {
1208 size_t n = 0UL;
1209 size_t index = get_bucket_index(key);
1210
1211 bucket_t& bucket = pbuckets[index];
1212
1213 local_iterator iprevious = bucket.before_begin();
1214 local_iterator icurrent = bucket.begin();
1215
1216 // Search for the key, if we have it.
1217 while ((icurrent != bucket.end()) && (!key_equal_function(icurrent->key_value_pair.first, key)))
1218 {
1219 ++iprevious;
1220 ++icurrent;
1221 }
1222
1223 // Did we find it?
1224 if (icurrent != bucket.end())
1225 {
1226 delete_data_node(iprevious, icurrent, bucket);
1227 n = 1;
1228 }
1229
1230 return n;
1231 }
1232#endif
1233
1234 //*********************************************************************
1237 //*********************************************************************
1238 iterator erase(const_iterator ielement)
1239 {
1240 // Make a note of the next one.
1241 iterator inext((pbuckets + number_of_buckets), ielement.get_bucket_list_iterator(), ielement.get_local_iterator());
1242 ++inext;
1243
1244 bucket_t& bucket = ielement.get_bucket();
1245 local_iterator iprevious = bucket.before_begin();
1246 local_iterator icurrent = ielement.get_local_iterator();
1247
1248 // Find the node previous to the one we're interested in.
1249 while (iprevious->etl_next != &*icurrent)
1250 {
1251 ++iprevious;
1252 }
1253
1254 delete_data_node(iprevious, icurrent, bucket);
1255
1256 return inext;
1257 }
1258
1259 //*********************************************************************
1265 //*********************************************************************
1266 iterator erase(const_iterator first_, const_iterator last_)
1267 {
1268 // Erasing everything?
1269 if ((first_ == begin()) && (last_ == end()))
1270 {
1271 clear();
1272 return end();
1273 }
1274
1275 // Get the starting point.
1276 bucket_t* pbucket = first_.get_bucket_list_iterator();
1277 bucket_t* pend_bucket = last_.get_bucket_list_iterator();
1278 local_iterator iprevious = pbucket->before_begin();
1279 local_iterator icurrent = first_.get_local_iterator();
1280 local_iterator iend = last_.get_local_iterator(); // Note: May not be in the same bucket as
1281 // icurrent.
1282
1283 // Find the node previous to the first one.
1284 while (iprevious->etl_next != &*icurrent)
1285 {
1286 ++iprevious;
1287 }
1288
1289 // Remember the item before the first erased one.
1290 iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious);
1291
1292 // Until we reach the end.
1293 while ((icurrent != iend) || (pbucket != pend_bucket))
1294 {
1295 icurrent = delete_data_node(iprevious, icurrent, *pbucket);
1296
1297 // Have we not reached the end?
1298 if ((icurrent != iend) || (pbucket != pend_bucket))
1299 {
1300 // At the end of this bucket?
1301 if ((icurrent == pbucket->end()))
1302 {
1303 // Find the next non-empty one.
1304 do {
1305 ++pbucket;
1306 } while (pbucket->empty());
1307
1308 iprevious = pbucket->before_begin();
1309 icurrent = pbucket->begin();
1310 }
1311 }
1312 }
1313
1314 return ++ibefore_erased;
1315 }
1316
1317 //*************************************************************************
1319 //*************************************************************************
1320 void clear()
1321 {
1322 initialise();
1323 }
1324
1325 //*********************************************************************
1329 //*********************************************************************
1330 size_t count(const_key_reference key) const
1331 {
1332 return (find(key) == end()) ? 0 : 1;
1333 }
1334
1335#if ETL_USING_CPP11
1336 //*********************************************************************
1340 //*********************************************************************
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
1343 {
1344 return (find(key) == end()) ? 0 : 1;
1345 }
1346#endif
1347
1348 //*********************************************************************
1352 //*********************************************************************
1354 {
1355 size_t index = get_bucket_index(key);
1356
1357 bucket_t* pbucket = pbuckets + index;
1358 bucket_t& bucket = *pbucket;
1359
1360 // Is the bucket not empty?
1361 if (!bucket.empty())
1362 {
1363 // Step though the list until we find the end or an equivalent key.
1364 local_iterator inode = bucket.begin();
1365 local_iterator iend = bucket.end();
1366
1367 while (inode != iend)
1368 {
1369 // Do we have this one?
1370 if (key_equal_function(key, inode->key_value_pair.first))
1371 {
1372 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1373 }
1374
1375 ++inode;
1376 }
1377 }
1378
1379 return end();
1380 }
1381
1382 //*********************************************************************
1386 //*********************************************************************
1387 const_iterator find(const_key_reference key) const
1388 {
1389 size_t index = get_bucket_index(key);
1390
1391 bucket_t* pbucket = pbuckets + index;
1392 bucket_t& bucket = *pbucket;
1393
1394 // Is the bucket not empty?
1395 if (!bucket.empty())
1396 {
1397 // Step though the list until we find the end or an equivalent key.
1398 local_iterator inode = bucket.begin();
1399 local_iterator iend = bucket.end();
1400
1401 while (inode != iend)
1402 {
1403 // Do we have this one?
1404 if (key_equal_function(key, inode->key_value_pair.first))
1405 {
1406 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1407 }
1408
1409 ++inode;
1410 }
1411 }
1412
1413 return end();
1414 }
1415
1416#if ETL_USING_CPP11
1417 //*********************************************************************
1421 //*********************************************************************
1422 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1423 iterator find(const K& key)
1424 {
1425 size_t index = get_bucket_index(key);
1426
1427 bucket_t* pbucket = pbuckets + index;
1428 bucket_t& bucket = *pbucket;
1429
1430 // Is the bucket not empty?
1431 if (!bucket.empty())
1432 {
1433 // Step though the list until we find the end or an equivalent key.
1434 local_iterator inode = bucket.begin();
1435 local_iterator iend = bucket.end();
1436
1437 while (inode != iend)
1438 {
1439 // Do we have this one?
1440 if (key_equal_function(key, inode->key_value_pair.first))
1441 {
1442 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1443 }
1444
1445 ++inode;
1446 }
1447 }
1448
1449 return end();
1450 }
1451#endif
1452
1453#if ETL_USING_CPP11
1454 //*********************************************************************
1458 //*********************************************************************
1459 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1460 const_iterator find(const K& key) const
1461 {
1462 size_t index = get_bucket_index(key);
1463
1464 bucket_t* pbucket = pbuckets + index;
1465 bucket_t& bucket = *pbucket;
1466
1467 // Is the bucket not empty?
1468 if (!bucket.empty())
1469 {
1470 // Step though the list until we find the end or an equivalent key.
1471 local_iterator inode = bucket.begin();
1472 local_iterator iend = bucket.end();
1473
1474 while (inode != iend)
1475 {
1476 // Do we have this one?
1477 if (key_equal_function(key, inode->key_value_pair.first))
1478 {
1479 return iterator((pbuckets + number_of_buckets), pbucket, inode);
1480 }
1481
1482 ++inode;
1483 }
1484 }
1485
1486 return end();
1487 }
1488#endif
1489
1490 //*********************************************************************
1498 //*********************************************************************
1499 ETL_OR_STD::pair<iterator, iterator> equal_range(const_key_reference key)
1500 {
1501 iterator f = find(key);
1502 iterator l = f;
1503
1504 if (l != end())
1505 {
1506 ++l;
1507 }
1508
1509 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1510 }
1511
1512 //*********************************************************************
1520 //*********************************************************************
1521 ETL_OR_STD::pair<const_iterator, const_iterator> equal_range(const_key_reference key) const
1522 {
1523 const_iterator f = find(key);
1524 const_iterator l = f;
1525
1526 if (l != end())
1527 {
1528 ++l;
1529 }
1530
1531 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1532 }
1533
1534#if ETL_USING_CPP11
1535 //*********************************************************************
1543 //*********************************************************************
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)
1546 {
1547 iterator f = find(key);
1548 iterator l = f;
1549
1550 if (l != end())
1551 {
1552 ++l;
1553 }
1554
1555 return ETL_OR_STD::pair<iterator, iterator>(f, l);
1556 }
1557#endif
1558
1559#if ETL_USING_CPP11
1560 //*********************************************************************
1568 //*********************************************************************
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
1571 {
1572 const_iterator f = find(key);
1573 const_iterator l = f;
1574
1575 if (l != end())
1576 {
1577 ++l;
1578 }
1579
1580 return ETL_OR_STD::pair<const_iterator, const_iterator>(f, l);
1581 }
1582#endif
1583
1584 //*************************************************************************
1586 //*************************************************************************
1587 size_type size() const
1588 {
1589 return pnodepool->size();
1590 }
1591
1592 //*************************************************************************
1594 //*************************************************************************
1595 size_type max_size() const
1596 {
1597 return pnodepool->max_size();
1598 }
1599
1600 //*************************************************************************
1602 //*************************************************************************
1603 size_type capacity() const
1604 {
1605 return pnodepool->max_size();
1606 }
1607
1608 //*************************************************************************
1610 //*************************************************************************
1611 bool empty() const
1612 {
1613 return pnodepool->empty();
1614 }
1615
1616 //*************************************************************************
1618 //*************************************************************************
1619 bool full() const
1620 {
1621 return pnodepool->full();
1622 }
1623
1624 //*************************************************************************
1627 //*************************************************************************
1628 size_t available() const
1629 {
1630 return pnodepool->available();
1631 }
1632
1633 //*************************************************************************
1636 //*************************************************************************
1637 float load_factor() const
1638 {
1639 return static_cast<float>(size()) / static_cast<float>(bucket_count());
1640 }
1641
1642 //*************************************************************************
1645 //*************************************************************************
1646 hasher hash_function() const
1647 {
1648 return key_hash_function;
1649 }
1650
1651 //*************************************************************************
1654 //*************************************************************************
1655 key_equal key_eq() const
1656 {
1657 return key_equal_function;
1658 }
1659
1660 //*************************************************************************
1662 //*************************************************************************
1664 {
1665 // Skip if doing self assignment
1666 if (this != &rhs)
1667 {
1668 key_hash_function = rhs.hash_function();
1669 key_equal_function = rhs.key_eq();
1670 assign(rhs.cbegin(), rhs.cend());
1671 }
1672
1673 return *this;
1674 }
1675#if ETL_USING_CPP11
1676 //*************************************************************************
1678 //*************************************************************************
1680 {
1681 // Skip if doing self assignment
1682 if (this != &rhs)
1683 {
1684 clear();
1685 key_hash_function = rhs.hash_function();
1686 key_equal_function = rhs.key_eq();
1687 this->move(rhs.begin(), rhs.end());
1688 }
1689
1690 return *this;
1691 }
1692#endif
1693
1694 //*************************************************************************
1696 //*************************************************************************
1698 {
1699 return find(key) != end();
1700 }
1701
1702#if ETL_USING_CPP11
1703 //*************************************************************************
1705 //*************************************************************************
1706 template <typename K, typename KE = TKeyEqual, etl::enable_if_t<comparator_is_transparent<KE>::value, int> = 0>
1707 bool contains(const K& key) const
1708 {
1709 return find(key) != end();
1710 }
1711#endif
1712
1713 protected:
1714
1715 //*********************************************************************
1717 //*********************************************************************
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_)
1722 , first(pbuckets)
1723 , last(pbuckets)
1724 , key_hash_function(key_hash_function_)
1725 , key_equal_function(key_equal_function_)
1726 {
1727 }
1728
1729 //*********************************************************************
1731 //*********************************************************************
1733 {
1734 if (!empty())
1735 {
1736 // For each bucket...
1737 for (size_t i = 0UL; i < number_of_buckets; ++i)
1738 {
1739 bucket_t& bucket = pbuckets[i];
1740
1741 if (!bucket.empty())
1742 {
1743 // For each item in the bucket...
1744 local_iterator it = bucket.begin();
1745
1746 while (it != bucket.end())
1747 {
1748 // Destroy the value contents.
1749 it->key_value_pair.~value_type();
1750 ETL_DECREMENT_DEBUG_COUNT;
1751
1752 ++it;
1753 }
1754
1755 // Now it's safe to clear the bucket.
1756 bucket.clear();
1757 }
1758 }
1759
1760 // Now it's safe to clear the entire pool in one go.
1761 pnodepool->release_all();
1762 }
1763
1764 first = pbuckets;
1765 last = first;
1766 }
1767
1768#if ETL_USING_CPP11
1769 //*************************************************************************
1771 //*************************************************************************
1772 void move(iterator b, iterator e)
1773 {
1774 while (b != e)
1775 {
1776 iterator temp = b;
1777 ++temp;
1778 insert(etl::move(*b));
1779 b = temp;
1780 }
1781 }
1782#endif
1783
1784 private:
1785
1786 //*************************************************************************
1788 //*************************************************************************
1789 node_t* allocate_data_node()
1790 {
1791 node_t* (etl::ipool::*func)() = &etl::ipool::allocate<node_t>;
1792 return (pnodepool->*func)();
1793 }
1794
1795 //*********************************************************************
1797 //*********************************************************************
1798 void adjust_first_last_markers_after_insert(bucket_t* pbucket)
1799 {
1800 if (size() == 1)
1801 {
1802 first = pbucket;
1803 last = pbucket;
1804 }
1805 else
1806 {
1807 if (pbucket < first)
1808 {
1809 first = pbucket;
1810 }
1811 else if (pbucket > last)
1812 {
1813 last = pbucket;
1814 }
1815 }
1816 }
1817
1818 //*********************************************************************
1820 //*********************************************************************
1821 void adjust_first_last_markers_after_erase(bucket_t* pbucket)
1822 {
1823 if (empty())
1824 {
1825 first = pbuckets;
1826 last = pbuckets;
1827 }
1828 else
1829 {
1830 if (pbucket == first)
1831 {
1832 // We erased the first so, we need to search again from where we
1833 // erased.
1834 while (first->empty())
1835 {
1836 ++first;
1837 }
1838 }
1839 else if (pbucket == last)
1840 {
1841 // We erased the last, so we need to search again. Start from the
1842 // first, go no further than the current last.
1843 pbucket = first;
1844 bucket_t* pend = last;
1845
1846 last = first;
1847
1848 while (pbucket != pend)
1849 {
1850 if (!pbucket->empty())
1851 {
1852 last = pbucket;
1853 }
1854
1855 ++pbucket;
1856 }
1857 }
1858 }
1859 }
1860
1861 //*********************************************************************
1863 //*********************************************************************
1864 local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket)
1865 {
1866 local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket.
1867 icurrent->key_value_pair.~value_type(); // Destroy the value.
1868 pnodepool->release(&*icurrent); // Release it back to the pool.
1869 adjust_first_last_markers_after_erase(&bucket);
1870 ETL_DECREMENT_DEBUG_COUNT;
1871
1872 return inext;
1873 }
1874
1875 // Disable copy construction.
1877
1879 pool_t* pnodepool;
1880
1882 bucket_t* pbuckets;
1883
1885 const size_t number_of_buckets;
1886
1888 bucket_t* first;
1889 bucket_t* last;
1890
1892 hasher key_hash_function;
1893
1895 key_equal key_equal_function;
1896
1898 ETL_DECLARE_DEBUG_COUNT;
1899
1900 //*************************************************************************
1902 //*************************************************************************
1903#if defined(ETL_POLYMORPHIC_UNORDERED_MAP) || defined(ETL_POLYMORPHIC_CONTAINERS)
1904
1905 public:
1906
1907 virtual ~iunordered_map() {}
1908#else
1909
1910 protected:
1911
1913#endif
1914 };
1915
1916 //***************************************************************************
1922 //***************************************************************************
1923 template <typename TKey, typename T, typename THash, typename TKeyEqual>
1925 {
1926 const bool sizes_match = (lhs.size() == rhs.size());
1927 bool elements_match = true;
1928
1930
1931 if (sizes_match)
1932 {
1933 itr_t l_begin = lhs.begin();
1934 itr_t l_end = lhs.end();
1935
1936 while ((l_begin != l_end) && elements_match)
1937 {
1938 const TKey key = l_begin->first;
1939 const T l_value = l_begin->second;
1940
1941 // See if the lhs key exists in the rhs.
1942 ETL_OR_STD::pair<itr_t, itr_t> range = rhs.equal_range(key);
1943
1944 if (range.first != rhs.end())
1945 {
1946 // See if the values match
1947 const T r_value = range.first->second;
1948
1949 elements_match = (r_value == l_value);
1950 }
1951 else
1952 {
1953 elements_match = false;
1954 }
1955
1956 ++l_begin;
1957 }
1958 }
1959
1960 return (sizes_match && elements_match);
1961 }
1962
1963 //***************************************************************************
1969 //***************************************************************************
1970 template <typename TKey, typename T, typename THash, typename TKeyEqual>
1972 {
1973 return !(lhs == rhs);
1974 }
1975
1976 //*************************************************************************
1978 //*************************************************************************
1979 template <typename TKey, typename TValue, const size_t MAX_SIZE_, const size_t MAX_BUCKETS_ = MAX_SIZE_, typename THash = etl::hash<TKey>,
1980 typename TKeyEqual = etl::equal_to<TKey> >
1981 class unordered_map : public etl::iunordered_map<TKey, TValue, THash, TKeyEqual>
1982 {
1983 private:
1984
1986
1987 public:
1988
1989 static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_;
1990 static ETL_CONSTANT size_t MAX_BUCKETS = MAX_BUCKETS_;
1991
1992 //*************************************************************************
1994 //*************************************************************************
1995 unordered_map(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
1996 : base(node_pool, buckets, MAX_BUCKETS_, hash, equal)
1997 {
1998 }
1999
2000 //*************************************************************************
2002 //*************************************************************************
2004 : base(node_pool, buckets, MAX_BUCKETS_, other.hash_function(), other.key_eq())
2005 {
2006 base::assign(other.cbegin(), other.cend());
2007 }
2008
2009#if ETL_USING_CPP11
2010 //*************************************************************************
2012 //*************************************************************************
2014 : base(node_pool, buckets, MAX_BUCKETS_, other.hash_function(), other.key_eq())
2015 {
2016 if (this != &other)
2017 {
2018 base::move(other.begin(), other.end());
2019 }
2020 }
2021#endif
2022
2023 //*************************************************************************
2028 //*************************************************************************
2029 template <typename TIterator>
2030 unordered_map(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
2031 : base(node_pool, buckets, MAX_BUCKETS_, hash, equal)
2032 {
2033 base::assign(first_, last_);
2034 }
2035
2036#if ETL_HAS_INITIALIZER_LIST
2037 //*************************************************************************
2039 //*************************************************************************
2040 unordered_map(std::initializer_list<ETL_OR_STD::pair<TKey, TValue>> init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual())
2041 : base(node_pool, buckets, MAX_BUCKETS_, hash, equal)
2042 {
2043 base::assign(init.begin(), init.end());
2044 }
2045#endif
2046
2047 //*************************************************************************
2049 //*************************************************************************
2051 {
2053 }
2054
2055 //*************************************************************************
2057 //*************************************************************************
2059 {
2060 base::operator=(rhs);
2061 return *this;
2062 }
2063
2064#if ETL_USING_CPP11
2065 //*************************************************************************
2067 //*************************************************************************
2068 unordered_map& operator=(unordered_map&& rhs)
2069 {
2070 base::operator=(etl::move(rhs));
2071 return *this;
2072 }
2073#endif
2074
2075 private:
2076
2079
2081 typename base::bucket_t buckets[MAX_BUCKETS_];
2082 };
2083
2084 //*************************************************************************
2086 //*************************************************************************
2087#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST
2088 template <typename... TPairs>
2089 unordered_map(TPairs...)
2090 -> unordered_map<typename etl::nth_type_t<0, TPairs...>::first_type, typename etl::nth_type_t<0, TPairs...>::second_type, sizeof...(TPairs)>;
2091#endif
2092
2093 //*************************************************************************
2095 //*************************************************************************
2096#if ETL_USING_CPP11 && ETL_HAS_INITIALIZER_LIST
2097 template <typename TKey, typename T, typename THash = etl::hash<TKey>, typename TKeyEqual = etl::equal_to<TKey>, typename... TPairs>
2098 constexpr auto make_unordered_map(TPairs&&... pairs) -> etl::unordered_map<TKey, T, sizeof...(TPairs), sizeof...(TPairs), THash, TKeyEqual>
2099 {
2100 return {etl::forward<TPairs>(pairs)...};
2101 }
2102#endif
2103} // namespace etl
2104
2105#endif
bool empty() const
Returns true if the list has no elements.
Definition intrusive_forward_list.h:250
void clear()
Clears the intrusive_forward_list.
Definition intrusive_forward_list.h:154
Definition intrusive_forward_list.h:457
iterator insert_after(iterator position, value_type &value)
Definition intrusive_forward_list.h:760
iterator end()
Gets the end of the intrusive_forward_list.
Definition intrusive_forward_list.h:713
iterator before_begin()
Gets before the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:689
iterator begin()
Gets the beginning of the intrusive_forward_list.
Definition intrusive_forward_list.h:673
Definition unordered_map.h:334
Definition unordered_map.h:193
A templated unordered_map implementation that uses a fixed size buffer.
Definition unordered_map.h:1982
unordered_map(const unordered_map &other)
Copy constructor.
Definition unordered_map.h:2003
unordered_map(const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Default constructor.
Definition unordered_map.h:1995
~unordered_map()
Destructor.
Definition unordered_map.h:2050
unordered_map & operator=(const unordered_map &rhs)
Assignment operator.
Definition unordered_map.h:2058
unordered_map(TIterator first_, TIterator last_, const THash &hash=THash(), const TKeyEqual &equal=TKeyEqual())
Definition unordered_map.h:2030
ETL_CONSTEXPR14 bool operator!=(const etl::bitset< Active_Bits, TElement > &lhs, const etl::bitset< Active_Bits, TElement > &rhs) ETL_NOEXCEPT
Definition bitset_new.h:2529
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
Definition exception.h:59
ETL_CONSTEXPR17 etl::enable_if<!etl::is_same< T, etl::nullptr_t >::value, T >::type * addressof(T &t)
Definition addressof.h:52
T * allocate()
Definition ipool.h:333
Definition ipool.h:109
Definition pool.h:54
float load_factor() const
Definition unordered_map.h:1637
iterator erase(const_iterator first_, const_iterator last_)
Definition unordered_map.h:1266
size_type get_bucket_index(const_key_reference key) const
Definition unordered_map.h:595
iterator begin()
Definition unordered_map.h:487
void initialise()
Initialise the unordered_map.
Definition unordered_map.h:1732
const_iterator find(const_key_reference key) const
Definition unordered_map.h:1387
size_type size() const
Gets the size of the unordered_map.
Definition unordered_map.h:1587
const_local_iterator cend(size_t i) const
Definition unordered_map.h:586
~iunordered_map()
Destructor.
Definition unordered_map.h:1912
iterator end()
Definition unordered_map.h:541
size_t available() const
Definition unordered_map.h:1628
local_iterator end(size_t i)
Definition unordered_map.h:568
hasher hash_function() const
Definition unordered_map.h:1646
const_local_iterator cbegin(size_t i) const
Definition unordered_map.h:532
local_iterator begin(size_t i)
Definition unordered_map.h:514
const_local_iterator end(size_t i) const
Definition unordered_map.h:577
iunordered_map & operator=(const iunordered_map &rhs)
Assignment operator.
Definition unordered_map.h:1663
size_type bucket_size(const_key_reference key) const
Definition unordered_map.h:616
void insert(TIterator first_, TIterator last_)
Definition unordered_map.h:1158
size_type max_bucket_count() const
Definition unordered_map.h:641
const_iterator end() const
Definition unordered_map.h:550
mapped_reference operator[](const_key_reference key)
Definition unordered_map.h:705
bool full() const
Checks to see if the unordered_map is full.
Definition unordered_map.h:1619
size_t count(const_key_reference key) const
Definition unordered_map.h:1330
iterator find(const_key_reference key)
Definition unordered_map.h:1353
bool contains(const_key_reference key) const
Check if the unordered_map contains the key.
Definition unordered_map.h:1697
ETL_OR_STD::pair< const_iterator, const_iterator > equal_range(const_key_reference key) const
Definition unordered_map.h:1521
const_iterator begin() const
Definition unordered_map.h:496
ETL_OR_STD::pair< iterator, iterator > equal_range(const_key_reference key)
Definition unordered_map.h:1499
void clear()
Clears the unordered_map.
Definition unordered_map.h:1320
iterator erase(const_iterator ielement)
Definition unordered_map.h:1238
iunordered_map(pool_t &node_pool_, bucket_t *pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_)
Constructor.
Definition unordered_map.h:1718
const_local_iterator begin(size_t i) const
Definition unordered_map.h:523
bool empty() const
Checks to see if the unordered_map is empty.
Definition unordered_map.h:1611
key_equal key_eq() const
Definition unordered_map.h:1655
mapped_reference at(const_key_reference key)
Definition unordered_map.h:796
size_t erase(const_key_reference key)
Definition unordered_map.h:1172
const key_type & const_key_reference
Defines the parameter types.
Definition unordered_map.h:149
size_type capacity() const
Gets the maximum possible size of the unordered_map.
Definition unordered_map.h:1603
size_type bucket_count() const
Definition unordered_map.h:650
const_iterator cend() const
Definition unordered_map.h:559
iterator insert(const_iterator, const_reference key_value_pair)
Definition unordered_map.h:1130
const_mapped_reference at(const_key_reference key) const
Definition unordered_map.h:832
size_type max_size() const
Gets the maximum possible size of the unordered_map.
Definition unordered_map.h:1595
ETL_OR_STD::pair< iterator, bool > insert(const_reference key_value_pair)
Definition unordered_map.h:971
void assign(TIterator first_, TIterator last_)
Definition unordered_map.h:948
const_iterator cbegin() const
Definition unordered_map.h:505
Definition unordered_map.h:130
Definition unordered_map.h:71
Definition unordered_map.h:85
Definition unordered_map.h:113
Definition unordered_map.h:99
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR14 bool operator==(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1081
ETL_CONSTEXPR14 bool operator!=(const etl::array< T, SIZE > &lhs, const etl::array< T, SIZE > &rhs)
Definition array.h:1093
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition iterator.h:967
iterator
Definition iterator.h:424
Definition unordered_map.h:161