LCOV - code coverage report
Current view: top level - xpcom/ds - nsCOMArray.h (source / functions) Hit Total Coverage
Test: output.info Lines: 71 113 62.8 %
Date: 2017-07-14 16:53:18 Functions: 150 554 27.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             : #ifndef nsCOMArray_h__
       8             : #define nsCOMArray_h__
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : #include "mozilla/ArrayIterator.h"
      12             : #include "mozilla/MemoryReporting.h"
      13             : #include "mozilla/ReverseIterator.h"
      14             : 
      15             : #include "nsCycleCollectionNoteChild.h"
      16             : #include "nsTArray.h"
      17             : #include "nsISupports.h"
      18             : 
      19             : // See below for the definition of nsCOMArray<T>
      20             : 
      21             : // a class that's nsISupports-specific, so that we can contain the
      22             : // work of this class in the XPCOM dll
      23             : class nsCOMArray_base
      24             : {
      25             :   friend class nsArrayBase;
      26             : protected:
      27        1308 :   nsCOMArray_base() {}
      28          30 :   explicit nsCOMArray_base(int32_t aCount) : mArray(aCount) {}
      29             :   nsCOMArray_base(const nsCOMArray_base& aOther);
      30             :   ~nsCOMArray_base();
      31             : 
      32             :   int32_t IndexOf(nsISupports* aObject, uint32_t aStartIndex = 0) const;
      33           0 :   bool Contains(nsISupports* aObject) const
      34             :   {
      35           0 :     return IndexOf(aObject) != -1;
      36             :   }
      37             : 
      38             :   int32_t IndexOfObject(nsISupports* aObject) const;
      39             :   bool ContainsObject(nsISupports* aObject) const
      40             :   {
      41             :     return IndexOfObject(aObject) != -1;
      42             :   }
      43             : 
      44             :   typedef bool (*nsBaseArrayEnumFunc)(void* aElement, void* aData);
      45             : 
      46             :   // enumerate through the array with a callback.
      47             :   bool EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const;
      48             : 
      49             :   bool EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const;
      50             : 
      51             :   typedef int (*nsBaseArrayComparatorFunc)(nsISupports* aElement1,
      52             :                                            nsISupports* aElement2,
      53             :                                            void* aData);
      54             : 
      55             :   struct nsCOMArrayComparatorContext
      56             :   {
      57             :     nsBaseArrayComparatorFunc mComparatorFunc;
      58             :     void* mData;
      59             :   };
      60             : 
      61             :   static int nsCOMArrayComparator(const void* aElement1, const void* aElement2,
      62             :                                   void* aData);
      63             :   void Sort(nsBaseArrayComparatorFunc aFunc, void* aData);
      64             : 
      65             :   bool InsertObjectAt(nsISupports* aObject, int32_t aIndex);
      66             :   void InsertElementAt(uint32_t aIndex, nsISupports* aElement);
      67             :   void InsertElementAt(uint32_t aIndex, already_AddRefed<nsISupports> aElement);
      68             :   bool InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex);
      69             :   void InsertElementsAt(uint32_t aIndex, const nsCOMArray_base& aElements);
      70             :   void InsertElementsAt(uint32_t aIndex, nsISupports* const* aElements,
      71             :                         uint32_t aCount);
      72             :   void ReplaceObjectAt(nsISupports* aObject, int32_t aIndex);
      73             :   void ReplaceElementAt(uint32_t aIndex, nsISupports* aElement)
      74             :   {
      75             :     nsISupports* oldElement = mArray[aIndex];
      76             :     NS_IF_ADDREF(mArray[aIndex] = aElement);
      77             :     NS_IF_RELEASE(oldElement);
      78             :   }
      79        3840 :   bool AppendObject(nsISupports* aObject)
      80             :   {
      81        3840 :     return InsertObjectAt(aObject, Count());
      82             :   }
      83           3 :   void AppendElement(nsISupports* aElement)
      84             :   {
      85           3 :     InsertElementAt(Length(), aElement);
      86           3 :   }
      87          45 :   void AppendElement(already_AddRefed<nsISupports> aElement)
      88             :   {
      89          45 :     InsertElementAt(Length(), mozilla::Move(aElement));
      90          45 :   }
      91             : 
      92         758 :   bool AppendObjects(const nsCOMArray_base& aObjects)
      93             :   {
      94         758 :     return InsertObjectsAt(aObjects, Count());
      95             :   }
      96           0 :   void AppendElements(const nsCOMArray_base& aElements)
      97             :   {
      98           0 :     return InsertElementsAt(Length(), aElements);
      99             :   }
     100             :   void AppendElements(nsISupports* const* aElements, uint32_t aCount)
     101             :   {
     102             :     return InsertElementsAt(Length(), aElements, aCount);
     103             :   }
     104             :   bool RemoveObject(nsISupports* aObject);
     105           0 :   nsISupports** Elements() { return mArray.Elements(); }
     106           1 :   void SwapElements(nsCOMArray_base& aOther)
     107             :   {
     108           1 :     mArray.SwapElements(aOther.mArray);
     109           1 :   }
     110             : 
     111             :   void Adopt(nsISupports** aElements, uint32_t aCount);
     112             :   uint32_t Forget(nsISupports*** aElements);
     113             : public:
     114             :   // elements in the array (including null elements!)
     115        7216 :   int32_t Count() const { return mArray.Length(); }
     116             :   // nsTArray-compatible version
     117        1466 :   uint32_t Length() const { return mArray.Length(); }
     118          47 :   bool IsEmpty() const { return mArray.IsEmpty(); }
     119             : 
     120             :   // If the array grows, the newly created entries will all be null;
     121             :   // if the array shrinks, the excess entries will all be released.
     122             :   bool SetCount(int32_t aNewCount);
     123             :   // nsTArray-compatible version
     124           0 :   void TruncateLength(uint32_t aNewLength)
     125             :   {
     126           0 :     if (mArray.Length() > aNewLength) {
     127           0 :       RemoveElementsAt(aNewLength, mArray.Length() - aNewLength);
     128             :     }
     129           0 :   }
     130             : 
     131             :   // remove all elements in the array, and call NS_RELEASE on each one
     132             :   void Clear();
     133             : 
     134       10472 :   nsISupports* ObjectAt(int32_t aIndex) const { return mArray[aIndex]; }
     135             :   // nsTArray-compatible version
     136         565 :   nsISupports* ElementAt(uint32_t aIndex) const { return mArray[aIndex]; }
     137             : 
     138          21 :   nsISupports* SafeObjectAt(int32_t aIndex) const
     139             :   {
     140          21 :     return mArray.SafeElementAt(aIndex, nullptr);
     141             :   }
     142             :   // nsTArray-compatible version
     143           0 :   nsISupports* SafeElementAt(uint32_t aIndex) const
     144             :   {
     145           0 :     return mArray.SafeElementAt(aIndex, nullptr);
     146             :   }
     147             : 
     148          47 :   nsISupports* operator[](int32_t aIndex) const { return mArray[aIndex]; }
     149             : 
     150             :   // remove an element at a specific position, shrinking the array
     151             :   // as necessary
     152             :   bool RemoveObjectAt(int32_t aIndex);
     153             :   // nsTArray-compatible version
     154             :   void RemoveElementAt(uint32_t aIndex);
     155             : 
     156             :   // remove a range of elements at a specific position, shrinking the array
     157             :   // as necessary
     158             :   bool RemoveObjectsAt(int32_t aIndex, int32_t aCount);
     159             :   // nsTArray-compatible version
     160             :   void RemoveElementsAt(uint32_t aIndex, uint32_t aCount);
     161             : 
     162             :   void SwapElementsAt(uint32_t aIndex1, uint32_t aIndex2)
     163             :   {
     164             :     nsISupports* tmp = mArray[aIndex1];
     165             :     mArray[aIndex1] = mArray[aIndex2];
     166             :     mArray[aIndex2] = tmp;
     167             :   }
     168             : 
     169             :   // Ensures there is enough space to store a total of aCapacity objects.
     170             :   // This method never deletes any objects.
     171         208 :   void SetCapacity(uint32_t aCapacity) { mArray.SetCapacity(aCapacity); }
     172             :   uint32_t Capacity() { return mArray.Capacity(); }
     173             : 
     174             :   // Measures the size of the array's element storage. If you want to measure
     175             :   // anything hanging off the array, you must iterate over the elements and
     176             :   // measure them individually; hence the "Shallow" prefix. Note that because
     177             :   // each element in an nsCOMArray<T> is actually a T* any such iteration
     178             :   // should use a SizeOfIncludingThis() function on each element rather than a
     179             :   // SizeOfExcludingThis() function, so that the memory taken by the T itself
     180             :   // is included as well as anything it points to.
     181           5 :   size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     182             :   {
     183           5 :     return mArray.ShallowSizeOfExcludingThis(aMallocSizeOf);
     184             :   }
     185             : 
     186             : private:
     187             : 
     188             :   // the actual storage
     189             :   nsTArray<nsISupports*> mArray;
     190             : 
     191             :   // don't implement these, defaults will muck with refcounts!
     192             :   nsCOMArray_base& operator=(const nsCOMArray_base& aOther) = delete;
     193             : };
     194             : 
     195             : inline void
     196             : ImplCycleCollectionUnlink(nsCOMArray_base& aField)
     197             : {
     198             :   aField.Clear();
     199             : }
     200             : 
     201             : inline void
     202           0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
     203             :                             nsCOMArray_base& aField,
     204             :                             const char* aName,
     205             :                             uint32_t aFlags = 0)
     206             : {
     207           0 :   aFlags |= CycleCollectionEdgeNameArrayFlag;
     208           0 :   int32_t length = aField.Count();
     209           0 :   for (int32_t i = 0; i < length; ++i) {
     210           0 :     CycleCollectionNoteChild(aCallback, aField[i], aName, aFlags);
     211             :   }
     212           0 : }
     213             : 
     214             : 
     215             : // a non-XPCOM, refcounting array of XPCOM objects
     216             : // used as a member variable or stack variable - this object is NOT
     217             : // refcounted, but the objects that it holds are
     218             : //
     219             : // most of the read-only accessors like ObjectAt()/etc do NOT refcount
     220             : // on the way out. This means that you can do one of two things:
     221             : //
     222             : // * does an addref, but holds onto a reference
     223             : // nsCOMPtr<T> foo = array[i];
     224             : //
     225             : // * avoids the refcount, but foo might go stale if array[i] is ever
     226             : // * modified/removed. Be careful not to NS_RELEASE(foo)!
     227             : // T* foo = array[i];
     228             : //
     229             : // This array will accept null as an argument for any object, and will store
     230             : // null in the array. But that also means that methods like ObjectAt() may
     231             : // return null when referring to an existing, but null entry in the array.
     232             : template<class T>
     233             : class nsCOMArray : public nsCOMArray_base
     234             : {
     235             : public:
     236             :   typedef int32_t                                       index_type;
     237             :   typedef mozilla::ArrayIterator<T*, nsCOMArray>        iterator;
     238             :   typedef mozilla::ArrayIterator<const T*, nsCOMArray>  const_iterator;
     239             :   typedef mozilla::ReverseIterator<iterator>            reverse_iterator;
     240             :   typedef mozilla::ReverseIterator<const_iterator>      const_reverse_iterator;
     241             : 
     242        1306 :   nsCOMArray() {}
     243          30 :   explicit nsCOMArray(int32_t aCount) : nsCOMArray_base(aCount) {}
     244         758 :   explicit nsCOMArray(const nsCOMArray<T>& aOther) : nsCOMArray_base(aOther) {}
     245           0 :   nsCOMArray(nsCOMArray<T>&& aOther) { SwapElements(aOther); }
     246         901 :   ~nsCOMArray() {}
     247             : 
     248             :   // We have a move assignment operator, but no copy assignment operator.
     249           1 :   nsCOMArray<T>& operator=(nsCOMArray<T> && aOther)
     250             :   {
     251           1 :     SwapElements(aOther);
     252           1 :     return *this;
     253             :   }
     254             : 
     255             :   // these do NOT refcount on the way out, for speed
     256       10472 :   T* ObjectAt(int32_t aIndex) const
     257             :   {
     258       10472 :     return static_cast<T*>(nsCOMArray_base::ObjectAt(aIndex));
     259             :   }
     260             :   // nsTArray-compatible version
     261         565 :   T* ElementAt(uint32_t aIndex) const
     262             :   {
     263         565 :     return static_cast<T*>(nsCOMArray_base::ElementAt(aIndex));
     264             :   }
     265             : 
     266             :   // these do NOT refcount on the way out, for speed
     267           9 :   T* SafeObjectAt(int32_t aIndex) const
     268             :   {
     269           9 :     return static_cast<T*>(nsCOMArray_base::SafeObjectAt(aIndex));
     270             :   }
     271             :   // nsTArray-compatible version
     272           0 :   T* SafeElementAt(uint32_t aIndex) const
     273             :   {
     274           0 :     return static_cast<T*>(nsCOMArray_base::SafeElementAt(aIndex));
     275             :   }
     276             : 
     277             :   // indexing operator for syntactic sugar
     278       10388 :   T* operator[](int32_t aIndex) const { return ObjectAt(aIndex); }
     279             : 
     280             :   // index of the element in question.. does NOT refcount
     281             :   // note: this does not check COM object identity. Use
     282             :   // IndexOfObject() for that purpose
     283           1 :   int32_t IndexOf(T* aObject, uint32_t aStartIndex = 0) const
     284             :   {
     285           1 :     return nsCOMArray_base::IndexOf(aObject, aStartIndex);
     286             :   }
     287           0 :   bool Contains(T* aObject) const
     288             :   {
     289           0 :     return nsCOMArray_base::Contains(aObject);
     290             :   }
     291             : 
     292             :   // index of the element in question.. be careful!
     293             :   // this is much slower than IndexOf() because it uses
     294             :   // QueryInterface to determine actual COM identity of the object
     295             :   // if you need to do this frequently then consider enforcing
     296             :   // COM object identity before adding/comparing elements
     297           1 :   int32_t IndexOfObject(T* aObject) const
     298             :   {
     299           1 :     return nsCOMArray_base::IndexOfObject(aObject);
     300             :   }
     301             :   bool ContainsObject(nsISupports* aObject) const
     302             :   {
     303             :     return nsCOMArray_base::ContainsObject(aObject);
     304             :   }
     305             : 
     306             :   // inserts aObject at aIndex, shifting the objects at aIndex and
     307             :   // later to make space
     308          11 :   bool InsertObjectAt(T* aObject, int32_t aIndex)
     309             :   {
     310          11 :     return nsCOMArray_base::InsertObjectAt(aObject, aIndex);
     311             :   }
     312             :   // nsTArray-compatible version
     313           0 :   void InsertElementAt(uint32_t aIndex, T* aElement)
     314             :   {
     315           0 :     nsCOMArray_base::InsertElementAt(aIndex, aElement);
     316           0 :   }
     317             : 
     318             :   // inserts the objects from aObject at aIndex, shifting the
     319             :   // objects at aIndex and later to make space
     320           0 :   bool InsertObjectsAt(const nsCOMArray<T>& aObjects, int32_t aIndex)
     321             :   {
     322           0 :     return nsCOMArray_base::InsertObjectsAt(aObjects, aIndex);
     323             :   }
     324             :   // nsTArray-compatible version
     325             :   void InsertElementsAt(uint32_t aIndex, const nsCOMArray<T>& aElements)
     326             :   {
     327             :     nsCOMArray_base::InsertElementsAt(aIndex, aElements);
     328             :   }
     329             :   void InsertElementsAt(uint32_t aIndex, T* const* aElements, uint32_t aCount)
     330             :   {
     331             :     nsCOMArray_base::InsertElementsAt(
     332             :       aIndex, reinterpret_cast<nsISupports* const*>(aElements), aCount);
     333             :   }
     334             : 
     335             :   // replaces an existing element. Warning: if the array grows,
     336             :   // the newly created entries will all be null
     337           0 :   void ReplaceObjectAt(T* aObject, int32_t aIndex)
     338             :   {
     339           0 :     nsCOMArray_base::ReplaceObjectAt(aObject, aIndex);
     340           0 :   }
     341             :   // nsTArray-compatible version
     342             :   void ReplaceElementAt(uint32_t aIndex, T* aElement)
     343             :   {
     344             :     nsCOMArray_base::ReplaceElementAt(aIndex, aElement);
     345             :   }
     346             : 
     347             :   typedef int (*nsCOMArrayComparatorFunc)(T* aElement1, T* aElement2,
     348             :                                           void* aData);
     349             : 
     350           6 :   void Sort(nsCOMArrayComparatorFunc aFunc, void* aData)
     351             :   {
     352           6 :     nsCOMArray_base::Sort(nsBaseArrayComparatorFunc(aFunc), aData);
     353           6 :   }
     354             : 
     355             :   // append an object, growing the array as necessary
     356        3834 :   bool AppendObject(T* aObject)
     357             :   {
     358        3834 :     return nsCOMArray_base::AppendObject(aObject);
     359             :   }
     360             :   // nsTArray-compatible version
     361           3 :   void AppendElement(T* aElement)
     362             :   {
     363           3 :     nsCOMArray_base::AppendElement(aElement);
     364           3 :   }
     365          45 :   void AppendElement(already_AddRefed<T> aElement)
     366             :   {
     367          45 :     nsCOMArray_base::AppendElement(mozilla::Move(aElement));
     368          45 :   }
     369             : 
     370             :   // append objects, growing the array as necessary
     371           0 :   bool AppendObjects(const nsCOMArray<T>& aObjects)
     372             :   {
     373           0 :     return nsCOMArray_base::AppendObjects(aObjects);
     374             :   }
     375             :   // nsTArray-compatible version
     376           0 :   void AppendElements(const nsCOMArray<T>& aElements)
     377             :   {
     378           0 :     return nsCOMArray_base::AppendElements(aElements);
     379             :   }
     380             :   void AppendElements(T* const* aElements, uint32_t aCount)
     381             :   {
     382             :     InsertElementsAt(Length(), aElements, aCount);
     383             :   }
     384             : 
     385             :   // remove the first instance of the given object and shrink the
     386             :   // array as necessary
     387             :   // Warning: if you pass null here, it will remove the first null element
     388          22 :   bool RemoveObject(T* aObject)
     389             :   {
     390          22 :     return nsCOMArray_base::RemoveObject(aObject);
     391             :   }
     392             :   // nsTArray-compatible version
     393           0 :   bool RemoveElement(T* aElement)
     394             :   {
     395           0 :     return nsCOMArray_base::RemoveObject(aElement);
     396             :   }
     397             : 
     398             :   T** Elements()
     399             :   {
     400             :     return reinterpret_cast<T**>(nsCOMArray_base::Elements());
     401             :   }
     402           1 :   void SwapElements(nsCOMArray<T>& aOther)
     403             :   {
     404           1 :     nsCOMArray_base::SwapElements(aOther);
     405           1 :   }
     406             : 
     407             :   /**
     408             :    * Adopt parameters that resulted from an XPIDL outparam. The aElements
     409             :    * parameter will be freed as a result of the call.
     410             :    *
     411             :    * Example usage:
     412             :    * nsCOMArray<nsISomeInterface> array;
     413             :    * nsISomeInterface** elements;
     414             :    * uint32_t length;
     415             :    * ptr->GetSomeArray(&elements, &length);
     416             :    * array.Adopt(elements, length);
     417             :    */
     418             :   void Adopt(T** aElements, uint32_t aSize)
     419             :   {
     420             :     nsCOMArray_base::Adopt(reinterpret_cast<nsISupports**>(aElements), aSize);
     421             :   }
     422             : 
     423             :   /**
     424             :    * Export the contents of this array to an XPIDL outparam. The array will be
     425             :    * Clear()'d after this operation.
     426             :    *
     427             :    * Example usage:
     428             :    * nsCOMArray<nsISomeInterface> array;
     429             :    * *length = array.Forget(retval);
     430             :    */
     431           0 :   uint32_t Forget(T*** aElements)
     432             :   {
     433           0 :     return nsCOMArray_base::Forget(reinterpret_cast<nsISupports***>(aElements));
     434             :   }
     435             : 
     436             :   // Methods for range-based for loops.
     437         162 :   iterator begin() { return iterator(*this, 0); }
     438         140 :   const_iterator begin() const { return const_iterator(*this, 0); }
     439             :   const_iterator cbegin() const { return begin(); }
     440         162 :   iterator end() { return iterator(*this, Length()); }
     441         140 :   const_iterator end() const { return const_iterator(*this, Length()); }
     442             :   const_iterator cend() const { return end(); }
     443             : 
     444             :   // Methods for reverse iterating.
     445             :   reverse_iterator rbegin() { return reverse_iterator(end()); }
     446             :   const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
     447             :   const_reverse_iterator crbegin() const { return rbegin(); }
     448             :   reverse_iterator rend() { return reverse_iterator(begin()); }
     449             :   const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
     450             :   const_reverse_iterator crend() const { return rend(); }
     451             : 
     452             : private:
     453             : 
     454             :   // don't implement these!
     455             :   nsCOMArray<T>& operator=(const nsCOMArray<T>& aOther) = delete;
     456             : };
     457             : 
     458             : template<typename T>
     459             : inline void
     460           0 : ImplCycleCollectionUnlink(nsCOMArray<T>& aField)
     461             : {
     462           0 :   aField.Clear();
     463           0 : }
     464             : 
     465             : template<typename E>
     466             : inline void
     467           1 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
     468             :                             nsCOMArray<E>& aField,
     469             :                             const char* aName,
     470             :                             uint32_t aFlags = 0)
     471             : {
     472           1 :   aFlags |= CycleCollectionEdgeNameArrayFlag;
     473           1 :   int32_t length = aField.Count();
     474           1 :   for (int32_t i = 0; i < length; ++i) {
     475           0 :     CycleCollectionNoteChild(aCallback, aField[i], aName, aFlags);
     476             :   }
     477           1 : }
     478             : 
     479             : #endif

Generated by: LCOV version 1.13