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
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/
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
15 * The Original Code is XPCOM Array implementation.
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.
23 * Alec Flett <alecf@netscape.com>
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.
37 * ***** END LICENSE BLOCK ***** */
40 #include "nsArrayEnumerator.h"
41 #include "nsWeakReference.h"
42 #include "nsThreadUtils.h"
45 struct findIndexOfClosure
47 nsISupports
*targetElement
;
52 static PRBool
FindElementCallback(void* aElement
, void* aClosure
);
54 NS_INTERFACE_MAP_BEGIN(nsArray
)
55 NS_INTERFACE_MAP_ENTRY(nsIArray
)
56 NS_INTERFACE_MAP_ENTRY(nsIMutableArray
)
57 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIMutableArray
)
60 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsArrayCC
)
61 NS_INTERFACE_MAP_ENTRY(nsIArray
)
62 NS_INTERFACE_MAP_ENTRY(nsIMutableArray
)
63 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIMutableArray
)
72 NS_IMPL_ADDREF(nsArray
)
73 NS_IMPL_RELEASE(nsArray
)
75 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsArrayCC
)
76 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsArrayCC
)
78 NS_IMPL_CYCLE_COLLECTION_CLASS(nsArrayCC
)
79 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsArrayCC
)
81 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
82 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsArrayCC
)
83 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mArray
)
84 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
87 nsArray::GetLength(PRUint32
* aLength
)
89 *aLength
= mArray
.Count();
94 nsArray::QueryElementAt(PRUint32 aIndex
,
98 nsISupports
* obj
= mArray
.SafeObjectAt(aIndex
);
99 if (!obj
) return NS_ERROR_ILLEGAL_VALUE
;
101 // no need to worry about a leak here, because SafeObjectAt()
102 // doesn't addref its result
103 return obj
->QueryInterface(aIID
, aResult
);
107 nsArray::IndexOf(PRUint32 aStartIndex
, nsISupports
* aElement
,
110 // optimize for the common case by forwarding to mArray
111 if (aStartIndex
== 0) {
112 PRUint32 idx
= mArray
.IndexOf(aElement
);
113 if (idx
== PR_UINT32_MAX
)
114 return NS_ERROR_FAILURE
;
120 findIndexOfClosure closure
= { aElement
, aStartIndex
, 0 };
121 PRBool notFound
= mArray
.EnumerateForwards(FindElementCallback
, &closure
);
123 return NS_ERROR_FAILURE
;
125 *aResult
= closure
.resultIndex
;
130 nsArray::Enumerate(nsISimpleEnumerator
**aResult
)
132 return NS_NewArrayEnumerator(aResult
, static_cast<nsIArray
*>(this));
135 // nsIMutableArray implementation
138 nsArray::AppendElement(nsISupports
* aElement
, PRBool aWeak
)
142 nsCOMPtr
<nsISupports
> elementRef
=
143 getter_AddRefs(static_cast<nsISupports
*>
144 (NS_GetWeakReference(aElement
)));
145 NS_ASSERTION(elementRef
, "AppendElement: Trying to use weak references on an object that doesn't support it");
147 return NS_ERROR_FAILURE
;
148 result
= mArray
.AppendObject(elementRef
);
152 // add the object directly
153 result
= mArray
.AppendObject(aElement
);
155 return result
? NS_OK
: NS_ERROR_FAILURE
;
159 nsArray::RemoveElementAt(PRUint32 aIndex
)
161 PRBool result
= mArray
.RemoveObjectAt(aIndex
);
162 return result
? NS_OK
: NS_ERROR_FAILURE
;
166 nsArray::InsertElementAt(nsISupports
* aElement
, PRUint32 aIndex
, PRBool aWeak
)
168 nsCOMPtr
<nsISupports
> elementRef
;
171 getter_AddRefs(static_cast<nsISupports
*>
172 (NS_GetWeakReference(aElement
)));
173 NS_ASSERTION(elementRef
, "InsertElementAt: Trying to use weak references on an object that doesn't support it");
175 return NS_ERROR_FAILURE
;
177 elementRef
= aElement
;
179 PRBool result
= mArray
.InsertObjectAt(elementRef
, aIndex
);
180 return result
? NS_OK
: NS_ERROR_FAILURE
;
184 nsArray::ReplaceElementAt(nsISupports
* aElement
, PRUint32 aIndex
, PRBool aWeak
)
186 nsCOMPtr
<nsISupports
> elementRef
;
189 getter_AddRefs(static_cast<nsISupports
*>
190 (NS_GetWeakReference(aElement
)));
191 NS_ASSERTION(elementRef
, "ReplaceElementAt: Trying to use weak references on an object that doesn't support it");
193 return NS_ERROR_FAILURE
;
195 elementRef
= aElement
;
197 PRBool result
= mArray
.ReplaceObjectAt(elementRef
, aIndex
);
198 return result
? NS_OK
: NS_ERROR_FAILURE
;
209 // static helper routines
212 FindElementCallback(void *aElement
, void* aClosure
)
214 findIndexOfClosure
* closure
=
215 static_cast<findIndexOfClosure
*>(aClosure
);
217 nsISupports
* element
=
218 static_cast<nsISupports
*>(aElement
);
220 // don't start searching until we're past the startIndex
221 if (closure
->resultIndex
>= closure
->startIndex
&&
222 element
== closure
->targetElement
) {
223 return PR_FALSE
; // stop! We found it
225 closure
->resultIndex
++;
230 NS_METHOD
nsArrayConstructor(nsISupports
*aOuter
, const nsIID
& aIID
, void **aResult
) {
232 return NS_ERROR_NO_AGGREGATION
;
234 nsCOMPtr
<nsIArray
> inst
= NS_IsMainThread() ? new nsArrayCC
: new nsArray
;
236 return NS_ERROR_OUT_OF_MEMORY
;
238 return inst
->QueryInterface(aIID
, aResult
);