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 "nsWeakReference.h"
9 #include "nsThreadUtils.h"
12 struct findIndexOfClosure
14 nsISupports
*targetElement
;
19 static bool FindElementCallback(void* aElement
, void* aClosure
);
21 NS_INTERFACE_MAP_BEGIN(nsArray
)
22 NS_INTERFACE_MAP_ENTRY(nsIArray
)
23 NS_INTERFACE_MAP_ENTRY(nsIMutableArray
)
24 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIMutableArray
)
27 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsArrayCC
)
28 NS_INTERFACE_MAP_ENTRY(nsIArray
)
29 NS_INTERFACE_MAP_ENTRY(nsIMutableArray
)
30 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIMutableArray
)
39 NS_IMPL_ADDREF(nsArray
)
40 NS_IMPL_RELEASE(nsArray
)
42 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsArrayCC
)
43 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsArrayCC
)
45 NS_IMPL_CYCLE_COLLECTION_CLASS(nsArrayCC
)
46 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsArrayCC
)
48 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
49 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsArrayCC
)
50 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArray
)
51 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
54 nsArray::GetLength(uint32_t* aLength
)
56 *aLength
= mArray
.Count();
61 nsArray::QueryElementAt(uint32_t aIndex
,
65 nsISupports
* obj
= mArray
.SafeObjectAt(aIndex
);
66 if (!obj
) return NS_ERROR_ILLEGAL_VALUE
;
68 // no need to worry about a leak here, because SafeObjectAt()
69 // doesn't addref its result
70 return obj
->QueryInterface(aIID
, aResult
);
74 nsArray::IndexOf(uint32_t aStartIndex
, nsISupports
* aElement
,
77 // optimize for the common case by forwarding to mArray
78 if (aStartIndex
== 0) {
79 uint32_t idx
= mArray
.IndexOf(aElement
);
80 if (idx
== UINT32_MAX
)
81 return NS_ERROR_FAILURE
;
87 findIndexOfClosure closure
= { aElement
, aStartIndex
, 0 };
88 bool notFound
= mArray
.EnumerateForwards(FindElementCallback
, &closure
);
90 return NS_ERROR_FAILURE
;
92 *aResult
= closure
.resultIndex
;
97 nsArray::Enumerate(nsISimpleEnumerator
**aResult
)
99 return NS_NewArrayEnumerator(aResult
, static_cast<nsIArray
*>(this));
102 // nsIMutableArray implementation
105 nsArray::AppendElement(nsISupports
* aElement
, bool aWeak
)
109 nsCOMPtr
<nsIWeakReference
> elementRef
= do_GetWeakReference(aElement
);
110 NS_ASSERTION(elementRef
, "AppendElement: Trying to use weak references on an object that doesn't support it");
112 return NS_ERROR_FAILURE
;
113 result
= mArray
.AppendObject(elementRef
);
117 // add the object directly
118 result
= mArray
.AppendObject(aElement
);
120 return result
? NS_OK
: NS_ERROR_FAILURE
;
124 nsArray::RemoveElementAt(uint32_t aIndex
)
126 bool result
= mArray
.RemoveObjectAt(aIndex
);
127 return result
? NS_OK
: NS_ERROR_FAILURE
;
131 nsArray::InsertElementAt(nsISupports
* aElement
, uint32_t aIndex
, bool aWeak
)
133 nsCOMPtr
<nsISupports
> elementRef
;
135 elementRef
= do_GetWeakReference(aElement
);
136 NS_ASSERTION(elementRef
, "InsertElementAt: Trying to use weak references on an object that doesn't support it");
138 return NS_ERROR_FAILURE
;
140 elementRef
= aElement
;
142 bool result
= mArray
.InsertObjectAt(elementRef
, aIndex
);
143 return result
? NS_OK
: NS_ERROR_FAILURE
;
147 nsArray::ReplaceElementAt(nsISupports
* aElement
, uint32_t aIndex
, bool aWeak
)
149 nsCOMPtr
<nsISupports
> elementRef
;
151 elementRef
= do_GetWeakReference(aElement
);
152 NS_ASSERTION(elementRef
, "ReplaceElementAt: Trying to use weak references on an object that doesn't support it");
154 return NS_ERROR_FAILURE
;
156 elementRef
= aElement
;
158 bool result
= mArray
.ReplaceObjectAt(elementRef
, aIndex
);
159 return result
? NS_OK
: NS_ERROR_FAILURE
;
170 // static helper routines
173 FindElementCallback(void *aElement
, void* aClosure
)
175 findIndexOfClosure
* closure
=
176 static_cast<findIndexOfClosure
*>(aClosure
);
178 nsISupports
* element
=
179 static_cast<nsISupports
*>(aElement
);
181 // don't start searching until we're past the startIndex
182 if (closure
->resultIndex
>= closure
->startIndex
&&
183 element
== closure
->targetElement
) {
184 return false; // stop! We found it
186 closure
->resultIndex
++;
192 nsArray::XPCOMConstructor(nsISupports
*aOuter
, const nsIID
& aIID
, void **aResult
)
195 return NS_ERROR_NO_AGGREGATION
;
197 nsCOMPtr
<nsIMutableArray
> inst
= Create();
198 return inst
->QueryInterface(aIID
, aResult
);
201 already_AddRefed
<nsIMutableArray
>
204 nsCOMPtr
<nsIMutableArray
> inst
= NS_IsMainThread() ? new nsArrayCC
: new nsArray
;
205 return inst
.forget();