Bug 1854550 - pt 12. Allow inlining between mozjemalloc and PHC r=glandium
[gecko.git] / xpcom / ds / nsCOMArray.cpp
blobd388857573000be79cd061923498f97ed37c0491
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 #include "nsCOMArray.h"
9 #include "mozilla/MemoryReporting.h"
10 #include "mozilla/OperatorNewExtensions.h"
11 #include "nsQuickSort.h"
13 #include "nsCOMPtr.h"
15 // This specialization is private to nsCOMArray.
16 // It exists solely to automatically zero-out newly created array elements.
17 template <>
18 class nsTArrayElementTraits<nsISupports*> {
19 typedef nsISupports* E;
21 public:
22 // Zero out the value
23 static inline void Construct(E* aE) {
24 new (mozilla::KnownNotNull, static_cast<void*>(aE)) E();
26 // Invoke the copy-constructor in place.
27 template <class A>
28 static inline void Construct(E* aE, const A& aArg) {
29 new (mozilla::KnownNotNull, static_cast<void*>(aE)) E(aArg);
31 // Construct in place.
32 template <class... Args>
33 static inline void Emplace(E* aE, Args&&... aArgs) {
34 new (mozilla::KnownNotNull, static_cast<void*>(aE))
35 E(std::forward<Args>(aArgs)...);
37 // Invoke the destructor in place.
38 static inline void Destruct(E* aE) { aE->~E(); }
41 static void ReleaseObjects(nsTArray<nsISupports*>& aArray);
43 // implementations of non-trivial methods in nsCOMArray_base
45 nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther) {
46 // make sure we do only one allocation
47 mArray.SetCapacity(aOther.Count());
48 AppendObjects(aOther);
51 nsCOMArray_base::~nsCOMArray_base() { Clear(); }
53 int32_t nsCOMArray_base::IndexOf(nsISupports* aObject,
54 uint32_t aStartIndex) const {
55 return mArray.IndexOf(aObject, aStartIndex);
58 int32_t nsCOMArray_base::IndexOfObject(nsISupports* aObject) const {
59 nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
60 if (NS_WARN_IF(!supports)) {
61 return -1;
64 uint32_t i, count;
65 int32_t retval = -1;
66 count = mArray.Length();
67 for (i = 0; i < count; ++i) {
68 nsCOMPtr<nsISupports> arrayItem = do_QueryInterface(mArray[i]);
69 if (arrayItem == supports) {
70 retval = i;
71 break;
74 return retval;
77 bool nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc,
78 void* aData) const {
79 for (uint32_t index = 0; index < mArray.Length(); ++index) {
80 if (!(*aFunc)(mArray[index], aData)) {
81 return false;
85 return true;
88 bool nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc,
89 void* aData) const {
90 for (uint32_t index = mArray.Length(); index--;) {
91 if (!(*aFunc)(mArray[index], aData)) {
92 return false;
96 return true;
99 int nsCOMArray_base::VoidStarComparator(const void* aElement1,
100 const void* aElement2, void* aData) {
101 auto ctx = static_cast<nsISupportsComparatorContext*>(aData);
102 return (*ctx->mComparatorFunc)(*static_cast<nsISupports* const*>(aElement1),
103 *static_cast<nsISupports* const*>(aElement2),
104 ctx->mData);
107 void nsCOMArray_base::Sort(nsISupportsComparatorFunc aFunc, void* aData) {
108 if (mArray.Length() > 1) {
109 nsISupportsComparatorContext ctx = {aFunc, aData};
110 NS_QuickSort(mArray.Elements(), mArray.Length(), sizeof(nsISupports*),
111 VoidStarComparator, &ctx);
115 bool nsCOMArray_base::InsertObjectAt(nsISupports* aObject, int32_t aIndex) {
116 if ((uint32_t)aIndex > mArray.Length()) {
117 return false;
120 mArray.InsertElementAt(aIndex, aObject);
122 NS_IF_ADDREF(aObject);
123 return true;
126 void nsCOMArray_base::InsertElementAt(uint32_t aIndex, nsISupports* aElement) {
127 mArray.InsertElementAt(aIndex, aElement);
128 NS_IF_ADDREF(aElement);
131 void nsCOMArray_base::InsertElementAt(uint32_t aIndex,
132 already_AddRefed<nsISupports> aElement) {
133 mArray.InsertElementAt(aIndex, aElement.take());
136 bool nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects,
137 int32_t aIndex) {
138 if ((uint32_t)aIndex > mArray.Length()) {
139 return false;
142 mArray.InsertElementsAt(aIndex, aObjects.mArray);
144 // need to addref all these
145 uint32_t count = aObjects.Length();
146 for (uint32_t i = 0; i < count; ++i) {
147 NS_IF_ADDREF(aObjects[i]);
150 return true;
153 void nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
154 const nsCOMArray_base& aElements) {
155 mArray.InsertElementsAt(aIndex, aElements.mArray);
157 // need to addref all these
158 uint32_t count = aElements.Length();
159 for (uint32_t i = 0; i < count; ++i) {
160 NS_IF_ADDREF(aElements[i]);
164 void nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
165 nsISupports* const* aElements,
166 uint32_t aCount) {
167 mArray.InsertElementsAt(aIndex, aElements, aCount);
169 // need to addref all these
170 for (uint32_t i = 0; i < aCount; ++i) {
171 NS_IF_ADDREF(aElements[i]);
175 void nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, int32_t aIndex) {
176 mArray.EnsureLengthAtLeast(aIndex + 1);
177 nsISupports* oldObject = mArray[aIndex];
178 // Make sure to addref first, in case aObject == oldObject
179 NS_IF_ADDREF(mArray[aIndex] = aObject);
180 NS_IF_RELEASE(oldObject);
183 bool nsCOMArray_base::RemoveObject(nsISupports* aObject) {
184 bool result = mArray.RemoveElement(aObject);
185 if (result) {
186 NS_IF_RELEASE(aObject);
188 return result;
191 bool nsCOMArray_base::RemoveObjectAt(int32_t aIndex) {
192 if (uint32_t(aIndex) < mArray.Length()) {
193 nsISupports* element = mArray[aIndex];
195 mArray.RemoveElementAt(aIndex);
196 NS_IF_RELEASE(element);
197 return true;
200 return false;
203 void nsCOMArray_base::RemoveElementAt(uint32_t aIndex) {
204 nsISupports* element = mArray[aIndex];
205 mArray.RemoveElementAt(aIndex);
206 NS_IF_RELEASE(element);
209 bool nsCOMArray_base::RemoveObjectsAt(int32_t aIndex, int32_t aCount) {
210 if (uint32_t(aIndex) + uint32_t(aCount) <= mArray.Length()) {
211 nsTArray<nsISupports*> elementsToDestroy(aCount);
212 elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
213 mArray.RemoveElementsAt(aIndex, aCount);
214 ReleaseObjects(elementsToDestroy);
215 return true;
218 return false;
221 void nsCOMArray_base::RemoveElementsAt(uint32_t aIndex, uint32_t aCount) {
222 nsTArray<nsISupports*> elementsToDestroy(aCount);
223 elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
224 mArray.RemoveElementsAt(aIndex, aCount);
225 ReleaseObjects(elementsToDestroy);
228 // useful for destructors
229 void ReleaseObjects(nsTArray<nsISupports*>& aArray) {
230 for (uint32_t i = 0; i < aArray.Length(); ++i) {
231 NS_IF_RELEASE(aArray[i]);
235 void nsCOMArray_base::Clear() {
236 nsTArray<nsISupports*> objects = std::move(mArray);
237 ReleaseObjects(objects);
240 bool nsCOMArray_base::SetCount(int32_t aNewCount) {
241 NS_ASSERTION(aNewCount >= 0, "SetCount(negative index)");
242 if (aNewCount < 0) {
243 return false;
246 int32_t count = mArray.Length();
247 if (count > aNewCount) {
248 RemoveObjectsAt(aNewCount, mArray.Length() - aNewCount);
250 mArray.SetLength(aNewCount);
251 return true;