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 /* If the value converts to hashval_t just use it. */
41 template<typename T
> static hashval_t
hash (T v
) { return v
; }
43 /* Return true if the two keys passed as arguments are equal. */
47 equal_keys (const T
&a
, const T
&b
)
52 /* Called to dispose of the key and value before marking the entry as
55 template<typename T
> static void remove (T
&v
) { v
.~T (); }
57 /* Mark the passed in entry as being deleted. */
63 mark_key_deleted (e
.m_key
);
66 /* Mark the passed in entry as being empty. */
72 mark_key_empty (e
.m_key
);
75 /* Return true if the passed in entry is marked as deleted. */
81 return e
.m_key
== (void *)1;
84 /* Return true if the passed in entry is marked as empty. */
86 template<typename T
> static bool is_empty (T
&e
) { return e
.m_key
== NULL
; }
91 mark_key_deleted (T
*&k
)
93 k
= reinterpret_cast<T
*> (1);
98 mark_key_empty (T
*&k
)
100 k
= static_cast<T
*> (0);
104 template<typename Key
, typename Value
,
105 typename Traits
= default_hashmap_traits
>
113 typedef hash_entry value_type
;
114 typedef Key compare_type
;
115 typedef int store_values_directly
;
117 static hashval_t
hash (const hash_entry
&e
)
119 return Traits::hash (e
.m_key
);
122 static bool equal (const hash_entry
&a
, const Key
&b
)
124 return Traits::equal_keys (a
.m_key
, b
);
127 static void remove (hash_entry
&e
) { Traits::remove (e
); }
129 static void mark_deleted (hash_entry
&e
) { Traits::mark_deleted (e
); }
131 static bool is_deleted (const hash_entry
&e
)
133 return Traits::is_deleted (e
);
136 static void mark_empty (hash_entry
&e
) { Traits::mark_empty (e
); }
137 static bool is_empty (const hash_entry
&e
) { return Traits::is_empty (e
); }
141 explicit hash_map (size_t n
= 13) : m_table (n
) {}
143 /* If key k isn't already in the map add key k with value v to the map, and
144 return false. Otherwise set the value of the entry for key k to be v and
147 bool put (const Key
&k
, const Value
&v
)
149 hash_entry
*e
= m_table
.find_slot_with_hash (k
, Traits::hash (k
),
151 bool existed
= !hash_entry::is_empty (*e
);
159 /* if the passed in key is in the map return its value otherwise NULL. */
161 Value
*get (const Key
&k
)
163 hash_entry
&e
= m_table
.find_with_hash (k
, Traits::hash (k
));
164 return Traits::is_empty (e
) ? NULL
: &e
.m_value
;
167 /* Return a reference to the value for the passed in key, creating the entry
168 if it doesn't already exist. If existed is not NULL then it is set to false
169 if the key was not previously in the map, and true otherwise. */
171 Value
&get_or_insert (const Key
&k
, bool *existed
= NULL
)
173 hash_entry
*e
= m_table
.find_slot_with_hash (k
, Traits::hash (k
),
175 bool ins
= Traits::is_empty (*e
);
185 void remove (const Key
&k
)
187 m_table
.remove_elt_with_hash (k
, Traits::hash (k
));
190 /* Call the call back on each pair of key and value with the passed in
193 template<typename Arg
, bool (*f
)(const Key
&, const Value
&, Arg
)>
194 void traverse (Arg a
) const
196 for (typename hash_table
<hash_entry
>::iterator iter
= m_table
.begin ();
197 iter
!= m_table
.end (); ++iter
)
198 f ((*iter
).m_key
, (*iter
).m_value
, a
);
201 template<typename Arg
, bool (*f
)(const Key
&, Value
*, Arg
)>
202 void traverse (Arg a
) const
204 for (typename hash_table
<hash_entry
>::iterator iter
= m_table
.begin ();
205 iter
!= m_table
.end (); ++iter
)
206 if (!f ((*iter
).m_key
, &(*iter
).m_value
, a
))
211 hash_table
<hash_entry
> m_table
;