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