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 XPCOM Array implementation.
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 : #include "nsArray.h"
40 : #include "nsArrayEnumerator.h"
41 : #include "nsWeakReference.h"
42 : #include "nsThreadUtils.h"
43 :
44 : // used by IndexOf()
45 : struct findIndexOfClosure
46 : {
47 : nsISupports *targetElement;
48 : PRUint32 startIndex;
49 : PRUint32 resultIndex;
50 : };
51 :
52 : static bool FindElementCallback(void* aElement, void* aClosure);
53 :
54 88 : NS_INTERFACE_MAP_BEGIN(nsArray)
55 88 : NS_INTERFACE_MAP_ENTRY(nsIArray)
56 44 : NS_INTERFACE_MAP_ENTRY(nsIMutableArray)
57 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray)
58 0 : NS_INTERFACE_MAP_END
59 :
60 33126 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsArrayCC)
61 25288 : NS_INTERFACE_MAP_ENTRY(nsIArray)
62 22372 : NS_INTERFACE_MAP_ENTRY(nsIMutableArray)
63 18640 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray)
64 12743 : NS_INTERFACE_MAP_END
65 :
66 3238 : nsArray::~nsArray()
67 : {
68 1619 : Clear();
69 1619 : }
70 :
71 :
72 176 : NS_IMPL_ADDREF(nsArray)
73 220 : NS_IMPL_RELEASE(nsArray)
74 :
75 14581 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsArrayCC)
76 16156 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsArrayCC)
77 :
78 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsArrayCC)
79 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsArrayCC)
80 0 : tmp->Clear();
81 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
82 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsArrayCC)
83 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mArray)
84 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
85 :
86 : NS_IMETHODIMP
87 2112 : nsArray::GetLength(PRUint32* aLength)
88 : {
89 2112 : *aLength = mArray.Count();
90 2112 : return NS_OK;
91 : }
92 :
93 : NS_IMETHODIMP
94 1116 : nsArray::QueryElementAt(PRUint32 aIndex,
95 : const nsIID& aIID,
96 : void ** aResult)
97 : {
98 1116 : nsISupports * obj = mArray.SafeObjectAt(aIndex);
99 1116 : if (!obj) return NS_ERROR_ILLEGAL_VALUE;
100 :
101 : // no need to worry about a leak here, because SafeObjectAt()
102 : // doesn't addref its result
103 1116 : return obj->QueryInterface(aIID, aResult);
104 : }
105 :
106 : NS_IMETHODIMP
107 0 : nsArray::IndexOf(PRUint32 aStartIndex, nsISupports* aElement,
108 : PRUint32* aResult)
109 : {
110 : // optimize for the common case by forwarding to mArray
111 0 : if (aStartIndex == 0) {
112 0 : PRUint32 idx = mArray.IndexOf(aElement);
113 0 : if (idx == PR_UINT32_MAX)
114 0 : return NS_ERROR_FAILURE;
115 :
116 0 : *aResult = idx;
117 0 : return NS_OK;
118 : }
119 :
120 0 : findIndexOfClosure closure = { aElement, aStartIndex, 0 };
121 0 : bool notFound = mArray.EnumerateForwards(FindElementCallback, &closure);
122 0 : if (notFound)
123 0 : return NS_ERROR_FAILURE;
124 :
125 0 : *aResult = closure.resultIndex;
126 0 : return NS_OK;
127 : }
128 :
129 : NS_IMETHODIMP
130 31 : nsArray::Enumerate(nsISimpleEnumerator **aResult)
131 : {
132 31 : return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this));
133 : }
134 :
135 : // nsIMutableArray implementation
136 :
137 : NS_IMETHODIMP
138 992 : nsArray::AppendElement(nsISupports* aElement, bool aWeak)
139 : {
140 : bool result;
141 992 : if (aWeak) {
142 : nsCOMPtr<nsISupports> elementRef =
143 : getter_AddRefs(static_cast<nsISupports*>
144 0 : (NS_GetWeakReference(aElement)));
145 0 : NS_ASSERTION(elementRef, "AppendElement: Trying to use weak references on an object that doesn't support it");
146 0 : if (!elementRef)
147 0 : return NS_ERROR_FAILURE;
148 0 : result = mArray.AppendObject(elementRef);
149 : }
150 :
151 : else {
152 : // add the object directly
153 992 : result = mArray.AppendObject(aElement);
154 : }
155 992 : return result ? NS_OK : NS_ERROR_FAILURE;
156 : }
157 :
158 : NS_IMETHODIMP
159 1 : nsArray::RemoveElementAt(PRUint32 aIndex)
160 : {
161 1 : bool result = mArray.RemoveObjectAt(aIndex);
162 1 : return result ? NS_OK : NS_ERROR_FAILURE;
163 : }
164 :
165 : NS_IMETHODIMP
166 1 : nsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex, bool aWeak)
167 : {
168 2 : nsCOMPtr<nsISupports> elementRef;
169 1 : if (aWeak) {
170 : elementRef =
171 : getter_AddRefs(static_cast<nsISupports*>
172 0 : (NS_GetWeakReference(aElement)));
173 0 : NS_ASSERTION(elementRef, "InsertElementAt: Trying to use weak references on an object that doesn't support it");
174 0 : if (!elementRef)
175 0 : return NS_ERROR_FAILURE;
176 : } else {
177 1 : elementRef = aElement;
178 : }
179 1 : bool result = mArray.InsertObjectAt(elementRef, aIndex);
180 1 : return result ? NS_OK : NS_ERROR_FAILURE;
181 : }
182 :
183 : NS_IMETHODIMP
184 315 : nsArray::ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex, bool aWeak)
185 : {
186 630 : nsCOMPtr<nsISupports> elementRef;
187 315 : if (aWeak) {
188 : elementRef =
189 : getter_AddRefs(static_cast<nsISupports*>
190 0 : (NS_GetWeakReference(aElement)));
191 0 : NS_ASSERTION(elementRef, "ReplaceElementAt: Trying to use weak references on an object that doesn't support it");
192 0 : if (!elementRef)
193 0 : return NS_ERROR_FAILURE;
194 : } else {
195 315 : elementRef = aElement;
196 : }
197 315 : bool result = mArray.ReplaceObjectAt(elementRef, aIndex);
198 315 : return result ? NS_OK : NS_ERROR_FAILURE;
199 : }
200 :
201 : NS_IMETHODIMP
202 1620 : nsArray::Clear()
203 : {
204 1620 : mArray.Clear();
205 1620 : return NS_OK;
206 : }
207 :
208 : //
209 : // static helper routines
210 : //
211 : bool
212 0 : FindElementCallback(void *aElement, void* aClosure)
213 : {
214 : findIndexOfClosure* closure =
215 0 : static_cast<findIndexOfClosure*>(aClosure);
216 :
217 : nsISupports* element =
218 0 : static_cast<nsISupports*>(aElement);
219 :
220 : // don't start searching until we're past the startIndex
221 0 : if (closure->resultIndex >= closure->startIndex &&
222 : element == closure->targetElement) {
223 0 : return false; // stop! We found it
224 : }
225 0 : closure->resultIndex++;
226 :
227 0 : return true;
228 : }
229 :
230 : nsresult
231 1575 : nsArrayConstructor(nsISupports *aOuter, const nsIID& aIID, void **aResult)
232 : {
233 1575 : if (aOuter)
234 0 : return NS_ERROR_NO_AGGREGATION;
235 :
236 4725 : nsCOMPtr<nsIArray> inst = NS_IsMainThread() ? new nsArrayCC : new nsArray;
237 1575 : if (!inst)
238 0 : return NS_ERROR_OUT_OF_MEMORY;
239 :
240 1575 : return inst->QueryInterface(aIID, aResult);
241 4392 : }
|