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/. */
7 #ifndef nsTHashKeys_h__
8 #define nsTHashKeys_h__
11 #include "nsISupports.h"
13 #include "PLDHashTable.h"
17 #include "nsCRTGlue.h"
18 #include "nsUnicharUtils.h"
19 #include "nsPointerHashKeys.h"
27 #include "mozilla/HashFunctions.h"
31 // These are defined analogously to the HashString overloads in mfbt.
33 inline uint32_t HashString(const nsAString
& aStr
) {
34 return HashString(aStr
.BeginReading(), aStr
.Length());
37 inline uint32_t HashString(const nsACString
& aStr
) {
38 return HashString(aStr
.BeginReading(), aStr
.Length());
41 } // namespace mozilla
43 /** @file nsHashKeys.h
44 * standard HashKey classes for nsBaseHashtable and relatives. Each of these
45 * classes follows the nsTHashtable::EntryType specification
47 * Lightweight keytypes provided here:
55 * nsClearingPtrHashKey
57 * nsClearingVoidPtrHashKey
67 * hashkey wrapper using nsAString KeyType
69 * @see nsTHashtable::EntryType for specification
71 class nsStringHashKey
: public PLDHashEntryHdr
{
73 typedef const nsAString
& KeyType
;
74 typedef const nsAString
* KeyTypePointer
;
76 explicit nsStringHashKey(KeyTypePointer aStr
) : mStr(*aStr
) {}
77 nsStringHashKey(const nsStringHashKey
&) = delete;
78 nsStringHashKey(nsStringHashKey
&& aToMove
)
79 : PLDHashEntryHdr(std::move(aToMove
)), mStr(std::move(aToMove
.mStr
)) {}
80 ~nsStringHashKey() = default;
82 KeyType
GetKey() const { return mStr
; }
83 bool KeyEquals(const KeyTypePointer aKey
) const { return mStr
.Equals(*aKey
); }
85 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
86 static PLDHashNumber
HashKey(const KeyTypePointer aKey
) {
87 return mozilla::HashString(*aKey
);
90 #ifdef MOZILLA_INTERNAL_API
91 // To avoid double-counting, only measure the string if it is unshared.
92 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
93 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
97 enum { ALLOW_MEMMOVE
= true };
103 #ifdef MOZILLA_INTERNAL_API
106 * hashkey wrapper using nsAString KeyType
108 * This is internal-API only because nsCaseInsensitiveStringComparator is
111 * @see nsTHashtable::EntryType for specification
113 class nsStringCaseInsensitiveHashKey
: public PLDHashEntryHdr
{
115 typedef const nsAString
& KeyType
;
116 typedef const nsAString
* KeyTypePointer
;
118 explicit nsStringCaseInsensitiveHashKey(KeyTypePointer aStr
) : mStr(*aStr
) {
119 // take it easy just deal HashKey
122 nsStringCaseInsensitiveHashKey(const nsStringCaseInsensitiveHashKey
&) =
124 nsStringCaseInsensitiveHashKey(nsStringCaseInsensitiveHashKey
&& aToMove
)
125 : PLDHashEntryHdr(std::move(aToMove
)), mStr(std::move(aToMove
.mStr
)) {}
126 ~nsStringCaseInsensitiveHashKey() = default;
128 KeyType
GetKey() const { return mStr
; }
129 bool KeyEquals(const KeyTypePointer aKey
) const {
130 return mStr
.Equals(*aKey
, nsCaseInsensitiveStringComparator
);
133 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
134 static PLDHashNumber
HashKey(const KeyTypePointer aKey
) {
135 nsAutoString
tmKey(*aKey
);
137 return mozilla::HashString(tmKey
);
139 enum { ALLOW_MEMMOVE
= true };
141 // To avoid double-counting, only measure the string if it is unshared.
142 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
143 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
153 * hashkey wrapper using nsACString KeyType
155 * @see nsTHashtable::EntryType for specification
157 class nsCStringHashKey
: public PLDHashEntryHdr
{
159 typedef const nsACString
& KeyType
;
160 typedef const nsACString
* KeyTypePointer
;
162 explicit nsCStringHashKey(const nsACString
* aStr
) : mStr(*aStr
) {}
163 nsCStringHashKey(nsCStringHashKey
&& aOther
)
164 : PLDHashEntryHdr(std::move(aOther
)), mStr(std::move(aOther
.mStr
)) {}
165 ~nsCStringHashKey() = default;
167 KeyType
GetKey() const { return mStr
; }
168 bool KeyEquals(KeyTypePointer aKey
) const { return mStr
.Equals(*aKey
); }
170 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
171 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
172 return mozilla::HashString(*aKey
);
175 #ifdef MOZILLA_INTERNAL_API
176 // To avoid double-counting, only measure the string if it is unshared.
177 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
178 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
182 enum { ALLOW_MEMMOVE
= true };
185 const nsCString mStr
;
189 * hashkey wrapper using uint32_t KeyType
191 * @see nsTHashtable::EntryType for specification
193 class nsUint32HashKey
: public PLDHashEntryHdr
{
195 typedef const uint32_t& KeyType
;
196 typedef const uint32_t* KeyTypePointer
;
198 explicit nsUint32HashKey(KeyTypePointer aKey
) : mValue(*aKey
) {}
199 nsUint32HashKey(nsUint32HashKey
&& aOther
)
200 : PLDHashEntryHdr(std::move(aOther
)), mValue(std::move(aOther
.mValue
)) {}
201 ~nsUint32HashKey() = default;
203 KeyType
GetKey() const { return mValue
; }
204 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mValue
; }
206 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
207 static PLDHashNumber
HashKey(KeyTypePointer aKey
) { return *aKey
; }
208 enum { ALLOW_MEMMOVE
= true };
211 const uint32_t mValue
;
215 * hashkey wrapper using uint64_t KeyType
217 * @see nsTHashtable::EntryType for specification
219 class nsUint64HashKey
: public PLDHashEntryHdr
{
221 typedef const uint64_t& KeyType
;
222 typedef const uint64_t* KeyTypePointer
;
224 explicit nsUint64HashKey(KeyTypePointer aKey
) : mValue(*aKey
) {}
225 nsUint64HashKey(nsUint64HashKey
&& aOther
)
226 : PLDHashEntryHdr(std::move(aOther
)), mValue(std::move(aOther
.mValue
)) {}
227 ~nsUint64HashKey() = default;
229 KeyType
GetKey() const { return mValue
; }
230 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mValue
; }
232 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
233 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
234 return PLDHashNumber(*aKey
);
236 enum { ALLOW_MEMMOVE
= true };
239 const uint64_t mValue
;
243 * hashkey wrapper using float KeyType
245 * @see nsTHashtable::EntryType for specification
247 class nsFloatHashKey
: public PLDHashEntryHdr
{
249 typedef const float& KeyType
;
250 typedef const float* KeyTypePointer
;
252 explicit nsFloatHashKey(KeyTypePointer aKey
) : mValue(*aKey
) {}
253 nsFloatHashKey(nsFloatHashKey
&& aOther
)
254 : PLDHashEntryHdr(std::move(aOther
)), mValue(std::move(aOther
.mValue
)) {}
255 ~nsFloatHashKey() = default;
257 KeyType
GetKey() const { return mValue
; }
258 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mValue
; }
260 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
261 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
262 return *reinterpret_cast<const uint32_t*>(aKey
);
264 enum { ALLOW_MEMMOVE
= true };
271 * hashkey wrapper using intptr_t KeyType
273 * @see nsTHashtable::EntryType for specification
275 class IntPtrHashKey
: public PLDHashEntryHdr
{
277 typedef const intptr_t& KeyType
;
278 typedef const intptr_t* KeyTypePointer
;
280 explicit IntPtrHashKey(KeyTypePointer aKey
) : mValue(*aKey
) {}
281 IntPtrHashKey(IntPtrHashKey
&& aOther
)
282 : PLDHashEntryHdr(std::move(aOther
)), mValue(aOther
.mValue
) {}
283 ~IntPtrHashKey() = default;
285 KeyType
GetKey() const { return mValue
; }
286 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mValue
; }
288 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
289 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
290 return mozilla::HashGeneric(*aKey
);
292 enum { ALLOW_MEMMOVE
= true };
295 const intptr_t mValue
;
299 * hashkey wrapper using nsISupports* KeyType
301 * @see nsTHashtable::EntryType for specification
303 class nsISupportsHashKey
: public PLDHashEntryHdr
{
305 typedef nsISupports
* KeyType
;
306 typedef const nsISupports
* KeyTypePointer
;
308 explicit nsISupportsHashKey(const nsISupports
* aKey
)
309 : mSupports(const_cast<nsISupports
*>(aKey
)) {}
310 nsISupportsHashKey(nsISupportsHashKey
&& aOther
)
311 : PLDHashEntryHdr(std::move(aOther
)),
312 mSupports(std::move(aOther
.mSupports
)) {}
313 ~nsISupportsHashKey() = default;
315 KeyType
GetKey() const { return mSupports
; }
316 bool KeyEquals(KeyTypePointer aKey
) const { return aKey
== mSupports
; }
318 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
319 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
320 return NS_PTR_TO_UINT32(aKey
) >> 2;
322 enum { ALLOW_MEMMOVE
= true };
325 nsCOMPtr
<nsISupports
> mSupports
;
329 * hashkey wrapper using refcounted * KeyType
331 * @see nsTHashtable::EntryType for specification
334 class nsRefPtrHashKey
: public PLDHashEntryHdr
{
337 typedef const T
* KeyTypePointer
;
339 explicit nsRefPtrHashKey(const T
* aKey
) : mKey(const_cast<T
*>(aKey
)) {}
340 nsRefPtrHashKey(nsRefPtrHashKey
&& aOther
)
341 : PLDHashEntryHdr(std::move(aOther
)), mKey(std::move(aOther
.mKey
)) {}
342 ~nsRefPtrHashKey() = default;
344 KeyType
GetKey() const { return mKey
; }
345 bool KeyEquals(KeyTypePointer aKey
) const { return aKey
== mKey
; }
347 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
348 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
349 return NS_PTR_TO_UINT32(aKey
) >> 2;
351 enum { ALLOW_MEMMOVE
= true };
358 inline void ImplCycleCollectionTraverse(
359 nsCycleCollectionTraversalCallback
& aCallback
, nsRefPtrHashKey
<T
>& aField
,
360 const char* aName
, uint32_t aFlags
= 0) {
361 CycleCollectionNoteChild(aCallback
, aField
.GetKey(), aName
, aFlags
);
365 * hashkey wrapper using T* KeyType that sets key to nullptr upon
366 * destruction. Relevant only in cases where a memory pointer-scanner
367 * like valgrind might get confused about stale references.
369 * @see nsTHashtable::EntryType for specification
373 class nsClearingPtrHashKey
: public nsPtrHashKey
<T
> {
375 explicit nsClearingPtrHashKey(const T
* aKey
) : nsPtrHashKey
<T
>(aKey
) {}
376 nsClearingPtrHashKey(nsClearingPtrHashKey
&& aToMove
)
377 : nsPtrHashKey
<T
>(std::move(aToMove
)) {}
378 ~nsClearingPtrHashKey() { nsPtrHashKey
<T
>::mKey
= nullptr; }
381 typedef nsClearingPtrHashKey
<const void> nsClearingVoidPtrHashKey
;
384 * hashkey wrapper using a function pointer KeyType
386 * @see nsTHashtable::EntryType for specification
389 class nsFuncPtrHashKey
: public PLDHashEntryHdr
{
392 typedef const T
* KeyTypePointer
;
394 explicit nsFuncPtrHashKey(const T
* aKey
) : mKey(*const_cast<T
*>(aKey
)) {}
395 nsFuncPtrHashKey(const nsFuncPtrHashKey
<T
>& aToCopy
) : mKey(aToCopy
.mKey
) {}
396 ~nsFuncPtrHashKey() = default;
398 KeyType
GetKey() const { return const_cast<T
&>(mKey
); }
399 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mKey
; }
401 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
402 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
403 return NS_PTR_TO_UINT32(*aKey
) >> 2;
405 enum { ALLOW_MEMMOVE
= true };
412 * hashkey wrapper using nsID KeyType
414 * @see nsTHashtable::EntryType for specification
416 class nsIDHashKey
: public PLDHashEntryHdr
{
418 typedef const nsID
& KeyType
;
419 typedef const nsID
* KeyTypePointer
;
421 explicit nsIDHashKey(const nsID
* aInID
) : mID(*aInID
) {}
422 nsIDHashKey(nsIDHashKey
&& aOther
)
423 : PLDHashEntryHdr(std::move(aOther
)), mID(std::move(aOther
.mID
)) {}
424 ~nsIDHashKey() = default;
426 KeyType
GetKey() const { return mID
; }
427 bool KeyEquals(KeyTypePointer aKey
) const { return aKey
->Equals(mID
); }
429 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
430 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
431 // Hash the nsID object's raw bytes.
432 return mozilla::HashBytes(aKey
, sizeof(KeyType
));
435 enum { ALLOW_MEMMOVE
= true };
442 * hashkey wrapper using nsID* KeyType
444 * @see nsTHashtable::EntryType for specification
446 class nsIDPointerHashKey
: public PLDHashEntryHdr
{
448 typedef const nsID
* KeyType
;
449 typedef const nsID
* KeyTypePointer
;
451 explicit nsIDPointerHashKey(const nsID
* aInID
) : mID(aInID
) {}
452 nsIDPointerHashKey(nsIDPointerHashKey
&& aOther
)
453 : PLDHashEntryHdr(std::move(aOther
)), mID(aOther
.mID
) {}
454 ~nsIDPointerHashKey() = default;
456 KeyType
GetKey() const { return mID
; }
457 bool KeyEquals(KeyTypePointer aKey
) const { return aKey
->Equals(*mID
); }
459 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
460 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
461 // Hash the nsID object's raw bytes.
462 return mozilla::HashBytes(aKey
, sizeof(*aKey
));
465 enum { ALLOW_MEMMOVE
= true };
472 * hashkey wrapper for "dependent" const char*; this class does not "own"
473 * its string pointer.
475 * This class must only be used if the strings have a lifetime longer than
476 * the hashtable they occupy. This normally occurs only for static
477 * strings or strings that have been arena-allocated.
479 * @see nsTHashtable::EntryType for specification
481 class nsDepCharHashKey
: public PLDHashEntryHdr
{
483 typedef const char* KeyType
;
484 typedef const char* KeyTypePointer
;
486 explicit nsDepCharHashKey(const char* aKey
) : mKey(aKey
) {}
487 nsDepCharHashKey(nsDepCharHashKey
&& aOther
)
488 : PLDHashEntryHdr(std::move(aOther
)), mKey(std::move(aOther
.mKey
)) {}
489 ~nsDepCharHashKey() = default;
491 const char* GetKey() const { return mKey
; }
492 bool KeyEquals(const char* aKey
) const { return !strcmp(mKey
, aKey
); }
494 static const char* KeyToPointer(const char* aKey
) { return aKey
; }
495 static PLDHashNumber
HashKey(const char* aKey
) {
496 return mozilla::HashString(aKey
);
498 enum { ALLOW_MEMMOVE
= true };
505 * hashkey wrapper for const char*; at construction, this class duplicates
506 * a string pointed to by the pointer so that it doesn't matter whether or not
507 * the string lives longer than the hash table.
509 class nsCharPtrHashKey
: public PLDHashEntryHdr
{
511 typedef const char* KeyType
;
512 typedef const char* KeyTypePointer
;
514 explicit nsCharPtrHashKey(const char* aKey
) : mKey(strdup(aKey
)) {}
516 nsCharPtrHashKey(const nsCharPtrHashKey
&) = delete;
517 nsCharPtrHashKey(nsCharPtrHashKey
&& aOther
)
518 : PLDHashEntryHdr(std::move(aOther
)), mKey(aOther
.mKey
) {
519 aOther
.mKey
= nullptr;
522 ~nsCharPtrHashKey() {
524 free(const_cast<char*>(mKey
));
528 const char* GetKey() const { return mKey
; }
529 bool KeyEquals(KeyTypePointer aKey
) const { return !strcmp(mKey
, aKey
); }
531 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
532 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
533 return mozilla::HashString(aKey
);
536 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
537 return aMallocSizeOf(mKey
);
540 enum { ALLOW_MEMMOVE
= true };
547 * hashkey wrapper for const char16_t*; at construction, this class duplicates
548 * a string pointed to by the pointer so that it doesn't matter whether or not
549 * the string lives longer than the hash table.
551 class nsUnicharPtrHashKey
: public PLDHashEntryHdr
{
553 typedef const char16_t
* KeyType
;
554 typedef const char16_t
* KeyTypePointer
;
556 explicit nsUnicharPtrHashKey(const char16_t
* aKey
) : mKey(NS_xstrdup(aKey
)) {}
557 nsUnicharPtrHashKey(const nsUnicharPtrHashKey
& aToCopy
) = delete;
558 nsUnicharPtrHashKey(nsUnicharPtrHashKey
&& aOther
)
559 : PLDHashEntryHdr(std::move(aOther
)), mKey(aOther
.mKey
) {
560 aOther
.mKey
= nullptr;
563 ~nsUnicharPtrHashKey() {
565 free(const_cast<char16_t
*>(mKey
));
569 const char16_t
* GetKey() const { return mKey
; }
570 bool KeyEquals(KeyTypePointer aKey
) const { return !NS_strcmp(mKey
, aKey
); }
572 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
573 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
574 return mozilla::HashString(aKey
);
577 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
578 return aMallocSizeOf(mKey
);
581 enum { ALLOW_MEMMOVE
= true };
584 const char16_t
* mKey
;
589 template <typename T
>
590 PLDHashNumber
Hash(const T
& aValue
) {
591 return aValue
.Hash();
594 } // namespace mozilla
597 * Hashtable key class to use with objects for which Hash() and operator==()
600 template <typename T
>
601 class nsGenericHashKey
: public PLDHashEntryHdr
{
603 typedef const T
& KeyType
;
604 typedef const T
* KeyTypePointer
;
606 explicit nsGenericHashKey(KeyTypePointer aKey
) : mKey(*aKey
) {}
607 nsGenericHashKey(const nsGenericHashKey
&) = delete;
608 nsGenericHashKey(nsGenericHashKey
&& aOther
)
609 : PLDHashEntryHdr(std::move(aOther
)), mKey(std::move(aOther
.mKey
)) {}
611 KeyType
GetKey() const { return mKey
; }
612 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mKey
; }
614 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
615 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
616 return ::mozilla::Hash(*aKey
);
618 enum { ALLOW_MEMMOVE
= true };
624 #endif // nsTHashKeys_h__