1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef nsTHashKeys_h__
8 #define nsTHashKeys_h__
9
10 #include "nsID.h"
11 #include "nsISupports.h"
12 #include "nsIHashable.h"
13 #include "nsAutoPtr.h"
14 #include "nsCOMPtr.h"
15 #include "PLDHashTable.h"
16 #include <new>
17
18 #include "nsString.h"
19 #include "nsCRTGlue.h"
20 #include "nsUnicharUtils.h"
21 #include "nsPointerHashKeys.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "mozilla/HashFunctions.h"
27 #include "mozilla/Move.h"
28
29 namespace mozilla {
30
31 // These are defined analogously to the HashString overloads in mfbt.
32
HashString(const nsAString & aStr)33 inline uint32_t HashString(const nsAString& aStr) {
34 return HashString(aStr.BeginReading(), aStr.Length());
35 }
36
HashString(const nsACString & aStr)37 inline uint32_t HashString(const nsACString& aStr) {
38 return HashString(aStr.BeginReading(), aStr.Length());
39 }
40
41 } // namespace mozilla
42
43 /** @file nsHashKeys.h
44 * standard HashKey classes for nsBaseHashtable and relatives. Each of these
45 * classes follows the nsTHashtable::EntryType specification
46 *
47 * Lightweight keytypes provided here:
48 * nsStringHashKey
49 * nsCStringHashKey
50 * nsUint32HashKey
51 * nsUint64HashKey
52 * nsFloatHashKey
53 * nsPtrHashKey
54 * nsClearingPtrHashKey
55 * nsVoidPtrHashKey
56 * nsClearingVoidPtrHashKey
57 * nsISupportsHashKey
58 * nsIDHashKey
59 * nsDepCharHashKey
60 * nsCharPtrHashKey
61 * nsUnicharPtrHashKey
62 * nsHashableHashKey
63 * nsGenericHashKey
64 */
65
66 /**
67 * hashkey wrapper using nsAString KeyType
68 *
69 * @see nsTHashtable::EntryType for specification
70 */
71 class nsStringHashKey : public PLDHashEntryHdr {
72 public:
73 typedef const nsAString& KeyType;
74 typedef const nsAString* KeyTypePointer;
75
nsStringHashKey(KeyTypePointer aStr)76 explicit nsStringHashKey(KeyTypePointer aStr) : mStr(*aStr) {}
nsStringHashKey(const nsStringHashKey & aToCopy)77 nsStringHashKey(const nsStringHashKey& aToCopy) : mStr(aToCopy.mStr) {}
~nsStringHashKey()78 ~nsStringHashKey() {}
79
GetKey()80 KeyType GetKey() const { return mStr; }
KeyEquals(const KeyTypePointer aKey)81 bool KeyEquals(const KeyTypePointer aKey) const { return mStr.Equals(*aKey); }
82
KeyToPointer(KeyType aKey)83 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(const KeyTypePointer aKey)84 static PLDHashNumber HashKey(const KeyTypePointer aKey) {
85 return mozilla::HashString(*aKey);
86 }
87
88 #ifdef MOZILLA_INTERNAL_API
89 // To avoid double-counting, only measure the string if it is unshared.
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)90 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
91 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
92 }
93 #endif
94
95 enum { ALLOW_MEMMOVE = true };
96
97 private:
98 const nsString mStr;
99 };
100
101 #ifdef MOZILLA_INTERNAL_API
102
103 /**
104 * hashkey wrapper using nsAString KeyType
105 *
106 * This is internal-API only because nsCaseInsensitiveStringComparator is
107 * internal-only.
108 *
109 * @see nsTHashtable::EntryType for specification
110 */
111 class nsStringCaseInsensitiveHashKey : public PLDHashEntryHdr {
112 public:
113 typedef const nsAString& KeyType;
114 typedef const nsAString* KeyTypePointer;
115
nsStringCaseInsensitiveHashKey(KeyTypePointer aStr)116 explicit nsStringCaseInsensitiveHashKey(KeyTypePointer aStr) : mStr(*aStr) {
117 // take it easy just deal HashKey
118 }
nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey & aToCopy)119 nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey& aToCopy)
120 : mStr(aToCopy.mStr) {}
~nsStringCaseInsensitiveHashKey()121 ~nsStringCaseInsensitiveHashKey() {}
122
GetKey()123 KeyType GetKey() const { return mStr; }
KeyEquals(const KeyTypePointer aKey)124 bool KeyEquals(const KeyTypePointer aKey) const {
125 return mStr.Equals(*aKey, nsCaseInsensitiveStringComparator());
126 }
127
KeyToPointer(KeyType aKey)128 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(const KeyTypePointer aKey)129 static PLDHashNumber HashKey(const KeyTypePointer aKey) {
130 nsAutoString tmKey(*aKey);
131 ToLowerCase(tmKey);
132 return mozilla::HashString(tmKey);
133 }
134 enum { ALLOW_MEMMOVE = true };
135
136 // To avoid double-counting, only measure the string if it is unshared.
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)137 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
138 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
139 }
140
141 private:
142 const nsString mStr;
143 };
144
145 #endif
146
147 /**
148 * hashkey wrapper using nsACString KeyType
149 *
150 * @see nsTHashtable::EntryType for specification
151 */
152 class nsCStringHashKey : public PLDHashEntryHdr {
153 public:
154 typedef const nsACString& KeyType;
155 typedef const nsACString* KeyTypePointer;
156
nsCStringHashKey(const nsACString * aStr)157 explicit nsCStringHashKey(const nsACString* aStr) : mStr(*aStr) {}
nsCStringHashKey(const nsCStringHashKey & aToCopy)158 nsCStringHashKey(const nsCStringHashKey& aToCopy) : mStr(aToCopy.mStr) {}
~nsCStringHashKey()159 ~nsCStringHashKey() {}
160
GetKey()161 KeyType GetKey() const { return mStr; }
KeyEquals(KeyTypePointer aKey)162 bool KeyEquals(KeyTypePointer aKey) const { return mStr.Equals(*aKey); }
163
KeyToPointer(KeyType aKey)164 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(KeyTypePointer aKey)165 static PLDHashNumber HashKey(KeyTypePointer aKey) {
166 return mozilla::HashString(*aKey);
167 }
168
169 #ifdef MOZILLA_INTERNAL_API
170 // To avoid double-counting, only measure the string if it is unshared.
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)171 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
172 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
173 }
174 #endif
175
176 enum { ALLOW_MEMMOVE = true };
177
178 private:
179 const nsCString mStr;
180 };
181
182 /**
183 * hashkey wrapper using uint32_t KeyType
184 *
185 * @see nsTHashtable::EntryType for specification
186 */
187 class nsUint32HashKey : public PLDHashEntryHdr {
188 public:
189 typedef const uint32_t& KeyType;
190 typedef const uint32_t* KeyTypePointer;
191
nsUint32HashKey(KeyTypePointer aKey)192 explicit nsUint32HashKey(KeyTypePointer aKey) : mValue(*aKey) {}
nsUint32HashKey(const nsUint32HashKey & aToCopy)193 nsUint32HashKey(const nsUint32HashKey& aToCopy) : mValue(aToCopy.mValue) {}
~nsUint32HashKey()194 ~nsUint32HashKey() {}
195
GetKey()196 KeyType GetKey() const { return mValue; }
KeyEquals(KeyTypePointer aKey)197 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
198
KeyToPointer(KeyType aKey)199 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(KeyTypePointer aKey)200 static PLDHashNumber HashKey(KeyTypePointer aKey) { return *aKey; }
201 enum { ALLOW_MEMMOVE = true };
202
203 private:
204 const uint32_t mValue;
205 };
206
207 /**
208 * hashkey wrapper using uint64_t KeyType
209 *
210 * @see nsTHashtable::EntryType for specification
211 */
212 class nsUint64HashKey : public PLDHashEntryHdr {
213 public:
214 typedef const uint64_t& KeyType;
215 typedef const uint64_t* KeyTypePointer;
216
nsUint64HashKey(KeyTypePointer aKey)217 explicit nsUint64HashKey(KeyTypePointer aKey) : mValue(*aKey) {}
nsUint64HashKey(const nsUint64HashKey & aToCopy)218 nsUint64HashKey(const nsUint64HashKey& aToCopy) : mValue(aToCopy.mValue) {}
~nsUint64HashKey()219 ~nsUint64HashKey() {}
220
GetKey()221 KeyType GetKey() const { return mValue; }
KeyEquals(KeyTypePointer aKey)222 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
223
KeyToPointer(KeyType aKey)224 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(KeyTypePointer aKey)225 static PLDHashNumber HashKey(KeyTypePointer aKey) {
226 return PLDHashNumber(*aKey);
227 }
228 enum { ALLOW_MEMMOVE = true };
229
230 private:
231 const uint64_t mValue;
232 };
233
234 /**
235 * hashkey wrapper using float KeyType
236 *
237 * @see nsTHashtable::EntryType for specification
238 */
239 class nsFloatHashKey : public PLDHashEntryHdr {
240 public:
241 typedef const float& KeyType;
242 typedef const float* KeyTypePointer;
243
nsFloatHashKey(KeyTypePointer aKey)244 explicit nsFloatHashKey(KeyTypePointer aKey) : mValue(*aKey) {}
nsFloatHashKey(const nsFloatHashKey & aToCopy)245 nsFloatHashKey(const nsFloatHashKey& aToCopy) : mValue(aToCopy.mValue) {}
~nsFloatHashKey()246 ~nsFloatHashKey() {}
247
GetKey()248 KeyType GetKey() const { return mValue; }
KeyEquals(KeyTypePointer aKey)249 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
250
KeyToPointer(KeyType aKey)251 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(KeyTypePointer aKey)252 static PLDHashNumber HashKey(KeyTypePointer aKey) {
253 return *reinterpret_cast<const uint32_t*>(aKey);
254 }
255 enum { ALLOW_MEMMOVE = true };
256
257 private:
258 const float mValue;
259 };
260
261 /**
262 * hashkey wrapper using nsISupports* KeyType
263 *
264 * @see nsTHashtable::EntryType for specification
265 */
266 class nsISupportsHashKey : public PLDHashEntryHdr {
267 public:
268 typedef nsISupports* KeyType;
269 typedef const nsISupports* KeyTypePointer;
270
nsISupportsHashKey(const nsISupports * aKey)271 explicit nsISupportsHashKey(const nsISupports* aKey)
272 : mSupports(const_cast<nsISupports*>(aKey)) {}
nsISupportsHashKey(const nsISupportsHashKey & aToCopy)273 nsISupportsHashKey(const nsISupportsHashKey& aToCopy)
274 : mSupports(aToCopy.mSupports) {}
~nsISupportsHashKey()275 ~nsISupportsHashKey() {}
276
GetKey()277 KeyType GetKey() const { return mSupports; }
KeyEquals(KeyTypePointer aKey)278 bool KeyEquals(KeyTypePointer aKey) const { return aKey == mSupports; }
279
KeyToPointer(KeyType aKey)280 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
HashKey(KeyTypePointer aKey)281 static PLDHashNumber HashKey(KeyTypePointer aKey) {
282 return NS_PTR_TO_UINT32(aKey) >> 2;
283 }
284 enum { ALLOW_MEMMOVE = true };
285
286 private:
287 nsCOMPtr<nsISupports> mSupports;
288 };
289
290 /**
291 * hashkey wrapper using refcounted * KeyType
292 *
293 * @see nsTHashtable::EntryType for specification
294 */
295 template <class T>
296 class nsRefPtrHashKey : public PLDHashEntryHdr {
297 public:
298 typedef T* KeyType;
299 typedef const T* KeyTypePointer;
300
nsRefPtrHashKey(const T * aKey)301 explicit nsRefPtrHashKey(const T* aKey) : mKey(const_cast<T*>(aKey)) {}
nsRefPtrHashKey(const nsRefPtrHashKey & aToCopy)302 nsRefPtrHashKey(const nsRefPtrHashKey& aToCopy) : mKey(aToCopy.mKey) {}
~nsRefPtrHashKey()303 ~nsRefPtrHashKey() {}
304
GetKey()305 KeyType GetKey() const { return mKey; }
KeyEquals(KeyTypePointer aKey)306 bool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
307
KeyToPointer(KeyType aKey)308 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
HashKey(KeyTypePointer aKey)309 static PLDHashNumber HashKey(KeyTypePointer aKey) {
310 return NS_PTR_TO_UINT32(aKey) >> 2;
311 }
312 enum { ALLOW_MEMMOVE = true };
313
314 private:
315 RefPtr<T> mKey;
316 };
317
318 template <class T>
319 inline void ImplCycleCollectionTraverse(
320 nsCycleCollectionTraversalCallback& aCallback, nsRefPtrHashKey<T>& aField,
321 const char* aName, uint32_t aFlags = 0) {
322 CycleCollectionNoteChild(aCallback, aField.GetKey(), aName, aFlags);
323 }
324
325 /**
326 * hashkey wrapper using T* KeyType that sets key to nullptr upon
327 * destruction. Relevant only in cases where a memory pointer-scanner
328 * like valgrind might get confused about stale references.
329 *
330 * @see nsTHashtable::EntryType for specification
331 */
332
333 template <class T>
334 class nsClearingPtrHashKey : public nsPtrHashKey<T> {
335 public:
nsClearingPtrHashKey(const T * aKey)336 explicit nsClearingPtrHashKey(const T* aKey) : nsPtrHashKey<T>(aKey) {}
nsClearingPtrHashKey(const nsClearingPtrHashKey<T> & aToCopy)337 nsClearingPtrHashKey(const nsClearingPtrHashKey<T>& aToCopy)
338 : nsPtrHashKey<T>(aToCopy) {}
~nsClearingPtrHashKey()339 ~nsClearingPtrHashKey() { nsPtrHashKey<T>::mKey = nullptr; }
340 };
341
342 typedef nsClearingPtrHashKey<const void> nsClearingVoidPtrHashKey;
343
344 /**
345 * hashkey wrapper using a function pointer KeyType
346 *
347 * @see nsTHashtable::EntryType for specification
348 */
349 template <class T>
350 class nsFuncPtrHashKey : public PLDHashEntryHdr {
351 public:
352 typedef T& KeyType;
353 typedef const T* KeyTypePointer;
354
nsFuncPtrHashKey(const T * aKey)355 explicit nsFuncPtrHashKey(const T* aKey) : mKey(*const_cast<T*>(aKey)) {}
nsFuncPtrHashKey(const nsFuncPtrHashKey<T> & aToCopy)356 nsFuncPtrHashKey(const nsFuncPtrHashKey<T>& aToCopy) : mKey(aToCopy.mKey) {}
~nsFuncPtrHashKey()357 ~nsFuncPtrHashKey() {}
358
GetKey()359 KeyType GetKey() const { return const_cast<T&>(mKey); }
KeyEquals(KeyTypePointer aKey)360 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mKey; }
361
KeyToPointer(KeyType aKey)362 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(KeyTypePointer aKey)363 static PLDHashNumber HashKey(KeyTypePointer aKey) {
364 return NS_PTR_TO_UINT32(*aKey) >> 2;
365 }
366 enum { ALLOW_MEMMOVE = true };
367
368 protected:
369 T mKey;
370 };
371
372 /**
373 * hashkey wrapper using nsID KeyType
374 *
375 * @see nsTHashtable::EntryType for specification
376 */
377 class nsIDHashKey : public PLDHashEntryHdr {
378 public:
379 typedef const nsID& KeyType;
380 typedef const nsID* KeyTypePointer;
381
nsIDHashKey(const nsID * aInID)382 explicit nsIDHashKey(const nsID* aInID) : mID(*aInID) {}
nsIDHashKey(const nsIDHashKey & aToCopy)383 nsIDHashKey(const nsIDHashKey& aToCopy) : mID(aToCopy.mID) {}
~nsIDHashKey()384 ~nsIDHashKey() {}
385
GetKey()386 KeyType GetKey() const { return mID; }
KeyEquals(KeyTypePointer aKey)387 bool KeyEquals(KeyTypePointer aKey) const { return aKey->Equals(mID); }
388
KeyToPointer(KeyType aKey)389 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(KeyTypePointer aKey)390 static PLDHashNumber HashKey(KeyTypePointer aKey) {
391 // Hash the nsID object's raw bytes.
392 return mozilla::HashBytes(aKey, sizeof(KeyType));
393 }
394
395 enum { ALLOW_MEMMOVE = true };
396
397 private:
398 const nsID mID;
399 };
400
401 /**
402 * hashkey wrapper for "dependent" const char*; this class does not "own"
403 * its string pointer.
404 *
405 * This class must only be used if the strings have a lifetime longer than
406 * the hashtable they occupy. This normally occurs only for static
407 * strings or strings that have been arena-allocated.
408 *
409 * @see nsTHashtable::EntryType for specification
410 */
411 class nsDepCharHashKey : public PLDHashEntryHdr {
412 public:
413 typedef const char* KeyType;
414 typedef const char* KeyTypePointer;
415
nsDepCharHashKey(const char * aKey)416 explicit nsDepCharHashKey(const char* aKey) : mKey(aKey) {}
nsDepCharHashKey(const nsDepCharHashKey & aToCopy)417 nsDepCharHashKey(const nsDepCharHashKey& aToCopy) : mKey(aToCopy.mKey) {}
~nsDepCharHashKey()418 ~nsDepCharHashKey() {}
419
GetKey()420 const char* GetKey() const { return mKey; }
KeyEquals(const char * aKey)421 bool KeyEquals(const char* aKey) const { return !strcmp(mKey, aKey); }
422
KeyToPointer(const char * aKey)423 static const char* KeyToPointer(const char* aKey) { return aKey; }
HashKey(const char * aKey)424 static PLDHashNumber HashKey(const char* aKey) {
425 return mozilla::HashString(aKey);
426 }
427 enum { ALLOW_MEMMOVE = true };
428
429 private:
430 const char* mKey;
431 };
432
433 /**
434 * hashkey wrapper for const char*; at construction, this class duplicates
435 * a string pointed to by the pointer so that it doesn't matter whether or not
436 * the string lives longer than the hash table.
437 */
438 class nsCharPtrHashKey : public PLDHashEntryHdr {
439 public:
440 typedef const char* KeyType;
441 typedef const char* KeyTypePointer;
442
nsCharPtrHashKey(const char * aKey)443 explicit nsCharPtrHashKey(const char* aKey) : mKey(strdup(aKey)) {}
nsCharPtrHashKey(const nsCharPtrHashKey & aToCopy)444 nsCharPtrHashKey(const nsCharPtrHashKey& aToCopy)
445 : mKey(strdup(aToCopy.mKey)) {}
446
nsCharPtrHashKey(nsCharPtrHashKey && aOther)447 nsCharPtrHashKey(nsCharPtrHashKey&& aOther) : mKey(aOther.mKey) {
448 aOther.mKey = nullptr;
449 }
450
~nsCharPtrHashKey()451 ~nsCharPtrHashKey() {
452 if (mKey) {
453 free(const_cast<char*>(mKey));
454 }
455 }
456
GetKey()457 const char* GetKey() const { return mKey; }
KeyEquals(KeyTypePointer aKey)458 bool KeyEquals(KeyTypePointer aKey) const { return !strcmp(mKey, aKey); }
459
KeyToPointer(KeyType aKey)460 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
HashKey(KeyTypePointer aKey)461 static PLDHashNumber HashKey(KeyTypePointer aKey) {
462 return mozilla::HashString(aKey);
463 }
464
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)465 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
466 return aMallocSizeOf(mKey);
467 }
468
469 enum { ALLOW_MEMMOVE = true };
470
471 private:
472 const char* mKey;
473 };
474
475 /**
476 * hashkey wrapper for const char16_t*; at construction, this class duplicates
477 * a string pointed to by the pointer so that it doesn't matter whether or not
478 * the string lives longer than the hash table.
479 */
480 class nsUnicharPtrHashKey : public PLDHashEntryHdr {
481 public:
482 typedef const char16_t* KeyType;
483 typedef const char16_t* KeyTypePointer;
484
nsUnicharPtrHashKey(const char16_t * aKey)485 explicit nsUnicharPtrHashKey(const char16_t* aKey) : mKey(NS_strdup(aKey)) {}
nsUnicharPtrHashKey(const nsUnicharPtrHashKey & aToCopy)486 nsUnicharPtrHashKey(const nsUnicharPtrHashKey& aToCopy)
487 : mKey(NS_strdup(aToCopy.mKey)) {}
488
nsUnicharPtrHashKey(nsUnicharPtrHashKey && aOther)489 nsUnicharPtrHashKey(nsUnicharPtrHashKey&& aOther) : mKey(aOther.mKey) {
490 aOther.mKey = nullptr;
491 }
492
~nsUnicharPtrHashKey()493 ~nsUnicharPtrHashKey() {
494 if (mKey) {
495 free(const_cast<char16_t*>(mKey));
496 }
497 }
498
GetKey()499 const char16_t* GetKey() const { return mKey; }
KeyEquals(KeyTypePointer aKey)500 bool KeyEquals(KeyTypePointer aKey) const { return !NS_strcmp(mKey, aKey); }
501
KeyToPointer(KeyType aKey)502 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
HashKey(KeyTypePointer aKey)503 static PLDHashNumber HashKey(KeyTypePointer aKey) {
504 return mozilla::HashString(aKey);
505 }
506
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)507 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
508 return aMallocSizeOf(mKey);
509 }
510
511 enum { ALLOW_MEMMOVE = true };
512
513 private:
514 const char16_t* mKey;
515 };
516
517 /**
518 * Hashtable key class to use with objects that support nsIHashable
519 */
520 class nsHashableHashKey : public PLDHashEntryHdr {
521 public:
522 typedef nsIHashable* KeyType;
523 typedef const nsIHashable* KeyTypePointer;
524
nsHashableHashKey(const nsIHashable * aKey)525 explicit nsHashableHashKey(const nsIHashable* aKey)
526 : mKey(const_cast<nsIHashable*>(aKey)) {}
nsHashableHashKey(const nsHashableHashKey & aToCopy)527 nsHashableHashKey(const nsHashableHashKey& aToCopy) : mKey(aToCopy.mKey) {}
~nsHashableHashKey()528 ~nsHashableHashKey() {}
529
GetKey()530 nsIHashable* GetKey() const { return mKey; }
531
KeyEquals(const nsIHashable * aKey)532 bool KeyEquals(const nsIHashable* aKey) const {
533 bool eq;
534 if (NS_SUCCEEDED(mKey->Equals(const_cast<nsIHashable*>(aKey), &eq))) {
535 return eq;
536 }
537 return false;
538 }
539
KeyToPointer(nsIHashable * aKey)540 static const nsIHashable* KeyToPointer(nsIHashable* aKey) { return aKey; }
HashKey(const nsIHashable * aKey)541 static PLDHashNumber HashKey(const nsIHashable* aKey) {
542 uint32_t code = 8888; // magic number if GetHashCode fails :-(
543 #ifdef DEBUG
544 nsresult rv =
545 #endif
546 const_cast<nsIHashable*>(aKey)->GetHashCode(&code);
547 NS_ASSERTION(NS_SUCCEEDED(rv), "GetHashCode should not throw!");
548 return code;
549 }
550
551 enum { ALLOW_MEMMOVE = true };
552
553 private:
554 nsCOMPtr<nsIHashable> mKey;
555 };
556
557 namespace mozilla {
558
559 template <typename T>
Hash(const T & aValue)560 PLDHashNumber Hash(const T& aValue) {
561 return aValue.Hash();
562 }
563
564 } // namespace mozilla
565
566 /**
567 * Hashtable key class to use with objects for which Hash() and operator==()
568 * are defined.
569 */
570 template <typename T>
571 class nsGenericHashKey : public PLDHashEntryHdr {
572 public:
573 typedef const T& KeyType;
574 typedef const T* KeyTypePointer;
575
nsGenericHashKey(KeyTypePointer aKey)576 explicit nsGenericHashKey(KeyTypePointer aKey) : mKey(*aKey) {}
nsGenericHashKey(const nsGenericHashKey<T> & aOther)577 nsGenericHashKey(const nsGenericHashKey<T>& aOther) : mKey(aOther.mKey) {}
578
GetKey()579 KeyType GetKey() const { return mKey; }
KeyEquals(KeyTypePointer aKey)580 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mKey; }
581
KeyToPointer(KeyType aKey)582 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(KeyTypePointer aKey)583 static PLDHashNumber HashKey(KeyTypePointer aKey) {
584 return ::mozilla::Hash(*aKey);
585 }
586 enum { ALLOW_MEMMOVE = true };
587
588 private:
589 T mKey;
590 };
591
592 #endif // nsTHashKeys_h__
593