Bumping gaia.json for 8 gaia revision(s) a=gaia-bump
[gecko.git] / dom / base / nsPropertyTable.cpp
blobe49549b8055921195ced2eaca18701d39aa65389
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim:cindent:ts=2:et:sw=2:
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This Original Code has been modified by IBM Corporation. Modifications made by IBM
9 * described herein are Copyright (c) International Business Machines Corporation, 2000.
10 * Modifications to Mozilla code or documentation identified per MPL Section 3.3
12 * Date Modified by Description of modification
13 * 04/20/2000 IBM Corp. OS/2 VisualAge build.
16 /**
17 * nsPropertyTable allows a set of arbitrary key/value pairs to be stored
18 * for any number of nodes, in a global hashtable rather than on the nodes
19 * themselves. Nodes can be any type of object; the hashtable keys are
20 * nsIAtom pointers, and the values are void pointers.
23 #include "nsPropertyTable.h"
25 #include "mozilla/MemoryReporting.h"
27 #include "pldhash.h"
28 #include "nsError.h"
29 #include "nsIAtom.h"
31 struct PropertyListMapEntry : public PLDHashEntryHdr {
32 const void *key;
33 void *value;
36 //----------------------------------------------------------------------
38 class nsPropertyTable::PropertyList {
39 public:
40 PropertyList(nsIAtom* aName,
41 NSPropertyDtorFunc aDtorFunc,
42 void* aDtorData,
43 bool aTransfer);
44 ~PropertyList();
46 // Removes the property associated with the given object, and destroys
47 // the property value
48 bool DeletePropertyFor(nsPropertyOwner aObject);
50 // Destroy all remaining properties (without removing them)
51 void Destroy();
53 bool Equals(nsIAtom *aPropertyName)
55 return mName == aPropertyName;
58 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
60 nsCOMPtr<nsIAtom> mName; // property name
61 PLDHashTable mObjectValueMap; // map of object/value pairs
62 NSPropertyDtorFunc mDtorFunc; // property specific value dtor function
63 void* mDtorData; // pointer to pass to dtor
64 bool mTransfer; // whether to transfer in
65 // TransferOrDeleteAllPropertiesFor
67 PropertyList* mNext;
70 void
71 nsPropertyTable::DeleteAllProperties()
73 while (mPropertyList) {
74 PropertyList* tmp = mPropertyList;
76 mPropertyList = mPropertyList->mNext;
77 tmp->Destroy();
78 delete tmp;
82 void
83 nsPropertyTable::DeleteAllPropertiesFor(nsPropertyOwner aObject)
85 for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
86 prop->DeletePropertyFor(aObject);
90 nsresult
91 nsPropertyTable::TransferOrDeleteAllPropertiesFor(nsPropertyOwner aObject,
92 nsPropertyTable *aOtherTable)
94 nsresult rv = NS_OK;
95 for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
96 if (prop->mTransfer) {
97 PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
98 (PL_DHashTableLookup(&prop->mObjectValueMap, aObject));
99 if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
100 rv = aOtherTable->SetProperty(aObject, prop->mName,
101 entry->value, prop->mDtorFunc,
102 prop->mDtorData, prop->mTransfer);
103 if (NS_FAILED(rv)) {
104 DeleteAllPropertiesFor(aObject);
105 aOtherTable->DeleteAllPropertiesFor(aObject);
107 break;
110 PL_DHashTableRawRemove(&prop->mObjectValueMap, entry);
113 else {
114 prop->DeletePropertyFor(aObject);
118 return rv;
121 void
122 nsPropertyTable::Enumerate(nsPropertyOwner aObject,
123 NSPropertyFunc aCallback, void *aData)
125 PropertyList* prop;
126 for (prop = mPropertyList; prop; prop = prop->mNext) {
127 PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
128 (PL_DHashTableLookup(&prop->mObjectValueMap, aObject));
129 if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
130 aCallback(const_cast<void*>(aObject.get()), prop->mName, entry->value,
131 aData);
136 struct PropertyEnumeratorData
138 nsIAtom* mName;
139 NSPropertyFunc mCallBack;
140 void* mData;
143 static PLDHashOperator
144 PropertyEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
145 uint32_t aNumber, void* aArg)
147 PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(aHdr);
148 PropertyEnumeratorData* data = static_cast<PropertyEnumeratorData*>(aArg);
149 data->mCallBack(const_cast<void*>(entry->key), data->mName, entry->value,
150 data->mData);
151 return PL_DHASH_NEXT;
154 void
155 nsPropertyTable::EnumerateAll(NSPropertyFunc aCallBack, void* aData)
157 for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
158 PropertyEnumeratorData data = { prop->mName, aCallBack, aData };
159 PL_DHashTableEnumerate(&prop->mObjectValueMap, PropertyEnumerator, &data);
163 void*
164 nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
165 nsIAtom *aPropertyName,
166 bool aRemove,
167 nsresult *aResult)
169 NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
170 nsresult rv = NS_PROPTABLE_PROP_NOT_THERE;
171 void *propValue = nullptr;
173 PropertyList* propertyList = GetPropertyListFor(aPropertyName);
174 if (propertyList) {
175 PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
176 (PL_DHashTableLookup(&propertyList->mObjectValueMap, aObject));
177 if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
178 propValue = entry->value;
179 if (aRemove) {
180 // don't call propertyList->mDtorFunc. That's the caller's job now.
181 PL_DHashTableRawRemove(&propertyList->mObjectValueMap, entry);
183 rv = NS_OK;
187 if (aResult)
188 *aResult = rv;
190 return propValue;
193 nsresult
194 nsPropertyTable::SetPropertyInternal(nsPropertyOwner aObject,
195 nsIAtom *aPropertyName,
196 void *aPropertyValue,
197 NSPropertyDtorFunc aPropDtorFunc,
198 void *aPropDtorData,
199 bool aTransfer,
200 void **aOldValue)
202 NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
204 PropertyList* propertyList = GetPropertyListFor(aPropertyName);
206 if (propertyList) {
207 // Make sure the dtor function and data and the transfer flag match
208 if (aPropDtorFunc != propertyList->mDtorFunc ||
209 aPropDtorData != propertyList->mDtorData ||
210 aTransfer != propertyList->mTransfer) {
211 NS_WARNING("Destructor/data mismatch while setting property");
212 return NS_ERROR_INVALID_ARG;
215 } else {
216 propertyList = new PropertyList(aPropertyName, aPropDtorFunc,
217 aPropDtorData, aTransfer);
218 if (!propertyList || !propertyList->mObjectValueMap.ops) {
219 delete propertyList;
220 return NS_ERROR_OUT_OF_MEMORY;
223 propertyList->mNext = mPropertyList;
224 mPropertyList = propertyList;
227 // The current property value (if there is one) is replaced and the current
228 // value is destroyed
229 nsresult result = NS_OK;
230 PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
231 (PL_DHashTableAdd(&propertyList->mObjectValueMap, aObject));
232 if (!entry)
233 return NS_ERROR_OUT_OF_MEMORY;
234 // A nullptr entry->key is the sign that the entry has just been allocated
235 // for us. If it's non-nullptr then we have an existing entry.
236 if (entry->key) {
237 if (aOldValue)
238 *aOldValue = entry->value;
239 else if (propertyList->mDtorFunc)
240 propertyList->mDtorFunc(const_cast<void*>(entry->key), aPropertyName,
241 entry->value, propertyList->mDtorData);
242 result = NS_PROPTABLE_PROP_OVERWRITTEN;
244 else if (aOldValue) {
245 *aOldValue = nullptr;
247 entry->key = aObject;
248 entry->value = aPropertyValue;
250 return result;
253 nsresult
254 nsPropertyTable::DeleteProperty(nsPropertyOwner aObject,
255 nsIAtom *aPropertyName)
257 NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
259 PropertyList* propertyList = GetPropertyListFor(aPropertyName);
260 if (propertyList) {
261 if (propertyList->DeletePropertyFor(aObject))
262 return NS_OK;
265 return NS_PROPTABLE_PROP_NOT_THERE;
268 nsPropertyTable::PropertyList*
269 nsPropertyTable::GetPropertyListFor(nsIAtom* aPropertyName) const
271 PropertyList* result;
273 for (result = mPropertyList; result; result = result->mNext) {
274 if (result->Equals(aPropertyName)) {
275 break;
279 return result;
282 //----------------------------------------------------------------------
284 nsPropertyTable::PropertyList::PropertyList(nsIAtom *aName,
285 NSPropertyDtorFunc aDtorFunc,
286 void *aDtorData,
287 bool aTransfer)
288 : mName(aName),
289 mDtorFunc(aDtorFunc),
290 mDtorData(aDtorData),
291 mTransfer(aTransfer),
292 mNext(nullptr)
294 PL_DHashTableInit(&mObjectValueMap, PL_DHashGetStubOps(), this,
295 sizeof(PropertyListMapEntry));
298 nsPropertyTable::PropertyList::~PropertyList()
300 PL_DHashTableFinish(&mObjectValueMap);
304 static PLDHashOperator
305 DestroyPropertyEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
306 uint32_t number, void *arg)
308 nsPropertyTable::PropertyList *propList =
309 static_cast<nsPropertyTable::PropertyList*>(table->data);
310 PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(hdr);
312 propList->mDtorFunc(const_cast<void*>(entry->key), propList->mName,
313 entry->value, propList->mDtorData);
314 return PL_DHASH_NEXT;
317 void
318 nsPropertyTable::PropertyList::Destroy()
320 // Enumerate any remaining object/value pairs and destroy the value object
321 if (mDtorFunc)
322 PL_DHashTableEnumerate(&mObjectValueMap, DestroyPropertyEnumerator,
323 nullptr);
326 bool
327 nsPropertyTable::PropertyList::DeletePropertyFor(nsPropertyOwner aObject)
329 PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
330 (PL_DHashTableLookup(&mObjectValueMap, aObject));
331 if (!PL_DHASH_ENTRY_IS_BUSY(entry))
332 return false;
334 void* value = entry->value;
335 PL_DHashTableRawRemove(&mObjectValueMap, entry);
337 if (mDtorFunc)
338 mDtorFunc(const_cast<void*>(aObject.get()), mName, value, mDtorData);
340 return true;
343 size_t
344 nsPropertyTable::PropertyList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
346 size_t n = aMallocSizeOf(this);
347 n += PL_DHashTableSizeOfExcludingThis(&mObjectValueMap, nullptr, aMallocSizeOf);
348 return n;
351 size_t
352 nsPropertyTable::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
354 size_t n = 0;
356 for (PropertyList *prop = mPropertyList; prop; prop = prop->mNext) {
357 n += prop->SizeOfIncludingThis(aMallocSizeOf);
360 return n;
363 size_t
364 nsPropertyTable::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
366 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
369 /* static */
370 void
371 nsPropertyTable::SupportsDtorFunc(void *aObject, nsIAtom *aPropertyName,
372 void *aPropertyValue, void *aData)
374 nsISupports *propertyValue = static_cast<nsISupports*>(aPropertyValue);
375 NS_IF_RELEASE(propertyValue);