3 // Copyright (C) 2005, 2006 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 2, or (at your option) any later
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING. If not, write to
18 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19 // MA 02111-1307, USA.
21 // As a special exception, you may use this file as part of a free
22 // software library without restriction. Specifically, if other files
23 // instantiate templates or use macros or inline functions from this
24 // file, or you compile this file and link it with other files to
25 // produce an executable, this file does not by itself cause the
26 // resulting executable to be covered by the GNU General Public
27 // License. This exception does not however invalidate any other
28 // reasons why the executable file might be covered by the GNU General
31 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
33 // Permission to use, copy, modify, sell, and distribute this software
34 // is hereby granted without fee, provided that the above copyright
35 // notice appears in all copies, and that both that copyright notice
36 // and this permission notice appear in supporting documentation. None
37 // of the above authors, nor IBM Haifa Research Laboratories, make any
38 // representation about the suitability of this software for any
39 // purpose. It is provided "as is" without express or implied
43 * @file gp_ht_map_.hpp
44 * Contains an implementation class for gp_ht_map_.
47 #include <ext/pb_ds/tag_and_trait.hpp>
48 #include <ext/pb_ds/detail/hash_fn/ranged_probe_fn.hpp>
49 #include <ext/pb_ds/detail/types_traits.hpp>
50 #include <ext/pb_ds/exception.hpp>
51 #include <ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp>
53 #ifdef PB_DS_HT_MAP_TRACE_
55 #endif // PB_DS_HT_MAP_TRACE_
56 #ifdef PB_DS_USE_MAP_DEBUG_BASE
57 #include <ext/pb_ds/detail/map_debug_base.hpp>
58 #endif // #ifdef PB_DS_USE_MAP_DEBUG_BASE
65 #ifdef PB_DS_GP_HT_MAP_DEBUG__
66 #define PB_DS_DBG_ASSERT(X) assert(X)
67 #define PB_DS_DBG_VERIFY(X) assert(X)
68 #define PB_DS_DBG_ONLY(X) X
69 #else // #ifdef PB_DS_GP_HT_MAP_DEBUG__
70 #define PB_DS_DBG_ASSERT(X)
71 #define PB_DS_DBG_VERIFY(X) {if((X)==0);}
72 #define PB_DS_DBG_ONLY(X) ;
73 #endif // #ifdef PB_DS_GP_HT_MAP_DEBUG__
75 #define PB_DS_CLASS_T_DEC \
83 class Comb_Probe_Fn, \
87 #ifdef PB_DS_DATA_TRUE_INDICATOR
88 #define PB_DS_CLASS_NAME \
90 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
92 #ifdef PB_DS_DATA_FALSE_INDICATOR
93 #define PB_DS_CLASS_NAME \
95 #endif // #ifdef PB_DS_DATA_FALSE_INDICATOR
97 #define PB_DS_CLASS_C_DEC \
109 #define PB_DS_HASH_EQ_FN_C_DEC \
116 #define PB_DS_RANGED_PROBE_FN_C_DEC \
125 #define PB_DS_TYPES_TRAITS_C_DEC \
132 #ifdef PB_DS_USE_MAP_DEBUG_BASE
133 #define PB_DS_MAP_DEBUG_BASE_C_DEC \
137 typename Allocator::template rebind< \
138 Key>::other::const_reference>
139 #endif // #ifdef PB_DS_USE_MAP_DEBUG_BASE
141 #ifdef PB_DS_DATA_TRUE_INDICATOR
142 #define PB_DS_V2F(X) (X).first
143 #define PB_DS_V2S(X) (X).second
144 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
146 #ifdef PB_DS_DATA_FALSE_INDICATOR
147 #define PB_DS_V2F(X) (X)
148 #define PB_DS_V2S(X) Mapped()
149 #endif // #ifdef PB_DS_DATA_FALSE_INDICATOR
151 #define PB_DS_STATIC_ASSERT(UNIQUE, E) \
153 static_assert_dumclass< \
154 sizeof(static_assert<(bool)(E)>)> \
155 UNIQUE##static_assert_type
157 template<typename Key,
166 class PB_DS_CLASS_NAME :
167 #ifdef PB_DS_GP_HT_MAP_DEBUG__
168 protected PB_DS_MAP_DEBUG_BASE_C_DEC,
169 #endif // #ifdef PB_DS_GP_HT_MAP_DEBUG__
170 public PB_DS_HASH_EQ_FN_C_DEC,
171 public Resize_Policy,
172 public PB_DS_RANGED_PROBE_FN_C_DEC,
173 public PB_DS_TYPES_TRAITS_C_DEC
179 typename PB_DS_TYPES_TRAITS_C_DEC::store_extra_false_type
180 store_hash_false_type;
183 typename PB_DS_TYPES_TRAITS_C_DEC::store_extra_true_type
184 store_hash_true_type;
186 typedef typename PB_DS_TYPES_TRAITS_C_DEC::value_type value_type_;
188 typedef typename PB_DS_TYPES_TRAITS_C_DEC::pointer pointer_;
191 typename PB_DS_TYPES_TRAITS_C_DEC::const_pointer
194 typedef typename PB_DS_TYPES_TRAITS_C_DEC::reference reference_;
197 typename PB_DS_TYPES_TRAITS_C_DEC::const_reference
200 #define PB_DS_GEN_POS \
201 typename Allocator::size_type
203 #include <ext/pb_ds/detail/unordered_iterator/const_point_iterator.hpp>
204 #include <ext/pb_ds/detail/unordered_iterator/point_iterator.hpp>
205 #include <ext/pb_ds/detail/unordered_iterator/const_iterator.hpp>
206 #include <ext/pb_ds/detail/unordered_iterator/iterator.hpp>
212 typedef typename Allocator::size_type size_type;
214 typedef typename Allocator::difference_type difference_type;
216 typedef Hash_Fn hash_fn;
220 typedef Allocator allocator;
222 typedef Probe_Fn probe_fn;
224 typedef Comb_Probe_Fn comb_probe_fn;
226 typedef Resize_Policy resize_policy;
230 store_hash = Store_Hash
233 typedef typename PB_DS_TYPES_TRAITS_C_DEC::key_type key_type;
235 typedef typename PB_DS_TYPES_TRAITS_C_DEC::key_pointer key_pointer;
238 typename PB_DS_TYPES_TRAITS_C_DEC::const_key_pointer
241 typedef typename PB_DS_TYPES_TRAITS_C_DEC::key_reference key_reference;
244 typename PB_DS_TYPES_TRAITS_C_DEC::const_key_reference
247 typedef typename PB_DS_TYPES_TRAITS_C_DEC::mapped_type mapped_type;
250 typename PB_DS_TYPES_TRAITS_C_DEC::mapped_pointer
254 typename PB_DS_TYPES_TRAITS_C_DEC::const_mapped_pointer
255 const_mapped_pointer;
258 typename PB_DS_TYPES_TRAITS_C_DEC::mapped_reference
262 typename PB_DS_TYPES_TRAITS_C_DEC::const_mapped_reference
263 const_mapped_reference;
265 typedef typename PB_DS_TYPES_TRAITS_C_DEC::value_type value_type;
267 typedef typename PB_DS_TYPES_TRAITS_C_DEC::pointer pointer;
269 typedef typename PB_DS_TYPES_TRAITS_C_DEC::const_pointer const_pointer;
271 typedef typename PB_DS_TYPES_TRAITS_C_DEC::reference reference;
274 typename PB_DS_TYPES_TRAITS_C_DEC::const_reference
277 #ifdef PB_DS_DATA_TRUE_INDICATOR
278 typedef point_iterator_ point_iterator;
279 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
281 #ifdef PB_DS_DATA_FALSE_INDICATOR
282 typedef const_point_iterator_ point_iterator;
283 #endif // #ifdef PB_DS_DATA_FALSE_INDICATOR
285 typedef const_point_iterator_ const_point_iterator;
287 #ifdef PB_DS_DATA_TRUE_INDICATOR
288 typedef iterator_ iterator;
289 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
291 #ifdef PB_DS_DATA_FALSE_INDICATOR
292 typedef const_iterator_ iterator;
293 #endif // #ifdef PB_DS_DATA_FALSE_INDICATOR
295 typedef const_iterator_ const_iterator;
301 PB_DS_CLASS_NAME(const PB_DS_CLASS_C_DEC& other);
303 PB_DS_CLASS_NAME(const Hash_Fn& r_hash_fn);
305 PB_DS_CLASS_NAME(const Hash_Fn& r_hash_fn, const Eq_Fn& r_eq_fn);
307 PB_DS_CLASS_NAME(const Hash_Fn& r_hash_fn, const Eq_Fn& r_eq_fn, const Comb_Probe_Fn& r_comb_probe_fn);
309 PB_DS_CLASS_NAME(const Hash_Fn& r_hash_fn, const Eq_Fn& r_eq_fn, const Comb_Probe_Fn& r_comb_probe_fn, const Probe_Fn& r_probe_fn);
311 PB_DS_CLASS_NAME(const Hash_Fn& r_hash_fn, const Eq_Fn& r_eq_fn, const Comb_Probe_Fn& r_comb_probe_fn, const Probe_Fn& r_probe_fn, const Resize_Policy& r_resize_policy);
313 template<typename It>
315 copy_from_range(It first_it, It last_it);
321 swap(PB_DS_CLASS_C_DEC& other);
348 get_probe_fn() const;
354 get_comb_probe_fn() const;
360 get_resize_policy() const;
362 inline std::pair<point_iterator, bool>
363 insert(const_reference r_val)
365 PB_DS_DBG_ONLY(PB_DS_CLASS_C_DEC::assert_valid();)
367 return (insert_imp(r_val, traits_base::m_store_extra_indicator));
370 inline mapped_reference
371 operator[](const_key_reference r_key)
373 #ifdef PB_DS_DATA_TRUE_INDICATOR
374 return (subscript_imp(r_key, traits_base::m_store_extra_indicator));
375 #else // #ifdef PB_DS_DATA_TRUE_INDICATOR
378 return (traits_base::s_null_mapped);
379 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
382 inline point_iterator
383 find(const_key_reference r_key);
385 inline const_point_iterator
386 find(const_key_reference r_key) const;
388 inline point_iterator
391 inline const_point_iterator
395 erase(const_key_reference r_key);
397 template<typename Pred>
407 inline const_iterator
413 inline const_iterator
416 #ifdef PB_DS_GP_HT_MAP_DEBUG__
419 assert_valid() const;
421 #endif // #ifdef PB_DS_GP_HT_MAP_DEBUG__
423 #ifdef PB_DS_HT_MAP_TRACE_
428 #endif // #ifdef PB_DS_HT_MAP_TRACE_
431 typedef PB_DS_TYPES_TRAITS_C_DEC traits_base;
440 typedef char entry_status;
442 struct entry : public PB_DS_TYPES_TRAITS_C_DEC::stored_value_type
448 typename Allocator::template rebind<entry>::other
451 typedef typename entry_allocator::pointer entry_pointer;
453 typedef typename entry_allocator::const_pointer const_entry_pointer;
455 typedef typename entry_allocator::reference entry_reference;
458 typename entry_allocator::const_reference
459 const_entry_reference;
461 typedef typename entry_allocator::pointer entry_array;
463 typedef PB_DS_RANGED_PROBE_FN_C_DEC ranged_probe_fn_base;
465 #ifdef PB_DS_GP_HT_MAP_DEBUG__
466 typedef PB_DS_MAP_DEBUG_BASE_C_DEC map_debug_base;
467 #endif // #ifdef PB_DS_GP_HT_MAP_DEBUG__
469 typedef PB_DS_HASH_EQ_FN_C_DEC hash_eq_fn_base;
471 typedef Resize_Policy resize_base;
473 #ifdef PB_DS_DATA_TRUE_INDICATOR
474 friend class iterator_;
475 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
477 friend class const_iterator_;
479 typedef typename PB_DS_TYPES_TRAITS_C_DEC::comp_hash comp_hash;
490 erase_all_valid_entries(entry_array a_entries_resized, size_type size);
493 do_resize_if_needed();
496 do_resize_if_needed_no_throw();
499 resize_imp(size_type new_size);
502 do_resize(size_type new_size);
505 resize_imp(entry_array a_entries_resized, size_type old_size);
508 resize_imp_reassign(entry_pointer p_e, entry_array a_entries_resized, store_hash_false_type);
511 resize_imp_reassign(entry_pointer p_e, entry_array a_entries_resized, store_hash_true_type);
514 find_ins_pos(const_key_reference r_key, store_hash_false_type);
517 find_ins_pos(const_key_reference r_key, store_hash_true_type);
519 inline std::pair<point_iterator, bool>
520 insert_imp(const_reference r_val, store_hash_false_type);
522 inline std::pair<point_iterator, bool>
523 insert_imp(const_reference r_val, store_hash_true_type);
526 insert_new_imp(const_reference r_val, size_type pos)
528 PB_DS_DBG_ASSERT(m_a_entries[pos].m_stat != valid_entry_status);
530 if (do_resize_if_needed())
531 pos = find_ins_pos(PB_DS_V2F(r_val),
532 traits_base::m_store_extra_indicator);
534 PB_DS_DBG_ASSERT(m_a_entries[pos].m_stat != valid_entry_status);
536 entry* const p_e = m_a_entries + pos;
538 new (&p_e->m_value) value_type(r_val);
540 p_e->m_stat = valid_entry_status;
542 resize_base::notify_inserted(++m_num_used_e);
544 PB_DS_DBG_ONLY(map_debug_base::
545 insert_new(PB_DS_V2F(p_e->m_value));)
547 PB_DS_DBG_ONLY(assert_valid();)
549 return (&p_e->m_value);
553 insert_new_imp(const_reference r_val, comp_hash& r_pos_hash_pair)
555 PB_DS_DBG_ASSERT(m_a_entries[r_pos_hash_pair.first].m_stat !=
558 if (do_resize_if_needed())
559 r_pos_hash_pair = find_ins_pos(
561 traits_base::m_store_extra_indicator);
563 PB_DS_DBG_ASSERT(m_a_entries[r_pos_hash_pair.first].m_stat !=
566 entry* const p_e = m_a_entries + r_pos_hash_pair.first;
568 new (&p_e->m_value) value_type(r_val);
570 p_e->m_hash = r_pos_hash_pair.second;
572 p_e->m_stat = valid_entry_status;
574 resize_base::notify_inserted(++m_num_used_e);
576 PB_DS_DBG_ONLY(map_debug_base::insert_new(
577 PB_DS_V2F(p_e->m_value));)
579 PB_DS_DBG_ONLY(assert_valid();)
581 return (&p_e->m_value);
584 #ifdef PB_DS_DATA_TRUE_INDICATOR
585 inline mapped_reference
586 subscript_imp(const_key_reference r_key, store_hash_false_type)
588 PB_DS_DBG_ONLY(assert_valid();)
590 const size_type pos =
591 find_ins_pos(r_key, traits_base::m_store_extra_indicator);
593 entry_pointer p_e =& m_a_entries[pos];
595 if (p_e->m_stat != valid_entry_status)
596 return (insert_new_imp(
602 PB_DS_DBG_ONLY(map_debug_base::check_key_exists(r_key);)
604 return (p_e->m_value.second);
607 inline mapped_reference
608 subscript_imp(const_key_reference r_key, store_hash_true_type)
610 PB_DS_DBG_ONLY(assert_valid();)
612 comp_hash pos_hash_pair =
613 find_ins_pos(r_key, traits_base::m_store_extra_indicator);
615 if (m_a_entries[pos_hash_pair.first].m_stat != valid_entry_status)
616 return (insert_new_imp(
620 pos_hash_pair)->second);
622 PB_DS_DBG_ONLY(map_debug_base::check_key_exists(r_key));
624 return ((m_a_entries + pos_hash_pair.first)->m_value.second);
626 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
629 find_key_pointer(const_key_reference r_key, store_hash_false_type)
631 const size_type hash = ranged_probe_fn_base::operator()(r_key);
635 resize_base::notify_find_search_start();
637 // Loop until entry is found or until all possible entries accessed.
639 for (i = 0; i < m_num_e; ++i)
641 const size_type pos =
642 ranged_probe_fn_base::operator()( r_key, hash, i);
644 entry* const p_e = m_a_entries + pos;
648 case empty_entry_status:
650 resize_base::notify_find_search_end();
652 PB_DS_DBG_ONLY(map_debug_base::
653 check_key_does_not_exist(r_key);)
658 case valid_entry_status:
659 if (hash_eq_fn_base::operator()(
660 PB_DS_V2F(p_e->m_value),
663 resize_base::notify_find_search_end();
665 PB_DS_DBG_ONLY(map_debug_base::check_key_exists(r_key);)
667 return ((pointer)&p_e->m_value);
670 case erased_entry_status:
676 resize_base::notify_find_search_collision();
679 PB_DS_DBG_ONLY(map_debug_base::
680 check_key_does_not_exist(r_key);)
682 resize_base::notify_find_search_end();
688 find_key_pointer(const_key_reference r_key, store_hash_true_type)
690 comp_hash pos_hash_pair = ranged_probe_fn_base::operator()(r_key);
694 resize_base::notify_find_search_start();
696 // Loop until entry is found or until all possible entries accessed.
698 for (i = 0; i < m_num_e; ++i)
700 const size_type pos =
701 ranged_probe_fn_base::operator()( r_key, pos_hash_pair.second, i);
703 entry* const p_e = m_a_entries + pos;
707 case empty_entry_status:
709 resize_base::notify_find_search_end();
711 PB_DS_DBG_ONLY(map_debug_base::
712 check_key_does_not_exist(r_key);)
717 case valid_entry_status:
718 if (hash_eq_fn_base::operator()(
719 PB_DS_V2F(p_e->m_value),
721 r_key, pos_hash_pair.second))
723 resize_base::notify_find_search_end();
725 PB_DS_DBG_ONLY(map_debug_base::check_key_exists(r_key);)
727 return ((pointer)&p_e->m_value);
730 case erased_entry_status:
736 resize_base::notify_find_search_collision();
739 PB_DS_DBG_ONLY(map_debug_base::
740 check_key_does_not_exist(r_key);)
742 resize_base::notify_find_search_end();
748 erase_imp(const_key_reference r_key, true_type);
751 erase_imp(const_key_reference r_key, false_type);
754 erase_entry(entry_pointer p_e);
756 #ifdef PB_DS_DATA_TRUE_INDICATOR
758 inc_it_state(pointer& r_p_value, size_type& r_pos) const
760 inc_it_state((const_mapped_pointer& )r_p_value, r_pos);
762 #endif // #ifdef PB_DS_DATA_TRUE_INDICATOR
765 inc_it_state(const_pointer& r_p_value, size_type& r_pos) const
767 PB_DS_DBG_ASSERT(r_p_value != NULL);
769 for (++r_pos; r_pos < m_num_e; ++r_pos)
771 const_entry_pointer p_e =& m_a_entries[r_pos];
773 if (p_e->m_stat == valid_entry_status)
775 r_p_value =& p_e->m_value;
785 get_start_it_state(const_pointer& r_p_value, size_type& r_pos) const
787 for (r_pos = 0; r_pos < m_num_e; ++r_pos)
789 const_entry_pointer p_e =& m_a_entries[r_pos];
791 if (p_e->m_stat == valid_entry_status)
793 r_p_value =& p_e->m_value;
803 get_start_it_state(pointer& r_p_value, size_type& r_pos)
805 for (r_pos = 0; r_pos < m_num_e; ++r_pos)
807 entry_pointer p_e =& m_a_entries[r_pos];
809 if (p_e->m_stat == valid_entry_status)
811 r_p_value =& p_e->m_value;
820 #ifdef PB_DS_GP_HT_MAP_DEBUG__
823 assert_entry_array_valid(const entry_array a_entries, store_hash_false_type) const;
826 assert_entry_array_valid(const entry_array a_entries, store_hash_true_type) const;
828 #endif // #ifdef PB_DS_GP_HT_MAP_DEBUG__
831 static entry_allocator s_entry_allocator;
833 entry_pointer m_a_entries;
837 size_type m_num_used_e;
839 static iterator s_end_it;
841 static const_iterator s_const_end_it;
849 pb_ds::null_hash_fn>::value
852 PB_DS_STATIC_ASSERT(sth, store_hash_ok);
855 #include <ext/pb_ds/detail/gp_hash_table_map_/constructor_destructor_fn_imps.hpp>
856 #include <ext/pb_ds/detail/gp_hash_table_map_/find_fn_imps.hpp>
857 #include <ext/pb_ds/detail/gp_hash_table_map_/resize_fn_imps.hpp>
858 #include <ext/pb_ds/detail/gp_hash_table_map_/debug_fn_imps.hpp>
859 #include <ext/pb_ds/detail/gp_hash_table_map_/info_fn_imps.hpp>
860 #include <ext/pb_ds/detail/gp_hash_table_map_/policy_access_fn_imps.hpp>
861 #include <ext/pb_ds/detail/gp_hash_table_map_/erase_fn_imps.hpp>
862 #include <ext/pb_ds/detail/gp_hash_table_map_/iterator_fn_imps.hpp>
863 #include <ext/pb_ds/detail/gp_hash_table_map_/insert_fn_imps.hpp>
864 #include <ext/pb_ds/detail/gp_hash_table_map_/trace_fn_imps.hpp>
866 #undef PB_DS_CLASS_T_DEC
868 #undef PB_DS_CLASS_C_DEC
870 #undef PB_DS_HASH_EQ_FN_C_DEC
872 #undef PB_DS_RANGED_PROBE_FN_C_DEC
874 #undef PB_DS_TYPES_TRAITS_C_DEC
876 #undef PB_DS_MAP_DEBUG_BASE_C_DEC
878 #undef PB_DS_CLASS_NAME
883 #undef PB_DS_DBG_ASSERT
884 #undef PB_DS_DBG_VERIFY
885 #undef PB_DS_DBG_ONLY
887 #undef PB_DS_STATIC_ASSERT
889 } // namespace detail