Coverage Report

Created: 2018-09-25 14:53

/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