Back out due to mochiserver breakage. (no_r=me)
[mozilla-central.git] / xpcom / ds / nsArray.cpp
blob0a5d2f9d253721620a5f44a7a824270954daa91c
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
13 * License.
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.
22 * Contributor(s):
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 ***** */
39 #include "nsArray.h"
40 #include "nsArrayEnumerator.h"
41 #include "nsWeakReference.h"
42 #include "nsThreadUtils.h"
44 // used by IndexOf()
45 struct findIndexOfClosure
47 nsISupports *targetElement;
48 PRUint32 startIndex;
49 PRUint32 resultIndex;
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)
58 NS_INTERFACE_MAP_END
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)
64 NS_INTERFACE_MAP_END
66 nsArray::~nsArray()
68 Clear();
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)
80 tmp->Clear();
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
86 NS_IMETHODIMP
87 nsArray::GetLength(PRUint32* aLength)
89 *aLength = mArray.Count();
90 return NS_OK;
93 NS_IMETHODIMP
94 nsArray::QueryElementAt(PRUint32 aIndex,
95 const nsIID& aIID,
96 void ** aResult)
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);
106 NS_IMETHODIMP
107 nsArray::IndexOf(PRUint32 aStartIndex, nsISupports* aElement,
108 PRUint32* aResult)
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;
116 *aResult = idx;
117 return NS_OK;
120 findIndexOfClosure closure = { aElement, aStartIndex, 0 };
121 PRBool notFound = mArray.EnumerateForwards(FindElementCallback, &closure);
122 if (notFound)
123 return NS_ERROR_FAILURE;
125 *aResult = closure.resultIndex;
126 return NS_OK;
129 NS_IMETHODIMP
130 nsArray::Enumerate(nsISimpleEnumerator **aResult)
132 return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this));
135 // nsIMutableArray implementation
137 NS_IMETHODIMP
138 nsArray::AppendElement(nsISupports* aElement, PRBool aWeak)
140 PRBool result;
141 if (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");
146 if (!elementRef)
147 return NS_ERROR_FAILURE;
148 result = mArray.AppendObject(elementRef);
151 else {
152 // add the object directly
153 result = mArray.AppendObject(aElement);
155 return result ? NS_OK : NS_ERROR_FAILURE;
158 NS_IMETHODIMP
159 nsArray::RemoveElementAt(PRUint32 aIndex)
161 PRBool result = mArray.RemoveObjectAt(aIndex);
162 return result ? NS_OK : NS_ERROR_FAILURE;
165 NS_IMETHODIMP
166 nsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex, PRBool aWeak)
168 nsCOMPtr<nsISupports> elementRef;
169 if (aWeak) {
170 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");
174 if (!elementRef)
175 return NS_ERROR_FAILURE;
176 } else {
177 elementRef = aElement;
179 PRBool result = mArray.InsertObjectAt(elementRef, aIndex);
180 return result ? NS_OK : NS_ERROR_FAILURE;
183 NS_IMETHODIMP
184 nsArray::ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex, PRBool aWeak)
186 nsCOMPtr<nsISupports> elementRef;
187 if (aWeak) {
188 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");
192 if (!elementRef)
193 return NS_ERROR_FAILURE;
194 } else {
195 elementRef = aElement;
197 PRBool result = mArray.ReplaceObjectAt(elementRef, aIndex);
198 return result ? NS_OK : NS_ERROR_FAILURE;
201 NS_IMETHODIMP
202 nsArray::Clear()
204 mArray.Clear();
205 return NS_OK;
209 // static helper routines
211 PRBool
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++;
227 return PR_TRUE;
230 nsresult
231 nsArrayConstructor(nsISupports *aOuter, const nsIID& aIID, void **aResult)
233 if (aOuter)
234 return NS_ERROR_NO_AGGREGATION;
236 nsCOMPtr<nsIArray> inst = NS_IsMainThread() ? new nsArrayCC : new nsArray;
237 if (!inst)
238 return NS_ERROR_OUT_OF_MEMORY;
240 return inst->QueryInterface(aIID, aResult);