Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / xpcom / ds / nsHashKeys.h
blob2231293f667f0f819c67a08420db8a20233abe75
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__
10 #include "nsID.h"
11 #include "nsISupports.h"
12 #include "nsCOMPtr.h"
13 #include "PLDHashTable.h"
14 #include <new>
16 #include "nsString.h"
17 #include "nsCRTGlue.h"
18 #include "nsUnicharUtils.h"
19 #include "nsPointerHashKeys.h"
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include <type_traits>
26 #include <utility>
28 #include "mozilla/HashFunctions.h"
30 namespace mozilla {
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:
49 * nsStringHashKey
50 * nsCStringHashKey
51 * nsUint32HashKey
52 * nsUint64HashKey
53 * nsFloatHashKey
54 * IntPtrHashKey
55 * nsPtrHashKey
56 * nsVoidPtrHashKey
57 * nsISupportsHashKey
58 * nsIDHashKey
59 * nsDepCharHashKey
60 * nsCharPtrHashKey
61 * nsUnicharPtrHashKey
62 * nsGenericHashKey
65 /**
66 * hashkey wrapper using nsAString KeyType
68 * @see nsTHashtable::EntryType for specification
70 class nsStringHashKey : public PLDHashEntryHdr {
71 public:
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);
94 #endif
96 enum { ALLOW_MEMMOVE = true };
98 private:
99 nsString mStr;
102 #ifdef MOZILLA_INTERNAL_API
104 namespace mozilla::detail {
106 template <class CharT, bool Unicode = true>
107 struct comparatorTraits {};
109 template <>
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,
114 aRhsLength);
118 template <>
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,
123 aRhsLength);
127 template <>
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,
132 aRhsLength);
136 } // namespace mozilla::detail
139 * This is internal-API only because nsCaseInsensitive{C}StringComparator is
140 * internal-only.
142 * @see nsTHashtable::EntryType for specification
145 template <typename T, bool Unicode>
146 class nsTStringCaseInsensitiveHashKey : public PLDHashEntryHdr {
147 public:
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&) =
156 delete;
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);
170 ToLowerCase(tmKey);
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);
180 private:
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 {
199 public:
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);
221 #endif
223 enum { ALLOW_MEMMOVE = true };
225 private:
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 {
237 public:
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 };
255 private:
256 const T mValue;
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 {
279 public:
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 };
297 private:
298 const float mValue;
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 {
314 public:
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 };
332 private:
333 nsCOMPtr<nsISupports> mSupports;
337 * hashkey wrapper using refcounted * KeyType
339 * @see nsTHashtable::EntryType for specification
341 template <class T>
342 class nsRefPtrHashKey : public PLDHashEntryHdr {
343 public:
344 using KeyType = T*;
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 };
360 private:
361 RefPtr<T> mKey;
364 template <class T>
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
376 template <class T>
377 class nsFuncPtrHashKey : public PLDHashEntryHdr {
378 public:
379 typedef T& KeyType;
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 };
395 protected:
396 T mKey;
400 * hashkey wrapper using nsID KeyType
402 * @see nsTHashtable::EntryType for specification
404 class nsIDHashKey : public PLDHashEntryHdr {
405 public:
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 };
425 private:
426 nsID mID;
430 * hashkey wrapper using nsID* KeyType
432 * @see nsTHashtable::EntryType for specification
434 class nsIDPointerHashKey : public PLDHashEntryHdr {
435 public:
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 };
455 private:
456 const nsID* mID;
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 {
470 public:
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 };
488 private:
489 const char* mKey;
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 {
498 public:
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() {
511 if (mKey) {
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 };
530 private:
531 const char* mKey;
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 {
540 public:
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() {
552 if (mKey) {
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 };
571 private:
572 const char16_t* mKey;
575 namespace mozilla {
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==()
586 * are defined.
588 template <typename T>
589 class nsGenericHashKey : public PLDHashEntryHdr {
590 public:
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 };
608 private:
609 T mKey;
612 #endif // nsTHashKeys_h__