xpcom/glue/nsCOMArray.cpp

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

mercurial