LCOV - code coverage report
Current view: top level - dom/base - nsPropertyTable.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 81 134 60.4 %
Date: 2017-07-14 16:53:18 Functions: 11 18 61.1 %
Legend: Lines: hit not hit

          Line data    Source code
       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             :  * This Original Code has been modified by IBM Corporation. Modifications made by IBM
       8             :  * described herein are Copyright (c) International Business Machines Corporation, 2000.
       9             :  * Modifications to Mozilla code or documentation identified per MPL Section 3.3
      10             :  *
      11             :  * Date             Modified by     Description of modification
      12             :  * 04/20/2000       IBM Corp.      OS/2 VisualAge build.
      13             :  */
      14             : 
      15             : /**
      16             :  * nsPropertyTable allows a set of arbitrary key/value pairs to be stored
      17             :  * for any number of nodes, in a global hashtable rather than on the nodes
      18             :  * themselves.  Nodes can be any type of object; the hashtable keys are
      19             :  * nsIAtom pointers, and the values are void pointers.
      20             :  */
      21             : 
      22             : #include "nsPropertyTable.h"
      23             : 
      24             : #include "mozilla/MemoryReporting.h"
      25             : 
      26             : #include "PLDHashTable.h"
      27             : #include "nsError.h"
      28             : #include "nsIAtom.h"
      29             : 
      30             : struct PropertyListMapEntry : public PLDHashEntryHdr {
      31             :   const void  *key;
      32             :   void        *value;
      33             : };
      34             : 
      35             : //----------------------------------------------------------------------
      36             : 
      37             : class nsPropertyTable::PropertyList {
      38             : public:
      39             :   PropertyList(nsIAtom*           aName,
      40             :                NSPropertyDtorFunc aDtorFunc,
      41             :                void*              aDtorData,
      42             :                bool               aTransfer);
      43             :   ~PropertyList();
      44             : 
      45             :   // Removes the property associated with the given object, and destroys
      46             :   // the property value
      47             :   bool DeletePropertyFor(nsPropertyOwner aObject);
      48             : 
      49             :   // Destroy all remaining properties (without removing them)
      50             :   void Destroy();
      51             : 
      52       34853 :   bool Equals(nsIAtom *aPropertyName)
      53             :   {
      54       34853 :     return mName == aPropertyName;
      55             :   }
      56             : 
      57             :   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
      58             : 
      59             :   nsCOMPtr<nsIAtom>  mName;           // property name
      60             :   PLDHashTable       mObjectValueMap; // map of object/value pairs
      61             :   NSPropertyDtorFunc mDtorFunc;       // property specific value dtor function
      62             :   void*              mDtorData;       // pointer to pass to dtor
      63             :   bool               mTransfer;       // whether to transfer in
      64             :                                       // TransferOrDeleteAllPropertiesFor
      65             : 
      66             :   PropertyList*      mNext;
      67             : };
      68             : 
      69             : void
      70           0 : nsPropertyTable::DeleteAllProperties()
      71             : {
      72           0 :   while (mPropertyList) {
      73           0 :     PropertyList* tmp = mPropertyList;
      74             : 
      75           0 :     mPropertyList = mPropertyList->mNext;
      76           0 :     tmp->Destroy();
      77           0 :     delete tmp;
      78             :   }
      79           0 : }
      80             : 
      81             : void
      82           0 : nsPropertyTable::DeleteAllPropertiesFor(nsPropertyOwner aObject)
      83             : {
      84           0 :   for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
      85           0 :     prop->DeletePropertyFor(aObject);
      86             :   }
      87           0 : }
      88             : 
      89             : nsresult
      90           0 : nsPropertyTable::TransferOrDeleteAllPropertiesFor(nsPropertyOwner aObject,
      91             :                                                   nsPropertyTable *aOtherTable)
      92             : {
      93           0 :   nsresult rv = NS_OK;
      94           0 :   for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
      95           0 :     if (prop->mTransfer) {
      96             :       auto entry = static_cast<PropertyListMapEntry*>
      97           0 :                               (prop->mObjectValueMap.Search(aObject));
      98           0 :       if (entry) {
      99           0 :         rv = aOtherTable->SetProperty(aObject, prop->mName,
     100             :                                       entry->value, prop->mDtorFunc,
     101           0 :                                       prop->mDtorData, prop->mTransfer);
     102           0 :         if (NS_FAILED(rv)) {
     103           0 :           DeleteAllPropertiesFor(aObject);
     104           0 :           aOtherTable->DeleteAllPropertiesFor(aObject);
     105             : 
     106           0 :           break;
     107             :         }
     108             : 
     109           0 :         prop->mObjectValueMap.RemoveEntry(entry);
     110             :       }
     111             :     }
     112             :     else {
     113           0 :       prop->DeletePropertyFor(aObject);
     114             :     }
     115             :   }
     116             : 
     117           0 :   return rv;
     118             : }
     119             : 
     120             : void
     121           1 : nsPropertyTable::Enumerate(nsPropertyOwner aObject,
     122             :                            NSPropertyFunc aCallback, void *aData)
     123             : {
     124             :   PropertyList* prop;
     125           1 :   for (prop = mPropertyList; prop; prop = prop->mNext) {
     126             :     auto entry = static_cast<PropertyListMapEntry*>
     127           0 :                             (prop->mObjectValueMap.Search(aObject));
     128           0 :     if (entry) {
     129           0 :       aCallback(const_cast<void*>(aObject.get()), prop->mName, entry->value,
     130           0 :                 aData);
     131             :     }
     132             :   }
     133           1 : }
     134             : 
     135             : void
     136           0 : nsPropertyTable::EnumerateAll(NSPropertyFunc aCallBack, void* aData)
     137             : {
     138           0 :   for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
     139           0 :     for (auto iter = prop->mObjectValueMap.Iter(); !iter.Done(); iter.Next()) {
     140           0 :       auto entry = static_cast<PropertyListMapEntry*>(iter.Get());
     141           0 :       aCallBack(const_cast<void*>(entry->key), prop->mName, entry->value,
     142           0 :                 aData);
     143             :     }
     144             :   }
     145           0 : }
     146             : 
     147             : void*
     148        4912 : nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
     149             :                                      nsIAtom    *aPropertyName,
     150             :                                      bool        aRemove,
     151             :                                      nsresult   *aResult)
     152             : {
     153        4912 :   NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
     154        4912 :   nsresult rv = NS_PROPTABLE_PROP_NOT_THERE;
     155        4912 :   void *propValue = nullptr;
     156             : 
     157        4912 :   PropertyList* propertyList = GetPropertyListFor(aPropertyName);
     158        4912 :   if (propertyList) {
     159             :     auto entry = static_cast<PropertyListMapEntry*>
     160        2252 :                             (propertyList->mObjectValueMap.Search(aObject));
     161        2252 :     if (entry) {
     162         977 :       propValue = entry->value;
     163         977 :       if (aRemove) {
     164             :         // don't call propertyList->mDtorFunc.  That's the caller's job now.
     165          13 :         propertyList->mObjectValueMap.RemoveEntry(entry);
     166             :       }
     167         977 :       rv = NS_OK;
     168             :     }
     169             :   }
     170             : 
     171        4912 :   if (aResult)
     172         259 :     *aResult = rv;
     173             : 
     174        4912 :   return propValue;
     175             : }
     176             : 
     177             : nsresult
     178         402 : nsPropertyTable::SetPropertyInternal(nsPropertyOwner     aObject,
     179             :                                      nsIAtom            *aPropertyName,
     180             :                                      void               *aPropertyValue,
     181             :                                      NSPropertyDtorFunc  aPropDtorFunc,
     182             :                                      void               *aPropDtorData,
     183             :                                      bool                aTransfer,
     184             :                                      void              **aOldValue)
     185             : {
     186         402 :   NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
     187             : 
     188         402 :   PropertyList* propertyList = GetPropertyListFor(aPropertyName);
     189             : 
     190         402 :   if (propertyList) {
     191             :     // Make sure the dtor function and data and the transfer flag match
     192         652 :     if (aPropDtorFunc != propertyList->mDtorFunc ||
     193         652 :         aPropDtorData != propertyList->mDtorData ||
     194         326 :         aTransfer != propertyList->mTransfer) {
     195           0 :       NS_WARNING("Destructor/data mismatch while setting property");
     196           0 :       return NS_ERROR_INVALID_ARG;
     197             :     }
     198             : 
     199             :   } else {
     200          76 :     propertyList = new PropertyList(aPropertyName, aPropDtorFunc,
     201          76 :                                     aPropDtorData, aTransfer);
     202          76 :     propertyList->mNext = mPropertyList;
     203          76 :     mPropertyList = propertyList;
     204             :   }
     205             : 
     206             :   // The current property value (if there is one) is replaced and the current
     207             :   // value is destroyed
     208         402 :   nsresult result = NS_OK;
     209             :   auto entry = static_cast<PropertyListMapEntry*>
     210         402 :     (propertyList->mObjectValueMap.Add(aObject, mozilla::fallible));
     211         402 :   if (!entry)
     212           0 :     return NS_ERROR_OUT_OF_MEMORY;
     213             :   // A nullptr entry->key is the sign that the entry has just been allocated
     214             :   // for us.  If it's non-nullptr then we have an existing entry.
     215         402 :   if (entry->key) {
     216         257 :     if (aOldValue)
     217           0 :       *aOldValue = entry->value;
     218         257 :     else if (propertyList->mDtorFunc)
     219         257 :       propertyList->mDtorFunc(const_cast<void*>(entry->key), aPropertyName,
     220         257 :                               entry->value, propertyList->mDtorData);
     221         257 :     result = NS_PROPTABLE_PROP_OVERWRITTEN;
     222             :   }
     223         145 :   else if (aOldValue) {
     224           0 :     *aOldValue = nullptr;
     225             :   }
     226         402 :   entry->key = aObject;
     227         402 :   entry->value = aPropertyValue;
     228             : 
     229         402 :   return result;
     230             : }
     231             : 
     232             : nsresult
     233          35 : nsPropertyTable::DeleteProperty(nsPropertyOwner aObject,
     234             :                                 nsIAtom    *aPropertyName)
     235             : {
     236          35 :   NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
     237             : 
     238          35 :   PropertyList* propertyList = GetPropertyListFor(aPropertyName);
     239          35 :   if (propertyList) {
     240          17 :     if (propertyList->DeletePropertyFor(aObject))
     241          17 :       return NS_OK;
     242             :   }
     243             : 
     244          18 :   return NS_PROPTABLE_PROP_NOT_THERE;
     245             : }
     246             : 
     247             : nsPropertyTable::PropertyList*
     248        5349 : nsPropertyTable::GetPropertyListFor(nsIAtom* aPropertyName) const
     249             : {
     250             :   PropertyList* result;
     251             : 
     252       37607 :   for (result = mPropertyList; result; result = result->mNext) {
     253       34853 :     if (result->Equals(aPropertyName)) {
     254        2595 :       break;
     255             :     }
     256             :   }
     257             : 
     258        5349 :   return result;
     259             : }
     260             : 
     261             : //----------------------------------------------------------------------
     262             : 
     263          76 : nsPropertyTable::PropertyList::PropertyList(nsIAtom            *aName,
     264             :                                             NSPropertyDtorFunc  aDtorFunc,
     265             :                                             void               *aDtorData,
     266          76 :                                             bool                aTransfer)
     267             :   : mName(aName),
     268             :     mObjectValueMap(PLDHashTable::StubOps(), sizeof(PropertyListMapEntry)),
     269             :     mDtorFunc(aDtorFunc),
     270             :     mDtorData(aDtorData),
     271             :     mTransfer(aTransfer),
     272          76 :     mNext(nullptr)
     273             : {
     274          76 : }
     275             : 
     276           0 : nsPropertyTable::PropertyList::~PropertyList()
     277             : {
     278           0 : }
     279             : 
     280             : void
     281           0 : nsPropertyTable::PropertyList::Destroy()
     282             : {
     283             :   // Enumerate any remaining object/value pairs and destroy the value object.
     284           0 :   if (mDtorFunc) {
     285           0 :     for (auto iter = mObjectValueMap.Iter(); !iter.Done(); iter.Next()) {
     286           0 :       auto entry = static_cast<PropertyListMapEntry*>(iter.Get());
     287           0 :       mDtorFunc(const_cast<void*>(entry->key), mName, entry->value, mDtorData);
     288             :     }
     289             :   }
     290           0 : }
     291             : 
     292             : bool
     293          17 : nsPropertyTable::PropertyList::DeletePropertyFor(nsPropertyOwner aObject)
     294             : {
     295             :   auto entry =
     296          17 :     static_cast<PropertyListMapEntry*>(mObjectValueMap.Search(aObject));
     297          17 :   if (!entry)
     298           0 :     return false;
     299             : 
     300          17 :   void* value = entry->value;
     301          17 :   mObjectValueMap.RemoveEntry(entry);
     302             : 
     303          17 :   if (mDtorFunc)
     304          17 :     mDtorFunc(const_cast<void*>(aObject.get()), mName, value, mDtorData);
     305             : 
     306          17 :   return true;
     307             : }
     308             : 
     309             : size_t
     310          23 : nsPropertyTable::PropertyList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     311             : {
     312          23 :   size_t n = aMallocSizeOf(this);
     313          23 :   n += mObjectValueMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
     314          23 :   return n;
     315             : }
     316             : 
     317             : size_t
     318          21 : nsPropertyTable::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     319             : {
     320          21 :   size_t n = 0;
     321             : 
     322          44 :   for (PropertyList *prop = mPropertyList; prop; prop = prop->mNext) {
     323          23 :     n += prop->SizeOfIncludingThis(aMallocSizeOf);
     324             :   }
     325             : 
     326          21 :   return n;
     327             : }
     328             : 
     329             : size_t
     330           0 : nsPropertyTable::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     331             : {
     332           0 :   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
     333             : }
     334             : 
     335             : /* static */
     336             : void
     337           1 : nsPropertyTable::SupportsDtorFunc(void *aObject, nsIAtom *aPropertyName,
     338             :                                   void *aPropertyValue, void *aData)
     339             : {
     340           1 :   nsISupports *propertyValue = static_cast<nsISupports*>(aPropertyValue);
     341           1 :   NS_IF_RELEASE(propertyValue);
     342           1 : }

Generated by: LCOV version 1.13