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 nsInterfaceHashtable_h__
8 #define nsInterfaceHashtable_h__
9
10 #include "nsBaseHashtable.h"
11 #include "nsHashKeys.h"
12 #include "nsCOMPtr.h"
13
14 /**
15 * templated hashtable class maps keys to interface pointers.
16 * See nsBaseHashtable for complete declaration.
17 * @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
18 * for a complete specification.
19 * @param Interface the interface-type being wrapped
20 * @see nsDataHashtable, nsClassHashtable
21 */
22 template<class KeyClass, class Interface>
23 class nsInterfaceHashtable
24 : public nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>
25 {
26 public:
27 typedef typename KeyClass::KeyType KeyType;
28 typedef Interface* UserDataType;
29 typedef nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*> base_type;
30
nsInterfaceHashtable()31 nsInterfaceHashtable() {}
nsInterfaceHashtable(uint32_t aInitLength)32 explicit nsInterfaceHashtable(uint32_t aInitLength)
33 : nsBaseHashtable<KeyClass, nsCOMPtr<Interface>, Interface*>(aInitLength)
34 {
35 }
36
37 /**
38 * @copydoc nsBaseHashtable::Get
39 * @param aData This is an XPCOM getter, so aData is already_addrefed.
40 * If the key doesn't exist, aData will be set to nullptr.
41 */
42 bool Get(KeyType aKey, UserDataType* aData) const;
43
44 /**
45 * @copydoc nsBaseHashtable::Get
46 */
47 already_AddRefed<Interface> Get(KeyType aKey) const;
48
49 /**
50 * Gets a weak reference to the hashtable entry.
51 * @param aFound If not nullptr, will be set to true if the entry is found,
52 * to false otherwise.
53 * @return The entry, or nullptr if not found. Do not release this pointer!
54 */
55 Interface* GetWeak(KeyType aKey, bool* aFound = nullptr) const;
56 };
57
58 template<typename K, typename T>
59 inline void
ImplCycleCollectionUnlink(nsInterfaceHashtable<K,T> & aField)60 ImplCycleCollectionUnlink(nsInterfaceHashtable<K, T>& aField)
61 {
62 aField.Clear();
63 }
64
65 template<typename K, typename T>
66 inline void
67 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
68 const nsInterfaceHashtable<K, T>& aField,
69 const char* aName,
70 uint32_t aFlags = 0)
71 {
72 for (auto iter = aField.ConstIter(); !iter.Done(); iter.Next()) {
73 CycleCollectionNoteChild(aCallback, iter.UserData(), aName, aFlags);
74 }
75 }
76
77 //
78 // nsInterfaceHashtable definitions
79 //
80
81 template<class KeyClass, class Interface>
82 bool
Get(KeyType aKey,UserDataType * aInterface)83 nsInterfaceHashtable<KeyClass, Interface>::Get(KeyType aKey,
84 UserDataType* aInterface) const
85 {
86 typename base_type::EntryType* ent = this->GetEntry(aKey);
87
88 if (ent) {
89 if (aInterface) {
90 *aInterface = ent->mData;
91
92 NS_IF_ADDREF(*aInterface);
93 }
94
95 return true;
96 }
97
98 // if the key doesn't exist, set *aInterface to null
99 // so that it is a valid XPCOM getter
100 if (aInterface) {
101 *aInterface = nullptr;
102 }
103
104 return false;
105 }
106
107 template<class KeyClass, class Interface>
108 already_AddRefed<Interface>
Get(KeyType aKey)109 nsInterfaceHashtable<KeyClass, Interface>::Get(KeyType aKey) const
110 {
111 typename base_type::EntryType* ent = this->GetEntry(aKey);
112 if (!ent) {
113 return nullptr;
114 }
115
116 nsCOMPtr<Interface> copy = ent->mData;
117 return copy.forget();
118 }
119
120 template<class KeyClass, class Interface>
121 Interface*
GetWeak(KeyType aKey,bool * aFound)122 nsInterfaceHashtable<KeyClass, Interface>::GetWeak(KeyType aKey,
123 bool* aFound) const
124 {
125 typename base_type::EntryType* ent = this->GetEntry(aKey);
126
127 if (ent) {
128 if (aFound) {
129 *aFound = true;
130 }
131
132 return ent->mData;
133 }
134
135 // Key does not exist, return nullptr and set aFound to false
136 if (aFound) {
137 *aFound = false;
138 }
139 return nullptr;
140 }
141
142 #endif // nsInterfaceHashtable_h__
143