1 /* A type-safe hash map.
2 Copyright (C) 2014 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
24 #include "hash-table.h"
26 /* implement default behavior for traits when types allow it. */
28 struct default_hashmap_traits
30 /* Hashes the passed in key. */
36 return uintptr_t(p
) >> 3;
39 /* The right thing to do here would be using is_integral to only allow
40 template arguments of integer type, but reimplementing that is a pain, so
41 we'll just promote everything to [u]int64_t and truncate to hashval_t. */
43 static hashval_t
hash (uint64_t v
) { return v
; }
44 static hashval_t
hash (int64_t v
) { return v
; }
46 /* Return true if the two keys passed as arguments are equal. */
50 equal_keys (const T
&a
, const T
&b
)
55 /* Called to dispose of the key and value before marking the entry as
58 template<typename T
> static void remove (T
&v
) { v
.~T (); }
60 /* Mark the passed in entry as being deleted. */
66 mark_key_deleted (e
.m_key
);
69 /* Mark the passed in entry as being empty. */
75 mark_key_empty (e
.m_key
);
78 /* Return true if the passed in entry is marked as deleted. */
84 return e
.m_key
== (void *)1;
87 /* Return true if the passed in entry is marked as empty. */
89 template<typename T
> static bool is_empty (T
&e
) { return e
.m_key
== NULL
; }
94 mark_key_deleted (T
*&k
)
96 k
= reinterpret_cast<T
*> (1);
101 mark_key_empty (T
*&k
)
103 k
= static_cast<T
*> (0);
107 template<typename Key
, typename Value
,
108 typename Traits
= default_hashmap_traits
>
116 typedef hash_entry value_type
;
117 typedef Key compare_type
;
118 typedef int store_values_directly
;
120 static hashval_t
hash (const hash_entry
&e
)
122 return Traits::hash (e
.m_key
);
125 static bool equal (const hash_entry
&a
, const Key
&b
)
127 return Traits::equal_keys (a
.m_key
, b
);
130 static void remove (hash_entry
&e
) { Traits::remove (e
); }
132 static void mark_deleted (hash_entry
&e
) { Traits::mark_deleted (e
); }
134 static bool is_deleted (const hash_entry
&e
)
136 return Traits::is_deleted (e
);
139 static void mark_empty (hash_entry
&e
) { Traits::mark_empty (e
); }
140 static bool is_empty (const hash_entry
&e
) { return Traits::is_empty (e
); }
144 explicit hash_map (size_t n
= 13) : m_table (n
) {}
146 /* If key k isn't already in the map add key k with value v to the map, and
147 return false. Otherwise set the value of the entry for key k to be v and
150 bool put (const Key
&k
, const Value
&v
)
152 hash_entry
*e
= m_table
.find_slot_with_hash (k
, Traits::hash (k
),
154 bool existed
= !hash_entry::is_empty (*e
);
162 /* if the passed in key is in the map return its value otherwise NULL. */
164 Value
*get (const Key
&k
)
166 hash_entry
&e
= m_table
.find_with_hash (k
, Traits::hash (k
));
167 return Traits::is_empty (e
) ? NULL
: &e
.m_value
;
170 /* Return a reference to the value for the passed in key, creating the entry
171 if it doesn't already exist. If existed is not NULL then it is set to false
172 if the key was not previously in the map, and true otherwise. */
174 Value
&get_or_insert (const Key
&k
, bool *existed
= NULL
)
176 hash_entry
*e
= m_table
.find_slot_with_hash (k
, Traits::hash (k
),
178 bool ins
= Traits::is_empty (*e
);
188 void remove (const Key
&k
)
190 m_table
.remove_elt_with_hash (k
, Traits::hash (k
));
193 /* Call the call back on each pair of key and value with the passed in
196 template<typename Arg
, bool (*f
)(const Key
&, const Value
&, Arg
)>
197 void traverse (Arg a
) const
199 for (typename hash_table
<hash_entry
>::iterator iter
= m_table
.begin ();
200 iter
!= m_table
.end (); ++iter
)
201 f ((*iter
).m_key
, (*iter
).m_value
, a
);
204 template<typename Arg
, bool (*f
)(const Key
&, Value
*, Arg
)>
205 void traverse (Arg a
) const
207 for (typename hash_table
<hash_entry
>::iterator iter
= m_table
.begin ();
208 iter
!= m_table
.end (); ++iter
)
209 if (!f ((*iter
).m_key
, &(*iter
).m_value
, a
))
214 hash_table
<hash_entry
> m_table
;