xref: /dragonfly/contrib/gcc-8.0/gcc/hash-map.h (revision 38fd1498)
1*38fd1498Szrj /* A type-safe hash map.
2*38fd1498Szrj    Copyright (C) 2014-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj 
21*38fd1498Szrj #ifndef hash_map_h
22*38fd1498Szrj #define hash_map_h
23*38fd1498Szrj 
24*38fd1498Szrj template<typename KeyId, typename Value,
25*38fd1498Szrj 	 typename Traits>
class(user)26*38fd1498Szrj class GTY((user)) hash_map
27*38fd1498Szrj {
28*38fd1498Szrj   typedef typename Traits::key_type Key;
29*38fd1498Szrj   struct hash_entry
30*38fd1498Szrj   {
31*38fd1498Szrj     Key m_key;
32*38fd1498Szrj     Value m_value;
33*38fd1498Szrj 
34*38fd1498Szrj     typedef hash_entry value_type;
35*38fd1498Szrj     typedef Key compare_type;
36*38fd1498Szrj 
37*38fd1498Szrj     static hashval_t hash (const hash_entry &e)
38*38fd1498Szrj       {
39*38fd1498Szrj        	return Traits::hash (e.m_key);
40*38fd1498Szrj       }
41*38fd1498Szrj 
42*38fd1498Szrj     static bool equal (const hash_entry &a, const Key &b)
43*38fd1498Szrj        	{
44*38fd1498Szrj 	  return Traits::equal_keys (a.m_key, b);
45*38fd1498Szrj        	}
46*38fd1498Szrj 
47*38fd1498Szrj     static void remove (hash_entry &e) { Traits::remove (e); }
48*38fd1498Szrj 
49*38fd1498Szrj     static void mark_deleted (hash_entry &e) { Traits::mark_deleted (e); }
50*38fd1498Szrj 
51*38fd1498Szrj     static bool is_deleted (const hash_entry &e)
52*38fd1498Szrj       {
53*38fd1498Szrj        	return Traits::is_deleted (e);
54*38fd1498Szrj       }
55*38fd1498Szrj 
56*38fd1498Szrj     static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
57*38fd1498Szrj     static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
58*38fd1498Szrj 
59*38fd1498Szrj     static void ggc_mx (hash_entry &e)
60*38fd1498Szrj       {
61*38fd1498Szrj 	gt_ggc_mx (e.m_key);
62*38fd1498Szrj 	gt_ggc_mx (e.m_value);
63*38fd1498Szrj       }
64*38fd1498Szrj 
65*38fd1498Szrj     static void ggc_maybe_mx (hash_entry &e)
66*38fd1498Szrj       {
67*38fd1498Szrj 	if (Traits::maybe_mx)
68*38fd1498Szrj 	  ggc_mx (e);
69*38fd1498Szrj       }
70*38fd1498Szrj 
71*38fd1498Szrj     static void pch_nx (hash_entry &e)
72*38fd1498Szrj       {
73*38fd1498Szrj 	gt_pch_nx (e.m_key);
74*38fd1498Szrj 	gt_pch_nx (e.m_value);
75*38fd1498Szrj       }
76*38fd1498Szrj 
77*38fd1498Szrj     static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
78*38fd1498Szrj       {
79*38fd1498Szrj 	pch_nx_helper (e.m_key, op, c);
80*38fd1498Szrj 	pch_nx_helper (e.m_value, op, c);
81*38fd1498Szrj       }
82*38fd1498Szrj 
83*38fd1498Szrj     static int keep_cache_entry (hash_entry &e)
84*38fd1498Szrj       {
85*38fd1498Szrj 	return ggc_marked_p (e.m_key);
86*38fd1498Szrj       }
87*38fd1498Szrj 
88*38fd1498Szrj   private:
89*38fd1498Szrj     template<typename T>
90*38fd1498Szrj     static void
91*38fd1498Szrj       pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
92*38fd1498Szrj 	{
93*38fd1498Szrj 	  gt_pch_nx (&x, op, cookie);
94*38fd1498Szrj 	}
95*38fd1498Szrj 
96*38fd1498Szrj     static void
97*38fd1498Szrj       pch_nx_helper (int, gt_pointer_operator, void *)
98*38fd1498Szrj 	{
99*38fd1498Szrj 	}
100*38fd1498Szrj 
101*38fd1498Szrj     static void
102*38fd1498Szrj       pch_nx_helper (unsigned int, gt_pointer_operator, void *)
103*38fd1498Szrj 	{
104*38fd1498Szrj 	}
105*38fd1498Szrj 
106*38fd1498Szrj     static void
107*38fd1498Szrj       pch_nx_helper (bool, gt_pointer_operator, void *)
108*38fd1498Szrj 	{
109*38fd1498Szrj 	}
110*38fd1498Szrj 
111*38fd1498Szrj     template<typename T>
112*38fd1498Szrj       static void
113*38fd1498Szrj       pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
114*38fd1498Szrj 	{
115*38fd1498Szrj 	  op (&x, cookie);
116*38fd1498Szrj 	}
117*38fd1498Szrj   };
118*38fd1498Szrj 
119*38fd1498Szrj public:
120*38fd1498Szrj   explicit hash_map (size_t n = 13, bool ggc = false,
121*38fd1498Szrj 		     bool gather_mem_stats = GATHER_STATISTICS
122*38fd1498Szrj 		     CXX_MEM_STAT_INFO)
123*38fd1498Szrj     : m_table (n, ggc, gather_mem_stats, HASH_MAP_ORIGIN PASS_MEM_STAT) {}
124*38fd1498Szrj 
125*38fd1498Szrj   explicit hash_map (const hash_map &h, bool ggc = false,
126*38fd1498Szrj 		     bool gather_mem_stats = GATHER_STATISTICS
127*38fd1498Szrj 		     CXX_MEM_STAT_INFO)
128*38fd1498Szrj     : m_table (h.m_table, ggc, gather_mem_stats,
129*38fd1498Szrj 	       HASH_MAP_ORIGIN PASS_MEM_STAT) {}
130*38fd1498Szrj 
131*38fd1498Szrj   /* Create a hash_map in ggc memory.  */
132*38fd1498Szrj   static hash_map *create_ggc (size_t size,
133*38fd1498Szrj 			       bool gather_mem_stats = GATHER_STATISTICS
134*38fd1498Szrj 			       CXX_MEM_STAT_INFO)
135*38fd1498Szrj     {
136*38fd1498Szrj       hash_map *map = ggc_alloc<hash_map> ();
137*38fd1498Szrj       new (map) hash_map (size, true, gather_mem_stats PASS_MEM_STAT);
138*38fd1498Szrj       return map;
139*38fd1498Szrj     }
140*38fd1498Szrj 
141*38fd1498Szrj   /* If key k isn't already in the map add key k with value v to the map, and
142*38fd1498Szrj      return false.  Otherwise set the value of the entry for key k to be v and
143*38fd1498Szrj      return true.  */
144*38fd1498Szrj 
145*38fd1498Szrj   bool put (const Key &k, const Value &v)
146*38fd1498Szrj     {
147*38fd1498Szrj       hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
148*38fd1498Szrj 						   INSERT);
149*38fd1498Szrj       bool existed = !hash_entry::is_empty (*e);
150*38fd1498Szrj       if (!existed)
151*38fd1498Szrj 	e->m_key = k;
152*38fd1498Szrj 
153*38fd1498Szrj       e->m_value = v;
154*38fd1498Szrj       return existed;
155*38fd1498Szrj     }
156*38fd1498Szrj 
157*38fd1498Szrj   /* if the passed in key is in the map return its value otherwise NULL.  */
158*38fd1498Szrj 
159*38fd1498Szrj   Value *get (const Key &k)
160*38fd1498Szrj     {
161*38fd1498Szrj       hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
162*38fd1498Szrj       return Traits::is_empty (e) ? NULL : &e.m_value;
163*38fd1498Szrj     }
164*38fd1498Szrj 
165*38fd1498Szrj   /* Return a reference to the value for the passed in key, creating the entry
166*38fd1498Szrj      if it doesn't already exist.  If existed is not NULL then it is set to false
167*38fd1498Szrj      if the key was not previously in the map, and true otherwise.  */
168*38fd1498Szrj 
169*38fd1498Szrj   Value &get_or_insert (const Key &k, bool *existed = NULL)
170*38fd1498Szrj     {
171*38fd1498Szrj       hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
172*38fd1498Szrj 						   INSERT);
173*38fd1498Szrj       bool ins = Traits::is_empty (*e);
174*38fd1498Szrj       if (ins)
175*38fd1498Szrj 	e->m_key = k;
176*38fd1498Szrj 
177*38fd1498Szrj       if (existed != NULL)
178*38fd1498Szrj 	*existed = !ins;
179*38fd1498Szrj 
180*38fd1498Szrj       return e->m_value;
181*38fd1498Szrj     }
182*38fd1498Szrj 
183*38fd1498Szrj   void remove (const Key &k)
184*38fd1498Szrj     {
185*38fd1498Szrj       m_table.remove_elt_with_hash (k, Traits::hash (k));
186*38fd1498Szrj     }
187*38fd1498Szrj 
188*38fd1498Szrj   /* Call the call back on each pair of key and value with the passed in
189*38fd1498Szrj      arg.  */
190*38fd1498Szrj 
191*38fd1498Szrj   template<typename Arg, bool (*f)(const typename Traits::key_type &,
192*38fd1498Szrj 				   const Value &, Arg)>
193*38fd1498Szrj   void traverse (Arg a) const
194*38fd1498Szrj     {
195*38fd1498Szrj       for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
196*38fd1498Szrj 	   iter != m_table.end (); ++iter)
197*38fd1498Szrj 	f ((*iter).m_key, (*iter).m_value, a);
198*38fd1498Szrj     }
199*38fd1498Szrj 
200*38fd1498Szrj   template<typename Arg, bool (*f)(const typename Traits::key_type &,
201*38fd1498Szrj 				   Value *, Arg)>
202*38fd1498Szrj   void traverse (Arg a) const
203*38fd1498Szrj     {
204*38fd1498Szrj       for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
205*38fd1498Szrj 	   iter != m_table.end (); ++iter)
206*38fd1498Szrj 	if (!f ((*iter).m_key, &(*iter).m_value, a))
207*38fd1498Szrj 	  break;
208*38fd1498Szrj     }
209*38fd1498Szrj 
210*38fd1498Szrj   size_t elements () const { return m_table.elements (); }
211*38fd1498Szrj 
212*38fd1498Szrj   void empty () { m_table.empty(); }
213*38fd1498Szrj 
214*38fd1498Szrj   class iterator
215*38fd1498Szrj   {
216*38fd1498Szrj   public:
217*38fd1498Szrj     explicit iterator (const typename hash_table<hash_entry>::iterator &iter) :
218*38fd1498Szrj       m_iter (iter) {}
219*38fd1498Szrj 
220*38fd1498Szrj     iterator &operator++ ()
221*38fd1498Szrj     {
222*38fd1498Szrj       ++m_iter;
223*38fd1498Szrj       return *this;
224*38fd1498Szrj     }
225*38fd1498Szrj 
226*38fd1498Szrj     std::pair<Key, Value> operator* ()
227*38fd1498Szrj     {
228*38fd1498Szrj       hash_entry &e = *m_iter;
229*38fd1498Szrj       return std::pair<Key, Value> (e.m_key, e.m_value);
230*38fd1498Szrj     }
231*38fd1498Szrj 
232*38fd1498Szrj     bool
233*38fd1498Szrj     operator != (const iterator &other) const
234*38fd1498Szrj     {
235*38fd1498Szrj       return m_iter != other.m_iter;
236*38fd1498Szrj     }
237*38fd1498Szrj 
238*38fd1498Szrj   private:
239*38fd1498Szrj     typename hash_table<hash_entry>::iterator m_iter;
240*38fd1498Szrj   };
241*38fd1498Szrj 
242*38fd1498Szrj   /* Standard iterator retrieval methods.  */
243*38fd1498Szrj 
244*38fd1498Szrj   iterator  begin () const { return iterator (m_table.begin ()); }
245*38fd1498Szrj   iterator end () const { return iterator (m_table.end ()); }
246*38fd1498Szrj 
247*38fd1498Szrj private:
248*38fd1498Szrj 
249*38fd1498Szrj   template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);
250*38fd1498Szrj   template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *);
251*38fd1498Szrj   template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
252*38fd1498Szrj   template<typename T, typename U, typename V> friend void gt_cleare_cache (hash_map<T, U, V> *);
253*38fd1498Szrj 
254*38fd1498Szrj   hash_table<hash_entry> m_table;
255*38fd1498Szrj };
256*38fd1498Szrj 
257*38fd1498Szrj /* ggc marking routines.  */
258*38fd1498Szrj 
259*38fd1498Szrj template<typename K, typename V, typename H>
260*38fd1498Szrj static inline void
gt_ggc_mx(hash_map<K,V,H> * h)261*38fd1498Szrj gt_ggc_mx (hash_map<K, V, H> *h)
262*38fd1498Szrj {
263*38fd1498Szrj   gt_ggc_mx (&h->m_table);
264*38fd1498Szrj }
265*38fd1498Szrj 
266*38fd1498Szrj template<typename K, typename V, typename H>
267*38fd1498Szrj static inline void
gt_pch_nx(hash_map<K,V,H> * h)268*38fd1498Szrj gt_pch_nx (hash_map<K, V, H> *h)
269*38fd1498Szrj {
270*38fd1498Szrj   gt_pch_nx (&h->m_table);
271*38fd1498Szrj }
272*38fd1498Szrj 
273*38fd1498Szrj template<typename K, typename V, typename H>
274*38fd1498Szrj static inline void
gt_cleare_cache(hash_map<K,V,H> * h)275*38fd1498Szrj gt_cleare_cache (hash_map<K, V, H> *h)
276*38fd1498Szrj {
277*38fd1498Szrj   if (h)
278*38fd1498Szrj     gt_cleare_cache (&h->m_table);
279*38fd1498Szrj }
280*38fd1498Szrj 
281*38fd1498Szrj template<typename K, typename V, typename H>
282*38fd1498Szrj static inline void
gt_pch_nx(hash_map<K,V,H> * h,gt_pointer_operator op,void * cookie)283*38fd1498Szrj gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
284*38fd1498Szrj {
285*38fd1498Szrj   op (&h->m_table.m_entries, cookie);
286*38fd1498Szrj }
287*38fd1498Szrj 
288*38fd1498Szrj #endif
289