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 <stdint.h>
8 #include <string.h>
9
10 #include "nsArrayEnumerator.h"
11 #include "nsIObjectInputStream.h"
12 #include "nsIObjectOutputStream.h"
13 #include "nsSupportsArray.h"
14 #include "nsSupportsArrayEnumerator.h"
15
16 // Disable deprecation warnings generated by nsISupportsArray and associated
17 // classes.
18 #if defined(__GNUC__)
19 #pragma GCC diagnostic push
20 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
21 #elif defined(_MSC_VER)
22 #pragma warning (push)
23 #pragma warning (disable : 4996)
24 #endif
25
26 nsresult
operator ()(const nsIID & aIID,void ** aResult) const27 nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const
28 {
29 nsresult status =
30 mCollection ? mCollection->QueryElementAt(mIndex, aIID, aResult) :
31 NS_ERROR_NULL_POINTER;
32
33 if (mErrorPtr) {
34 *mErrorPtr = status;
35 }
36
37 return status;
38 }
39
nsSupportsArray()40 nsSupportsArray::nsSupportsArray()
41 {
42 }
43
~nsSupportsArray()44 nsSupportsArray::~nsSupportsArray()
45 {
46 Clear();
47 }
48
49 nsresult
Create(nsISupports * aOuter,REFNSIID aIID,void ** aResult)50 nsSupportsArray::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
51 {
52 if (aOuter) {
53 return NS_ERROR_NO_AGGREGATION;
54 }
55
56 nsCOMPtr<nsISupportsArray> it = new nsSupportsArray();
57
58 return it->QueryInterface(aIID, aResult);
59 }
60
NS_IMPL_ISUPPORTS(nsSupportsArray,nsIArray,nsISupportsArray,nsICollection,nsISerializable)61 NS_IMPL_ISUPPORTS(nsSupportsArray, nsIArray, nsISupportsArray, nsICollection,
62 nsISerializable)
63
64 NS_IMETHODIMP
65 nsSupportsArray::Read(nsIObjectInputStream* aStream)
66 {
67 nsresult rv;
68
69 uint32_t newArraySize;
70 rv = aStream->Read32(&newArraySize);
71 if (NS_FAILED(rv)) {
72 return rv;
73 }
74
75 uint32_t count;
76 rv = aStream->Read32(&count);
77 if (NS_FAILED(rv)) {
78 return rv;
79 }
80
81 NS_ASSERTION(count <= newArraySize, "overlarge mCount!");
82 if (count > newArraySize) {
83 count = newArraySize;
84 }
85
86 // Don't clear out our array until we know we have enough space for the new
87 // one and have successfully copied everything out of the stream.
88 nsCOMArray<nsISupports> tmp;
89 tmp.SetCapacity(newArraySize);
90 tmp.SetCount(count);
91
92 auto elems = tmp.Elements();
93 for (uint32_t i = 0; i < count; i++) {
94 rv = aStream->ReadObject(true, &elems[i]);
95 if (NS_FAILED(rv)) {
96 return rv;
97 }
98 }
99
100 // Now clear out existing refs and replace with the new array.
101 mArray.Clear();
102 mArray.SwapElements(tmp);
103
104 return NS_OK;
105 }
106
107 NS_IMETHODIMP
Write(nsIObjectOutputStream * aStream)108 nsSupportsArray::Write(nsIObjectOutputStream* aStream)
109 {
110 nsresult rv;
111
112 rv = aStream->Write32(mArray.Capacity());
113 if (NS_FAILED(rv)) {
114 return rv;
115 }
116
117 rv = aStream->Write32(mArray.Length());
118 if (NS_FAILED(rv)) {
119 return rv;
120 }
121
122 for (size_t i = 0; i < mArray.Length(); i++) {
123 rv = aStream->WriteObject(mArray[i], true);
124 if (NS_FAILED(rv)) {
125 return rv;
126 }
127 }
128
129 return NS_OK;
130 }
131
132 NS_IMETHODIMP
GetElementAt(uint32_t aIndex,nsISupports ** aOutPtr)133 nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports** aOutPtr)
134 {
135 nsCOMPtr<nsISupports> elm = mArray.SafeElementAt(aIndex);
136 elm.forget(aOutPtr);
137 return NS_OK;
138 }
139
NS_IMETHODIMP_(int32_t)140 NS_IMETHODIMP_(int32_t)
141 nsSupportsArray::IndexOf(const nsISupports* aPossibleElement)
142 {
143 // nsCOMArray takes a non-const param, but it just passes through to
144 // nsTArray which takes a const param.
145 return mArray.IndexOf(const_cast<nsISupports*>(aPossibleElement));
146 }
147
NS_IMETHODIMP_(bool)148 NS_IMETHODIMP_(bool)
149 nsSupportsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex)
150 {
151 return mArray.InsertObjectAt(aElement, aIndex);
152 }
153
NS_IMETHODIMP_(bool)154 NS_IMETHODIMP_(bool)
155 nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex)
156 {
157 // nsCOMArray::ReplaceObjectAt will grow the array if necessary. Instead
158 // we do the bounds check and only replace if it's in range.
159 if (aIndex < mArray.Length()) {
160 mArray.ReplaceElementAt(aIndex, aElement);
161 return true;
162 }
163 return false;
164 }
165
NS_IMETHODIMP_(bool)166 NS_IMETHODIMP_(bool)
167 nsSupportsArray::RemoveElementAt(uint32_t aIndex)
168 {
169 return mArray.RemoveObjectAt(aIndex);
170 }
171
172 NS_IMETHODIMP
RemoveElement(nsISupports * aElement)173 nsSupportsArray::RemoveElement(nsISupports* aElement)
174 {
175 return mArray.RemoveObject(aElement) ? NS_OK : NS_ERROR_FAILURE;
176 }
177
178 NS_IMETHODIMP
Clear(void)179 nsSupportsArray::Clear(void)
180 {
181 mArray.Clear();
182 return NS_OK;
183 }
184
185 NS_IMETHODIMP
DeprecatedEnumerate(nsIEnumerator ** aResult)186 nsSupportsArray::DeprecatedEnumerate(nsIEnumerator** aResult)
187 {
188 RefPtr<nsSupportsArrayEnumerator> e = new nsSupportsArrayEnumerator(this);
189 e.forget(aResult);
190 return NS_OK;
191 }
192
193 NS_IMETHODIMP
Clone(nsISupportsArray ** aResult)194 nsSupportsArray::Clone(nsISupportsArray** aResult)
195 {
196 nsCOMPtr<nsISupportsArray> newArray;
197 nsresult rv = NS_NewISupportsArray(getter_AddRefs(newArray));
198 if (NS_WARN_IF(NS_FAILED(rv))) {
199 return rv;
200 }
201
202 for (size_t i = 0; i < mArray.Length(); i++) {
203 // AppendElement does an odd cast of bool to nsresult, we just cast back
204 // here.
205 if (!(bool)newArray->AppendElement(mArray[i])) {
206 return NS_ERROR_OUT_OF_MEMORY;
207 }
208 }
209
210 newArray.forget(aResult);
211 return NS_OK;
212 }
213
214 nsresult
NS_NewISupportsArray(nsISupportsArray ** aInstancePtrResult)215 NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult)
216 {
217 nsresult rv;
218 rv = nsSupportsArray::Create(nullptr, NS_GET_IID(nsISupportsArray),
219 (void**)aInstancePtrResult);
220 return rv;
221 }
222
223 /**
224 * nsIArray adapters.
225 */
226 NS_IMETHODIMP
GetLength(uint32_t * aLength)227 nsSupportsArray::GetLength(uint32_t* aLength) {
228 return Count(aLength);
229 }
230
231 NS_IMETHODIMP
QueryElementAt(uint32_t aIndex,const nsIID & aIID,void ** aResult)232 nsSupportsArray::QueryElementAt(uint32_t aIndex, const nsIID& aIID, void** aResult)
233 {
234 nsISupports* element = mArray.SafeElementAt(aIndex);
235 if (element) {
236 return element->QueryInterface(aIID, aResult);
237 }
238 return NS_ERROR_FAILURE;
239 }
240
241 NS_IMETHODIMP
IndexOf(uint32_t aStartIndex,nsISupports * aElement,uint32_t * aResult)242 nsSupportsArray::IndexOf(uint32_t aStartIndex, nsISupports* aElement, uint32_t* aResult)
243 {
244 int32_t idx = mArray.IndexOf(aElement, aStartIndex);
245 if (idx < 0) {
246 return NS_ERROR_FAILURE;
247 }
248
249 *aResult = static_cast<uint32_t>(idx);
250 return NS_OK;
251 }
252
253 NS_IMETHODIMP
Enumerate(nsISimpleEnumerator ** aResult)254 nsSupportsArray::Enumerate(nsISimpleEnumerator** aResult)
255 {
256 return NS_NewArrayEnumerator(aResult, this);
257 }
258
259 #if defined(__GNUC__)
260 #pragma GCC diagnostic pop
261 #elif defined(_MSC_VER)
262 #pragma warning (pop)
263 #endif
264
265