content/base/src/nsPropertyTable.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim:cindent:ts=2:et:sw=2:
     3  *
     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/.
     7  *
     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
    11  *
    12  * Date             Modified by     Description of modification
    13  * 04/20/2000       IBM Corp.      OS/2 VisualAge build.
    14  */
    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.
    21  */
    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;
    34 };
    36 //----------------------------------------------------------------------
    38 class nsPropertyTable::PropertyList {
    39 public:
    40   PropertyList(nsIAtom*           aName,
    41                NSPropertyDtorFunc aDtorFunc,
    42                void*              aDtorData,
    43                bool               aTransfer) NS_HIDDEN;
    44   ~PropertyList() NS_HIDDEN;
    46   // Removes the property associated with the given object, and destroys
    47   // the property value
    48   NS_HIDDEN_(bool) DeletePropertyFor(nsPropertyOwner aObject);
    50   // Destroy all remaining properties (without removing them)
    51   NS_HIDDEN_(void) Destroy();
    53   NS_HIDDEN_(bool) Equals(nsIAtom *aPropertyName)
    54   {
    55     return mName == aPropertyName;
    56   }
    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;
    68 };
    70 void
    71 nsPropertyTable::DeleteAllProperties()
    72 {
    73   while (mPropertyList) {
    74     PropertyList* tmp = mPropertyList;
    76     mPropertyList = mPropertyList->mNext;
    77     tmp->Destroy();
    78     delete tmp;
    79   }
    80 }
    82 void
    83 nsPropertyTable::DeleteAllPropertiesFor(nsPropertyOwner aObject)
    84 {
    85   for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
    86     prop->DeletePropertyFor(aObject);
    87   }
    88 }
    90 nsresult
    91 nsPropertyTable::TransferOrDeleteAllPropertiesFor(nsPropertyOwner aObject,
    92                                                   nsPropertyTable *aOtherTable)
    93 {
    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_DHashTableOperate(&prop->mObjectValueMap, aObject,
    99                                PL_DHASH_LOOKUP));
   100       if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
   101         rv = aOtherTable->SetProperty(aObject, prop->mName,
   102                                       entry->value, prop->mDtorFunc,
   103                                       prop->mDtorData, prop->mTransfer);
   104         if (NS_FAILED(rv)) {
   105           DeleteAllPropertiesFor(aObject);
   106           aOtherTable->DeleteAllPropertiesFor(aObject);
   108           break;
   109         }
   111         PL_DHashTableRawRemove(&prop->mObjectValueMap, entry);
   112       }
   113     }
   114     else {
   115       prop->DeletePropertyFor(aObject);
   116     }
   117   }
   119   return rv;
   120 }
   122 void
   123 nsPropertyTable::Enumerate(nsPropertyOwner aObject,
   124                            NSPropertyFunc aCallback, void *aData)
   125 {
   126   PropertyList* prop;
   127   for (prop = mPropertyList; prop; prop = prop->mNext) {
   128     PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
   129       (PL_DHashTableOperate(&prop->mObjectValueMap, aObject, PL_DHASH_LOOKUP));
   130     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
   131       aCallback(const_cast<void*>(aObject.get()), prop->mName, entry->value,
   132                  aData);
   133     }
   134   }
   135 }
   137 struct PropertyEnumeratorData
   138 {
   139   nsIAtom* mName;
   140   NSPropertyFunc mCallBack;
   141   void* mData;
   142 };
   144 static PLDHashOperator
   145 PropertyEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
   146                    uint32_t aNumber, void* aArg)
   147 {
   148   PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(aHdr);
   149   PropertyEnumeratorData* data = static_cast<PropertyEnumeratorData*>(aArg);
   150   data->mCallBack(const_cast<void*>(entry->key), data->mName, entry->value,
   151                   data->mData);
   152   return PL_DHASH_NEXT;
   153 }
   155 void
   156 nsPropertyTable::EnumerateAll(NSPropertyFunc aCallBack, void* aData)
   157 {
   158   for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
   159     PropertyEnumeratorData data = { prop->mName, aCallBack, aData };
   160     PL_DHashTableEnumerate(&prop->mObjectValueMap, PropertyEnumerator, &data);
   161   }
   162 }
   164 void*
   165 nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
   166                                      nsIAtom    *aPropertyName,
   167                                      bool        aRemove,
   168                                      nsresult   *aResult)
   169 {
   170   NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
   171   nsresult rv = NS_PROPTABLE_PROP_NOT_THERE;
   172   void *propValue = nullptr;
   174   PropertyList* propertyList = GetPropertyListFor(aPropertyName);
   175   if (propertyList) {
   176     PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
   177                                              (PL_DHashTableOperate(&propertyList->mObjectValueMap, aObject,
   178                              PL_DHASH_LOOKUP));
   179     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
   180       propValue = entry->value;
   181       if (aRemove) {
   182         // don't call propertyList->mDtorFunc.  That's the caller's job now.
   183         PL_DHashTableRawRemove(&propertyList->mObjectValueMap, entry);
   184       }
   185       rv = NS_OK;
   186     }
   187   }
   189   if (aResult)
   190     *aResult = rv;
   192   return propValue;
   193 }
   195 nsresult
   196 nsPropertyTable::SetPropertyInternal(nsPropertyOwner     aObject,
   197                                      nsIAtom            *aPropertyName,
   198                                      void               *aPropertyValue,
   199                                      NSPropertyDtorFunc  aPropDtorFunc,
   200                                      void               *aPropDtorData,
   201                                      bool                aTransfer,
   202                                      void              **aOldValue)
   203 {
   204   NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
   206   PropertyList* propertyList = GetPropertyListFor(aPropertyName);
   208   if (propertyList) {
   209     // Make sure the dtor function and data and the transfer flag match
   210     if (aPropDtorFunc != propertyList->mDtorFunc ||
   211         aPropDtorData != propertyList->mDtorData ||
   212         aTransfer != propertyList->mTransfer) {
   213       NS_WARNING("Destructor/data mismatch while setting property");
   214       return NS_ERROR_INVALID_ARG;
   215     }
   217   } else {
   218     propertyList = new PropertyList(aPropertyName, aPropDtorFunc,
   219                                     aPropDtorData, aTransfer);
   220     if (!propertyList || !propertyList->mObjectValueMap.ops) {
   221       delete propertyList;
   222       return NS_ERROR_OUT_OF_MEMORY;
   223     }
   225     propertyList->mNext = mPropertyList;
   226     mPropertyList = propertyList;
   227   }
   229   // The current property value (if there is one) is replaced and the current
   230   // value is destroyed
   231   nsresult result = NS_OK;
   232   PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
   233                                            (PL_DHashTableOperate(&propertyList->mObjectValueMap, aObject, PL_DHASH_ADD));
   234   if (!entry)
   235     return NS_ERROR_OUT_OF_MEMORY;
   236   // A nullptr entry->key is the sign that the entry has just been allocated
   237   // for us.  If it's non-nullptr then we have an existing entry.
   238   if (entry->key) {
   239     if (aOldValue)
   240       *aOldValue = entry->value;
   241     else if (propertyList->mDtorFunc)
   242       propertyList->mDtorFunc(const_cast<void*>(entry->key), aPropertyName,
   243                               entry->value, propertyList->mDtorData);
   244     result = NS_PROPTABLE_PROP_OVERWRITTEN;
   245   }
   246   else if (aOldValue) {
   247     *aOldValue = nullptr;
   248   }
   249   entry->key = aObject;
   250   entry->value = aPropertyValue;
   252   return result;
   253 }
   255 nsresult
   256 nsPropertyTable::DeleteProperty(nsPropertyOwner aObject,
   257                                 nsIAtom    *aPropertyName)
   258 {
   259   NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
   261   PropertyList* propertyList = GetPropertyListFor(aPropertyName);
   262   if (propertyList) {
   263     if (propertyList->DeletePropertyFor(aObject))
   264       return NS_OK;
   265   }
   267   return NS_PROPTABLE_PROP_NOT_THERE;
   268 }
   270 nsPropertyTable::PropertyList*
   271 nsPropertyTable::GetPropertyListFor(nsIAtom* aPropertyName) const
   272 {
   273   PropertyList* result;
   275   for (result = mPropertyList; result; result = result->mNext) {
   276     if (result->Equals(aPropertyName)) {
   277       break;
   278     }
   279   }
   281   return result;
   282 }
   284 //----------------------------------------------------------------------
   286 nsPropertyTable::PropertyList::PropertyList(nsIAtom            *aName,
   287                                             NSPropertyDtorFunc  aDtorFunc,
   288                                             void               *aDtorData,
   289                                             bool                aTransfer)
   290   : mName(aName),
   291     mDtorFunc(aDtorFunc),
   292     mDtorData(aDtorData),
   293     mTransfer(aTransfer),
   294     mNext(nullptr)
   295 {
   296   PL_DHashTableInit(&mObjectValueMap, PL_DHashGetStubOps(), this,
   297                     sizeof(PropertyListMapEntry), 16);
   298 }
   300 nsPropertyTable::PropertyList::~PropertyList()
   301 {
   302   PL_DHashTableFinish(&mObjectValueMap);
   303 }
   306 static PLDHashOperator
   307 DestroyPropertyEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
   308                           uint32_t number, void *arg)
   309 {
   310   nsPropertyTable::PropertyList *propList =
   311       static_cast<nsPropertyTable::PropertyList*>(table->data);
   312   PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(hdr);
   314   propList->mDtorFunc(const_cast<void*>(entry->key), propList->mName,
   315                       entry->value, propList->mDtorData);
   316   return PL_DHASH_NEXT;
   317 }
   319 void
   320 nsPropertyTable::PropertyList::Destroy()
   321 {
   322   // Enumerate any remaining object/value pairs and destroy the value object
   323   if (mDtorFunc)
   324     PL_DHashTableEnumerate(&mObjectValueMap, DestroyPropertyEnumerator,
   325                            nullptr);
   326 }
   328 bool
   329 nsPropertyTable::PropertyList::DeletePropertyFor(nsPropertyOwner aObject)
   330 {
   331   PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
   332                                            (PL_DHashTableOperate(&mObjectValueMap, aObject, PL_DHASH_LOOKUP));
   333   if (!PL_DHASH_ENTRY_IS_BUSY(entry))
   334     return false;
   336   void* value = entry->value;
   337   PL_DHashTableRawRemove(&mObjectValueMap, entry);
   339   if (mDtorFunc)
   340     mDtorFunc(const_cast<void*>(aObject.get()), mName, value, mDtorData);
   342   return true;
   343 }
   345 size_t
   346 nsPropertyTable::PropertyList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
   347 {
   348   size_t n = aMallocSizeOf(this);
   349   n += PL_DHashTableSizeOfExcludingThis(&mObjectValueMap, nullptr, aMallocSizeOf);
   350   return n;
   351 }
   353 size_t
   354 nsPropertyTable::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   355 {
   356   size_t n = 0;
   358   for (PropertyList *prop = mPropertyList; prop; prop = prop->mNext) {
   359     n += prop->SizeOfIncludingThis(aMallocSizeOf);
   360   }
   362   return n;
   363 }
   365 /* static */
   366 void
   367 nsPropertyTable::SupportsDtorFunc(void *aObject, nsIAtom *aPropertyName,
   368                                   void *aPropertyValue, void *aData)
   369 {
   370   nsISupports *propertyValue = static_cast<nsISupports*>(aPropertyValue);
   371   NS_IF_RELEASE(propertyValue);
   372 }

mercurial