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