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