]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/RefPtrHashMap.h
JavaScriptCore-576.tar.gz
[apple/javascriptcore.git] / wtf / RefPtrHashMap.h
1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21 namespace WTF {
22
23 // This specialization is a direct copy of HashMap, with overloaded functions
24 // to allow for lookup by pointer instead of RefPtr, avoiding ref-count churn.
25
26 // FIXME: Find a better way that doesn't require an entire copy of the HashMap template.
27
28 template<typename RawKeyType, typename ValueType, typename ValueTraits, typename HashFunctions>
29 struct RefPtrHashMapRawKeyTranslator {
30 typedef typename ValueType::first_type KeyType;
31 typedef typename ValueType::second_type MappedType;
32 typedef typename ValueTraits::FirstTraits KeyTraits;
33 typedef typename ValueTraits::SecondTraits MappedTraits;
34
35 static unsigned hash(RawKeyType key) { return HashFunctions::hash(key); }
36 static bool equal(const KeyType& a, RawKeyType b) { return HashFunctions::equal(a, b); }
37 static void translate(ValueType& location, RawKeyType key, const MappedType& mapped)
38 {
39 location.first = key;
40 location.second = mapped;
41 }
42 };
43
44 template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
45 class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> : public FastAllocBase {
46 private:
47 typedef KeyTraitsArg KeyTraits;
48 typedef MappedTraitsArg MappedTraits;
49 typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
50
51 public:
52 typedef typename KeyTraits::TraitType KeyType;
53 typedef T* RawKeyType;
54 typedef typename MappedTraits::TraitType MappedType;
55 typedef typename ValueTraits::TraitType ValueType;
56
57 private:
58 typedef HashArg HashFunctions;
59
60 typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
61 HashFunctions, ValueTraits, KeyTraits> HashTableType;
62
63 typedef RefPtrHashMapRawKeyTranslator<RawKeyType, ValueType, ValueTraits, HashFunctions>
64 RawKeyTranslator;
65
66 public:
67 typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
68 typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
69
70 void swap(HashMap&);
71
72 int size() const;
73 int capacity() const;
74 bool isEmpty() const;
75
76 // iterators iterate over pairs of keys and values
77 iterator begin();
78 iterator end();
79 const_iterator begin() const;
80 const_iterator end() const;
81
82 iterator find(const KeyType&);
83 iterator find(RawKeyType);
84 const_iterator find(const KeyType&) const;
85 const_iterator find(RawKeyType) const;
86 bool contains(const KeyType&) const;
87 bool contains(RawKeyType) const;
88 MappedType get(const KeyType&) const;
89 MappedType get(RawKeyType) const;
90 MappedType inlineGet(RawKeyType) const;
91
92 // replaces value but not key if key is already present
93 // return value is a pair of the iterator to the key location,
94 // and a boolean that's true if a new value was actually added
95 pair<iterator, bool> set(const KeyType&, const MappedType&);
96 pair<iterator, bool> set(RawKeyType, const MappedType&);
97
98 // does nothing if key is already present
99 // return value is a pair of the iterator to the key location,
100 // and a boolean that's true if a new value was actually added
101 pair<iterator, bool> add(const KeyType&, const MappedType&);
102 pair<iterator, bool> add(RawKeyType, const MappedType&);
103
104 void remove(const KeyType&);
105 void remove(RawKeyType);
106 void remove(iterator);
107 void clear();
108
109 MappedType take(const KeyType&); // efficient combination of get with remove
110 MappedType take(RawKeyType); // efficient combination of get with remove
111
112 private:
113 pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
114 pair<iterator, bool> inlineAdd(RawKeyType, const MappedType&);
115
116 HashTableType m_impl;
117 };
118
119 template<typename T, typename U, typename V, typename W, typename X>
120 inline void HashMap<RefPtr<T>, U, V, W, X>::swap(HashMap& other)
121 {
122 m_impl.swap(other.m_impl);
123 }
124
125 template<typename T, typename U, typename V, typename W, typename X>
126 inline int HashMap<RefPtr<T>, U, V, W, X>::size() const
127 {
128 return m_impl.size();
129 }
130
131 template<typename T, typename U, typename V, typename W, typename X>
132 inline int HashMap<RefPtr<T>, U, V, W, X>::capacity() const
133 {
134 return m_impl.capacity();
135 }
136
137 template<typename T, typename U, typename V, typename W, typename X>
138 inline bool HashMap<RefPtr<T>, U, V, W, X>::isEmpty() const
139 {
140 return m_impl.isEmpty();
141 }
142
143 template<typename T, typename U, typename V, typename W, typename X>
144 inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::begin()
145 {
146 return m_impl.begin();
147 }
148
149 template<typename T, typename U, typename V, typename W, typename X>
150 inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::end()
151 {
152 return m_impl.end();
153 }
154
155 template<typename T, typename U, typename V, typename W, typename X>
156 inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::begin() const
157 {
158 return m_impl.begin();
159 }
160
161 template<typename T, typename U, typename V, typename W, typename X>
162 inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::end() const
163 {
164 return m_impl.end();
165 }
166
167 template<typename T, typename U, typename V, typename W, typename X>
168 inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key)
169 {
170 return m_impl.find(key);
171 }
172
173 template<typename T, typename U, typename V, typename W, typename X>
174 inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key)
175 {
176 return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
177 }
178
179 template<typename T, typename U, typename V, typename W, typename X>
180 inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key) const
181 {
182 return m_impl.find(key);
183 }
184
185 template<typename T, typename U, typename V, typename W, typename X>
186 inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key) const
187 {
188 return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
189 }
190
191 template<typename T, typename U, typename V, typename W, typename X>
192 inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(const KeyType& key) const
193 {
194 return m_impl.contains(key);
195 }
196
197 template<typename T, typename U, typename V, typename W, typename X>
198 inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(RawKeyType key) const
199 {
200 return m_impl.template contains<RawKeyType, RawKeyTranslator>(key);
201 }
202
203 template<typename T, typename U, typename V, typename W, typename X>
204 inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
205 HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped)
206 {
207 typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
208 return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
209 }
210
211 template<typename T, typename U, typename V, typename W, typename X>
212 inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
213 HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(RawKeyType key, const MappedType& mapped)
214 {
215 return m_impl.template add<RawKeyType, MappedType, RawKeyTranslator>(key, mapped);
216 }
217
218 template<typename T, typename U, typename V, typename W, typename X>
219 pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
220 HashMap<RefPtr<T>, U, V, W, X>::set(const KeyType& key, const MappedType& mapped)
221 {
222 pair<iterator, bool> result = inlineAdd(key, mapped);
223 if (!result.second) {
224 // add call above didn't change anything, so set the mapped value
225 result.first->second = mapped;
226 }
227 return result;
228 }
229
230 template<typename T, typename U, typename V, typename W, typename X>
231 pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
232 HashMap<RefPtr<T>, U, V, W, X>::set(RawKeyType key, const MappedType& mapped)
233 {
234 pair<iterator, bool> result = inlineAdd(key, mapped);
235 if (!result.second) {
236 // add call above didn't change anything, so set the mapped value
237 result.first->second = mapped;
238 }
239 return result;
240 }
241
242 template<typename T, typename U, typename V, typename W, typename X>
243 pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
244 HashMap<RefPtr<T>, U, V, W, X>::add(const KeyType& key, const MappedType& mapped)
245 {
246 return inlineAdd(key, mapped);
247 }
248
249 template<typename T, typename U, typename V, typename W, typename X>
250 pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
251 HashMap<RefPtr<T>, U, V, W, X>::add(RawKeyType key, const MappedType& mapped)
252 {
253 return inlineAdd(key, mapped);
254 }
255
256 template<typename T, typename U, typename V, typename W, typename MappedTraits>
257 typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
258 HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(const KeyType& key) const
259 {
260 ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
261 if (!entry)
262 return MappedTraits::emptyValue();
263 return entry->second;
264 }
265
266 template<typename T, typename U, typename V, typename W, typename MappedTraits>
267 typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
268 inline HashMap<RefPtr<T>, U, V, W, MappedTraits>::inlineGet(RawKeyType key) const
269 {
270 ValueType* entry = const_cast<HashTableType&>(m_impl).template lookup<RawKeyType, RawKeyTranslator>(key);
271 if (!entry)
272 return MappedTraits::emptyValue();
273 return entry->second;
274 }
275
276 template<typename T, typename U, typename V, typename W, typename MappedTraits>
277 typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
278 HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(RawKeyType key) const
279 {
280 return inlineGet(key);
281 }
282
283 template<typename T, typename U, typename V, typename W, typename X>
284 inline void HashMap<RefPtr<T>, U, V, W, X>::remove(iterator it)
285 {
286 if (it.m_impl == m_impl.end())
287 return;
288 m_impl.internalCheckTableConsistency();
289 m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
290 }
291
292 template<typename T, typename U, typename V, typename W, typename X>
293 inline void HashMap<RefPtr<T>, U, V, W, X>::remove(const KeyType& key)
294 {
295 remove(find(key));
296 }
297
298 template<typename T, typename U, typename V, typename W, typename X>
299 inline void HashMap<RefPtr<T>, U, V, W, X>::remove(RawKeyType key)
300 {
301 remove(find(key));
302 }
303
304 template<typename T, typename U, typename V, typename W, typename X>
305 inline void HashMap<RefPtr<T>, U, V, W, X>::clear()
306 {
307 m_impl.clear();
308 }
309
310 template<typename T, typename U, typename V, typename W, typename MappedTraits>
311 typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
312 HashMap<RefPtr<T>, U, V, W, MappedTraits>::take(const KeyType& key)
313 {
314 // This can probably be made more efficient to avoid ref/deref churn.
315 iterator it = find(key);
316 if (it == end())
317 return MappedTraits::emptyValue();
318 typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType result = it->second;
319 remove(it);
320 return result;
321 }
322
323 template<typename T, typename U, typename V, typename W, typename MappedTraits>
324 typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
325 HashMap<RefPtr<T>, U, V, W, MappedTraits>::take(RawKeyType key)
326 {
327 // This can probably be made more efficient to avoid ref/deref churn.
328 iterator it = find(key);
329 if (it == end())
330 return MappedTraits::emptyValue();
331 typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType result = it->second;
332 remove(it);
333 return result;
334 }
335
336 } // namespace WTF