Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/ds/nsCOMArray.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
#include "nsCOMArray.h"
8
9
#include "mozilla/MemoryReporting.h"
10
#include "mozilla/OperatorNewExtensions.h"
11
#include "nsQuickSort.h"
12
13
#include "nsCOMPtr.h"
14
15
// This specialization is private to nsCOMArray.
16
// It exists solely to automatically zero-out newly created array elements.
17
template<>
18
class nsTArrayElementTraits<nsISupports*>
19
{
20
  typedef nsISupports* E;
21
public:
22
  // Zero out the value
23
  static inline void Construct(E* aE)
24
0
  {
25
0
    new (mozilla::KnownNotNull, static_cast<void*>(aE)) E();
26
0
  }
27
  // Invoke the copy-constructor in place.
28
  template<class A>
29
  static inline void Construct(E* aE, const A& aArg)
30
6
  {
31
6
    new (mozilla::KnownNotNull, static_cast<void*>(aE)) E(aArg);
32
6
  }
33
  // Invoke the destructor in place.
34
  static inline void Destruct(E* aE)
35
6
  {
36
6
    aE->~E();
37
6
  }
38
};
39
40
static void ReleaseObjects(nsTArray<nsISupports*>& aArray);
41
42
// implementations of non-trivial methods in nsCOMArray_base
43
44
nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther)
45
0
{
46
0
  // make sure we do only one allocation
47
0
  mArray.SetCapacity(aOther.Count());
48
0
  AppendObjects(aOther);
49
0
}
50
51
nsCOMArray_base::~nsCOMArray_base()
52
9
{
53
9
  Clear();
54
9
}
55
56
int32_t
57
nsCOMArray_base::IndexOf(nsISupports* aObject, uint32_t aStartIndex) const
58
0
{
59
0
  return mArray.IndexOf(aObject, aStartIndex);
60
0
}
61
62
int32_t
63
nsCOMArray_base::IndexOfObject(nsISupports* aObject) const
64
0
{
65
0
  nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
66
0
  if (NS_WARN_IF(!supports)) {
67
0
    return -1;
68
0
  }
69
0
70
0
  uint32_t i, count;
71
0
  int32_t retval = -1;
72
0
  count = mArray.Length();
73
0
  for (i = 0; i < count; ++i) {
74
0
    nsCOMPtr<nsISupports> arrayItem = do_QueryInterface(mArray[i]);
75
0
    if (arrayItem == supports) {
76
0
      retval = i;
77
0
      break;
78
0
    }
79
0
  }
80
0
  return retval;
81
0
}
82
83
bool
84
nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const
85
0
{
86
0
  for (uint32_t index = 0; index < mArray.Length(); ++index) {
87
0
    if (!(*aFunc)(mArray[index], aData)) {
88
0
      return false;
89
0
    }
90
0
  }
91
0
92
0
  return true;
93
0
}
94
95
bool
96
nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const
97
0
{
98
0
  for (uint32_t index = mArray.Length(); index--; ) {
99
0
    if (!(*aFunc)(mArray[index], aData)) {
100
0
      return false;
101
0
    }
102
0
  }
103
0
104
0
  return true;
105
0
}
106
107
int
108
nsCOMArray_base::nsCOMArrayComparator(const void* aElement1,
109
                                      const void* aElement2,
110
                                      void* aData)
111
0
{
112
0
  nsCOMArrayComparatorContext* ctx =
113
0
    static_cast<nsCOMArrayComparatorContext*>(aData);
114
0
  return (*ctx->mComparatorFunc)(*static_cast<nsISupports* const*>(aElement1),
115
0
                                 *static_cast<nsISupports* const*>(aElement2),
116
0
                                 ctx->mData);
117
0
}
118
119
void
120
nsCOMArray_base::Sort(nsBaseArrayComparatorFunc aFunc, void* aData)
121
6
{
122
6
  if (mArray.Length() > 1) {
123
0
    nsCOMArrayComparatorContext ctx = {aFunc, aData};
124
0
    NS_QuickSort(mArray.Elements(), mArray.Length(), sizeof(nsISupports*),
125
0
                 nsCOMArrayComparator, &ctx);
126
0
  }
127
6
}
128
129
bool
130
nsCOMArray_base::InsertObjectAt(nsISupports* aObject, int32_t aIndex)
131
3
{
132
3
  if ((uint32_t)aIndex > mArray.Length()) {
133
0
    return false;
134
0
  }
135
3
136
3
  if (!mArray.InsertElementAt(aIndex, aObject)) {
137
0
    return false;
138
0
  }
139
3
140
3
  NS_IF_ADDREF(aObject);
141
3
  return true;
142
3
}
143
144
void
145
nsCOMArray_base::InsertElementAt(uint32_t aIndex, nsISupports* aElement)
146
3
{
147
3
  mArray.InsertElementAt(aIndex, aElement);
148
3
  NS_IF_ADDREF(aElement);
149
3
}
150
151
void
152
nsCOMArray_base::InsertElementAt(uint32_t aIndex, already_AddRefed<nsISupports> aElement)
153
0
{
154
0
  mArray.InsertElementAt(aIndex, aElement.take());
155
0
}
156
157
bool
158
nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex)
159
0
{
160
0
  if ((uint32_t)aIndex > mArray.Length()) {
161
0
    return false;
162
0
  }
163
0
164
0
  if (!mArray.InsertElementsAt(aIndex, aObjects.mArray)) {
165
0
    return false;
166
0
  }
167
0
168
0
  // need to addref all these
169
0
  uint32_t count = aObjects.Length();
170
0
  for (uint32_t i = 0; i < count; ++i) {
171
0
    NS_IF_ADDREF(aObjects[i]);
172
0
  }
173
0
174
0
  return true;
175
0
}
176
177
void
178
nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
179
                                  const nsCOMArray_base& aElements)
180
0
{
181
0
  mArray.InsertElementsAt(aIndex, aElements.mArray);
182
0
183
0
  // need to addref all these
184
0
  uint32_t count = aElements.Length();
185
0
  for (uint32_t i = 0; i < count; ++i) {
186
0
    NS_IF_ADDREF(aElements[i]);
187
0
  }
188
0
}
189
190
void
191
nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
192
                                  nsISupports* const* aElements,
193
                                  uint32_t aCount)
194
0
{
195
0
  mArray.InsertElementsAt(aIndex, aElements, aCount);
196
0
197
0
  // need to addref all these
198
0
  for (uint32_t i = 0; i < aCount; ++i) {
199
0
    NS_IF_ADDREF(aElements[i]);
200
0
  }
201
0
}
202
203
void
204
nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, int32_t aIndex)
205
0
{
206
0
  mArray.EnsureLengthAtLeast(aIndex + 1);
207
0
  nsISupports* oldObject = mArray[aIndex];
208
0
  // Make sure to addref first, in case aObject == oldObject
209
0
  NS_IF_ADDREF(mArray[aIndex] = aObject);
210
0
  NS_IF_RELEASE(oldObject);
211
0
}
212
213
bool
214
nsCOMArray_base::RemoveObject(nsISupports* aObject)
215
0
{
216
0
  bool result = mArray.RemoveElement(aObject);
217
0
  if (result) {
218
0
    NS_IF_RELEASE(aObject);
219
0
  }
220
0
  return result;
221
0
}
222
223
bool
224
nsCOMArray_base::RemoveObjectAt(int32_t aIndex)
225
0
{
226
0
  if (uint32_t(aIndex) < mArray.Length()) {
227
0
    nsISupports* element = mArray[aIndex];
228
0
229
0
    mArray.RemoveElementAt(aIndex);
230
0
    NS_IF_RELEASE(element);
231
0
    return true;
232
0
  }
233
0
234
0
  return false;
235
0
}
236
237
void
238
nsCOMArray_base::RemoveElementAt(uint32_t aIndex)
239
0
{
240
0
  nsISupports* element = mArray[aIndex];
241
0
  mArray.RemoveElementAt(aIndex);
242
0
  NS_IF_RELEASE(element);
243
0
}
244
245
bool
246
nsCOMArray_base::RemoveObjectsAt(int32_t aIndex, int32_t aCount)
247
0
{
248
0
  if (uint32_t(aIndex) + uint32_t(aCount) <= mArray.Length()) {
249
0
    nsTArray<nsISupports*> elementsToDestroy(aCount);
250
0
    elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
251
0
    mArray.RemoveElementsAt(aIndex, aCount);
252
0
    ReleaseObjects(elementsToDestroy);
253
0
    return true;
254
0
  }
255
0
256
0
  return false;
257
0
}
258
259
void
260
nsCOMArray_base::RemoveElementsAt(uint32_t aIndex, uint32_t aCount)
261
0
{
262
0
  nsTArray<nsISupports*> elementsToDestroy(aCount);
263
0
  elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
264
0
  mArray.RemoveElementsAt(aIndex, aCount);
265
0
  ReleaseObjects(elementsToDestroy);
266
0
}
267
268
// useful for destructors
269
void
270
ReleaseObjects(nsTArray<nsISupports*>& aArray)
271
9
{
272
15
  for (uint32_t i = 0; i < aArray.Length(); ++i) {
273
6
    NS_IF_RELEASE(aArray[i]);
274
6
  }
275
9
}
276
277
void
278
nsCOMArray_base::Clear()
279
9
{
280
9
  nsTArray<nsISupports*> objects;
281
9
  objects.SwapElements(mArray);
282
9
  ReleaseObjects(objects);
283
9
}
284
285
bool
286
nsCOMArray_base::SetCount(int32_t aNewCount)
287
0
{
288
0
  NS_ASSERTION(aNewCount >= 0, "SetCount(negative index)");
289
0
  if (aNewCount < 0) {
290
0
    return false;
291
0
  }
292
0
293
0
  int32_t count = mArray.Length();
294
0
  if (count > aNewCount) {
295
0
    RemoveObjectsAt(aNewCount, mArray.Length() - aNewCount);
296
0
  }
297
0
  mArray.SetLength(aNewCount);
298
0
  return true;
299
0
}
300
301
void
302
nsCOMArray_base::Adopt(nsISupports** aElements, uint32_t aSize)
303
0
{
304
0
  Clear();
305
0
  mArray.AppendElements(aElements, aSize);
306
0
307
0
  // Free the allocated array as well.
308
0
  free(aElements);
309
0
}
310
311
uint32_t
312
nsCOMArray_base::Forget(nsISupports*** aElements)
313
0
{
314
0
  uint32_t length = Length();
315
0
  size_t array_size = sizeof(nsISupports*) * length;
316
0
  nsISupports** array = static_cast<nsISupports**>(moz_xmalloc(array_size));
317
0
  memmove(array, Elements(), array_size);
318
0
  *aElements = array;
319
0
  // Don't Release the contained pointers; the caller of the method will
320
0
  // do this eventually.
321
0
  mArray.Clear();
322
0
323
0
  return length;
324
0
}