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 : #include "nsCOMArray.h"
8 :
9 : #include "mozilla/MemoryReporting.h"
10 : #include "mozilla/OperatorNewExtensions.h"
11 :
12 : #include "nsCOMPtr.h"
13 :
14 : // This specialization is private to nsCOMArray.
15 : // It exists solely to automatically zero-out newly created array elements.
16 : template<>
17 : class nsTArrayElementTraits<nsISupports*>
18 : {
19 : typedef nsISupports* E;
20 : public:
21 : // Zero out the value
22 0 : static inline void Construct(E* aE)
23 : {
24 0 : new (mozilla::KnownNotNull, static_cast<void*>(aE)) E();
25 0 : }
26 : // Invoke the copy-constructor in place.
27 : template<class A>
28 3899 : static inline void Construct(E* aE, const A& aArg)
29 : {
30 3899 : new (mozilla::KnownNotNull, static_cast<void*>(aE)) E(aArg);
31 3899 : }
32 : // Invoke the destructor in place.
33 401 : static inline void Destruct(E* aE)
34 : {
35 : aE->~E();
36 401 : }
37 : };
38 :
39 : static void ReleaseObjects(nsTArray<nsISupports*>& aArray);
40 :
41 : // implementations of non-trivial methods in nsCOMArray_base
42 :
43 758 : nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther)
44 : {
45 : // make sure we do only one allocation
46 758 : mArray.SetCapacity(aOther.Count());
47 758 : AppendObjects(aOther);
48 758 : }
49 :
50 1802 : nsCOMArray_base::~nsCOMArray_base()
51 : {
52 901 : Clear();
53 901 : }
54 :
55 : int32_t
56 1 : nsCOMArray_base::IndexOf(nsISupports* aObject, uint32_t aStartIndex) const
57 : {
58 1 : return mArray.IndexOf(aObject, aStartIndex);
59 : }
60 :
61 : int32_t
62 1 : nsCOMArray_base::IndexOfObject(nsISupports* aObject) const
63 : {
64 2 : nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
65 1 : if (NS_WARN_IF(!supports)) {
66 0 : return -1;
67 : }
68 :
69 : uint32_t i, count;
70 1 : int32_t retval = -1;
71 1 : count = mArray.Length();
72 1 : for (i = 0; i < count; ++i) {
73 0 : nsCOMPtr<nsISupports> arrayItem = do_QueryInterface(mArray[i]);
74 0 : if (arrayItem == supports) {
75 0 : retval = i;
76 0 : break;
77 : }
78 : }
79 1 : return retval;
80 : }
81 :
82 : bool
83 0 : nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const
84 : {
85 0 : for (uint32_t index = 0; index < mArray.Length(); ++index) {
86 0 : if (!(*aFunc)(mArray[index], aData)) {
87 0 : return false;
88 : }
89 : }
90 :
91 0 : return true;
92 : }
93 :
94 : bool
95 0 : nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const
96 : {
97 0 : for (uint32_t index = mArray.Length(); index--; ) {
98 0 : if (!(*aFunc)(mArray[index], aData)) {
99 0 : return false;
100 : }
101 : }
102 :
103 0 : return true;
104 : }
105 :
106 : int
107 54 : nsCOMArray_base::nsCOMArrayComparator(const void* aElement1,
108 : const void* aElement2,
109 : void* aData)
110 : {
111 : nsCOMArrayComparatorContext* ctx =
112 54 : static_cast<nsCOMArrayComparatorContext*>(aData);
113 54 : return (*ctx->mComparatorFunc)(*static_cast<nsISupports* const*>(aElement1),
114 : *static_cast<nsISupports* const*>(aElement2),
115 54 : ctx->mData);
116 : }
117 :
118 : void
119 6 : nsCOMArray_base::Sort(nsBaseArrayComparatorFunc aFunc, void* aData)
120 : {
121 6 : if (mArray.Length() > 1) {
122 6 : nsCOMArrayComparatorContext ctx = {aFunc, aData};
123 6 : NS_QuickSort(mArray.Elements(), mArray.Length(), sizeof(nsISupports*),
124 6 : nsCOMArrayComparator, &ctx);
125 : }
126 6 : }
127 :
128 : bool
129 3851 : nsCOMArray_base::InsertObjectAt(nsISupports* aObject, int32_t aIndex)
130 : {
131 3851 : if ((uint32_t)aIndex > mArray.Length()) {
132 0 : return false;
133 : }
134 :
135 3851 : if (!mArray.InsertElementAt(aIndex, aObject)) {
136 0 : return false;
137 : }
138 :
139 3851 : NS_IF_ADDREF(aObject);
140 3851 : return true;
141 : }
142 :
143 : void
144 3 : nsCOMArray_base::InsertElementAt(uint32_t aIndex, nsISupports* aElement)
145 : {
146 3 : mArray.InsertElementAt(aIndex, aElement);
147 3 : NS_IF_ADDREF(aElement);
148 3 : }
149 :
150 : void
151 45 : nsCOMArray_base::InsertElementAt(uint32_t aIndex, already_AddRefed<nsISupports> aElement)
152 : {
153 45 : mArray.InsertElementAt(aIndex, aElement.take());
154 45 : }
155 :
156 : bool
157 758 : nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex)
158 : {
159 758 : if ((uint32_t)aIndex > mArray.Length()) {
160 0 : return false;
161 : }
162 :
163 758 : if (!mArray.InsertElementsAt(aIndex, aObjects.mArray)) {
164 0 : return false;
165 : }
166 :
167 : // need to addref all these
168 758 : uint32_t count = aObjects.Length();
169 758 : for (uint32_t i = 0; i < count; ++i) {
170 0 : NS_IF_ADDREF(aObjects[i]);
171 : }
172 :
173 758 : return true;
174 : }
175 :
176 : void
177 0 : nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
178 : const nsCOMArray_base& aElements)
179 : {
180 0 : mArray.InsertElementsAt(aIndex, aElements.mArray);
181 :
182 : // need to addref all these
183 0 : uint32_t count = aElements.Length();
184 0 : for (uint32_t i = 0; i < count; ++i) {
185 0 : NS_IF_ADDREF(aElements[i]);
186 : }
187 0 : }
188 :
189 : void
190 0 : nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
191 : nsISupports* const* aElements,
192 : uint32_t aCount)
193 : {
194 0 : mArray.InsertElementsAt(aIndex, aElements, aCount);
195 :
196 : // need to addref all these
197 0 : for (uint32_t i = 0; i < aCount; ++i) {
198 0 : NS_IF_ADDREF(aElements[i]);
199 : }
200 0 : }
201 :
202 : void
203 0 : nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, int32_t aIndex)
204 : {
205 0 : mArray.EnsureLengthAtLeast(aIndex + 1);
206 0 : nsISupports* oldObject = mArray[aIndex];
207 : // Make sure to addref first, in case aObject == oldObject
208 0 : NS_IF_ADDREF(mArray[aIndex] = aObject);
209 0 : NS_IF_RELEASE(oldObject);
210 0 : }
211 :
212 : bool
213 22 : nsCOMArray_base::RemoveObject(nsISupports* aObject)
214 : {
215 22 : bool result = mArray.RemoveElement(aObject);
216 22 : if (result) {
217 7 : NS_IF_RELEASE(aObject);
218 : }
219 22 : return result;
220 : }
221 :
222 : bool
223 0 : nsCOMArray_base::RemoveObjectAt(int32_t aIndex)
224 : {
225 0 : if (uint32_t(aIndex) < mArray.Length()) {
226 0 : nsISupports* element = mArray[aIndex];
227 :
228 0 : mArray.RemoveElementAt(aIndex);
229 0 : NS_IF_RELEASE(element);
230 0 : return true;
231 : }
232 :
233 0 : return false;
234 : }
235 :
236 : void
237 0 : nsCOMArray_base::RemoveElementAt(uint32_t aIndex)
238 : {
239 0 : nsISupports* element = mArray[aIndex];
240 0 : mArray.RemoveElementAt(aIndex);
241 0 : NS_IF_RELEASE(element);
242 0 : }
243 :
244 : bool
245 0 : nsCOMArray_base::RemoveObjectsAt(int32_t aIndex, int32_t aCount)
246 : {
247 0 : if (uint32_t(aIndex) + uint32_t(aCount) <= mArray.Length()) {
248 0 : nsTArray<nsISupports*> elementsToDestroy(aCount);
249 0 : elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
250 0 : mArray.RemoveElementsAt(aIndex, aCount);
251 0 : ReleaseObjects(elementsToDestroy);
252 0 : return true;
253 : }
254 :
255 0 : return false;
256 : }
257 :
258 : void
259 0 : nsCOMArray_base::RemoveElementsAt(uint32_t aIndex, uint32_t aCount)
260 : {
261 0 : nsTArray<nsISupports*> elementsToDestroy(aCount);
262 0 : elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
263 0 : mArray.RemoveElementsAt(aIndex, aCount);
264 0 : ReleaseObjects(elementsToDestroy);
265 0 : }
266 :
267 : // useful for destructors
268 : void
269 1002 : ReleaseObjects(nsTArray<nsISupports*>& aArray)
270 : {
271 1396 : for (uint32_t i = 0; i < aArray.Length(); ++i) {
272 394 : NS_IF_RELEASE(aArray[i]);
273 : }
274 1002 : }
275 :
276 : void
277 1002 : nsCOMArray_base::Clear()
278 : {
279 2004 : nsTArray<nsISupports*> objects;
280 1002 : objects.SwapElements(mArray);
281 1002 : ReleaseObjects(objects);
282 1002 : }
283 :
284 : bool
285 0 : nsCOMArray_base::SetCount(int32_t aNewCount)
286 : {
287 0 : NS_ASSERTION(aNewCount >= 0, "SetCount(negative index)");
288 0 : if (aNewCount < 0) {
289 0 : return false;
290 : }
291 :
292 0 : int32_t count = mArray.Length();
293 0 : if (count > aNewCount) {
294 0 : RemoveObjectsAt(aNewCount, mArray.Length() - aNewCount);
295 : }
296 0 : mArray.SetLength(aNewCount);
297 0 : return true;
298 : }
299 :
300 : void
301 0 : nsCOMArray_base::Adopt(nsISupports** aElements, uint32_t aSize)
302 : {
303 0 : Clear();
304 0 : mArray.AppendElements(aElements, aSize);
305 :
306 : // Free the allocated array as well.
307 0 : NS_Free(aElements);
308 0 : }
309 :
310 : uint32_t
311 0 : nsCOMArray_base::Forget(nsISupports*** aElements)
312 : {
313 0 : uint32_t length = Length();
314 0 : size_t array_size = sizeof(nsISupports*) * length;
315 0 : nsISupports** array = static_cast<nsISupports**>(NS_Alloc(array_size));
316 0 : memmove(array, Elements(), array_size);
317 0 : *aElements = array;
318 : // Don't Release the contained pointers; the caller of the method will
319 : // do this eventually.
320 0 : mArray.Clear();
321 :
322 0 : return length;
323 : }
|