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"
14 // This specialization is private to nsCOMArray.
15 // It exists solely to automatically zero-out newly created array elements.
17 class nsTArrayElementTraits
<nsISupports
*> {
18 typedef nsISupports
* E
;
22 static inline void Construct(E
* aE
) {
23 new (mozilla::KnownNotNull
, static_cast<void*>(aE
)) E();
25 // Invoke the copy-constructor in place.
27 static inline void Construct(E
* aE
, const A
& aArg
) {
28 new (mozilla::KnownNotNull
, static_cast<void*>(aE
)) E(aArg
);
30 // Construct in place.
31 template <class... Args
>
32 static inline void Emplace(E
* aE
, Args
&&... aArgs
) {
33 new (mozilla::KnownNotNull
, static_cast<void*>(aE
))
34 E(std::forward
<Args
>(aArgs
)...);
36 // Invoke the destructor in place.
37 static inline void Destruct(E
* aE
) { aE
->~E(); }
40 static void ReleaseObjects(nsTArray
<nsISupports
*>& aArray
);
42 // implementations of non-trivial methods in nsCOMArray_base
44 nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base
& aOther
) {
45 // make sure we do only one allocation
46 mArray
.SetCapacity(aOther
.Count());
47 AppendObjects(aOther
);
50 nsCOMArray_base::~nsCOMArray_base() { Clear(); }
52 int32_t nsCOMArray_base::IndexOf(nsISupports
* aObject
,
53 uint32_t aStartIndex
) const {
54 return mArray
.IndexOf(aObject
, aStartIndex
);
57 int32_t nsCOMArray_base::IndexOfObject(nsISupports
* aObject
) const {
58 nsCOMPtr
<nsISupports
> supports
= do_QueryInterface(aObject
);
59 if (NS_WARN_IF(!supports
)) {
65 count
= mArray
.Length();
66 for (i
= 0; i
< count
; ++i
) {
67 nsCOMPtr
<nsISupports
> arrayItem
= do_QueryInterface(mArray
[i
]);
68 if (arrayItem
== supports
) {
76 bool nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc
,
78 for (uint32_t index
= 0; index
< mArray
.Length(); ++index
) {
79 if (!(*aFunc
)(mArray
[index
], aData
)) {
87 bool nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc
,
89 for (uint32_t index
= mArray
.Length(); index
--;) {
90 if (!(*aFunc
)(mArray
[index
], aData
)) {
98 bool nsCOMArray_base::InsertObjectAt(nsISupports
* aObject
, int32_t aIndex
) {
99 if ((uint32_t)aIndex
> mArray
.Length()) {
103 mArray
.InsertElementAt(aIndex
, aObject
);
105 NS_IF_ADDREF(aObject
);
109 void nsCOMArray_base::InsertElementAt(uint32_t aIndex
, nsISupports
* aElement
) {
110 mArray
.InsertElementAt(aIndex
, aElement
);
111 NS_IF_ADDREF(aElement
);
114 void nsCOMArray_base::InsertElementAt(uint32_t aIndex
,
115 already_AddRefed
<nsISupports
> aElement
) {
116 mArray
.InsertElementAt(aIndex
, aElement
.take());
119 bool nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base
& aObjects
,
121 if ((uint32_t)aIndex
> mArray
.Length()) {
125 mArray
.InsertElementsAt(aIndex
, aObjects
.mArray
);
127 // need to addref all these
128 uint32_t count
= aObjects
.Length();
129 for (uint32_t i
= 0; i
< count
; ++i
) {
130 NS_IF_ADDREF(aObjects
[i
]);
136 void nsCOMArray_base::InsertElementsAt(uint32_t aIndex
,
137 const nsCOMArray_base
& aElements
) {
138 mArray
.InsertElementsAt(aIndex
, aElements
.mArray
);
140 // need to addref all these
141 uint32_t count
= aElements
.Length();
142 for (uint32_t i
= 0; i
< count
; ++i
) {
143 NS_IF_ADDREF(aElements
[i
]);
147 void nsCOMArray_base::InsertElementsAt(uint32_t aIndex
,
148 nsISupports
* const* aElements
,
150 mArray
.InsertElementsAt(aIndex
, aElements
, aCount
);
152 // need to addref all these
153 for (uint32_t i
= 0; i
< aCount
; ++i
) {
154 NS_IF_ADDREF(aElements
[i
]);
158 void nsCOMArray_base::ReplaceObjectAt(nsISupports
* aObject
, int32_t aIndex
) {
159 mArray
.EnsureLengthAtLeast(aIndex
+ 1);
160 nsISupports
* oldObject
= mArray
[aIndex
];
161 // Make sure to addref first, in case aObject == oldObject
162 NS_IF_ADDREF(mArray
[aIndex
] = aObject
);
163 NS_IF_RELEASE(oldObject
);
166 bool nsCOMArray_base::RemoveObject(nsISupports
* aObject
) {
167 bool result
= mArray
.RemoveElement(aObject
);
169 NS_IF_RELEASE(aObject
);
174 bool nsCOMArray_base::RemoveObjectAt(int32_t aIndex
) {
175 if (uint32_t(aIndex
) < mArray
.Length()) {
176 nsISupports
* element
= mArray
[aIndex
];
178 mArray
.RemoveElementAt(aIndex
);
179 NS_IF_RELEASE(element
);
186 void nsCOMArray_base::RemoveElementAt(uint32_t aIndex
) {
187 nsISupports
* element
= mArray
[aIndex
];
188 mArray
.RemoveElementAt(aIndex
);
189 NS_IF_RELEASE(element
);
192 bool nsCOMArray_base::RemoveObjectsAt(int32_t aIndex
, int32_t aCount
) {
193 if (uint32_t(aIndex
) + uint32_t(aCount
) <= mArray
.Length()) {
194 nsTArray
<nsISupports
*> elementsToDestroy(aCount
);
195 elementsToDestroy
.AppendElements(mArray
.Elements() + aIndex
, aCount
);
196 mArray
.RemoveElementsAt(aIndex
, aCount
);
197 ReleaseObjects(elementsToDestroy
);
204 void nsCOMArray_base::RemoveElementsAt(uint32_t aIndex
, uint32_t aCount
) {
205 nsTArray
<nsISupports
*> elementsToDestroy(aCount
);
206 elementsToDestroy
.AppendElements(mArray
.Elements() + aIndex
, aCount
);
207 mArray
.RemoveElementsAt(aIndex
, aCount
);
208 ReleaseObjects(elementsToDestroy
);
211 // useful for destructors
212 void ReleaseObjects(nsTArray
<nsISupports
*>& aArray
) {
213 for (uint32_t i
= 0; i
< aArray
.Length(); ++i
) {
214 NS_IF_RELEASE(aArray
[i
]);
218 void nsCOMArray_base::Clear() {
219 nsTArray
<nsISupports
*> objects
= std::move(mArray
);
220 ReleaseObjects(objects
);
223 bool nsCOMArray_base::SetCount(int32_t aNewCount
) {
224 NS_ASSERTION(aNewCount
>= 0, "SetCount(negative index)");
229 int32_t count
= mArray
.Length();
230 if (count
> aNewCount
) {
231 RemoveObjectsAt(aNewCount
, mArray
.Length() - aNewCount
);
233 mArray
.SetLength(aNewCount
);