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"
15 // This specialization is private to nsCOMArray.
16 // It exists solely to automatically zero-out newly created array elements.
18 class nsTArrayElementTraits
<nsISupports
*> {
19 typedef nsISupports
* E
;
23 static inline void Construct(E
* aE
) {
24 new (mozilla::KnownNotNull
, static_cast<void*>(aE
)) E();
26 // Invoke the copy-constructor in place.
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
)) {
66 count
= mArray
.Length();
67 for (i
= 0; i
< count
; ++i
) {
68 nsCOMPtr
<nsISupports
> arrayItem
= do_QueryInterface(mArray
[i
]);
69 if (arrayItem
== supports
) {
77 bool nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc
,
79 for (uint32_t index
= 0; index
< mArray
.Length(); ++index
) {
80 if (!(*aFunc
)(mArray
[index
], aData
)) {
88 bool nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc
,
90 for (uint32_t index
= mArray
.Length(); index
--;) {
91 if (!(*aFunc
)(mArray
[index
], aData
)) {
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
),
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()) {
120 mArray
.InsertElementAt(aIndex
, aObject
);
122 NS_IF_ADDREF(aObject
);
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
,
138 if ((uint32_t)aIndex
> mArray
.Length()) {
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
]);
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
,
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
);
186 NS_IF_RELEASE(aObject
);
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
);
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
);
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)");
246 int32_t count
= mArray
.Length();
247 if (count
> aNewCount
) {
248 RemoveObjectsAt(aNewCount
, mArray
.Length() - aNewCount
);
250 mArray
.SetLength(aNewCount
);