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"
25 #include <type_traits>
28 #include "mozilla/HashFunctions.h"
32 // These are defined analogously to the HashString overloads in mfbt.
34 inline uint32_t HashString(const nsAString
& aStr
) {
35 return HashString(aStr
.BeginReading(), aStr
.Length());
38 inline uint32_t HashString(const nsACString
& aStr
) {
39 return HashString(aStr
.BeginReading(), aStr
.Length());
42 } // namespace mozilla
44 /** @file nsHashKeys.h
45 * standard HashKey classes for nsBaseHashtable and relatives. Each of these
46 * classes follows the nsTHashtable::EntryType specification
48 * Lightweight keytypes provided here:
66 * hashkey wrapper using nsAString KeyType
68 * @see nsTHashtable::EntryType for specification
70 class nsStringHashKey
: public PLDHashEntryHdr
{
72 typedef const nsAString
& KeyType
;
73 typedef const nsAString
* KeyTypePointer
;
75 explicit nsStringHashKey(KeyTypePointer aStr
) : mStr(*aStr
) {}
76 nsStringHashKey(const nsStringHashKey
&) = delete;
77 nsStringHashKey(nsStringHashKey
&& aToMove
)
78 : PLDHashEntryHdr(std::move(aToMove
)), mStr(std::move(aToMove
.mStr
)) {}
79 ~nsStringHashKey() = default;
81 KeyType
GetKey() const { return mStr
; }
82 bool KeyEquals(const KeyTypePointer aKey
) const { return mStr
.Equals(*aKey
); }
84 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
85 static PLDHashNumber
HashKey(const KeyTypePointer aKey
) {
86 return mozilla::HashString(*aKey
);
89 #ifdef MOZILLA_INTERNAL_API
90 // To avoid double-counting, only measure the string if it is unshared.
91 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
92 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
96 enum { ALLOW_MEMMOVE
= true };
102 #ifdef MOZILLA_INTERNAL_API
104 namespace mozilla::detail
{
106 template <class CharT
, bool Unicode
= true>
107 struct comparatorTraits
{};
110 struct comparatorTraits
<char, false> {
111 static int caseInsensitiveCompare(const char* aLhs
, const char* aRhs
,
112 size_t aLhsLength
, size_t aRhsLength
) {
113 return nsCaseInsensitiveCStringComparator(aLhs
, aRhs
, aLhsLength
,
119 struct comparatorTraits
<char, true> {
120 static int caseInsensitiveCompare(const char* aLhs
, const char* aRhs
,
121 size_t aLhsLength
, size_t aRhsLength
) {
122 return nsCaseInsensitiveUTF8StringComparator(aLhs
, aRhs
, aLhsLength
,
128 struct comparatorTraits
<char16_t
, true> {
129 static int caseInsensitiveCompare(const char16_t
* aLhs
, const char16_t
* aRhs
,
130 size_t aLhsLength
, size_t aRhsLength
) {
131 return nsCaseInsensitiveStringComparator(aLhs
, aRhs
, aLhsLength
,
136 } // namespace mozilla::detail
139 * This is internal-API only because nsCaseInsensitive{C}StringComparator is
142 * @see nsTHashtable::EntryType for specification
145 template <typename T
, bool Unicode
>
146 class nsTStringCaseInsensitiveHashKey
: public PLDHashEntryHdr
{
148 typedef const nsTSubstring
<T
>& KeyType
;
149 typedef const nsTSubstring
<T
>* KeyTypePointer
;
151 explicit nsTStringCaseInsensitiveHashKey(KeyTypePointer aStr
) : mStr(*aStr
) {
152 // take it easy just deal HashKey
155 nsTStringCaseInsensitiveHashKey(const nsTStringCaseInsensitiveHashKey
&) =
157 nsTStringCaseInsensitiveHashKey(nsTStringCaseInsensitiveHashKey
&& aToMove
)
158 : PLDHashEntryHdr(std::move(aToMove
)), mStr(std::move(aToMove
.mStr
)) {}
159 ~nsTStringCaseInsensitiveHashKey() = default;
161 KeyType
GetKey() const { return mStr
; }
162 bool KeyEquals(const KeyTypePointer aKey
) const {
163 using comparator
= typename
mozilla::detail::comparatorTraits
<T
, Unicode
>;
164 return mStr
.Equals(*aKey
, comparator::caseInsensitiveCompare
);
167 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
168 static PLDHashNumber
HashKey(const KeyTypePointer aKey
) {
169 nsTAutoString
<T
> tmKey(*aKey
);
171 return mozilla::HashString(tmKey
);
173 enum { ALLOW_MEMMOVE
= true };
175 // To avoid double-counting, only measure the string if it is unshared.
176 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
177 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
181 const nsTString
<T
> mStr
;
184 using nsStringCaseInsensitiveHashKey
=
185 nsTStringCaseInsensitiveHashKey
<char16_t
, true>;
186 using nsCStringASCIICaseInsensitiveHashKey
=
187 nsTStringCaseInsensitiveHashKey
<char, false>;
188 using nsCStringUTF8CaseInsensitiveHashKey
=
189 nsTStringCaseInsensitiveHashKey
<char, true>;
191 #endif // MOZILLA_INTERNAL_API
194 * hashkey wrapper using nsACString KeyType
196 * @see nsTHashtable::EntryType for specification
198 class nsCStringHashKey
: public PLDHashEntryHdr
{
200 typedef const nsACString
& KeyType
;
201 typedef const nsACString
* KeyTypePointer
;
203 explicit nsCStringHashKey(const nsACString
* aStr
) : mStr(*aStr
) {}
204 nsCStringHashKey(nsCStringHashKey
&& aOther
)
205 : PLDHashEntryHdr(std::move(aOther
)), mStr(std::move(aOther
.mStr
)) {}
206 ~nsCStringHashKey() = default;
208 KeyType
GetKey() const { return mStr
; }
209 bool KeyEquals(KeyTypePointer aKey
) const { return mStr
.Equals(*aKey
); }
211 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
212 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
213 return mozilla::HashString(*aKey
);
216 #ifdef MOZILLA_INTERNAL_API
217 // To avoid double-counting, only measure the string if it is unshared.
218 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
219 return GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
223 enum { ALLOW_MEMMOVE
= true };
226 const nsCString mStr
;
230 * hashkey wrapper using integral or enum KeyTypes
232 * @see nsTHashtable::EntryType for specification
234 template <typename T
,
235 std::enable_if_t
<std::is_integral_v
<T
> || std::is_enum_v
<T
>, int> = 0>
236 class nsIntegralHashKey
: public PLDHashEntryHdr
{
238 using KeyType
= const T
&;
239 using KeyTypePointer
= const T
*;
241 explicit nsIntegralHashKey(KeyTypePointer aKey
) : mValue(*aKey
) {}
242 nsIntegralHashKey(nsIntegralHashKey
&& aOther
) noexcept
243 : PLDHashEntryHdr(std::move(aOther
)), mValue(aOther
.mValue
) {}
244 ~nsIntegralHashKey() = default;
246 KeyType
GetKey() const { return mValue
; }
247 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mValue
; }
249 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
250 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
251 return mozilla::HashGeneric(*aKey
);
253 enum { ALLOW_MEMMOVE
= true };
260 * hashkey wrapper using uint32_t KeyType
262 * @see nsTHashtable::EntryType for specification
264 using nsUint32HashKey
= nsIntegralHashKey
<uint32_t>;
267 * hashkey wrapper using uint64_t KeyType
269 * @see nsTHashtable::EntryType for specification
271 using nsUint64HashKey
= nsIntegralHashKey
<uint64_t>;
274 * hashkey wrapper using float KeyType
276 * @see nsTHashtable::EntryType for specification
278 class nsFloatHashKey
: public PLDHashEntryHdr
{
280 typedef const float& KeyType
;
281 typedef const float* KeyTypePointer
;
283 explicit nsFloatHashKey(KeyTypePointer aKey
) : mValue(*aKey
) {}
284 nsFloatHashKey(nsFloatHashKey
&& aOther
)
285 : PLDHashEntryHdr(std::move(aOther
)), mValue(std::move(aOther
.mValue
)) {}
286 ~nsFloatHashKey() = default;
288 KeyType
GetKey() const { return mValue
; }
289 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mValue
; }
291 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
292 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
293 return *reinterpret_cast<const uint32_t*>(aKey
);
295 enum { ALLOW_MEMMOVE
= true };
302 * hashkey wrapper using intptr_t KeyType
304 * @see nsTHashtable::EntryType for specification
306 using IntPtrHashKey
= nsIntegralHashKey
<intptr_t>;
309 * hashkey wrapper using nsISupports* KeyType
311 * @see nsTHashtable::EntryType for specification
313 class nsISupportsHashKey
: public PLDHashEntryHdr
{
315 using KeyType
= nsISupports
*;
316 using KeyTypePointer
= const nsISupports
*;
318 explicit nsISupportsHashKey(const nsISupports
* aKey
)
319 : mSupports(const_cast<nsISupports
*>(aKey
)) {}
320 nsISupportsHashKey(nsISupportsHashKey
&& aOther
) = default;
321 ~nsISupportsHashKey() = default;
323 KeyType
GetKey() const { return mSupports
; }
324 bool KeyEquals(KeyTypePointer aKey
) const { return aKey
== mSupports
; }
326 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
327 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
328 return mozilla::HashGeneric(aKey
);
330 enum { ALLOW_MEMMOVE
= true };
333 nsCOMPtr
<nsISupports
> mSupports
;
337 * hashkey wrapper using refcounted * KeyType
339 * @see nsTHashtable::EntryType for specification
342 class nsRefPtrHashKey
: public PLDHashEntryHdr
{
345 using KeyTypePointer
= const T
*;
347 explicit nsRefPtrHashKey(const T
* aKey
) : mKey(const_cast<T
*>(aKey
)) {}
348 nsRefPtrHashKey(nsRefPtrHashKey
&& aOther
) = default;
349 ~nsRefPtrHashKey() = default;
351 KeyType
GetKey() const { return mKey
; }
352 bool KeyEquals(KeyTypePointer aKey
) const { return aKey
== mKey
; }
354 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
355 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
356 return mozilla::HashGeneric(aKey
);
358 enum { ALLOW_MEMMOVE
= true };
365 inline void ImplCycleCollectionTraverse(
366 nsCycleCollectionTraversalCallback
& aCallback
, nsRefPtrHashKey
<T
>& aField
,
367 const char* aName
, uint32_t aFlags
= 0) {
368 CycleCollectionNoteChild(aCallback
, aField
.GetKey(), aName
, aFlags
);
372 * hashkey wrapper using a function pointer KeyType
374 * @see nsTHashtable::EntryType for specification
377 class nsFuncPtrHashKey
: public PLDHashEntryHdr
{
380 typedef const T
* KeyTypePointer
;
382 explicit nsFuncPtrHashKey(const T
* aKey
) : mKey(*const_cast<T
*>(aKey
)) {}
383 nsFuncPtrHashKey(const nsFuncPtrHashKey
<T
>& aToCopy
) : mKey(aToCopy
.mKey
) {}
384 ~nsFuncPtrHashKey() = default;
386 KeyType
GetKey() const { return const_cast<T
&>(mKey
); }
387 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mKey
; }
389 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
390 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
391 return mozilla::HashGeneric(*aKey
);
393 enum { ALLOW_MEMMOVE
= true };
400 * hashkey wrapper using nsID KeyType
402 * @see nsTHashtable::EntryType for specification
404 class nsIDHashKey
: public PLDHashEntryHdr
{
406 typedef const nsID
& KeyType
;
407 typedef const nsID
* KeyTypePointer
;
409 explicit nsIDHashKey(const nsID
* aInID
) : mID(*aInID
) {}
410 nsIDHashKey(nsIDHashKey
&& aOther
)
411 : PLDHashEntryHdr(std::move(aOther
)), mID(std::move(aOther
.mID
)) {}
412 ~nsIDHashKey() = default;
414 KeyType
GetKey() const { return mID
; }
415 bool KeyEquals(KeyTypePointer aKey
) const { return aKey
->Equals(mID
); }
417 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
418 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
419 // Hash the nsID object's raw bytes.
420 return mozilla::HashBytes(aKey
, sizeof(KeyType
));
423 enum { ALLOW_MEMMOVE
= true };
430 * hashkey wrapper using nsID* KeyType
432 * @see nsTHashtable::EntryType for specification
434 class nsIDPointerHashKey
: public PLDHashEntryHdr
{
436 typedef const nsID
* KeyType
;
437 typedef const nsID
* KeyTypePointer
;
439 explicit nsIDPointerHashKey(const nsID
* aInID
) : mID(aInID
) {}
440 nsIDPointerHashKey(nsIDPointerHashKey
&& aOther
)
441 : PLDHashEntryHdr(std::move(aOther
)), mID(aOther
.mID
) {}
442 ~nsIDPointerHashKey() = default;
444 KeyType
GetKey() const { return mID
; }
445 bool KeyEquals(KeyTypePointer aKey
) const { return aKey
->Equals(*mID
); }
447 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
448 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
449 // Hash the nsID object's raw bytes.
450 return mozilla::HashBytes(aKey
, sizeof(*aKey
));
453 enum { ALLOW_MEMMOVE
= true };
460 * hashkey wrapper for "dependent" const char*; this class does not "own"
461 * its string pointer.
463 * This class must only be used if the strings have a lifetime longer than
464 * the hashtable they occupy. This normally occurs only for static
465 * strings or strings that have been arena-allocated.
467 * @see nsTHashtable::EntryType for specification
469 class nsDepCharHashKey
: public PLDHashEntryHdr
{
471 typedef const char* KeyType
;
472 typedef const char* KeyTypePointer
;
474 explicit nsDepCharHashKey(const char* aKey
) : mKey(aKey
) {}
475 nsDepCharHashKey(nsDepCharHashKey
&& aOther
)
476 : PLDHashEntryHdr(std::move(aOther
)), mKey(std::move(aOther
.mKey
)) {}
477 ~nsDepCharHashKey() = default;
479 const char* GetKey() const { return mKey
; }
480 bool KeyEquals(const char* aKey
) const { return !strcmp(mKey
, aKey
); }
482 static const char* KeyToPointer(const char* aKey
) { return aKey
; }
483 static PLDHashNumber
HashKey(const char* aKey
) {
484 return mozilla::HashString(aKey
);
486 enum { ALLOW_MEMMOVE
= true };
493 * hashkey wrapper for const char*; at construction, this class duplicates
494 * a string pointed to by the pointer so that it doesn't matter whether or not
495 * the string lives longer than the hash table.
497 class nsCharPtrHashKey
: public PLDHashEntryHdr
{
499 typedef const char* KeyType
;
500 typedef const char* KeyTypePointer
;
502 explicit nsCharPtrHashKey(const char* aKey
) : mKey(strdup(aKey
)) {}
504 nsCharPtrHashKey(const nsCharPtrHashKey
&) = delete;
505 nsCharPtrHashKey(nsCharPtrHashKey
&& aOther
)
506 : PLDHashEntryHdr(std::move(aOther
)), mKey(aOther
.mKey
) {
507 aOther
.mKey
= nullptr;
510 ~nsCharPtrHashKey() {
512 free(const_cast<char*>(mKey
));
516 const char* GetKey() const { return mKey
; }
517 bool KeyEquals(KeyTypePointer aKey
) const { return !strcmp(mKey
, aKey
); }
519 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
520 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
521 return mozilla::HashString(aKey
);
524 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
525 return aMallocSizeOf(mKey
);
528 enum { ALLOW_MEMMOVE
= true };
535 * hashkey wrapper for const char16_t*; at construction, this class duplicates
536 * a string pointed to by the pointer so that it doesn't matter whether or not
537 * the string lives longer than the hash table.
539 class nsUnicharPtrHashKey
: public PLDHashEntryHdr
{
541 typedef const char16_t
* KeyType
;
542 typedef const char16_t
* KeyTypePointer
;
544 explicit nsUnicharPtrHashKey(const char16_t
* aKey
) : mKey(NS_xstrdup(aKey
)) {}
545 nsUnicharPtrHashKey(const nsUnicharPtrHashKey
& aToCopy
) = delete;
546 nsUnicharPtrHashKey(nsUnicharPtrHashKey
&& aOther
)
547 : PLDHashEntryHdr(std::move(aOther
)), mKey(aOther
.mKey
) {
548 aOther
.mKey
= nullptr;
551 ~nsUnicharPtrHashKey() {
553 free(const_cast<char16_t
*>(mKey
));
557 const char16_t
* GetKey() const { return mKey
; }
558 bool KeyEquals(KeyTypePointer aKey
) const { return !NS_strcmp(mKey
, aKey
); }
560 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return aKey
; }
561 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
562 return mozilla::HashString(aKey
);
565 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const {
566 return aMallocSizeOf(mKey
);
569 enum { ALLOW_MEMMOVE
= true };
572 const char16_t
* mKey
;
577 template <typename T
>
578 PLDHashNumber
Hash(const T
& aValue
) {
579 return aValue
.Hash();
582 } // namespace mozilla
585 * Hashtable key class to use with objects for which Hash() and operator==()
588 template <typename T
>
589 class nsGenericHashKey
: public PLDHashEntryHdr
{
591 typedef const T
& KeyType
;
592 typedef const T
* KeyTypePointer
;
594 explicit nsGenericHashKey(KeyTypePointer aKey
) : mKey(*aKey
) {}
595 nsGenericHashKey(const nsGenericHashKey
&) = delete;
596 nsGenericHashKey(nsGenericHashKey
&& aOther
)
597 : PLDHashEntryHdr(std::move(aOther
)), mKey(std::move(aOther
.mKey
)) {}
599 KeyType
GetKey() const { return mKey
; }
600 bool KeyEquals(KeyTypePointer aKey
) const { return *aKey
== mKey
; }
602 static KeyTypePointer
KeyToPointer(KeyType aKey
) { return &aKey
; }
603 static PLDHashNumber
HashKey(KeyTypePointer aKey
) {
604 return ::mozilla::Hash(*aKey
);
606 enum { ALLOW_MEMMOVE
= true };
612 #endif // nsTHashKeys_h__