3 // Copyright (C) 2005, 2006, 2007, 2009, 2010, 2011
4 // Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the terms
8 // of the GNU General Public License as published by the Free Software
9 // Foundation; either version 3, or (at your option) any later
12 // This library is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
26 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
28 // Permission to use, copy, modify, sell, and distribute this software
29 // is hereby granted without fee, provided that the above copyright
30 // notice appears in all copies, and that both that copyright notice
31 // and this permission notice appear in supporting documentation. None
32 // of the above authors, nor IBM Haifa Research Laboratories, make any
33 // representation about the suitability of this software for any
34 // purpose. It is provided "as is" without express or implied
38 * @file gp_ht_map_.hpp
39 * Contains an implementation class for gp_ht_map_.
42 #include <ext/pb_ds/tag_and_trait.hpp>
43 #include <ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp>
44 #include <ext/pb_ds/detail/types_traits.hpp>
45 #include <ext/pb_ds/exception.hpp>
46 #include <ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp>
48 #ifdef PB_DS_HT_MAP_TRACE_
52 #include <ext/pb_ds/detail/debug_map_base.hpp>
54 #include <debug/debug.h>
60 #define PB_DS_CLASS_T_DEC \
61 template<typename Key, typename Mapped, typename Hash_Fn, typename Eq_Fn, \
62 typename Allocator, bool Store_Hash, typename Comb_Probe_Fn, \
63 typename Probe_Fn, typename Resize_Policy>
65 #ifdef PB_DS_DATA_TRUE_INDICATOR
66 #define PB_DS_CLASS_NAME gp_ht_map_data_
69 #ifdef PB_DS_DATA_FALSE_INDICATOR
70 #define PB_DS_CLASS_NAME gp_ht_map_no_data_
73 #define PB_DS_CLASS_C_DEC \
74 PB_DS_CLASS_NAME<Key, Mapped, Hash_Fn, Eq_Fn, Allocator, \
75 Store_Hash, Comb_Probe_Fn, Probe_Fn, Resize_Policy>
77 #define PB_DS_HASH_EQ_FN_C_DEC \
78 hash_eq_fn<Key, Eq_Fn, Allocator, Store_Hash>
80 #define PB_DS_RANGED_PROBE_FN_C_DEC \
81 ranged_probe_fn<Key, Hash_Fn, Allocator, Comb_Probe_Fn, Probe_Fn, Store_Hash>
83 #define PB_DS_TYPES_TRAITS_C_DEC \
84 types_traits<Key, Mapped, Allocator, Store_Hash>
87 #define PB_DS_DEBUG_MAP_BASE_C_DEC \
88 debug_map_base<Key, Eq_Fn, typename Allocator::template rebind<Key>::other::const_reference>
91 #ifdef PB_DS_DATA_TRUE_INDICATOR
92 #define PB_DS_V2F(X) (X).first
93 #define PB_DS_V2S(X) (X).second
96 #ifdef PB_DS_DATA_FALSE_INDICATOR
97 #define PB_DS_V2F(X) (X)
98 #define PB_DS_V2S(X) Mapped()
101 #define PB_DS_CHECK_KEY_EXISTS(_Key) \
102 _GLIBCXX_DEBUG_ONLY(debug_base::check_key_exists(_Key, __FILE__, __LINE__);)
104 #define PB_DS_CHECK_KEY_DOES_NOT_EXIST(_Key) \
105 _GLIBCXX_DEBUG_ONLY(debug_base::check_key_does_not_exist(_Key, \
106 __FILE__, __LINE__);)
108 template<typename Key
,
114 typename Comb_Probe_Fn
,
116 typename Resize_Policy
>
117 class PB_DS_CLASS_NAME
:
118 #ifdef _GLIBCXX_DEBUG
119 protected PB_DS_DEBUG_MAP_BASE_C_DEC
,
121 public PB_DS_HASH_EQ_FN_C_DEC
,
122 public Resize_Policy
,
123 public PB_DS_RANGED_PROBE_FN_C_DEC
,
124 public PB_DS_TYPES_TRAITS_C_DEC
127 typedef PB_DS_TYPES_TRAITS_C_DEC traits_base
;
128 typedef typename
traits_base::value_type value_type_
;
129 typedef typename
traits_base::pointer pointer_
;
130 typedef typename
traits_base::const_pointer const_pointer_
;
131 typedef typename
traits_base::reference reference_
;
132 typedef typename
traits_base::const_reference const_reference_
;
133 typedef typename
traits_base::comp_hash comp_hash
;
140 } __attribute__ ((packed
));
142 struct entry
: public traits_base::stored_value_type
147 typedef typename
Allocator::template rebind
<entry
>::other entry_allocator
;
148 typedef typename
entry_allocator::pointer entry_pointer
;
149 typedef typename
entry_allocator::const_pointer const_entry_pointer
;
150 typedef typename
entry_allocator::reference entry_reference
;
151 typedef typename
entry_allocator::const_reference const_entry_reference
;
152 typedef typename
entry_allocator::pointer entry_array
;
154 typedef PB_DS_RANGED_PROBE_FN_C_DEC ranged_probe_fn_base
;
156 #ifdef _GLIBCXX_DEBUG
157 typedef PB_DS_DEBUG_MAP_BASE_C_DEC debug_base
;
160 typedef PB_DS_HASH_EQ_FN_C_DEC hash_eq_fn_base
;
161 typedef Resize_Policy resize_base
;
163 #define PB_DS_GEN_POS typename Allocator::size_type
165 #include <ext/pb_ds/detail/unordered_iterator/const_point_iterator.hpp>
166 #include <ext/pb_ds/detail/unordered_iterator/point_iterator.hpp>
167 #include <ext/pb_ds/detail/unordered_iterator/const_iterator.hpp>
168 #include <ext/pb_ds/detail/unordered_iterator/iterator.hpp>
173 typedef Allocator allocator_type
;
174 typedef typename
Allocator::size_type size_type
;
175 typedef typename
Allocator::difference_type difference_type
;
176 typedef Hash_Fn hash_fn
;
178 typedef Probe_Fn probe_fn
;
179 typedef Comb_Probe_Fn comb_probe_fn
;
180 typedef Resize_Policy resize_policy
;
184 store_hash
= Store_Hash
187 typedef typename
traits_base::key_type key_type
;
188 typedef typename
traits_base::key_pointer key_pointer
;
189 typedef typename
traits_base::const_key_pointer const_key_pointer
;
190 typedef typename
traits_base::key_reference key_reference
;
191 typedef typename
traits_base::const_key_reference const_key_reference
;
192 typedef typename
traits_base::mapped_type mapped_type
;
193 typedef typename
traits_base::mapped_pointer mapped_pointer
;
194 typedef typename
traits_base::const_mapped_pointer const_mapped_pointer
;
195 typedef typename
traits_base::mapped_reference mapped_reference
;
196 typedef typename
traits_base::const_mapped_reference const_mapped_reference
;
197 typedef typename
traits_base::value_type value_type
;
198 typedef typename
traits_base::pointer pointer
;
199 typedef typename
traits_base::const_pointer const_pointer
;
200 typedef typename
traits_base::reference reference
;
201 typedef typename
traits_base::const_reference const_reference
;
203 #ifdef PB_DS_DATA_TRUE_INDICATOR
204 typedef point_iterator_ point_iterator
;
207 #ifdef PB_DS_DATA_FALSE_INDICATOR
208 typedef const_point_iterator_ point_iterator
;
211 typedef const_point_iterator_ const_point_iterator
;
213 #ifdef PB_DS_DATA_TRUE_INDICATOR
214 typedef iterator_ iterator
;
217 #ifdef PB_DS_DATA_FALSE_INDICATOR
218 typedef const_iterator_ iterator
;
221 typedef const_iterator_ const_iterator
;
225 PB_DS_CLASS_NAME(const PB_DS_CLASS_C_DEC
&);
227 PB_DS_CLASS_NAME(const Hash_Fn
&);
229 PB_DS_CLASS_NAME(const Hash_Fn
&, const Eq_Fn
&);
231 PB_DS_CLASS_NAME(const Hash_Fn
&, const Eq_Fn
&, const Comb_Probe_Fn
&);
233 PB_DS_CLASS_NAME(const Hash_Fn
&, const Eq_Fn
&, const Comb_Probe_Fn
&,
236 PB_DS_CLASS_NAME(const Hash_Fn
&, const Eq_Fn
&, const Comb_Probe_Fn
&,
237 const Probe_Fn
&, const Resize_Policy
&);
239 template<typename It
>
241 copy_from_range(It first_it
, It last_it
);
247 swap(PB_DS_CLASS_C_DEC
& other
);
274 get_probe_fn() const;
280 get_comb_probe_fn() const;
286 get_resize_policy() const;
288 inline std::pair
<point_iterator
, bool>
289 insert(const_reference r_val
)
291 _GLIBCXX_DEBUG_ONLY(PB_DS_CLASS_C_DEC::assert_valid(__FILE__
, __LINE__
);)
292 return insert_imp(r_val
, traits_base::m_store_extra_indicator
);
295 inline mapped_reference
296 operator[](const_key_reference r_key
)
298 #ifdef PB_DS_DATA_TRUE_INDICATOR
299 return subscript_imp(r_key
, traits_base::m_store_extra_indicator
);
302 return traits_base::s_null_mapped
;
306 inline point_iterator
307 find(const_key_reference r_key
);
309 inline const_point_iterator
310 find(const_key_reference r_key
) const;
312 inline point_iterator
315 inline const_point_iterator
319 erase(const_key_reference r_key
);
321 template<typename Pred
>
331 inline const_iterator
337 inline const_iterator
340 #ifdef _GLIBCXX_DEBUG
342 assert_valid(const char* file
, int line
) const;
345 #ifdef PB_DS_HT_MAP_TRACE_
351 #ifdef PB_DS_DATA_TRUE_INDICATOR
352 friend class iterator_
;
355 friend class const_iterator_
;
364 erase_all_valid_entries(entry_array
, size_type
);
367 do_resize_if_needed();
370 do_resize_if_needed_no_throw();
373 resize_imp(size_type
);
376 do_resize(size_type
);
379 resize_imp(entry_array
, size_type
);
382 resize_imp_reassign(entry_pointer
, entry_array
, false_type
);
385 resize_imp_reassign(entry_pointer
, entry_array
, true_type
);
388 find_ins_pos(const_key_reference
, false_type
);
391 find_ins_pos(const_key_reference
, true_type
);
393 inline std::pair
<point_iterator
, bool>
394 insert_imp(const_reference
, false_type
);
396 inline std::pair
<point_iterator
, bool>
397 insert_imp(const_reference
, true_type
);
400 insert_new_imp(const_reference r_val
, size_type pos
)
402 _GLIBCXX_DEBUG_ASSERT(m_entries
[pos
].m_stat
!= valid_entry_status
);
404 if (do_resize_if_needed())
405 pos
= find_ins_pos(PB_DS_V2F(r_val
),
406 traits_base::m_store_extra_indicator
);
408 _GLIBCXX_DEBUG_ASSERT(m_entries
[pos
].m_stat
!= valid_entry_status
);
410 entry
* const p_e
= m_entries
+ pos
;
411 new (&p_e
->m_value
) value_type(r_val
);
412 p_e
->m_stat
= valid_entry_status
;
413 resize_base::notify_inserted(++m_num_used_e
);
415 _GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(p_e
->m_value
));)
417 _GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__
, __LINE__
);)
418 return &p_e
->m_value
;
422 insert_new_imp(const_reference r_val
, comp_hash
& r_pos_hash_pair
)
424 _GLIBCXX_DEBUG_ASSERT(m_entries
[r_pos_hash_pair
.first
].m_stat
!=
427 if (do_resize_if_needed())
428 r_pos_hash_pair
= find_ins_pos(PB_DS_V2F(r_val
),
429 traits_base::m_store_extra_indicator
);
431 _GLIBCXX_DEBUG_ASSERT(m_entries
[r_pos_hash_pair
.first
].m_stat
!=
434 entry
* const p_e
= m_entries
+ r_pos_hash_pair
.first
;
435 new (&p_e
->m_value
) value_type(r_val
);
436 p_e
->m_hash
= r_pos_hash_pair
.second
;
437 p_e
->m_stat
= valid_entry_status
;
439 resize_base::notify_inserted(++m_num_used_e
);
441 _GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(p_e
->m_value
));)
443 _GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__
, __LINE__
);)
444 return &p_e
->m_value
;
447 #ifdef PB_DS_DATA_TRUE_INDICATOR
448 inline mapped_reference
449 subscript_imp(const_key_reference key
, false_type
)
451 _GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__
, __LINE__
);)
453 const size_type pos
= find_ins_pos(key
,
454 traits_base::m_store_extra_indicator
);
456 entry_pointer p_e
= &m_entries
[pos
];
457 if (p_e
->m_stat
!= valid_entry_status
)
458 return insert_new_imp(value_type(key
, mapped_type()), pos
)->second
;
460 PB_DS_CHECK_KEY_EXISTS(key
)
461 return p_e
->m_value
.second
;
464 inline mapped_reference
465 subscript_imp(const_key_reference key
, true_type
)
467 _GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__
, __LINE__
);)
469 comp_hash pos_hash_pair
=
470 find_ins_pos(key
, traits_base::m_store_extra_indicator
);
472 if (m_entries
[pos_hash_pair
.first
].m_stat
!= valid_entry_status
)
473 return insert_new_imp(value_type(key
, mapped_type()),
474 pos_hash_pair
)->second
;
476 PB_DS_CHECK_KEY_EXISTS(key
)
477 return (m_entries
+ pos_hash_pair
.first
)->m_value
.second
;
482 find_key_pointer(const_key_reference key
, false_type
)
484 const size_type hash
= ranged_probe_fn_base::operator()(key
);
486 resize_base::notify_find_search_start();
488 // Loop until entry is found or until all possible entries accessed.
489 for (i
= 0; i
< m_num_e
; ++i
)
491 const size_type pos
= ranged_probe_fn_base::operator()(key
, hash
, i
);
493 entry
* const p_e
= m_entries
+ pos
;
496 case empty_entry_status
:
498 resize_base::notify_find_search_end();
499 PB_DS_CHECK_KEY_DOES_NOT_EXIST(key
)
503 case valid_entry_status
:
504 if (hash_eq_fn_base::operator()(PB_DS_V2F(p_e
->m_value
), key
))
506 resize_base::notify_find_search_end();
507 PB_DS_CHECK_KEY_EXISTS(key
)
508 return pointer(&p_e
->m_value
);
511 case erased_entry_status
:
514 _GLIBCXX_DEBUG_ASSERT(0);
517 resize_base::notify_find_search_collision();
520 PB_DS_CHECK_KEY_DOES_NOT_EXIST(key
)
521 resize_base::notify_find_search_end();
526 find_key_pointer(const_key_reference key
, true_type
)
528 comp_hash pos_hash_pair
= ranged_probe_fn_base::operator()(key
);
530 resize_base::notify_find_search_start();
532 // Loop until entry is found or until all possible entries accessed.
533 for (i
= 0; i
< m_num_e
; ++i
)
535 const size_type pos
=
536 ranged_probe_fn_base::operator()(key
, pos_hash_pair
.second
, i
);
538 entry
* const p_e
= m_entries
+ pos
;
542 case empty_entry_status
:
544 resize_base::notify_find_search_end();
545 PB_DS_CHECK_KEY_DOES_NOT_EXIST(key
)
549 case valid_entry_status
:
550 if (hash_eq_fn_base::operator()(PB_DS_V2F(p_e
->m_value
),
552 key
, pos_hash_pair
.second
))
554 resize_base::notify_find_search_end();
555 PB_DS_CHECK_KEY_EXISTS(key
)
556 return pointer(&p_e
->m_value
);
559 case erased_entry_status
:
562 _GLIBCXX_DEBUG_ASSERT(0);
565 resize_base::notify_find_search_collision();
568 PB_DS_CHECK_KEY_DOES_NOT_EXIST(key
)
569 resize_base::notify_find_search_end();
574 erase_imp(const_key_reference
, true_type
);
577 erase_imp(const_key_reference
, false_type
);
580 erase_entry(entry_pointer p_e
);
582 #ifdef PB_DS_DATA_TRUE_INDICATOR
584 inc_it_state(pointer
& r_p_value
, size_type
& r_pos
) const
585 { inc_it_state((const_mapped_pointer
& )r_p_value
, r_pos
); }
589 inc_it_state(const_pointer
& r_p_value
, size_type
& r_pos
) const
591 _GLIBCXX_DEBUG_ASSERT(r_p_value
!= 0);
592 for (++r_pos
; r_pos
< m_num_e
; ++r_pos
)
594 const_entry_pointer p_e
=& m_entries
[r_pos
];
595 if (p_e
->m_stat
== valid_entry_status
)
597 r_p_value
=& p_e
->m_value
;
605 get_start_it_state(const_pointer
& r_p_value
, size_type
& r_pos
) const
607 for (r_pos
= 0; r_pos
< m_num_e
; ++r_pos
)
609 const_entry_pointer p_e
= &m_entries
[r_pos
];
610 if (p_e
->m_stat
== valid_entry_status
)
612 r_p_value
= &p_e
->m_value
;
620 get_start_it_state(pointer
& r_p_value
, size_type
& r_pos
)
622 for (r_pos
= 0; r_pos
< m_num_e
; ++r_pos
)
624 entry_pointer p_e
= &m_entries
[r_pos
];
625 if (p_e
->m_stat
== valid_entry_status
)
627 r_p_value
= &p_e
->m_value
;
634 #ifdef _GLIBCXX_DEBUG
636 assert_entry_array_valid(const entry_array
, false_type
,
637 const char* file
, int line
) const;
640 assert_entry_array_valid(const entry_array
, true_type
,
641 const char* file
, int line
) const;
644 static entry_allocator s_entry_allocator
;
645 static iterator s_end_it
;
646 static const_iterator s_const_end_it
;
649 size_type m_num_used_e
;
650 entry_pointer m_entries
;
654 store_hash_ok
= !Store_Hash
655 || !is_same
<Hash_Fn
, __gnu_pbds::null_hash_fn
>::value
658 PB_DS_STATIC_ASSERT(sth
, store_hash_ok
);
661 #define PB_DS_ASSERT_VALID(X) \
662 _GLIBCXX_DEBUG_ONLY(X.assert_valid(__FILE__, __LINE__);)
664 #define PB_DS_DEBUG_VERIFY(_Cond) \
665 _GLIBCXX_DEBUG_VERIFY_AT(_Cond, \
666 _M_message(#_Cond" assertion from %1;:%2;") \
667 ._M_string(__FILE__)._M_integer(__LINE__) \
670 #include <ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp>
671 #include <ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp>
672 #include <ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp>
673 #include <ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp>
674 #include <ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp>
675 #include <ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp>
676 #include <ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp>
677 #include <ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp>
678 #include <ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp>
679 #include <ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp>
681 #undef PB_DS_DEBUG_VERIFY
682 #undef PB_DS_ASSERT_VALID
683 #undef PB_DS_CHECK_KEY_DOES_NOT_EXIST
684 #undef PB_DS_CHECK_KEY_EXISTS
685 #undef PB_DS_CLASS_T_DEC
686 #undef PB_DS_CLASS_C_DEC
687 #undef PB_DS_HASH_EQ_FN_C_DEC
688 #undef PB_DS_RANGED_PROBE_FN_C_DEC
689 #undef PB_DS_TYPES_TRAITS_C_DEC
690 #undef PB_DS_DEBUG_MAP_BASE_C_DEC
691 #undef PB_DS_CLASS_NAME
695 } // namespace detail
696 } // namespace __gnu_pbds