Bumping manifests a=b2g-bump
[gecko.git] / xpcom / glue / nsCOMArray.h
blob05b4f3ecfe365437f23f27ae448aea5616149644
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/. */
7 #ifndef nsCOMArray_h__
8 #define nsCOMArray_h__
10 #include "mozilla/Attributes.h"
11 #include "mozilla/MemoryReporting.h"
13 #include "nsCycleCollectionNoteChild.h"
14 #include "nsTArray.h"
15 #include "nsISupports.h"
17 // See below for the definition of nsCOMArray<T>
19 // a class that's nsISupports-specific, so that we can contain the
20 // work of this class in the XPCOM dll
21 class nsCOMArray_base
23 friend class nsArrayBase;
24 protected:
25 nsCOMArray_base() {}
26 explicit nsCOMArray_base(int32_t aCount) : mArray(aCount) {}
27 nsCOMArray_base(const nsCOMArray_base& aOther);
28 ~nsCOMArray_base();
30 int32_t IndexOf(nsISupports* aObject, uint32_t aStartIndex = 0) const;
31 bool Contains(nsISupports* aObject) const
33 return IndexOf(aObject) != -1;
36 int32_t IndexOfObject(nsISupports* aObject) const;
37 bool ContainsObject(nsISupports* aObject) const
39 return IndexOfObject(aObject) != -1;
42 typedef bool (*nsBaseArrayEnumFunc)(void* aElement, void* aData);
44 // enumerate through the array with a callback.
45 bool EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const;
47 bool EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const;
49 typedef int (*nsBaseArrayComparatorFunc)(nsISupports* aElement1,
50 nsISupports* aElement2,
51 void* aData);
53 struct nsCOMArrayComparatorContext
55 nsBaseArrayComparatorFunc mComparatorFunc;
56 void* mData;
59 static int nsCOMArrayComparator(const void* aElement1, const void* aElement2,
60 void* aData);
61 void Sort(nsBaseArrayComparatorFunc aFunc, void* aData);
63 bool InsertObjectAt(nsISupports* aObject, int32_t aIndex);
64 void InsertElementAt(uint32_t aIndex, nsISupports* aElement);
65 bool InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex);
66 void InsertElementsAt(uint32_t aIndex, const nsCOMArray_base& aElements);
67 void InsertElementsAt(uint32_t aIndex, nsISupports* const* aElements,
68 uint32_t aCount);
69 bool ReplaceObjectAt(nsISupports* aObject, int32_t aIndex);
70 void ReplaceElementAt(uint32_t aIndex, nsISupports* aElement)
72 nsISupports* oldElement = mArray[aIndex];
73 NS_IF_ADDREF(mArray[aIndex] = aElement);
74 NS_IF_RELEASE(oldElement);
76 bool AppendObject(nsISupports* aObject)
78 return InsertObjectAt(aObject, Count());
80 void AppendElement(nsISupports* aElement)
82 InsertElementAt(Length(), aElement);
84 bool AppendObjects(const nsCOMArray_base& aObjects)
86 return InsertObjectsAt(aObjects, Count());
88 void AppendElements(const nsCOMArray_base& aElements)
90 return InsertElementsAt(Length(), aElements);
92 void AppendElements(nsISupports* const* aElements, uint32_t aCount)
94 return InsertElementsAt(Length(), aElements, aCount);
96 bool RemoveObject(nsISupports* aObject);
97 nsISupports** Elements() { return mArray.Elements(); }
98 void SwapElements(nsCOMArray_base& aOther)
100 mArray.SwapElements(aOther.mArray);
103 void Adopt(nsISupports** aElements, uint32_t aCount);
104 uint32_t Forget(nsISupports*** aElements);
105 public:
106 // elements in the array (including null elements!)
107 int32_t Count() const { return mArray.Length(); }
108 // nsTArray-compatible version
109 uint32_t Length() const { return mArray.Length(); }
110 bool IsEmpty() const { return mArray.IsEmpty(); }
112 // If the array grows, the newly created entries will all be null;
113 // if the array shrinks, the excess entries will all be released.
114 bool SetCount(int32_t aNewCount);
115 // nsTArray-compatible version
116 void TruncateLength(uint32_t aNewLength)
118 if (mArray.Length() > aNewLength) {
119 RemoveElementsAt(aNewLength, mArray.Length() - aNewLength);
123 // remove all elements in the array, and call NS_RELEASE on each one
124 void Clear();
126 nsISupports* ObjectAt(int32_t aIndex) const { return mArray[aIndex]; }
127 // nsTArray-compatible version
128 nsISupports* ElementAt(uint32_t aIndex) const { return mArray[aIndex]; }
130 nsISupports* SafeObjectAt(int32_t aIndex) const
132 return mArray.SafeElementAt(aIndex, nullptr);
134 // nsTArray-compatible version
135 nsISupports* SafeElementAt(uint32_t aIndex) const
137 return mArray.SafeElementAt(aIndex, nullptr);
140 nsISupports* operator[](int32_t aIndex) const { return mArray[aIndex]; }
142 // remove an element at a specific position, shrinking the array
143 // as necessary
144 bool RemoveObjectAt(int32_t aIndex);
145 // nsTArray-compatible version
146 void RemoveElementAt(uint32_t aIndex);
148 // remove a range of elements at a specific position, shrinking the array
149 // as necessary
150 bool RemoveObjectsAt(int32_t aIndex, int32_t aCount);
151 // nsTArray-compatible version
152 void RemoveElementsAt(uint32_t aIndex, uint32_t aCount);
154 void SwapElementsAt(uint32_t aIndex1, uint32_t aIndex2)
156 nsISupports* tmp = mArray[aIndex1];
157 mArray[aIndex1] = mArray[aIndex2];
158 mArray[aIndex2] = tmp;
161 // Ensures there is enough space to store a total of aCapacity objects.
162 // This method never deletes any objects.
163 void SetCapacity(uint32_t aCapacity) { mArray.SetCapacity(aCapacity); }
164 uint32_t Capacity() { return mArray.Capacity(); }
166 typedef size_t (*nsBaseArraySizeOfElementIncludingThisFunc)(
167 nsISupports* aElement, mozilla::MallocSizeOf aMallocSizeOf, void* aData);
169 // Measures the size of the array's element storage, and if
170 // |aSizeOfElement| is non-nullptr, measures the size of things pointed to
171 // by elements.
172 size_t SizeOfExcludingThis(
173 nsBaseArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
174 mozilla::MallocSizeOf aMallocSizeOf, void* aData = nullptr) const;
176 private:
178 // the actual storage
179 nsTArray<nsISupports*> mArray;
181 // don't implement these, defaults will muck with refcounts!
182 nsCOMArray_base& operator=(const nsCOMArray_base& aOther) MOZ_DELETE;
185 inline void
186 ImplCycleCollectionUnlink(nsCOMArray_base& aField)
188 aField.Clear();
191 inline void
192 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
193 nsCOMArray_base& aField,
194 const char* aName,
195 uint32_t aFlags = 0)
197 aFlags |= CycleCollectionEdgeNameArrayFlag;
198 int32_t length = aField.Count();
199 for (int32_t i = 0; i < length; ++i) {
200 CycleCollectionNoteChild(aCallback, aField[i], aName, aFlags);
205 // a non-XPCOM, refcounting array of XPCOM objects
206 // used as a member variable or stack variable - this object is NOT
207 // refcounted, but the objects that it holds are
209 // most of the read-only accessors like ObjectAt()/etc do NOT refcount
210 // on the way out. This means that you can do one of two things:
212 // * does an addref, but holds onto a reference
213 // nsCOMPtr<T> foo = array[i];
215 // * avoids the refcount, but foo might go stale if array[i] is ever
216 // * modified/removed. Be careful not to NS_RELEASE(foo)!
217 // T* foo = array[i];
219 // This array will accept null as an argument for any object, and will
220 // store null in the array, just like nsVoidArray. But that also means
221 // that methods like ObjectAt() may return null when referring to an
222 // existing, but null entry in the array.
223 template<class T>
224 class nsCOMArray : public nsCOMArray_base
226 public:
227 nsCOMArray() {}
228 explicit nsCOMArray(int32_t aCount) : nsCOMArray_base(aCount) {}
229 explicit nsCOMArray(const nsCOMArray<T>& aOther) : nsCOMArray_base(aOther) {}
230 nsCOMArray(nsCOMArray<T>&& aOther) { SwapElements(aOther); }
231 ~nsCOMArray() {}
233 // We have a move assignment operator, but no copy assignment operator.
234 nsCOMArray<T>& operator=(nsCOMArray<T> && aOther)
236 SwapElements(aOther);
237 return *this;
240 // these do NOT refcount on the way out, for speed
241 T* ObjectAt(int32_t aIndex) const
243 return static_cast<T*>(nsCOMArray_base::ObjectAt(aIndex));
245 // nsTArray-compatible version
246 T* ElementAt(uint32_t aIndex) const
248 return static_cast<T*>(nsCOMArray_base::ElementAt(aIndex));
251 // these do NOT refcount on the way out, for speed
252 T* SafeObjectAt(int32_t aIndex) const
254 return static_cast<T*>(nsCOMArray_base::SafeObjectAt(aIndex));
256 // nsTArray-compatible version
257 T* SafeElementAt(uint32_t aIndex) const
259 return static_cast<T*>(nsCOMArray_base::SafeElementAt(aIndex));
262 // indexing operator for syntactic sugar
263 T* operator[](int32_t aIndex) const { return ObjectAt(aIndex); }
265 // index of the element in question.. does NOT refcount
266 // note: this does not check COM object identity. Use
267 // IndexOfObject() for that purpose
268 int32_t IndexOf(T* aObject, uint32_t aStartIndex = 0) const
270 return nsCOMArray_base::IndexOf(aObject, aStartIndex);
272 bool Contains(T* aObject) const
274 return nsCOMArray_base::Contains(aObject);
277 // index of the element in question.. be careful!
278 // this is much slower than IndexOf() because it uses
279 // QueryInterface to determine actual COM identity of the object
280 // if you need to do this frequently then consider enforcing
281 // COM object identity before adding/comparing elements
282 int32_t IndexOfObject(T* aObject) const
284 return nsCOMArray_base::IndexOfObject(aObject);
286 bool ContainsObject(nsISupports* aObject) const
288 return nsCOMArray_base::ContainsObject(aObject);
291 // inserts aObject at aIndex, shifting the objects at aIndex and
292 // later to make space
293 bool InsertObjectAt(T* aObject, int32_t aIndex)
295 return nsCOMArray_base::InsertObjectAt(aObject, aIndex);
297 // nsTArray-compatible version
298 void InsertElementAt(uint32_t aIndex, T* aElement)
300 nsCOMArray_base::InsertElementAt(aIndex, aElement);
303 // inserts the objects from aObject at aIndex, shifting the
304 // objects at aIndex and later to make space
305 bool InsertObjectsAt(const nsCOMArray<T>& aObjects, int32_t aIndex)
307 return nsCOMArray_base::InsertObjectsAt(aObjects, aIndex);
309 // nsTArray-compatible version
310 void InsertElementsAt(uint32_t aIndex, const nsCOMArray<T>& aElements)
312 nsCOMArray_base::InsertElementsAt(aIndex, aElements);
314 void InsertElementsAt(uint32_t aIndex, T* const* aElements, uint32_t aCount)
316 nsCOMArray_base::InsertElementsAt(
317 aIndex, reinterpret_cast<nsISupports* const*>(aElements), aCount);
320 // replaces an existing element. Warning: if the array grows,
321 // the newly created entries will all be null
322 bool ReplaceObjectAt(T* aObject, int32_t aIndex)
324 return nsCOMArray_base::ReplaceObjectAt(aObject, aIndex);
326 // nsTArray-compatible version
327 void ReplaceElementAt(uint32_t aIndex, T* aElement)
329 nsCOMArray_base::ReplaceElementAt(aIndex, aElement);
332 // Enumerator callback function. Return false to stop
333 // Here's a more readable form:
334 // bool enumerate(T* aElement, void* aData)
335 typedef bool (*nsCOMArrayEnumFunc)(T* aElement, void* aData);
337 // enumerate through the array with a callback.
338 bool EnumerateForwards(nsCOMArrayEnumFunc aFunc, void* aData)
340 return nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc(aFunc),
341 aData);
344 bool EnumerateBackwards(nsCOMArrayEnumFunc aFunc, void* aData)
346 return nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc(aFunc),
347 aData);
350 typedef int (*nsCOMArrayComparatorFunc)(T* aElement1, T* aElement2,
351 void* aData);
353 void Sort(nsCOMArrayComparatorFunc aFunc, void* aData)
355 nsCOMArray_base::Sort(nsBaseArrayComparatorFunc(aFunc), aData);
358 // append an object, growing the array as necessary
359 bool AppendObject(T* aObject)
361 return nsCOMArray_base::AppendObject(aObject);
363 // nsTArray-compatible version
364 void AppendElement(T* aElement)
366 nsCOMArray_base::AppendElement(aElement);
369 // append objects, growing the array as necessary
370 bool AppendObjects(const nsCOMArray<T>& aObjects)
372 return nsCOMArray_base::AppendObjects(aObjects);
374 // nsTArray-compatible version
375 void AppendElements(const nsCOMArray<T>& aElements)
377 return nsCOMArray_base::AppendElements(aElements);
379 void AppendElements(T* const* aElements, uint32_t aCount)
381 InsertElementsAt(Length(), aElements, aCount);
384 // remove the first instance of the given object and shrink the
385 // array as necessary
386 // Warning: if you pass null here, it will remove the first null element
387 bool RemoveObject(T* aObject)
389 return nsCOMArray_base::RemoveObject(aObject);
391 // nsTArray-compatible version
392 bool RemoveElement(T* aElement)
394 return nsCOMArray_base::RemoveObject(aElement);
397 T** Elements()
399 return reinterpret_cast<T**>(nsCOMArray_base::Elements());
401 void SwapElements(nsCOMArray<T>& aOther)
403 nsCOMArray_base::SwapElements(aOther);
406 // Each element in an nsCOMArray<T> is actually a T*, so this function is
407 // "IncludingThis" rather than "ExcludingThis" because it needs to measure
408 // the memory taken by the T itself as well as anything it points to.
409 typedef size_t (*nsCOMArraySizeOfElementIncludingThisFunc)(
410 T* aElement, mozilla::MallocSizeOf aMallocSizeOf, void* aData);
412 size_t SizeOfExcludingThis(
413 nsCOMArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
414 mozilla::MallocSizeOf aMallocSizeOf, void* aData = nullptr) const
416 return nsCOMArray_base::SizeOfExcludingThis(
417 nsBaseArraySizeOfElementIncludingThisFunc(aSizeOfElementIncludingThis),
418 aMallocSizeOf, aData);
422 * Adopt parameters that resulted from an XPIDL outparam. The aElements
423 * parameter will be freed as a result of the call.
425 * Example usage:
426 * nsCOMArray<nsISomeInterface> array;
427 * nsISomeInterface** elements;
428 * uint32_t length;
429 * ptr->GetSomeArray(&elements, &length);
430 * array.Adopt(elements, length);
432 void Adopt(T** aElements, uint32_t aSize)
434 nsCOMArray_base::Adopt(reinterpret_cast<nsISupports**>(aElements), aSize);
438 * Export the contents of this array to an XPIDL outparam. The array will be
439 * Clear()'d after this operation.
441 * Example usage:
442 * nsCOMArray<nsISomeInterface> array;
443 * *length = array.Forget(retval);
445 uint32_t Forget(T*** aElements)
447 return nsCOMArray_base::Forget(reinterpret_cast<nsISupports***>(aElements));
450 private:
452 // don't implement these!
453 nsCOMArray<T>& operator=(const nsCOMArray<T>& aOther) MOZ_DELETE;
456 template<typename T>
457 inline void
458 ImplCycleCollectionUnlink(nsCOMArray<T>& aField)
460 aField.Clear();
463 template<typename E>
464 inline void
465 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
466 nsCOMArray<E>& aField,
467 const char* aName,
468 uint32_t aFlags = 0)
470 aFlags |= CycleCollectionEdgeNameArrayFlag;
471 int32_t length = aField.Count();
472 for (int32_t i = 0; i < length; ++i) {
473 CycleCollectionNoteChild(aCallback, aField[i], aName, aFlags);
477 #endif