1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "nsArray.h"
8 #include "nsArrayEnumerator.h"
9 #include "nsThreadUtils.h"
10
11 NS_INTERFACE_MAP_BEGIN(nsArray)
NS_INTERFACE_MAP_ENTRY(nsIArray)12 NS_INTERFACE_MAP_ENTRY(nsIArray)
13 NS_INTERFACE_MAP_ENTRY(nsIArrayExtensions)
14 NS_INTERFACE_MAP_ENTRY(nsIMutableArray)
15 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray)
16 NS_INTERFACE_MAP_END
17
18 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsArrayCC)
19 NS_INTERFACE_MAP_ENTRY(nsIArray)
20 NS_INTERFACE_MAP_ENTRY(nsIArrayExtensions)
21 NS_INTERFACE_MAP_ENTRY(nsIMutableArray)
22 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray)
23 NS_INTERFACE_MAP_END
24
25 nsArrayBase::~nsArrayBase() { Clear(); }
26
27 NS_IMPL_ADDREF(nsArray)
28 NS_IMPL_RELEASE(nsArray)
29
30 NS_IMPL_CYCLE_COLLECTION_CLASS(nsArrayCC)
31
32 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsArrayCC)
33 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsArrayCC)
34
35 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsArrayCC)
36 tmp->Clear();
37 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsArrayCC)38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsArrayCC)
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArray)
40 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
41
42 NS_IMETHODIMP
43 nsArrayBase::GetLength(uint32_t* aLength) {
44 *aLength = mArray.Count();
45 return NS_OK;
46 }
47
48 NS_IMETHODIMP
QueryElementAt(uint32_t aIndex,const nsIID & aIID,void ** aResult)49 nsArrayBase::QueryElementAt(uint32_t aIndex, const nsIID& aIID,
50 void** aResult) {
51 nsISupports* obj = mArray.SafeObjectAt(aIndex);
52 if (!obj) {
53 return NS_ERROR_ILLEGAL_VALUE;
54 }
55
56 // no need to worry about a leak here, because SafeObjectAt()
57 // doesn't addref its result
58 return obj->QueryInterface(aIID, aResult);
59 }
60
61 NS_IMETHODIMP
IndexOf(uint32_t aStartIndex,nsISupports * aElement,uint32_t * aResult)62 nsArrayBase::IndexOf(uint32_t aStartIndex, nsISupports* aElement,
63 uint32_t* aResult) {
64 int32_t idx = mArray.IndexOf(aElement, aStartIndex);
65 if (idx == -1) {
66 return NS_ERROR_FAILURE;
67 }
68
69 *aResult = static_cast<uint32_t>(idx);
70 return NS_OK;
71 }
72
73 NS_IMETHODIMP
ScriptedEnumerate(const nsIID & aElemIID,uint8_t aArgc,nsISimpleEnumerator ** aResult)74 nsArrayBase::ScriptedEnumerate(const nsIID& aElemIID, uint8_t aArgc,
75 nsISimpleEnumerator** aResult) {
76 if (aArgc > 0) {
77 return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this),
78 aElemIID);
79 }
80 return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this));
81 }
82
83 NS_IMETHODIMP
EnumerateImpl(const nsID & aElemIID,nsISimpleEnumerator ** aResult)84 nsArrayBase::EnumerateImpl(const nsID& aElemIID,
85 nsISimpleEnumerator** aResult) {
86 return NS_NewArrayEnumerator(aResult, static_cast<nsIArray*>(this), aElemIID);
87 }
88
89 // nsIMutableArray implementation
90
91 NS_IMETHODIMP
AppendElement(nsISupports * aElement)92 nsArrayBase::AppendElement(nsISupports* aElement) {
93 bool result = mArray.AppendObject(aElement);
94 return result ? NS_OK : NS_ERROR_FAILURE;
95 }
96
97 NS_IMETHODIMP
RemoveElementAt(uint32_t aIndex)98 nsArrayBase::RemoveElementAt(uint32_t aIndex) {
99 bool result = mArray.RemoveObjectAt(aIndex);
100 return result ? NS_OK : NS_ERROR_FAILURE;
101 }
102
103 NS_IMETHODIMP
InsertElementAt(nsISupports * aElement,uint32_t aIndex)104 nsArrayBase::InsertElementAt(nsISupports* aElement, uint32_t aIndex) {
105 bool result = mArray.InsertObjectAt(aElement, aIndex);
106 return result ? NS_OK : NS_ERROR_FAILURE;
107 }
108
109 NS_IMETHODIMP
ReplaceElementAt(nsISupports * aElement,uint32_t aIndex)110 nsArrayBase::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) {
111 mArray.ReplaceObjectAt(aElement, aIndex);
112 return NS_OK;
113 }
114
115 NS_IMETHODIMP
Clear()116 nsArrayBase::Clear() {
117 mArray.Clear();
118 return NS_OK;
119 }
120
121 // nsIArrayExtensions implementation.
122
123 NS_IMETHODIMP
Count(uint32_t * aResult)124 nsArrayBase::Count(uint32_t* aResult) { return GetLength(aResult); }
125
126 NS_IMETHODIMP
GetElementAt(uint32_t aIndex,nsISupports ** aResult)127 nsArrayBase::GetElementAt(uint32_t aIndex, nsISupports** aResult) {
128 nsCOMPtr<nsISupports> obj = mArray.SafeObjectAt(aIndex);
129 obj.forget(aResult);
130 return NS_OK;
131 }
132
XPCOMConstructor(nsISupports * aOuter,const nsIID & aIID,void ** aResult)133 nsresult nsArrayBase::XPCOMConstructor(nsISupports* aOuter, const nsIID& aIID,
134 void** aResult) {
135 if (aOuter) {
136 return NS_ERROR_NO_AGGREGATION;
137 }
138
139 nsCOMPtr<nsIMutableArray> inst = Create();
140 return inst->QueryInterface(aIID, aResult);
141 }
142
Create()143 already_AddRefed<nsIMutableArray> nsArrayBase::Create() {
144 nsCOMPtr<nsIMutableArray> inst;
145 if (NS_IsMainThread()) {
146 inst = new nsArrayCC;
147 } else {
148 inst = new nsArray;
149 }
150 return inst.forget();
151 }
152