xpcom/ds/nsArray.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:18c60abd499f
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 "nsArray.h"
7 #include "nsArrayEnumerator.h"
8 #include "nsIWeakReference.h"
9 #include "nsIWeakReferenceUtils.h"
10 #include "nsThreadUtils.h"
11
12 // used by IndexOf()
13 struct findIndexOfClosure
14 {
15 nsISupports *targetElement;
16 uint32_t startIndex;
17 uint32_t resultIndex;
18 };
19
20 static bool FindElementCallback(void* aElement, void* aClosure);
21
22 NS_INTERFACE_MAP_BEGIN(nsArray)
23 NS_INTERFACE_MAP_ENTRY(nsIArray)
24 NS_INTERFACE_MAP_ENTRY(nsIMutableArray)
25 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray)
26 NS_INTERFACE_MAP_END
27
28 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsArrayCC)
29 NS_INTERFACE_MAP_ENTRY(nsIArray)
30 NS_INTERFACE_MAP_ENTRY(nsIMutableArray)
31 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray)
32 NS_INTERFACE_MAP_END
33
34 nsArray::~nsArray()
35 {
36 Clear();
37 }
38
39
40 NS_IMPL_ADDREF(nsArray)
41 NS_IMPL_RELEASE(nsArray)
42
43 NS_IMPL_CYCLE_COLLECTION_CLASS(nsArrayCC)
44
45 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsArrayCC)
46 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsArrayCC)
47
48 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsArrayCC)
49 tmp->Clear();
50 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
51 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsArrayCC)
52 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArray)
53 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
54
55 NS_IMETHODIMP
56 nsArray::GetLength(uint32_t* aLength)
57 {
58 *aLength = mArray.Count();
59 return NS_OK;
60 }
61
62 NS_IMETHODIMP
63 nsArray::QueryElementAt(uint32_t aIndex,
64 const nsIID& aIID,
65 void ** aResult)
66 {
67 nsISupports * obj = mArray.SafeObjectAt(aIndex);
68 if (!obj) return NS_ERROR_ILLEGAL_VALUE;
69
70 // no need to worry about a leak here, because SafeObjectAt()
71 // doesn't addref its result
72 return obj->QueryInterface(aIID, aResult);
73 }
74
75 NS_IMETHODIMP
76 nsArray::IndexOf(uint32_t aStartIndex, nsISupports* aElement,
77 uint32_t* aResult)
78 {
79 // optimize for the common case by forwarding to mArray
80 if (aStartIndex == 0) {
81 uint32_t idx = mArray.IndexOf(aElement);
82 if (idx == UINT32_MAX)
83 return NS_ERROR_FAILURE;
84
85 *aResult = idx;
86 return NS_OK;
87 }
88
89 findIndexOfClosure closure = { aElement, aStartIndex, 0 };
90 bool notFound = mArray.EnumerateForwards(FindElementCallback, &closure);
91 if (notFound)
92 return NS_ERROR_FAILURE;
93
94 *aResult = closure.resultIndex;
95 return NS_OK;
96 }
97
98 NS_IMETHODIMP
99 nsArray::Enumerate(nsISimpleEnumerator **aResult)
100 {
101 return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this));
102 }
103
104 // nsIMutableArray implementation
105
106 NS_IMETHODIMP
107 nsArray::AppendElement(nsISupports* aElement, bool aWeak)
108 {
109 bool result;
110 if (aWeak) {
111 nsCOMPtr<nsIWeakReference> elementRef = do_GetWeakReference(aElement);
112 NS_ASSERTION(elementRef, "AppendElement: Trying to use weak references on an object that doesn't support it");
113 if (!elementRef)
114 return NS_ERROR_FAILURE;
115 result = mArray.AppendObject(elementRef);
116 }
117
118 else {
119 // add the object directly
120 result = mArray.AppendObject(aElement);
121 }
122 return result ? NS_OK : NS_ERROR_FAILURE;
123 }
124
125 NS_IMETHODIMP
126 nsArray::RemoveElementAt(uint32_t aIndex)
127 {
128 bool result = mArray.RemoveObjectAt(aIndex);
129 return result ? NS_OK : NS_ERROR_FAILURE;
130 }
131
132 NS_IMETHODIMP
133 nsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex, bool aWeak)
134 {
135 nsCOMPtr<nsISupports> elementRef;
136 if (aWeak) {
137 elementRef = do_GetWeakReference(aElement);
138 NS_ASSERTION(elementRef, "InsertElementAt: Trying to use weak references on an object that doesn't support it");
139 if (!elementRef)
140 return NS_ERROR_FAILURE;
141 } else {
142 elementRef = aElement;
143 }
144 bool result = mArray.InsertObjectAt(elementRef, aIndex);
145 return result ? NS_OK : NS_ERROR_FAILURE;
146 }
147
148 NS_IMETHODIMP
149 nsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex, bool aWeak)
150 {
151 nsCOMPtr<nsISupports> elementRef;
152 if (aWeak) {
153 elementRef = do_GetWeakReference(aElement);
154 NS_ASSERTION(elementRef, "ReplaceElementAt: Trying to use weak references on an object that doesn't support it");
155 if (!elementRef)
156 return NS_ERROR_FAILURE;
157 } else {
158 elementRef = aElement;
159 }
160 bool result = mArray.ReplaceObjectAt(elementRef, aIndex);
161 return result ? NS_OK : NS_ERROR_FAILURE;
162 }
163
164 NS_IMETHODIMP
165 nsArray::Clear()
166 {
167 mArray.Clear();
168 return NS_OK;
169 }
170
171 //
172 // static helper routines
173 //
174 bool
175 FindElementCallback(void *aElement, void* aClosure)
176 {
177 findIndexOfClosure* closure =
178 static_cast<findIndexOfClosure*>(aClosure);
179
180 nsISupports* element =
181 static_cast<nsISupports*>(aElement);
182
183 // don't start searching until we're past the startIndex
184 if (closure->resultIndex >= closure->startIndex &&
185 element == closure->targetElement) {
186 return false; // stop! We found it
187 }
188 closure->resultIndex++;
189
190 return true;
191 }
192
193 nsresult
194 nsArray::XPCOMConstructor(nsISupports *aOuter, const nsIID& aIID, void **aResult)
195 {
196 if (aOuter)
197 return NS_ERROR_NO_AGGREGATION;
198
199 nsCOMPtr<nsIMutableArray> inst = Create();
200 return inst->QueryInterface(aIID, aResult);
201 }
202
203 already_AddRefed<nsIMutableArray>
204 nsArray::Create()
205 {
206 nsCOMPtr<nsIMutableArray> inst = NS_IsMainThread() ? new nsArrayCC : new nsArray;
207 return inst.forget();
208 }

mercurial