/src/mozilla-central/xpcom/ds/nsStringEnumerator.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
8 | | #include "nsStringEnumerator.h" |
9 | | #include "nsSimpleEnumerator.h" |
10 | | #include "nsSupportsPrimitives.h" |
11 | | #include "mozilla/Attributes.h" |
12 | | #include "mozilla/ResultExtensions.h" |
13 | | #include "mozilla/dom/IteratorResultBinding.h" |
14 | | #include "mozilla/dom/RootedDictionary.h" |
15 | | #include "mozilla/dom/ToJSValue.h" |
16 | | #include "nsTArray.h" |
17 | | |
18 | | using namespace mozilla; |
19 | | using namespace mozilla::dom; |
20 | | |
21 | | namespace { |
22 | | |
23 | | class JSStringEnumerator final : public nsIJSEnumerator |
24 | | { |
25 | | NS_DECL_ISUPPORTS |
26 | | NS_DECL_NSIJSENUMERATOR |
27 | | |
28 | | explicit JSStringEnumerator(nsIStringEnumerator* aEnumerator) |
29 | | : mEnumerator(do_QueryInterface(aEnumerator)) |
30 | 0 | { |
31 | 0 | MOZ_ASSERT(mEnumerator); |
32 | 0 | } |
33 | | |
34 | | private: |
35 | 0 | ~JSStringEnumerator() = default; |
36 | | |
37 | | nsCOMPtr<nsIStringEnumerator> mEnumerator; |
38 | | }; |
39 | | |
40 | | } // anonymous namespace |
41 | | |
42 | | nsresult |
43 | | JSStringEnumerator::Iterator(nsIJSEnumerator** aResult) |
44 | 0 | { |
45 | 0 | RefPtr<JSStringEnumerator> result(this); |
46 | 0 | result.forget(aResult); |
47 | 0 | return NS_OK; |
48 | 0 | } |
49 | | |
50 | | nsresult |
51 | | JSStringEnumerator::Next(JSContext* aCx, JS::MutableHandleValue aResult) |
52 | 0 | { |
53 | 0 | RootedDictionary<IteratorResult> result(aCx); |
54 | 0 |
|
55 | 0 | nsAutoString elem; |
56 | 0 | if (NS_FAILED(mEnumerator->GetNext(elem))) { |
57 | 0 | result.mDone = true; |
58 | 0 | } else { |
59 | 0 | result.mDone = false; |
60 | 0 |
|
61 | 0 | if (!ToJSValue(aCx, elem, |
62 | 0 | JS::MutableHandleValue::fromMarkedLocation(&result.mValue))) { |
63 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
64 | 0 | } |
65 | 0 | } |
66 | 0 | |
67 | 0 | if (!ToJSValue(aCx, result, aResult)) { |
68 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
69 | 0 | } |
70 | 0 | return NS_OK; |
71 | 0 | } |
72 | | |
73 | | NS_IMPL_ISUPPORTS(JSStringEnumerator, nsIJSEnumerator) |
74 | | |
75 | | // |
76 | | // nsStringEnumeratorBase |
77 | | // |
78 | | |
79 | | nsresult |
80 | | nsStringEnumeratorBase::GetNext(nsAString& aResult) |
81 | 0 | { |
82 | 0 | nsAutoCString str; |
83 | 0 | MOZ_TRY(GetNext(str)); |
84 | 0 |
|
85 | 0 | CopyUTF8toUTF16(str, aResult); |
86 | 0 | return NS_OK; |
87 | 0 | } |
88 | | |
89 | | NS_IMETHODIMP |
90 | | nsStringEnumeratorBase::StringIterator(nsIJSEnumerator** aRetVal) |
91 | 0 | { |
92 | 0 | auto result = MakeRefPtr<JSStringEnumerator>(this); |
93 | 0 | result.forget(aRetVal); |
94 | 0 | return NS_OK; |
95 | 0 | } |
96 | | |
97 | | // |
98 | | // nsStringEnumerator |
99 | | // |
100 | | |
101 | | class nsStringEnumerator final |
102 | | : public nsSimpleEnumerator |
103 | | , public nsIStringEnumerator |
104 | | , public nsIUTF8StringEnumerator |
105 | | { |
106 | | public: |
107 | | nsStringEnumerator(const nsTArray<nsString>* aArray, bool aOwnsArray) |
108 | | : mArray(aArray) |
109 | | , mIndex(0) |
110 | | , mOwnsArray(aOwnsArray) |
111 | | , mIsUnicode(true) |
112 | 0 | {} |
113 | | |
114 | | nsStringEnumerator(const nsTArray<nsCString>* aArray, bool aOwnsArray) |
115 | | : mCArray(aArray) |
116 | | , mIndex(0) |
117 | | , mOwnsArray(aOwnsArray) |
118 | | , mIsUnicode(false) |
119 | 0 | {} |
120 | | |
121 | | nsStringEnumerator(const nsTArray<nsString>* aArray, nsISupports* aOwner) |
122 | | : mArray(aArray) |
123 | | , mIndex(0) |
124 | | , mOwner(aOwner) |
125 | | , mOwnsArray(false) |
126 | | , mIsUnicode(true) |
127 | 0 | {} |
128 | | |
129 | | nsStringEnumerator(const nsTArray<nsCString>* aArray, nsISupports* aOwner) |
130 | | : mCArray(aArray) |
131 | | , mIndex(0) |
132 | | , mOwner(aOwner) |
133 | | , mOwnsArray(false) |
134 | | , mIsUnicode(false) |
135 | 0 | {} |
136 | | |
137 | | NS_DECL_ISUPPORTS_INHERITED |
138 | | NS_DECL_NSIUTF8STRINGENUMERATOR |
139 | | NS_DECL_NSISTRINGENUMERATORBASE |
140 | | |
141 | | // have to declare nsIStringEnumerator manually, because of |
142 | | // overlapping method names |
143 | | NS_IMETHOD GetNext(nsAString& aResult) override; |
144 | | NS_DECL_NSISIMPLEENUMERATOR |
145 | | |
146 | | const nsID& DefaultInterface() override |
147 | 0 | { |
148 | 0 | if (mIsUnicode) { |
149 | 0 | return NS_GET_IID(nsISupportsString); |
150 | 0 | } |
151 | 0 | return NS_GET_IID(nsISupportsCString); |
152 | 0 | } |
153 | | |
154 | | private: |
155 | | ~nsStringEnumerator() |
156 | 0 | { |
157 | 0 | if (mOwnsArray) { |
158 | 0 | // const-casting is safe here, because the NS_New* |
159 | 0 | // constructors make sure mOwnsArray is consistent with |
160 | 0 | // the constness of the objects |
161 | 0 | if (mIsUnicode) { |
162 | 0 | delete const_cast<nsTArray<nsString>*>(mArray); |
163 | 0 | } else { |
164 | 0 | delete const_cast<nsTArray<nsCString>*>(mCArray); |
165 | 0 | } |
166 | 0 | } |
167 | 0 | } |
168 | | |
169 | | union |
170 | | { |
171 | | const nsTArray<nsString>* mArray; |
172 | | const nsTArray<nsCString>* mCArray; |
173 | | }; |
174 | | |
175 | | inline uint32_t Count() |
176 | 0 | { |
177 | 0 | return mIsUnicode ? mArray->Length() : mCArray->Length(); |
178 | 0 | } |
179 | | |
180 | | uint32_t mIndex; |
181 | | |
182 | | // the owner allows us to hold a strong reference to the object |
183 | | // that owns the array. Having a non-null value in mOwner implies |
184 | | // that mOwnsArray is false, because we rely on the real owner |
185 | | // to release the array |
186 | | nsCOMPtr<nsISupports> mOwner; |
187 | | bool mOwnsArray; |
188 | | bool mIsUnicode; |
189 | | }; |
190 | | |
191 | | NS_IMPL_ISUPPORTS_INHERITED(nsStringEnumerator, |
192 | | nsSimpleEnumerator, |
193 | | nsIStringEnumerator, |
194 | | nsIUTF8StringEnumerator) |
195 | | |
196 | | NS_IMETHODIMP |
197 | | nsStringEnumerator::HasMore(bool* aResult) |
198 | 0 | { |
199 | 0 | *aResult = mIndex < Count(); |
200 | 0 | return NS_OK; |
201 | 0 | } |
202 | | |
203 | | NS_IMETHODIMP |
204 | | nsStringEnumerator::HasMoreElements(bool* aResult) |
205 | 0 | { |
206 | 0 | return HasMore(aResult); |
207 | 0 | } |
208 | | |
209 | | NS_IMETHODIMP |
210 | | nsStringEnumerator::GetNext(nsISupports** aResult) |
211 | 0 | { |
212 | 0 | if (mIndex >= mArray->Length()) { |
213 | 0 | return NS_ERROR_FAILURE; |
214 | 0 | } |
215 | 0 | |
216 | 0 | if (mIsUnicode) { |
217 | 0 | nsSupportsString* stringImpl = new nsSupportsString(); |
218 | 0 | if (!stringImpl) { |
219 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
220 | 0 | } |
221 | 0 | |
222 | 0 | stringImpl->SetData(mArray->ElementAt(mIndex++)); |
223 | 0 | *aResult = stringImpl; |
224 | 0 | } else { |
225 | 0 | nsSupportsCString* cstringImpl = new nsSupportsCString(); |
226 | 0 | if (!cstringImpl) { |
227 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
228 | 0 | } |
229 | 0 | |
230 | 0 | cstringImpl->SetData(mCArray->ElementAt(mIndex++)); |
231 | 0 | *aResult = cstringImpl; |
232 | 0 | } |
233 | 0 | NS_ADDREF(*aResult); |
234 | 0 | return NS_OK; |
235 | 0 | } |
236 | | |
237 | | NS_IMETHODIMP |
238 | | nsStringEnumerator::GetNext(nsAString& aResult) |
239 | 0 | { |
240 | 0 | if (NS_WARN_IF(mIndex >= Count())) { |
241 | 0 | return NS_ERROR_UNEXPECTED; |
242 | 0 | } |
243 | 0 | |
244 | 0 | if (mIsUnicode) { |
245 | 0 | aResult = mArray->ElementAt(mIndex++); |
246 | 0 | } else { |
247 | 0 | CopyUTF8toUTF16(mCArray->ElementAt(mIndex++), aResult); |
248 | 0 | } |
249 | 0 |
|
250 | 0 | return NS_OK; |
251 | 0 | } |
252 | | |
253 | | NS_IMETHODIMP |
254 | | nsStringEnumerator::GetNext(nsACString& aResult) |
255 | 0 | { |
256 | 0 | if (NS_WARN_IF(mIndex >= Count())) { |
257 | 0 | return NS_ERROR_UNEXPECTED; |
258 | 0 | } |
259 | 0 | |
260 | 0 | if (mIsUnicode) { |
261 | 0 | CopyUTF16toUTF8(mArray->ElementAt(mIndex++), aResult); |
262 | 0 | } else { |
263 | 0 | aResult = mCArray->ElementAt(mIndex++); |
264 | 0 | } |
265 | 0 |
|
266 | 0 | return NS_OK; |
267 | 0 | } |
268 | | |
269 | | NS_IMETHODIMP |
270 | | nsStringEnumerator::StringIterator(nsIJSEnumerator** aRetVal) |
271 | 0 | { |
272 | 0 | auto result = MakeRefPtr<JSStringEnumerator>(this); |
273 | 0 | result.forget(aRetVal); |
274 | 0 | return NS_OK; |
275 | 0 | } |
276 | | |
277 | | template<class T> |
278 | | static inline nsresult |
279 | | StringEnumeratorTail(T** aResult) |
280 | 0 | { |
281 | 0 | if (!*aResult) { |
282 | 0 | return NS_ERROR_OUT_OF_MEMORY; |
283 | 0 | } |
284 | 0 | NS_ADDREF(*aResult); |
285 | 0 | return NS_OK; |
286 | 0 | } Unexecuted instantiation: Unified_cpp_xpcom_ds1.cpp:nsresult StringEnumeratorTail<nsIStringEnumerator>(nsIStringEnumerator**) Unexecuted instantiation: Unified_cpp_xpcom_ds1.cpp:nsresult StringEnumeratorTail<nsIUTF8StringEnumerator>(nsIUTF8StringEnumerator**) |
287 | | |
288 | | // |
289 | | // constructors |
290 | | // |
291 | | |
292 | | nsresult |
293 | | NS_NewStringEnumerator(nsIStringEnumerator** aResult, |
294 | | const nsTArray<nsString>* aArray, nsISupports* aOwner) |
295 | 0 | { |
296 | 0 | if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) { |
297 | 0 | return NS_ERROR_INVALID_ARG; |
298 | 0 | } |
299 | 0 | |
300 | 0 | *aResult = new nsStringEnumerator(aArray, aOwner); |
301 | 0 | return StringEnumeratorTail(aResult); |
302 | 0 | } |
303 | | |
304 | | |
305 | | nsresult |
306 | | NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult, |
307 | | const nsTArray<nsCString>* aArray, |
308 | | nsISupports* aOwner) |
309 | 0 | { |
310 | 0 | if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) { |
311 | 0 | return NS_ERROR_INVALID_ARG; |
312 | 0 | } |
313 | 0 | |
314 | 0 | *aResult = new nsStringEnumerator(aArray, aOwner); |
315 | 0 | return StringEnumeratorTail(aResult); |
316 | 0 | } |
317 | | |
318 | | nsresult |
319 | | NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult, |
320 | | nsTArray<nsString>* aArray) |
321 | 0 | { |
322 | 0 | if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) { |
323 | 0 | return NS_ERROR_INVALID_ARG; |
324 | 0 | } |
325 | 0 | |
326 | 0 | *aResult = new nsStringEnumerator(aArray, true); |
327 | 0 | return StringEnumeratorTail(aResult); |
328 | 0 | } |
329 | | |
330 | | nsresult |
331 | | NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult, |
332 | | nsTArray<nsCString>* aArray) |
333 | 0 | { |
334 | 0 | if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) { |
335 | 0 | return NS_ERROR_INVALID_ARG; |
336 | 0 | } |
337 | 0 | |
338 | 0 | *aResult = new nsStringEnumerator(aArray, true); |
339 | 0 | return StringEnumeratorTail(aResult); |
340 | 0 | } |
341 | | |
342 | | // const ones internally just forward to the non-const equivalents |
343 | | nsresult |
344 | | NS_NewStringEnumerator(nsIStringEnumerator** aResult, |
345 | | const nsTArray<nsString>* aArray) |
346 | 0 | { |
347 | 0 | if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) { |
348 | 0 | return NS_ERROR_INVALID_ARG; |
349 | 0 | } |
350 | 0 | |
351 | 0 | *aResult = new nsStringEnumerator(aArray, false); |
352 | 0 | return StringEnumeratorTail(aResult); |
353 | 0 | } |
354 | | |
355 | | nsresult |
356 | | NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult, |
357 | | const nsTArray<nsCString>* aArray) |
358 | 0 | { |
359 | 0 | if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) { |
360 | 0 | return NS_ERROR_INVALID_ARG; |
361 | 0 | } |
362 | 0 | |
363 | 0 | *aResult = new nsStringEnumerator(aArray, false); |
364 | 0 | return StringEnumeratorTail(aResult); |
365 | 0 | } |
366 | | |