|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include <string.h> |
|
7 #include "mozilla/MathAlgorithms.h" |
|
8 #include "nsSupportsArray.h" |
|
9 #include "nsSupportsArrayEnumerator.h" |
|
10 #include "nsIObjectInputStream.h" |
|
11 #include "nsIObjectOutputStream.h" |
|
12 |
|
13 #if DEBUG_SUPPORTSARRAY |
|
14 #define MAXSUPPORTS 20 |
|
15 |
|
16 class SupportsStats { |
|
17 public: |
|
18 SupportsStats(); |
|
19 ~SupportsStats(); |
|
20 |
|
21 }; |
|
22 |
|
23 static int sizesUsed; // number of the elements of the arrays used |
|
24 static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations. sorted |
|
25 static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array) |
|
26 static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used) |
|
27 static int GrowInPlace[MAXSUPPORTS]; |
|
28 |
|
29 // these are per-allocation |
|
30 static int MaxElements[3000]; |
|
31 |
|
32 // very evil |
|
33 #define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \ |
|
34 { \ |
|
35 if (sizesAlloced[i] == (int)(size)) \ |
|
36 { ((x)[i])++; break; } \ |
|
37 } \ |
|
38 if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \ |
|
39 { sizesAlloced[sizesUsed] = (size); \ |
|
40 ((x)[sizesUsed++])++; break; \ |
|
41 } \ |
|
42 } while (0); |
|
43 |
|
44 #define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \ |
|
45 { \ |
|
46 if (sizesAlloced[i] == (int)(size)) \ |
|
47 { ((x)[i])--; break; } \ |
|
48 } \ |
|
49 } while (0); |
|
50 |
|
51 |
|
52 SupportsStats::SupportsStats() |
|
53 { |
|
54 sizesUsed = 1; |
|
55 sizesAlloced[0] = 0; |
|
56 } |
|
57 |
|
58 SupportsStats::~SupportsStats() |
|
59 { |
|
60 int i; |
|
61 for (i = 0; i < sizesUsed; i++) |
|
62 { |
|
63 printf("Size %d:\n",sizesAlloced[i]); |
|
64 printf("\tNumber of SupportsArrays this size (max): %d\n",NumberOfSize[i]); |
|
65 printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize[i]); |
|
66 printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]); |
|
67 } |
|
68 printf("Max Size of SupportsArray:\n"); |
|
69 for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++) |
|
70 { |
|
71 if (MaxElements[i]) |
|
72 printf("\t%d: %d\n",i,MaxElements[i]); |
|
73 } |
|
74 } |
|
75 |
|
76 // Just so constructor/destructor get called |
|
77 SupportsStats gSupportsStats; |
|
78 #endif |
|
79 |
|
80 nsresult |
|
81 nsQueryElementAt::operator()( const nsIID& aIID, void** aResult ) const |
|
82 { |
|
83 nsresult status = mCollection |
|
84 ? mCollection->QueryElementAt(mIndex, aIID, aResult) |
|
85 : NS_ERROR_NULL_POINTER; |
|
86 |
|
87 if ( mErrorPtr ) |
|
88 *mErrorPtr = status; |
|
89 |
|
90 return status; |
|
91 } |
|
92 |
|
93 static const int32_t kGrowArrayBy = 8; |
|
94 static const int32_t kLinearThreshold = 16 * sizeof(nsISupports *); |
|
95 |
|
96 nsSupportsArray::nsSupportsArray() |
|
97 { |
|
98 mArray = mAutoArray; |
|
99 mArraySize = kAutoArraySize; |
|
100 mCount = 0; |
|
101 #if DEBUG_SUPPORTSARRAY |
|
102 mMaxCount = 0; |
|
103 mMaxSize = 0; |
|
104 ADD_TO_STATS(NumberOfSize,kAutoArraySize*sizeof(mArray[0])); |
|
105 MaxElements[0]++; |
|
106 #endif |
|
107 } |
|
108 |
|
109 nsSupportsArray::~nsSupportsArray() |
|
110 { |
|
111 DeleteArray(); |
|
112 } |
|
113 |
|
114 void nsSupportsArray::GrowArrayBy(int32_t aGrowBy) |
|
115 { |
|
116 // We have to grow the array. Grow by kGrowArrayBy slots if we're smaller |
|
117 // than kLinearThreshold bytes, or a power of two if we're larger. |
|
118 // This is much more efficient with most memory allocators, especially |
|
119 // if it's very large, or of the allocator is binned. |
|
120 if (aGrowBy < kGrowArrayBy) |
|
121 aGrowBy = kGrowArrayBy; |
|
122 |
|
123 uint32_t newCount = mArraySize + aGrowBy; // Minimum increase |
|
124 uint32_t newSize = sizeof(mArray[0]) * newCount; |
|
125 |
|
126 if (newSize >= (uint32_t) kLinearThreshold) |
|
127 { |
|
128 // newCount includes enough space for at least kGrowArrayBy new slots. |
|
129 // Select the next power-of-two size in bytes above that if newSize is |
|
130 // not a power of two. |
|
131 if (newSize & (newSize - 1)) |
|
132 newSize = 1u << mozilla::CeilingLog2(newSize); |
|
133 |
|
134 newCount = newSize / sizeof(mArray[0]); |
|
135 } |
|
136 // XXX This would be far more efficient in many allocators if we used |
|
137 // XXX PR_Realloc(), etc |
|
138 nsISupports** oldArray = mArray; |
|
139 |
|
140 mArray = new nsISupports*[newCount]; |
|
141 mArraySize = newCount; |
|
142 |
|
143 #if DEBUG_SUPPORTSARRAY |
|
144 if (oldArray == mArray) // can't happen without use of realloc |
|
145 ADD_TO_STATS(GrowInPlace,mCount); |
|
146 ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0])); |
|
147 if (mArraySize > mMaxSize) |
|
148 { |
|
149 ADD_TO_STATS(NumberOfSize,mArraySize*sizeof(mArray[0])); |
|
150 if (oldArray != &(mAutoArray[0])) |
|
151 SUB_FROM_STATS(NumberOfSize,mCount*sizeof(mArray[0])); |
|
152 mMaxSize = mArraySize; |
|
153 } |
|
154 #endif |
|
155 if (oldArray) { // need to move old data |
|
156 if (0 < mCount) { |
|
157 ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); |
|
158 } |
|
159 if (oldArray != &(mAutoArray[0])) { |
|
160 delete[] oldArray; |
|
161 } |
|
162 } |
|
163 } |
|
164 |
|
165 nsresult |
|
166 nsSupportsArray::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) |
|
167 { |
|
168 if (aOuter) |
|
169 return NS_ERROR_NO_AGGREGATION; |
|
170 |
|
171 nsCOMPtr<nsISupportsArray> it = new nsSupportsArray(); |
|
172 |
|
173 return it->QueryInterface(aIID, aResult); |
|
174 } |
|
175 |
|
176 NS_IMPL_ISUPPORTS(nsSupportsArray, nsISupportsArray, nsICollection, nsISerializable) |
|
177 |
|
178 NS_IMETHODIMP |
|
179 nsSupportsArray::Read(nsIObjectInputStream *aStream) |
|
180 { |
|
181 nsresult rv; |
|
182 |
|
183 uint32_t newArraySize; |
|
184 rv = aStream->Read32(&newArraySize); |
|
185 |
|
186 if (newArraySize <= kAutoArraySize) { |
|
187 if (mArray != mAutoArray) { |
|
188 delete[] mArray; |
|
189 mArray = mAutoArray; |
|
190 } |
|
191 newArraySize = kAutoArraySize; |
|
192 } |
|
193 else { |
|
194 if (newArraySize <= mArraySize) { |
|
195 // Keep non-default-size mArray, it's more than big enough. |
|
196 newArraySize = mArraySize; |
|
197 } |
|
198 else { |
|
199 nsISupports** array = new nsISupports*[newArraySize]; |
|
200 if (mArray != mAutoArray) |
|
201 delete[] mArray; |
|
202 mArray = array; |
|
203 } |
|
204 } |
|
205 mArraySize = newArraySize; |
|
206 |
|
207 rv = aStream->Read32(&mCount); |
|
208 if (NS_FAILED(rv)) return rv; |
|
209 |
|
210 NS_ASSERTION(mCount <= mArraySize, "overlarge mCount!"); |
|
211 if (mCount > mArraySize) |
|
212 mCount = mArraySize; |
|
213 |
|
214 for (uint32_t i = 0; i < mCount; i++) { |
|
215 rv = aStream->ReadObject(true, &mArray[i]); |
|
216 if (NS_FAILED(rv)) return rv; |
|
217 } |
|
218 |
|
219 return NS_OK; |
|
220 } |
|
221 |
|
222 NS_IMETHODIMP |
|
223 nsSupportsArray::Write(nsIObjectOutputStream *aStream) |
|
224 { |
|
225 nsresult rv; |
|
226 |
|
227 rv = aStream->Write32(mArraySize); |
|
228 if (NS_FAILED(rv)) return rv; |
|
229 |
|
230 rv = aStream->Write32(mCount); |
|
231 if (NS_FAILED(rv)) return rv; |
|
232 |
|
233 for (uint32_t i = 0; i < mCount; i++) { |
|
234 rv = aStream->WriteObject(mArray[i], true); |
|
235 if (NS_FAILED(rv)) return rv; |
|
236 } |
|
237 |
|
238 return NS_OK; |
|
239 } |
|
240 |
|
241 void nsSupportsArray::DeleteArray(void) |
|
242 { |
|
243 Clear(); |
|
244 if (mArray != &(mAutoArray[0])) { |
|
245 delete[] mArray; |
|
246 mArray = mAutoArray; |
|
247 mArraySize = kAutoArraySize; |
|
248 } |
|
249 } |
|
250 |
|
251 |
|
252 NS_IMETHODIMP_(bool) |
|
253 nsSupportsArray::Equals(const nsISupportsArray* aOther) |
|
254 { |
|
255 if (aOther) { |
|
256 uint32_t countOther; |
|
257 nsISupportsArray* other = const_cast<nsISupportsArray*>(aOther); |
|
258 nsresult rv = other->Count(&countOther); |
|
259 if (NS_FAILED( rv )) |
|
260 return false; |
|
261 |
|
262 if (mCount == countOther) { |
|
263 uint32_t index = mCount; |
|
264 nsCOMPtr<nsISupports> otherElem; |
|
265 while (index--) { |
|
266 if (NS_FAILED(other->GetElementAt(index, getter_AddRefs(otherElem)))) |
|
267 return false; |
|
268 if (mArray[index] != otherElem) |
|
269 return false; |
|
270 } |
|
271 return true; |
|
272 } |
|
273 } |
|
274 return false; |
|
275 } |
|
276 |
|
277 NS_IMETHODIMP |
|
278 nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports **aOutPtr) |
|
279 { |
|
280 *aOutPtr = nullptr; |
|
281 if (aIndex < mCount) { |
|
282 NS_IF_ADDREF(*aOutPtr = mArray[aIndex]); |
|
283 } |
|
284 return NS_OK; |
|
285 } |
|
286 |
|
287 NS_IMETHODIMP_(int32_t) |
|
288 nsSupportsArray::IndexOf(const nsISupports* aPossibleElement) |
|
289 { |
|
290 return IndexOfStartingAt(aPossibleElement, 0); |
|
291 } |
|
292 |
|
293 NS_IMETHODIMP_(int32_t) |
|
294 nsSupportsArray::IndexOfStartingAt(const nsISupports* aPossibleElement, |
|
295 uint32_t aStartIndex) |
|
296 { |
|
297 if (aStartIndex < mCount) { |
|
298 const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior |
|
299 const nsISupports** ep = (start + aStartIndex); |
|
300 const nsISupports** end = (start + mCount); |
|
301 while (ep < end) { |
|
302 if (aPossibleElement == *ep) { |
|
303 return (ep - start); |
|
304 } |
|
305 ep++; |
|
306 } |
|
307 } |
|
308 return -1; |
|
309 } |
|
310 |
|
311 NS_IMETHODIMP_(int32_t) |
|
312 nsSupportsArray::LastIndexOf(const nsISupports* aPossibleElement) |
|
313 { |
|
314 if (0 < mCount) { |
|
315 const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior |
|
316 const nsISupports** ep = (start + mCount); |
|
317 while (start <= --ep) { |
|
318 if (aPossibleElement == *ep) { |
|
319 return (ep - start); |
|
320 } |
|
321 } |
|
322 } |
|
323 return -1; |
|
324 } |
|
325 |
|
326 NS_IMETHODIMP_(bool) |
|
327 nsSupportsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex) |
|
328 { |
|
329 if (aIndex <= mCount) { |
|
330 if (mArraySize < (mCount + 1)) { |
|
331 // need to grow the array |
|
332 GrowArrayBy(1); |
|
333 } |
|
334 |
|
335 // Could be slightly more efficient if GrowArrayBy knew about the |
|
336 // split, but the difference is trivial. |
|
337 uint32_t slide = (mCount - aIndex); |
|
338 if (0 < slide) { |
|
339 ::memmove(mArray + aIndex + 1, mArray + aIndex, slide * sizeof(nsISupports*)); |
|
340 } |
|
341 |
|
342 mArray[aIndex] = aElement; |
|
343 NS_IF_ADDREF(aElement); |
|
344 mCount++; |
|
345 |
|
346 #if DEBUG_SUPPORTSARRAY |
|
347 if (mCount > mMaxCount && |
|
348 mCount < (int32_t)(sizeof(MaxElements)/sizeof(MaxElements[0]))) |
|
349 { |
|
350 MaxElements[mCount]++; |
|
351 MaxElements[mMaxCount]--; |
|
352 mMaxCount = mCount; |
|
353 } |
|
354 #endif |
|
355 return true; |
|
356 } |
|
357 return false; |
|
358 } |
|
359 |
|
360 NS_IMETHODIMP_(bool) |
|
361 nsSupportsArray::InsertElementsAt(nsISupportsArray* aElements, uint32_t aIndex) |
|
362 { |
|
363 if (!aElements) { |
|
364 return false; |
|
365 } |
|
366 uint32_t countElements; |
|
367 if (NS_FAILED( aElements->Count( &countElements ) )) |
|
368 return false; |
|
369 |
|
370 if (aIndex <= mCount) { |
|
371 if (mArraySize < (mCount + countElements)) { |
|
372 // need to grow the array |
|
373 GrowArrayBy(countElements); |
|
374 } |
|
375 |
|
376 // Could be slightly more efficient if GrowArrayBy knew about the |
|
377 // split, but the difference is trivial. |
|
378 uint32_t slide = (mCount - aIndex); |
|
379 if (0 < slide) { |
|
380 ::memmove(mArray + aIndex + countElements, mArray + aIndex, |
|
381 slide * sizeof(nsISupports*)); |
|
382 } |
|
383 |
|
384 for (uint32_t i = 0; i < countElements; ++i, ++mCount) { |
|
385 // use GetElementAt to copy and do AddRef for us |
|
386 if (NS_FAILED( aElements->GetElementAt( i, mArray + aIndex + i) )) |
|
387 return false; |
|
388 } |
|
389 |
|
390 #if DEBUG_SUPPORTSARRAY |
|
391 if (mCount > mMaxCount && |
|
392 mCount < (int32_t)(sizeof(MaxElements)/sizeof(MaxElements[0]))) |
|
393 { |
|
394 MaxElements[mCount]++; |
|
395 MaxElements[mMaxCount]--; |
|
396 mMaxCount = mCount; |
|
397 } |
|
398 #endif |
|
399 return true; |
|
400 } |
|
401 return false; |
|
402 } |
|
403 |
|
404 NS_IMETHODIMP_(bool) |
|
405 nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) |
|
406 { |
|
407 if (aIndex < mCount) { |
|
408 NS_IF_ADDREF(aElement); // addref first in case it's the same object! |
|
409 NS_IF_RELEASE(mArray[aIndex]); |
|
410 mArray[aIndex] = aElement; |
|
411 return true; |
|
412 } |
|
413 return false; |
|
414 } |
|
415 |
|
416 NS_IMETHODIMP_(bool) |
|
417 nsSupportsArray::RemoveElementsAt(uint32_t aIndex, uint32_t aCount) |
|
418 { |
|
419 if (aIndex + aCount <= mCount) { |
|
420 for (uint32_t i = 0; i < aCount; i++) |
|
421 NS_IF_RELEASE(mArray[aIndex+i]); |
|
422 mCount -= aCount; |
|
423 int32_t slide = (mCount - aIndex); |
|
424 if (0 < slide) { |
|
425 ::memmove(mArray + aIndex, mArray + aIndex + aCount, |
|
426 slide * sizeof(nsISupports*)); |
|
427 } |
|
428 return true; |
|
429 } |
|
430 return false; |
|
431 } |
|
432 |
|
433 NS_IMETHODIMP_(bool) |
|
434 nsSupportsArray::RemoveElement(const nsISupports* aElement, uint32_t aStartIndex) |
|
435 { |
|
436 int32_t theIndex = IndexOfStartingAt(aElement,aStartIndex); |
|
437 if (theIndex >= 0) |
|
438 return RemoveElementAt(theIndex); |
|
439 |
|
440 return false; |
|
441 } |
|
442 |
|
443 NS_IMETHODIMP_(bool) |
|
444 nsSupportsArray::RemoveLastElement(const nsISupports* aElement) |
|
445 { |
|
446 int32_t theIndex = LastIndexOf(aElement); |
|
447 if (theIndex >= 0) |
|
448 return RemoveElementAt(theIndex); |
|
449 |
|
450 return false; |
|
451 } |
|
452 |
|
453 NS_IMETHODIMP_(bool) |
|
454 nsSupportsArray::MoveElement(int32_t aFrom, int32_t aTo) |
|
455 { |
|
456 nsISupports *tempElement; |
|
457 |
|
458 if (aTo == aFrom) |
|
459 return true; |
|
460 |
|
461 if (aTo < 0 || aFrom < 0 || |
|
462 (uint32_t) aTo >= mCount || (uint32_t) aFrom >= mCount) |
|
463 { |
|
464 // can't extend the array when moving an element. Also catches mImpl = null |
|
465 return false; |
|
466 } |
|
467 tempElement = mArray[aFrom]; |
|
468 |
|
469 if (aTo < aFrom) |
|
470 { |
|
471 // Moving one element closer to the head; the elements inbetween move down |
|
472 ::memmove(mArray + aTo + 1, mArray + aTo, |
|
473 (aFrom-aTo) * sizeof(mArray[0])); |
|
474 mArray[aTo] = tempElement; |
|
475 } |
|
476 else // already handled aFrom == aTo |
|
477 { |
|
478 // Moving one element closer to the tail; the elements inbetween move up |
|
479 ::memmove(mArray + aFrom, mArray + aFrom + 1, |
|
480 (aTo-aFrom) * sizeof(mArray[0])); |
|
481 mArray[aTo] = tempElement; |
|
482 } |
|
483 |
|
484 return true; |
|
485 } |
|
486 |
|
487 NS_IMETHODIMP |
|
488 nsSupportsArray::Clear(void) |
|
489 { |
|
490 if (0 < mCount) { |
|
491 do { |
|
492 --mCount; |
|
493 NS_IF_RELEASE(mArray[mCount]); |
|
494 } while (0 != mCount); |
|
495 } |
|
496 return NS_OK; |
|
497 } |
|
498 |
|
499 NS_IMETHODIMP |
|
500 nsSupportsArray::Compact(void) |
|
501 { |
|
502 #if DEBUG_SUPPORTSARRAY |
|
503 uint32_t oldArraySize = mArraySize; |
|
504 #endif |
|
505 if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) { |
|
506 nsISupports** oldArray = mArray; |
|
507 if (mCount <= kAutoArraySize) { |
|
508 mArray = mAutoArray; |
|
509 mArraySize = kAutoArraySize; |
|
510 } |
|
511 else { |
|
512 mArray = new nsISupports*[mCount]; |
|
513 if (!mArray) { |
|
514 mArray = oldArray; |
|
515 return NS_OK; |
|
516 } |
|
517 mArraySize = mCount; |
|
518 } |
|
519 #if DEBUG_SUPPORTSARRAY |
|
520 if (oldArray == mArray && |
|
521 oldArray != &(mAutoArray[0])) // can't happen without use of realloc |
|
522 ADD_TO_STATS(GrowInPlace,oldArraySize); |
|
523 if (oldArray != &(mAutoArray[0])) |
|
524 ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0])); |
|
525 #endif |
|
526 ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); |
|
527 delete[] oldArray; |
|
528 } |
|
529 return NS_OK; |
|
530 } |
|
531 |
|
532 NS_IMETHODIMP_(bool) |
|
533 nsSupportsArray::SizeTo(int32_t aSize) |
|
534 { |
|
535 #if DEBUG_SUPPORTSARRAY |
|
536 uint32_t oldArraySize = mArraySize; |
|
537 #endif |
|
538 NS_ASSERTION(aSize >= 0, "negative aSize!"); |
|
539 |
|
540 // XXX for aSize < mCount we could resize to mCount |
|
541 if (mArraySize == (uint32_t) aSize || (uint32_t) aSize < mCount) |
|
542 return true; // nothing to do |
|
543 |
|
544 // switch back to autoarray if possible |
|
545 nsISupports** oldArray = mArray; |
|
546 if ((uint32_t) aSize <= kAutoArraySize) { |
|
547 mArray = mAutoArray; |
|
548 mArraySize = kAutoArraySize; |
|
549 } |
|
550 else { |
|
551 mArray = new nsISupports*[aSize]; |
|
552 if (!mArray) { |
|
553 mArray = oldArray; |
|
554 return false; |
|
555 } |
|
556 mArraySize = aSize; |
|
557 } |
|
558 #if DEBUG_SUPPORTSARRAY |
|
559 if (oldArray == mArray && |
|
560 oldArray != &(mAutoArray[0])) // can't happen without use of realloc |
|
561 ADD_TO_STATS(GrowInPlace,oldArraySize); |
|
562 if (oldArray != &(mAutoArray[0])) |
|
563 ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0])); |
|
564 #endif |
|
565 ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); |
|
566 if (oldArray != mAutoArray) |
|
567 delete[] oldArray; |
|
568 |
|
569 return true; |
|
570 } |
|
571 |
|
572 NS_IMETHODIMP |
|
573 nsSupportsArray::Enumerate(nsIEnumerator* *result) |
|
574 { |
|
575 nsSupportsArrayEnumerator* e = new nsSupportsArrayEnumerator(this); |
|
576 if (!e) |
|
577 return NS_ERROR_OUT_OF_MEMORY; |
|
578 *result = e; |
|
579 NS_ADDREF(e); |
|
580 return NS_OK; |
|
581 } |
|
582 |
|
583 NS_IMETHODIMP |
|
584 nsSupportsArray::Clone(nsISupportsArray** aResult) |
|
585 { |
|
586 nsCOMPtr<nsISupportsArray> newArray; |
|
587 nsresult rv = NS_NewISupportsArray(getter_AddRefs(newArray)); |
|
588 if (NS_WARN_IF(NS_FAILED(rv))) |
|
589 return rv; |
|
590 |
|
591 uint32_t count = 0; |
|
592 Count(&count); |
|
593 for (uint32_t i = 0; i < count; i++) { |
|
594 if (!newArray->InsertElementAt(mArray[i], i)) { |
|
595 return NS_ERROR_OUT_OF_MEMORY; |
|
596 } |
|
597 } |
|
598 |
|
599 newArray.forget(aResult); |
|
600 return NS_OK; |
|
601 } |
|
602 |
|
603 nsresult |
|
604 NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult) |
|
605 { |
|
606 nsresult rv; |
|
607 rv = nsSupportsArray::Create(nullptr, NS_GET_IID(nsISupportsArray), |
|
608 (void**)aInstancePtrResult); |
|
609 return rv; |
|
610 } |