OSDN Git Service

2010-06-03 Paolo Carlini <paolo.carlini@oracle.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / ext / pb_ds / detail / cc_hash_table_map_ / cc_ht_map_.hpp
1 // -*- C++ -*-
2
3 // Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
4 //
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 3, or (at your option) any later
9 // version.
10
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.
15
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24
25 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
26
27 // Permission to use, copy, modify, sell, and distribute this software
28 // is hereby granted without fee, provided that the above copyright
29 // notice appears in all copies, and that both that copyright notice
30 // and this permission notice appear in supporting documentation. None
31 // of the above authors, nor IBM Haifa Research Laboratories, make any
32 // representation about the suitability of this software for any
33 // purpose. It is provided "as is" without express or implied
34 // warranty.
35
36 /**
37  * @file cc_ht_map_.hpp
38  * Contains an implementation class for cc_ht_map_.
39  */
40
41 #include <utility>
42 #include <iterator>
43 #include <ext/pb_ds/detail/cond_dealtor.hpp>
44 #include <ext/pb_ds/tag_and_trait.hpp>
45 #include <ext/pb_ds/detail/hash_fn/ranged_hash_fn.hpp>
46 #include <ext/pb_ds/detail/types_traits.hpp>
47 #include <ext/pb_ds/exception.hpp>
48 #include <ext/pb_ds/detail/eq_fn/hash_eq_fn.hpp>
49 #ifdef _GLIBCXX_DEBUG
50 #include <ext/pb_ds/detail/debug_map_base.hpp>
51 #endif 
52 #ifdef PB_DS_HT_MAP_TRACE_
53 #include <iostream>
54 #endif 
55 #include <debug/debug.h>
56
57 namespace __gnu_pbds
58 {
59   namespace detail
60   {
61
62 #define PB_DS_CLASS_T_DEC \
63     template<typename Key, typename Mapped, typename Hash_Fn, \
64              typename Eq_Fn, typename Allocator, bool Store_Hash, \
65              typename Comb_Hash_Fn, typename Resize_Policy>
66
67 #ifdef PB_DS_DATA_TRUE_INDICATOR
68 #define PB_DS_CLASS_NAME cc_ht_map_data_
69 #endif 
70
71 #ifdef PB_DS_DATA_FALSE_INDICATOR
72 #define PB_DS_CLASS_NAME cc_ht_map_no_data_
73 #endif 
74
75 #define PB_DS_CLASS_C_DEC \
76     PB_DS_CLASS_NAME<Key, Mapped, Hash_Fn, Eq_Fn, Allocator,    \
77                      Store_Hash, Comb_Hash_Fn, Resize_Policy>
78
79 #define PB_DS_HASH_EQ_FN_C_DEC \
80     hash_eq_fn<Key, Eq_Fn, Allocator, Store_Hash>
81
82 #define PB_DS_RANGED_HASH_FN_C_DEC \
83     ranged_hash_fn<Key, Hash_Fn, Allocator, Comb_Hash_Fn, Store_Hash>
84
85 #define PB_DS_TYPES_TRAITS_C_DEC \
86     types_traits<Key, Mapped, Allocator, Store_Hash>
87
88 #ifdef _GLIBCXX_DEBUG
89 #define PB_DS_DEBUG_MAP_BASE_C_DEC \
90     debug_map_base<Key, Eq_Fn, typename Allocator::template rebind<Key>::other::const_reference>
91 #endif 
92
93 #ifdef PB_DS_DATA_TRUE_INDICATOR
94 #define PB_DS_V2F(X) (X).first
95 #define PB_DS_V2S(X) (X).second
96 #endif 
97
98 #ifdef PB_DS_DATA_FALSE_INDICATOR
99 #define PB_DS_V2F(X) (X)
100 #define PB_DS_V2S(X) Mapped_Data()
101 #endif 
102
103     // <011i$i0|\|-<|-|4i|\|i|\|g |-|4$|-| 74813.
104     template<typename Key,
105              typename Mapped,
106              typename Hash_Fn,
107              typename Eq_Fn,
108              typename Allocator,
109              bool Store_Hash,
110              typename Comb_Hash_Fn,
111              typename Resize_Policy >
112     class PB_DS_CLASS_NAME:
113 #ifdef _GLIBCXX_DEBUG
114       protected PB_DS_DEBUG_MAP_BASE_C_DEC,
115 #endif 
116       public PB_DS_HASH_EQ_FN_C_DEC,
117       public Resize_Policy,
118       public PB_DS_RANGED_HASH_FN_C_DEC,
119       public PB_DS_TYPES_TRAITS_C_DEC
120     {
121     private:
122       typedef PB_DS_TYPES_TRAITS_C_DEC traits_base;
123       typedef typename traits_base::comp_hash comp_hash;
124       typedef typename traits_base::value_type value_type_;
125       typedef typename traits_base::pointer pointer_;
126       typedef typename traits_base::const_pointer const_pointer_;
127       typedef typename traits_base::reference reference_;
128       typedef typename traits_base::const_reference const_reference_;
129
130       struct entry : public traits_base::stored_value_type
131       {
132         typename Allocator::template rebind<entry>::other::pointer m_p_next;
133       };
134
135       typedef cond_dealtor<entry, Allocator> cond_dealtor_t;
136
137       typedef typename Allocator::template rebind<entry>::other entry_allocator;
138       typedef typename entry_allocator::pointer entry_pointer;
139       typedef typename entry_allocator::const_pointer const_entry_pointer;
140       typedef typename entry_allocator::reference entry_reference;
141       typedef typename entry_allocator::const_reference const_entry_reference;
142
143       typedef typename Allocator::template rebind<entry_pointer>::other entry_pointer_allocator;
144       typedef typename entry_pointer_allocator::pointer entry_pointer_array;
145
146       typedef PB_DS_RANGED_HASH_FN_C_DEC ranged_hash_fn_base;
147       typedef PB_DS_HASH_EQ_FN_C_DEC hash_eq_fn_base;
148       typedef Resize_Policy resize_base;
149
150 #ifdef _GLIBCXX_DEBUG
151       typedef PB_DS_DEBUG_MAP_BASE_C_DEC debug_base;
152 #endif 
153
154 #define PB_DS_GEN_POS std::pair<entry_pointer, typename Allocator::size_type>
155
156 #include <ext/pb_ds/detail/unordered_iterator/const_point_iterator.hpp>
157 #include <ext/pb_ds/detail/unordered_iterator/point_iterator.hpp>
158 #include <ext/pb_ds/detail/unordered_iterator/const_iterator.hpp>
159 #include <ext/pb_ds/detail/unordered_iterator/iterator.hpp>
160
161 #undef PB_DS_GEN_POS
162
163     public:
164       typedef Allocator allocator_type;
165       typedef typename Allocator::size_type size_type;
166       typedef typename Allocator::difference_type difference_type;
167       typedef Hash_Fn hash_fn;
168       typedef Eq_Fn eq_fn;
169       typedef Comb_Hash_Fn comb_hash_fn;
170       typedef Resize_Policy resize_policy;
171
172       enum
173         {
174           store_hash = Store_Hash
175         };
176
177       typedef typename traits_base::key_type key_type;
178       typedef typename traits_base::key_pointer key_pointer;
179       typedef typename traits_base::const_key_pointer const_key_pointer;
180       typedef typename traits_base::key_reference key_reference;
181       typedef typename traits_base::const_key_reference const_key_reference;
182       typedef typename traits_base::mapped_type mapped_type;
183       typedef typename traits_base::mapped_pointer mapped_pointer;
184       typedef typename traits_base::const_mapped_pointer const_mapped_pointer;
185       typedef typename traits_base::mapped_reference mapped_reference;
186       typedef typename traits_base::const_mapped_reference const_mapped_reference;
187       typedef typename traits_base::value_type value_type;
188       typedef typename traits_base::pointer pointer;
189       typedef typename traits_base::const_pointer const_pointer;
190       typedef typename traits_base::reference reference;
191       typedef typename traits_base::const_reference const_reference;
192
193 #ifdef PB_DS_DATA_TRUE_INDICATOR
194       typedef point_iterator_ point_iterator;
195 #endif 
196
197 #ifdef PB_DS_DATA_FALSE_INDICATOR
198       typedef const_point_iterator_ point_iterator;
199 #endif 
200
201       typedef const_point_iterator_ const_point_iterator;
202
203 #ifdef PB_DS_DATA_TRUE_INDICATOR
204       typedef iterator_ iterator;
205 #endif 
206
207 #ifdef PB_DS_DATA_FALSE_INDICATOR
208       typedef const_iterator_ iterator;
209 #endif 
210
211       typedef const_iterator_ const_iterator;
212
213       PB_DS_CLASS_NAME();
214
215       PB_DS_CLASS_NAME(const Hash_Fn&);
216
217       PB_DS_CLASS_NAME(const Hash_Fn&, const Eq_Fn&);
218
219       PB_DS_CLASS_NAME(const Hash_Fn&, const Eq_Fn&, const Comb_Hash_Fn&);
220
221       PB_DS_CLASS_NAME(const Hash_Fn&, const Eq_Fn&, const Comb_Hash_Fn&, 
222                        const Resize_Policy&);
223
224       PB_DS_CLASS_NAME(const PB_DS_CLASS_C_DEC&);
225
226       virtual
227       ~PB_DS_CLASS_NAME();
228
229       void
230       swap(PB_DS_CLASS_C_DEC&);
231
232       template<typename It>
233       void
234       copy_from_range(It, It);
235
236       void
237       initialize();
238
239       inline size_type
240       size() const;
241
242       inline size_type
243       max_size() const;
244
245       inline bool
246       empty() const;
247
248       Hash_Fn& 
249       get_hash_fn();
250
251       const Hash_Fn& 
252       get_hash_fn() const;
253
254       Eq_Fn& 
255       get_eq_fn();
256
257       const Eq_Fn& 
258       get_eq_fn() const;
259
260       Comb_Hash_Fn& 
261       get_comb_hash_fn();
262
263       const Comb_Hash_Fn& 
264       get_comb_hash_fn() const;
265
266       Resize_Policy& 
267       get_resize_policy();
268
269       const Resize_Policy& 
270       get_resize_policy() const;
271
272       inline std::pair<point_iterator, bool>
273       insert(const_reference r_val)
274       { return insert_imp(r_val, traits_base::m_store_extra_indicator); }
275
276       inline mapped_reference
277       operator[](const_key_reference r_key)
278       {
279 #ifdef PB_DS_DATA_TRUE_INDICATOR
280         return (subscript_imp(r_key, traits_base::m_store_extra_indicator));
281 #else 
282         insert(r_key);
283         return traits_base::s_null_mapped;
284 #endif 
285       }
286
287       inline point_iterator
288       find(const_key_reference);
289
290       inline const_point_iterator
291       find(const_key_reference) const;
292
293       inline point_iterator
294       find_end();
295
296       inline const_point_iterator
297       find_end() const;
298
299       inline bool
300       erase(const_key_reference);
301
302       template<typename Pred>
303       inline size_type
304       erase_if(Pred);
305
306       void
307       clear();
308
309       inline iterator
310       begin();
311
312       inline const_iterator
313       begin() const;
314
315       inline iterator
316       end();
317
318       inline const_iterator
319       end() const;
320
321 #ifdef _GLIBCXX_DEBUG
322       void
323       assert_valid() const;
324 #endif 
325
326 #ifdef PB_DS_HT_MAP_TRACE_
327       void
328       trace() const;
329 #endif 
330
331     private:
332       void
333       deallocate_all();
334
335       inline bool
336       do_resize_if_needed();
337
338       inline void
339       do_resize_if_needed_no_throw();
340
341       void
342       resize_imp(size_type new_size);
343
344       void
345       do_resize(size_type new_size);
346
347       void
348       resize_imp_no_exceptions(size_type, entry_pointer_array, size_type);
349
350       inline entry_pointer
351       resize_imp_no_exceptions_reassign_pointer(entry_pointer, entry_pointer_array, false_type);
352
353       inline entry_pointer
354       resize_imp_no_exceptions_reassign_pointer(entry_pointer, entry_pointer_array, true_type);
355
356       void
357       deallocate_links_in_list(entry_pointer);
358
359       inline entry_pointer
360       get_entry(const_reference, false_type);
361
362       inline entry_pointer
363       get_entry(const_reference, true_type);
364
365       inline void
366       rels_entry(entry_pointer);
367
368 #ifdef PB_DS_DATA_TRUE_INDICATOR
369       inline mapped_reference
370       subscript_imp(const_key_reference r_key, false_type)
371       {
372         _GLIBCXX_DEBUG_ONLY(assert_valid();)
373         const size_type pos = ranged_hash_fn_base::operator()(r_key);
374         entry_pointer p_e = m_entries[pos];
375         resize_base::notify_insert_search_start();
376
377         while (p_e != 0 
378                && !hash_eq_fn_base::operator()(p_e->m_value.first, r_key))
379           {
380             resize_base::notify_insert_search_collision();
381             p_e = p_e->m_p_next;
382           }
383
384         resize_base::notify_insert_search_end();
385         if (p_e != 0)
386           {
387             _GLIBCXX_DEBUG_ONLY(debug_base::check_key_exists(r_key);)
388             return (p_e->m_value.second);
389           }
390
391         _GLIBCXX_DEBUG_ONLY(debug_base::check_key_does_not_exist(r_key);)
392         return insert_new_imp(value_type(r_key, mapped_type()), pos)->second;
393       }
394
395       inline mapped_reference
396       subscript_imp(const_key_reference r_key, true_type)
397       {
398         _GLIBCXX_DEBUG_ONLY(assert_valid();)
399         comp_hash pos_hash_pair = ranged_hash_fn_base::operator()(r_key);
400         entry_pointer p_e = m_entries[pos_hash_pair.first];
401         resize_base::notify_insert_search_start();
402         while (p_e != 0 && 
403                !hash_eq_fn_base::operator()(p_e->m_value.first, p_e->m_hash, r_key, pos_hash_pair.second))
404           {
405             resize_base::notify_insert_search_collision();
406             p_e = p_e->m_p_next;
407           }
408
409         resize_base::notify_insert_search_end();
410         if (p_e != 0)
411           {
412             _GLIBCXX_DEBUG_ONLY(debug_base::check_key_exists(r_key);)
413             return p_e->m_value.second;
414           }
415
416         _GLIBCXX_DEBUG_ONLY(debug_base::check_key_does_not_exist(r_key);)
417         return insert_new_imp(value_type(r_key, mapped_type()), 
418                               pos_hash_pair)->second;
419       }
420 #endif 
421
422       inline std::pair<point_iterator, bool>
423       insert_imp(const_reference, false_type);
424
425       inline std::pair<point_iterator, bool>
426       insert_imp(const_reference, true_type);
427
428       inline pointer
429       insert_new_imp(const_reference r_val, size_type pos)
430       {
431         if (do_resize_if_needed())
432           pos = ranged_hash_fn_base::operator()(PB_DS_V2F(r_val));
433
434         // Following lines might throw an exception.
435         entry_pointer p_e = get_entry(r_val, traits_base::m_no_throw_copies_indicator);
436
437         // At this point no exceptions can be thrown.
438         p_e->m_p_next = m_entries[pos];
439         m_entries[pos] = p_e;
440         resize_base::notify_inserted(++m_num_used_e);
441
442         _GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(r_val));)
443         _GLIBCXX_DEBUG_ONLY(assert_valid();)
444         return &p_e->m_value;
445       }
446
447       inline pointer
448       insert_new_imp(const_reference r_val, comp_hash& r_pos_hash_pair)
449       {
450         // Following lines might throw an exception.
451         if (do_resize_if_needed())
452           r_pos_hash_pair = ranged_hash_fn_base::operator()(PB_DS_V2F(r_val));
453
454         entry_pointer p_e = get_entry(r_val, traits_base::m_no_throw_copies_indicator);
455
456         // At this point no exceptions can be thrown.
457         p_e->m_hash = r_pos_hash_pair.second;
458         p_e->m_p_next = m_entries[r_pos_hash_pair.first];
459         m_entries[r_pos_hash_pair.first] = p_e;
460         resize_base::notify_inserted(++m_num_used_e);
461         _GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(r_val));)
462         _GLIBCXX_DEBUG_ONLY(assert_valid();)
463         return &p_e->m_value;
464       }
465
466       inline pointer
467       find_key_pointer(const_key_reference r_key, false_type)
468       {
469         entry_pointer p_e = m_entries[ranged_hash_fn_base::operator()(r_key)];
470         resize_base::notify_find_search_start();
471         while (p_e != 0 && 
472                !hash_eq_fn_base::operator()(PB_DS_V2F(p_e->m_value), r_key))
473           {
474             resize_base::notify_find_search_collision();
475             p_e = p_e->m_p_next;
476           }
477
478         resize_base::notify_find_search_end();
479
480 #ifdef _GLIBCXX_DEBUG
481         if (p_e == 0)
482           debug_base::check_key_does_not_exist(r_key);
483         else
484           debug_base::check_key_exists(r_key);
485 #endif 
486         return &p_e->m_value;
487       }
488
489       inline pointer
490       find_key_pointer(const_key_reference r_key, true_type)
491       {
492         comp_hash pos_hash_pair = ranged_hash_fn_base::operator()(r_key);
493         entry_pointer p_e = m_entries[pos_hash_pair.first];
494         resize_base::notify_find_search_start();
495         while (p_e != 0 && 
496                !hash_eq_fn_base::operator()(PB_DS_V2F(p_e->m_value),
497                                             p_e->m_hash,
498                                             r_key, pos_hash_pair.second))
499           {
500             resize_base::notify_find_search_collision();
501             p_e = p_e->m_p_next;
502           }
503
504         resize_base::notify_find_search_end();
505
506 #ifdef _GLIBCXX_DEBUG
507         if (p_e == 0)
508           debug_base::check_key_does_not_exist(r_key);
509         else
510           debug_base::check_key_exists(r_key);
511 #endif 
512         return &p_e->m_value;
513       }
514
515       inline bool
516       erase_in_pos_imp(const_key_reference, size_type);
517
518       inline bool
519       erase_in_pos_imp(const_key_reference, const comp_hash&);
520
521       inline void
522       erase_entry_pointer(entry_pointer&);
523
524 #ifdef PB_DS_DATA_TRUE_INDICATOR
525       void
526       inc_it_state(pointer& r_p_value, 
527                    std::pair<entry_pointer, size_type>& r_pos) const
528       {
529         inc_it_state((const_mapped_pointer& )r_p_value, r_pos);
530       }
531 #endif 
532
533       void
534       inc_it_state(const_pointer& r_p_value, 
535                    std::pair<entry_pointer, size_type>& r_pos) const
536       {
537         _GLIBCXX_DEBUG_ASSERT(r_p_value != 0);
538         r_pos.first = r_pos.first->m_p_next;
539         if (r_pos.first != 0)
540           {
541             r_p_value = &r_pos.first->m_value;
542             return;
543           }
544
545         for (++r_pos.second; r_pos.second < m_num_e; ++r_pos.second)
546           if (m_entries[r_pos.second] != 0)
547             {
548               r_pos.first = m_entries[r_pos.second];
549               r_p_value = &r_pos.first->m_value;
550               return;
551             }
552         r_p_value = 0;
553       }
554
555       void
556       get_start_it_state(pointer& r_p_value, 
557                          std::pair<entry_pointer, size_type>& r_pos) const
558       {
559         for (r_pos.second = 0; r_pos.second < m_num_e; ++r_pos.second)
560           if (m_entries[r_pos.second] != 0)
561             {
562               r_pos.first = m_entries[r_pos.second];
563               r_p_value = &r_pos.first->m_value;
564               return;
565             }
566         r_p_value = 0;
567       }
568
569 #ifdef _GLIBCXX_DEBUG
570       void
571       assert_entry_pointer_array_valid(const entry_pointer_array) const;
572
573       void
574       assert_entry_pointer_valid(const entry_pointer, true_type) const;
575
576       void
577       assert_entry_pointer_valid(const entry_pointer, false_type) const;
578 #endif 
579
580 #ifdef PB_DS_HT_MAP_TRACE_
581       void
582       trace_list(const_entry_pointer) const;
583 #endif 
584
585     private:
586 #ifdef PB_DS_DATA_TRUE_INDICATOR
587       friend class iterator_;
588 #endif 
589
590       friend class const_iterator_;
591
592       static entry_allocator            s_entry_allocator;
593       static entry_pointer_allocator    s_entry_pointer_allocator;
594       static iterator                   s_end_it;
595       static const_iterator             s_const_end_it;
596       static point_iterator             s_find_end_it;
597       static const_point_iterator       s_const_find_end_it;
598
599       size_type                         m_num_e;
600       size_type                         m_num_used_e;
601       entry_pointer_array               m_entries;
602
603       enum
604         {
605           store_hash_ok = !Store_Hash 
606                           || !is_same<Hash_Fn, __gnu_pbds::null_hash_fn>::value
607         };
608
609       PB_DS_STATIC_ASSERT(sth, store_hash_ok);
610     };
611
612 #include <ext/pb_ds/detail/cc_hash_table_map_/constructor_destructor_fn_imps.hpp>
613 #include <ext/pb_ds/detail/cc_hash_table_map_/entry_list_fn_imps.hpp>
614 #include <ext/pb_ds/detail/cc_hash_table_map_/find_fn_imps.hpp>
615 #include <ext/pb_ds/detail/cc_hash_table_map_/resize_fn_imps.hpp>
616 #include <ext/pb_ds/detail/cc_hash_table_map_/debug_fn_imps.hpp>
617 #include <ext/pb_ds/detail/cc_hash_table_map_/size_fn_imps.hpp>
618 #include <ext/pb_ds/detail/cc_hash_table_map_/policy_access_fn_imps.hpp>
619 #include <ext/pb_ds/detail/cc_hash_table_map_/erase_fn_imps.hpp>
620 #include <ext/pb_ds/detail/cc_hash_table_map_/iterators_fn_imps.hpp>
621 #include <ext/pb_ds/detail/cc_hash_table_map_/insert_fn_imps.hpp>
622 #include <ext/pb_ds/detail/cc_hash_table_map_/trace_fn_imps.hpp>
623
624 #undef PB_DS_CLASS_T_DEC
625 #undef PB_DS_CLASS_C_DEC
626 #undef PB_DS_HASH_EQ_FN_C_DEC
627 #undef PB_DS_RANGED_HASH_FN_C_DEC
628 #undef PB_DS_TYPES_TRAITS_C_DEC
629 #undef PB_DS_DEBUG_MAP_BASE_C_DEC
630 #undef PB_DS_CLASS_NAME
631 #undef PB_DS_V2F
632 #undef PB_DS_V2S
633
634   } // namespace detail
635 } // namespace __gnu_pbds
636