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/. */
7 #include "nsArrayEnumerator.h"
8 #include "nsIWeakReference.h"
9 #include "nsIWeakReferenceUtils.h"
10 #include "nsThreadUtils.h"
13 struct findIndexOfClosure
15 nsISupports
* targetElement
;
20 static bool FindElementCallback(void* aElement
, void* aClosure
);
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
)
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
)
34 nsArrayBase::~nsArrayBase()
40 NS_IMPL_ADDREF(nsArray
)
41 NS_IMPL_RELEASE(nsArray
)
43 NS_IMPL_CYCLE_COLLECTION_CLASS(nsArrayCC
)
45 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsArrayCC
)
46 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsArrayCC
)
48 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsArrayCC
)
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
56 nsArrayBase::GetLength(uint32_t* aLength
)
58 *aLength
= mArray
.Count();
63 nsArrayBase::QueryElementAt(uint32_t aIndex
,
67 nsISupports
* obj
= mArray
.SafeObjectAt(aIndex
);
69 return NS_ERROR_ILLEGAL_VALUE
;
72 // no need to worry about a leak here, because SafeObjectAt()
73 // doesn't addref its result
74 return obj
->QueryInterface(aIID
, aResult
);
78 nsArrayBase::IndexOf(uint32_t aStartIndex
, nsISupports
* aElement
,
81 // optimize for the common case by forwarding to mArray
82 if (aStartIndex
== 0) {
83 uint32_t idx
= mArray
.IndexOf(aElement
);
84 if (idx
== UINT32_MAX
) {
85 return NS_ERROR_FAILURE
;
92 findIndexOfClosure closure
= { aElement
, aStartIndex
, 0 };
93 bool notFound
= mArray
.EnumerateForwards(FindElementCallback
, &closure
);
95 return NS_ERROR_FAILURE
;
98 *aResult
= closure
.resultIndex
;
103 nsArrayBase::Enumerate(nsISimpleEnumerator
** aResult
)
105 return NS_NewArrayEnumerator(aResult
, static_cast<nsIArray
*>(this));
108 // nsIMutableArray implementation
111 nsArrayBase::AppendElement(nsISupports
* aElement
, bool aWeak
)
115 nsCOMPtr
<nsIWeakReference
> elementRef
= do_GetWeakReference(aElement
);
116 NS_ASSERTION(elementRef
,
117 "AppendElement: Trying to use weak references on an object that doesn't support it");
119 return NS_ERROR_FAILURE
;
121 result
= mArray
.AppendObject(elementRef
);
125 // add the object directly
126 result
= mArray
.AppendObject(aElement
);
128 return result
? NS_OK
: NS_ERROR_FAILURE
;
132 nsArrayBase::RemoveElementAt(uint32_t aIndex
)
134 bool result
= mArray
.RemoveObjectAt(aIndex
);
135 return result
? NS_OK
: NS_ERROR_FAILURE
;
139 nsArrayBase::InsertElementAt(nsISupports
* aElement
, uint32_t aIndex
, bool aWeak
)
141 nsCOMPtr
<nsISupports
> elementRef
;
143 elementRef
= do_GetWeakReference(aElement
);
144 NS_ASSERTION(elementRef
,
145 "InsertElementAt: Trying to use weak references on an object that doesn't support it");
147 return NS_ERROR_FAILURE
;
150 elementRef
= aElement
;
152 bool result
= mArray
.InsertObjectAt(elementRef
, aIndex
);
153 return result
? NS_OK
: NS_ERROR_FAILURE
;
157 nsArrayBase::ReplaceElementAt(nsISupports
* aElement
, uint32_t aIndex
, bool aWeak
)
159 nsCOMPtr
<nsISupports
> elementRef
;
161 elementRef
= do_GetWeakReference(aElement
);
162 NS_ASSERTION(elementRef
,
163 "ReplaceElementAt: Trying to use weak references on an object that doesn't support it");
165 return NS_ERROR_FAILURE
;
168 elementRef
= aElement
;
170 bool result
= mArray
.ReplaceObjectAt(elementRef
, aIndex
);
171 return result
? NS_OK
: NS_ERROR_FAILURE
;
182 // static helper routines
185 FindElementCallback(void* aElement
, void* aClosure
)
187 findIndexOfClosure
* closure
= static_cast<findIndexOfClosure
*>(aClosure
);
188 nsISupports
* element
= static_cast<nsISupports
*>(aElement
);
190 // don't start searching until we're past the startIndex
191 if (closure
->resultIndex
>= closure
->startIndex
&&
192 element
== closure
->targetElement
) {
193 return false; // stop! We found it
195 closure
->resultIndex
++;
201 nsArrayBase::XPCOMConstructor(nsISupports
* aOuter
, const nsIID
& aIID
,
205 return NS_ERROR_NO_AGGREGATION
;
208 nsCOMPtr
<nsIMutableArray
> inst
= Create();
209 return inst
->QueryInterface(aIID
, aResult
);
212 already_AddRefed
<nsIMutableArray
>
213 nsArrayBase::Create()
215 nsCOMPtr
<nsIMutableArray
> inst
;
216 if (NS_IsMainThread()) {
217 inst
= new nsArrayCC
;
221 return inst
.forget();