1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is a COM aware array class.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corp.
19 : * Portions created by the Initial Developer are Copyright (C) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Alec Flett <alecf@netscape.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef nsCOMArray_h__
40 : #define nsCOMArray_h__
41 :
42 : #include "mozilla/Attributes.h"
43 :
44 : #include "nsVoidArray.h"
45 : #include "nsISupports.h"
46 :
47 : // See below for the definition of nsCOMArray<T>
48 :
49 : // a class that's nsISupports-specific, so that we can contain the
50 : // work of this class in the XPCOM dll
51 : class NS_COM_GLUE nsCOMArray_base
52 : {
53 : friend class nsArray;
54 : protected:
55 255963 : nsCOMArray_base() {}
56 4352 : nsCOMArray_base(PRInt32 aCount) : mArray(aCount) {}
57 : nsCOMArray_base(const nsCOMArray_base& other);
58 : ~nsCOMArray_base();
59 :
60 32521 : PRInt32 IndexOf(nsISupports* aObject) const {
61 32521 : return mArray.IndexOf(aObject);
62 : }
63 :
64 : PRInt32 IndexOfObject(nsISupports* aObject) const;
65 :
66 0 : bool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData) {
67 0 : return mArray.EnumerateForwards(aFunc, aData);
68 : }
69 :
70 0 : bool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData) {
71 0 : return mArray.EnumerateBackwards(aFunc, aData);
72 : }
73 :
74 3935 : void Sort(nsVoidArrayComparatorFunc aFunc, void* aData) {
75 3935 : mArray.Sort(aFunc, aData);
76 3935 : }
77 :
78 : // any method which is not a direct forward to mArray should
79 : // avoid inline bodies, so that the compiler doesn't inline them
80 : // all over the place
81 : void Clear();
82 : bool InsertObjectAt(nsISupports* aObject, PRInt32 aIndex);
83 : bool InsertObjectsAt(const nsCOMArray_base& aObjects, PRInt32 aIndex);
84 : bool ReplaceObjectAt(nsISupports* aObject, PRInt32 aIndex);
85 176114 : bool AppendObject(nsISupports *aObject) {
86 176114 : return InsertObjectAt(aObject, Count());
87 : }
88 4721 : bool AppendObjects(const nsCOMArray_base& aObjects) {
89 4721 : return InsertObjectsAt(aObjects, Count());
90 : }
91 : bool RemoveObject(nsISupports *aObject);
92 : bool RemoveObjectAt(PRInt32 aIndex);
93 : bool RemoveObjectsAt(PRInt32 aIndex, PRInt32 aCount);
94 :
95 : public:
96 : // override nsVoidArray stuff so that they can be accessed by
97 : // consumers of nsCOMArray
98 1261547 : PRInt32 Count() const {
99 1261547 : return mArray.Count();
100 : }
101 : // If the array grows, the newly created entries will all be null;
102 : // if the array shrinks, the excess entries will all be released.
103 : bool SetCount(PRInt32 aNewCount);
104 :
105 668558 : nsISupports* ObjectAt(PRInt32 aIndex) const {
106 668558 : return static_cast<nsISupports*>(mArray.FastElementAt(aIndex));
107 : }
108 :
109 2384 : nsISupports* SafeObjectAt(PRInt32 aIndex) const {
110 2384 : return static_cast<nsISupports*>(mArray.SafeElementAt(aIndex));
111 : }
112 :
113 0 : nsISupports* operator[](PRInt32 aIndex) const {
114 0 : return ObjectAt(aIndex);
115 : }
116 :
117 : // Ensures there is enough space to store a total of aCapacity objects.
118 : // This method never deletes any objects.
119 120606 : bool SetCapacity(PRUint32 aCapacity) {
120 120247 : return aCapacity > 0 ? mArray.SizeTo(static_cast<PRInt32>(aCapacity))
121 240853 : : true;
122 : }
123 :
124 : // Measures the size of the array's element storage, and if
125 : // |aSizeOfElement| is non-NULL, measures the size of things pointed to by
126 : // elements.
127 0 : size_t SizeOfExcludingThis(
128 : nsVoidArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
129 : nsMallocSizeOfFun aMallocSizeOf, void* aData = NULL) const {
130 : return mArray.SizeOfExcludingThis(aSizeOfElementIncludingThis,
131 0 : aMallocSizeOf, aData);
132 : }
133 :
134 : private:
135 :
136 : // the actual storage
137 : nsVoidArray mArray;
138 :
139 : // don't implement these, defaults will muck with refcounts!
140 : nsCOMArray_base& operator=(const nsCOMArray_base& other) MOZ_DELETE;
141 : };
142 :
143 : // a non-XPCOM, refcounting array of XPCOM objects
144 : // used as a member variable or stack variable - this object is NOT
145 : // refcounted, but the objects that it holds are
146 : //
147 : // most of the read-only accessors like ObjectAt()/etc do NOT refcount
148 : // on the way out. This means that you can do one of two things:
149 : //
150 : // * does an addref, but holds onto a reference
151 : // nsCOMPtr<T> foo = array[i];
152 : //
153 : // * avoids the refcount, but foo might go stale if array[i] is ever
154 : // * modified/removed. Be careful not to NS_RELEASE(foo)!
155 : // T* foo = array[i];
156 : //
157 : // This array will accept null as an argument for any object, and will
158 : // store null in the array, just like nsVoidArray. But that also means
159 : // that methods like ObjectAt() may return null when referring to an
160 : // existing, but null entry in the array.
161 : template <class T>
162 : class nsCOMArray : public nsCOMArray_base
163 : {
164 : public:
165 254344 : nsCOMArray() {}
166 4352 : nsCOMArray(PRInt32 aCount) : nsCOMArray_base(aCount) {}
167 :
168 : // only to be used by trusted classes who are going to pass us the
169 : // right type!
170 1353 : nsCOMArray(const nsCOMArray<T>& aOther) : nsCOMArray_base(aOther) { }
171 :
172 260008 : ~nsCOMArray() {}
173 :
174 : // these do NOT refcount on the way out, for speed
175 649766 : T* ObjectAt(PRInt32 aIndex) const {
176 649766 : return static_cast<T*>(nsCOMArray_base::ObjectAt(aIndex));
177 : }
178 :
179 : // these do NOT refcount on the way out, for speed
180 1268 : T* SafeObjectAt(PRInt32 aIndex) const {
181 1268 : return static_cast<T*>(nsCOMArray_base::SafeObjectAt(aIndex));
182 : }
183 :
184 : // indexing operator for syntactic sugar
185 400992 : T* operator[](PRInt32 aIndex) const {
186 400992 : return ObjectAt(aIndex);
187 : }
188 :
189 : // index of the element in question.. does NOT refcount
190 : // note: this does not check COM object identity. Use
191 : // IndexOfObject() for that purpose
192 32521 : PRInt32 IndexOf(T* aObject) const {
193 32521 : return nsCOMArray_base::IndexOf(static_cast<nsISupports*>(aObject));
194 : }
195 :
196 : // index of the element in question.. be careful!
197 : // this is much slower than IndexOf() because it uses
198 : // QueryInterface to determine actual COM identity of the object
199 : // if you need to do this frequently then consider enforcing
200 : // COM object identity before adding/comparing elements
201 198 : PRInt32 IndexOfObject(T* aObject) const {
202 198 : return nsCOMArray_base::IndexOfObject(static_cast<nsISupports*>(aObject));
203 : }
204 :
205 : // inserts aObject at aIndex, shifting the objects at aIndex and
206 : // later to make space
207 286949 : bool InsertObjectAt(T* aObject, PRInt32 aIndex) {
208 286949 : return nsCOMArray_base::InsertObjectAt(static_cast<nsISupports*>(aObject), aIndex);
209 : }
210 :
211 : // inserts the objects from aObject at aIndex, shifting the
212 : // objects at aIndex and later to make space
213 0 : bool InsertObjectsAt(const nsCOMArray<T>& aObjects, PRInt32 aIndex) {
214 0 : return nsCOMArray_base::InsertObjectsAt(aObjects, aIndex);
215 : }
216 :
217 : // replaces an existing element. Warning: if the array grows,
218 : // the newly created entries will all be null
219 237948 : bool ReplaceObjectAt(T* aObject, PRInt32 aIndex) {
220 237948 : return nsCOMArray_base::ReplaceObjectAt(static_cast<nsISupports*>(aObject), aIndex);
221 : }
222 :
223 : // override nsVoidArray stuff so that they can be accessed by
224 : // other methods
225 :
226 : // elements in the array (including null elements!)
227 1068952 : PRInt32 Count() const {
228 1068952 : return nsCOMArray_base::Count();
229 : }
230 :
231 : // remove all elements in the array, and call NS_RELEASE on each one
232 30536 : void Clear() {
233 30536 : nsCOMArray_base::Clear();
234 30536 : }
235 :
236 : // Enumerator callback function. Return false to stop
237 : // Here's a more readable form:
238 : // bool enumerate(T* aElement, void* aData)
239 : typedef bool (* nsCOMArrayEnumFunc)
240 : (T* aElement, void *aData);
241 :
242 : // enumerate through the array with a callback.
243 0 : bool EnumerateForwards(nsCOMArrayEnumFunc aFunc, void* aData) {
244 : return nsCOMArray_base::EnumerateForwards(nsVoidArrayEnumFunc(aFunc),
245 0 : aData);
246 : }
247 :
248 0 : bool EnumerateBackwards(nsCOMArrayEnumFunc aFunc, void* aData) {
249 : return nsCOMArray_base::EnumerateBackwards(nsVoidArrayEnumFunc(aFunc),
250 0 : aData);
251 : }
252 :
253 : typedef int (* nsCOMArrayComparatorFunc)
254 : (T* aElement1, T* aElement2, void* aData);
255 :
256 3935 : void Sort(nsCOMArrayComparatorFunc aFunc, void* aData) {
257 3935 : nsCOMArray_base::Sort(nsVoidArrayComparatorFunc(aFunc), aData);
258 3935 : }
259 :
260 : // append an object, growing the array as necessary
261 175122 : bool AppendObject(T *aObject) {
262 175122 : return nsCOMArray_base::AppendObject(static_cast<nsISupports*>(aObject));
263 : }
264 :
265 : // append objects, growing the array as necessary
266 3368 : bool AppendObjects(const nsCOMArray<T>& aObjects) {
267 3368 : return nsCOMArray_base::AppendObjects(aObjects);
268 : }
269 :
270 : // remove the first instance of the given object and shrink the
271 : // array as necessary
272 : // Warning: if you pass null here, it will remove the first null element
273 14102 : bool RemoveObject(T *aObject) {
274 14102 : return nsCOMArray_base::RemoveObject(static_cast<nsISupports*>(aObject));
275 : }
276 :
277 : // remove an element at a specific position, shrinking the array
278 : // as necessary
279 296 : bool RemoveObjectAt(PRInt32 aIndex) {
280 296 : return nsCOMArray_base::RemoveObjectAt(aIndex);
281 : }
282 :
283 : // remove a range of elements at a specific position, shrinking the array
284 : // as necessary
285 2 : bool RemoveObjectsAt(PRInt32 aIndex, PRInt32 aCount) {
286 2 : return nsCOMArray_base::RemoveObjectsAt(aIndex, aCount);
287 : }
288 :
289 : // Each element in an nsCOMArray<T> is actually a T*, so this function is
290 : // "IncludingThis" rather than "ExcludingThis" because it needs to measure
291 : // the memory taken by the T itself as well as anything it points to.
292 : typedef size_t (* nsCOMArraySizeOfElementIncludingThisFunc)
293 : (T* aElement, nsMallocSizeOfFun aMallocSizeOf, void *aData);
294 :
295 0 : size_t SizeOfExcludingThis(
296 : nsCOMArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis,
297 : nsMallocSizeOfFun aMallocSizeOf, void *aData = NULL) const {
298 : return nsCOMArray_base::SizeOfExcludingThis(
299 : nsVoidArraySizeOfElementIncludingThisFunc(aSizeOfElementIncludingThis),
300 0 : aMallocSizeOf, aData);
301 : }
302 :
303 : private:
304 :
305 : // don't implement these!
306 : nsCOMArray<T>& operator=(const nsCOMArray<T>& other) MOZ_DELETE;
307 : };
308 :
309 :
310 : #endif
|