2014-08-27 Yvan Roux <yvan.roux@linaro.org>
[official-gcc.git] / gcc / hash-map.h
blobd2eed337ad4530ed9484cba927f80a955b5f8afd
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
9 version.
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
14 for more details.
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/>. */
21 #ifndef hash_map_h
22 #define hash_map_h
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. */
32 template<typename T>
33 static hashval_t
34 hash (T *p)
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. */
45 template<typename T>
46 static bool
47 equal_keys (const T &a, const T &b)
49 return a == b;
52 /* Called to dispose of the key and value before marking the entry as
53 deleted. */
55 template<typename T> static void remove (T &v) { v.~T (); }
57 /* Mark the passed in entry as being deleted. */
59 template<typename T>
60 static void
61 mark_deleted (T &e)
63 mark_key_deleted (e.m_key);
66 /* Mark the passed in entry as being empty. */
68 template<typename T>
69 static void
70 mark_empty (T &e)
72 mark_key_empty (e.m_key);
75 /* Return true if the passed in entry is marked as deleted. */
77 template<typename T>
78 static bool
79 is_deleted (T &e)
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; }
88 private:
89 template<typename T>
90 static void
91 mark_key_deleted (T *&k)
93 k = reinterpret_cast<T *> (1);
96 template<typename T>
97 static void
98 mark_key_empty (T *&k)
100 k = static_cast<T *> (0);
104 template<typename Key, typename Value,
105 typename Traits = default_hashmap_traits>
106 class hash_map
108 struct hash_entry
110 Key m_key;
111 Value m_value;
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); }
140 public:
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
145 return true. */
147 bool put (const Key &k, const Value &v)
149 hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
150 INSERT);
151 bool existed = !hash_entry::is_empty (*e);
152 if (!existed)
153 e->m_key = k;
155 e->m_value = v;
156 return existed;
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),
174 INSERT);
175 bool ins = Traits::is_empty (*e);
176 if (ins)
177 e->m_key = k;
179 if (existed != NULL)
180 *existed = !ins;
182 return e->m_value;
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
191 arg. */
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))
207 break;
210 private:
211 hash_table<hash_entry> m_table;
214 #endif