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