1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/ds/nsSupportsArray.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,610 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <string.h> 1.10 +#include "mozilla/MathAlgorithms.h" 1.11 +#include "nsSupportsArray.h" 1.12 +#include "nsSupportsArrayEnumerator.h" 1.13 +#include "nsIObjectInputStream.h" 1.14 +#include "nsIObjectOutputStream.h" 1.15 + 1.16 +#if DEBUG_SUPPORTSARRAY 1.17 +#define MAXSUPPORTS 20 1.18 + 1.19 +class SupportsStats { 1.20 +public: 1.21 + SupportsStats(); 1.22 + ~SupportsStats(); 1.23 + 1.24 +}; 1.25 + 1.26 +static int sizesUsed; // number of the elements of the arrays used 1.27 +static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations. sorted 1.28 +static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array) 1.29 +static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used) 1.30 +static int GrowInPlace[MAXSUPPORTS]; 1.31 + 1.32 +// these are per-allocation 1.33 +static int MaxElements[3000]; 1.34 + 1.35 +// very evil 1.36 +#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \ 1.37 + { \ 1.38 + if (sizesAlloced[i] == (int)(size)) \ 1.39 + { ((x)[i])++; break; } \ 1.40 + } \ 1.41 + if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \ 1.42 + { sizesAlloced[sizesUsed] = (size); \ 1.43 + ((x)[sizesUsed++])++; break; \ 1.44 + } \ 1.45 + } while (0); 1.46 + 1.47 +#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \ 1.48 + { \ 1.49 + if (sizesAlloced[i] == (int)(size)) \ 1.50 + { ((x)[i])--; break; } \ 1.51 + } \ 1.52 + } while (0); 1.53 + 1.54 + 1.55 +SupportsStats::SupportsStats() 1.56 +{ 1.57 + sizesUsed = 1; 1.58 + sizesAlloced[0] = 0; 1.59 +} 1.60 + 1.61 +SupportsStats::~SupportsStats() 1.62 +{ 1.63 + int i; 1.64 + for (i = 0; i < sizesUsed; i++) 1.65 + { 1.66 + printf("Size %d:\n",sizesAlloced[i]); 1.67 + printf("\tNumber of SupportsArrays this size (max): %d\n",NumberOfSize[i]); 1.68 + printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize[i]); 1.69 + printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]); 1.70 + } 1.71 + printf("Max Size of SupportsArray:\n"); 1.72 + for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++) 1.73 + { 1.74 + if (MaxElements[i]) 1.75 + printf("\t%d: %d\n",i,MaxElements[i]); 1.76 + } 1.77 +} 1.78 + 1.79 +// Just so constructor/destructor get called 1.80 +SupportsStats gSupportsStats; 1.81 +#endif 1.82 + 1.83 +nsresult 1.84 +nsQueryElementAt::operator()( const nsIID& aIID, void** aResult ) const 1.85 + { 1.86 + nsresult status = mCollection 1.87 + ? mCollection->QueryElementAt(mIndex, aIID, aResult) 1.88 + : NS_ERROR_NULL_POINTER; 1.89 + 1.90 + if ( mErrorPtr ) 1.91 + *mErrorPtr = status; 1.92 + 1.93 + return status; 1.94 + } 1.95 + 1.96 +static const int32_t kGrowArrayBy = 8; 1.97 +static const int32_t kLinearThreshold = 16 * sizeof(nsISupports *); 1.98 + 1.99 +nsSupportsArray::nsSupportsArray() 1.100 +{ 1.101 + mArray = mAutoArray; 1.102 + mArraySize = kAutoArraySize; 1.103 + mCount = 0; 1.104 +#if DEBUG_SUPPORTSARRAY 1.105 + mMaxCount = 0; 1.106 + mMaxSize = 0; 1.107 + ADD_TO_STATS(NumberOfSize,kAutoArraySize*sizeof(mArray[0])); 1.108 + MaxElements[0]++; 1.109 +#endif 1.110 +} 1.111 + 1.112 +nsSupportsArray::~nsSupportsArray() 1.113 +{ 1.114 + DeleteArray(); 1.115 +} 1.116 + 1.117 +void nsSupportsArray::GrowArrayBy(int32_t aGrowBy) 1.118 +{ 1.119 + // We have to grow the array. Grow by kGrowArrayBy slots if we're smaller 1.120 + // than kLinearThreshold bytes, or a power of two if we're larger. 1.121 + // This is much more efficient with most memory allocators, especially 1.122 + // if it's very large, or of the allocator is binned. 1.123 + if (aGrowBy < kGrowArrayBy) 1.124 + aGrowBy = kGrowArrayBy; 1.125 + 1.126 + uint32_t newCount = mArraySize + aGrowBy; // Minimum increase 1.127 + uint32_t newSize = sizeof(mArray[0]) * newCount; 1.128 + 1.129 + if (newSize >= (uint32_t) kLinearThreshold) 1.130 + { 1.131 + // newCount includes enough space for at least kGrowArrayBy new slots. 1.132 + // Select the next power-of-two size in bytes above that if newSize is 1.133 + // not a power of two. 1.134 + if (newSize & (newSize - 1)) 1.135 + newSize = 1u << mozilla::CeilingLog2(newSize); 1.136 + 1.137 + newCount = newSize / sizeof(mArray[0]); 1.138 + } 1.139 + // XXX This would be far more efficient in many allocators if we used 1.140 + // XXX PR_Realloc(), etc 1.141 + nsISupports** oldArray = mArray; 1.142 + 1.143 + mArray = new nsISupports*[newCount]; 1.144 + mArraySize = newCount; 1.145 + 1.146 +#if DEBUG_SUPPORTSARRAY 1.147 + if (oldArray == mArray) // can't happen without use of realloc 1.148 + ADD_TO_STATS(GrowInPlace,mCount); 1.149 + ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0])); 1.150 + if (mArraySize > mMaxSize) 1.151 + { 1.152 + ADD_TO_STATS(NumberOfSize,mArraySize*sizeof(mArray[0])); 1.153 + if (oldArray != &(mAutoArray[0])) 1.154 + SUB_FROM_STATS(NumberOfSize,mCount*sizeof(mArray[0])); 1.155 + mMaxSize = mArraySize; 1.156 + } 1.157 +#endif 1.158 + if (oldArray) { // need to move old data 1.159 + if (0 < mCount) { 1.160 + ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); 1.161 + } 1.162 + if (oldArray != &(mAutoArray[0])) { 1.163 + delete[] oldArray; 1.164 + } 1.165 + } 1.166 +} 1.167 + 1.168 +nsresult 1.169 +nsSupportsArray::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) 1.170 +{ 1.171 + if (aOuter) 1.172 + return NS_ERROR_NO_AGGREGATION; 1.173 + 1.174 + nsCOMPtr<nsISupportsArray> it = new nsSupportsArray(); 1.175 + 1.176 + return it->QueryInterface(aIID, aResult); 1.177 +} 1.178 + 1.179 +NS_IMPL_ISUPPORTS(nsSupportsArray, nsISupportsArray, nsICollection, nsISerializable) 1.180 + 1.181 +NS_IMETHODIMP 1.182 +nsSupportsArray::Read(nsIObjectInputStream *aStream) 1.183 +{ 1.184 + nsresult rv; 1.185 + 1.186 + uint32_t newArraySize; 1.187 + rv = aStream->Read32(&newArraySize); 1.188 + 1.189 + if (newArraySize <= kAutoArraySize) { 1.190 + if (mArray != mAutoArray) { 1.191 + delete[] mArray; 1.192 + mArray = mAutoArray; 1.193 + } 1.194 + newArraySize = kAutoArraySize; 1.195 + } 1.196 + else { 1.197 + if (newArraySize <= mArraySize) { 1.198 + // Keep non-default-size mArray, it's more than big enough. 1.199 + newArraySize = mArraySize; 1.200 + } 1.201 + else { 1.202 + nsISupports** array = new nsISupports*[newArraySize]; 1.203 + if (mArray != mAutoArray) 1.204 + delete[] mArray; 1.205 + mArray = array; 1.206 + } 1.207 + } 1.208 + mArraySize = newArraySize; 1.209 + 1.210 + rv = aStream->Read32(&mCount); 1.211 + if (NS_FAILED(rv)) return rv; 1.212 + 1.213 + NS_ASSERTION(mCount <= mArraySize, "overlarge mCount!"); 1.214 + if (mCount > mArraySize) 1.215 + mCount = mArraySize; 1.216 + 1.217 + for (uint32_t i = 0; i < mCount; i++) { 1.218 + rv = aStream->ReadObject(true, &mArray[i]); 1.219 + if (NS_FAILED(rv)) return rv; 1.220 + } 1.221 + 1.222 + return NS_OK; 1.223 +} 1.224 + 1.225 +NS_IMETHODIMP 1.226 +nsSupportsArray::Write(nsIObjectOutputStream *aStream) 1.227 +{ 1.228 + nsresult rv; 1.229 + 1.230 + rv = aStream->Write32(mArraySize); 1.231 + if (NS_FAILED(rv)) return rv; 1.232 + 1.233 + rv = aStream->Write32(mCount); 1.234 + if (NS_FAILED(rv)) return rv; 1.235 + 1.236 + for (uint32_t i = 0; i < mCount; i++) { 1.237 + rv = aStream->WriteObject(mArray[i], true); 1.238 + if (NS_FAILED(rv)) return rv; 1.239 + } 1.240 + 1.241 + return NS_OK; 1.242 +} 1.243 + 1.244 +void nsSupportsArray::DeleteArray(void) 1.245 +{ 1.246 + Clear(); 1.247 + if (mArray != &(mAutoArray[0])) { 1.248 + delete[] mArray; 1.249 + mArray = mAutoArray; 1.250 + mArraySize = kAutoArraySize; 1.251 + } 1.252 +} 1.253 + 1.254 + 1.255 +NS_IMETHODIMP_(bool) 1.256 +nsSupportsArray::Equals(const nsISupportsArray* aOther) 1.257 +{ 1.258 + if (aOther) { 1.259 + uint32_t countOther; 1.260 + nsISupportsArray* other = const_cast<nsISupportsArray*>(aOther); 1.261 + nsresult rv = other->Count(&countOther); 1.262 + if (NS_FAILED( rv )) 1.263 + return false; 1.264 + 1.265 + if (mCount == countOther) { 1.266 + uint32_t index = mCount; 1.267 + nsCOMPtr<nsISupports> otherElem; 1.268 + while (index--) { 1.269 + if (NS_FAILED(other->GetElementAt(index, getter_AddRefs(otherElem)))) 1.270 + return false; 1.271 + if (mArray[index] != otherElem) 1.272 + return false; 1.273 + } 1.274 + return true; 1.275 + } 1.276 + } 1.277 + return false; 1.278 +} 1.279 + 1.280 +NS_IMETHODIMP 1.281 +nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports **aOutPtr) 1.282 +{ 1.283 + *aOutPtr = nullptr; 1.284 + if (aIndex < mCount) { 1.285 + NS_IF_ADDREF(*aOutPtr = mArray[aIndex]); 1.286 + } 1.287 + return NS_OK; 1.288 +} 1.289 + 1.290 +NS_IMETHODIMP_(int32_t) 1.291 +nsSupportsArray::IndexOf(const nsISupports* aPossibleElement) 1.292 +{ 1.293 + return IndexOfStartingAt(aPossibleElement, 0); 1.294 +} 1.295 + 1.296 +NS_IMETHODIMP_(int32_t) 1.297 +nsSupportsArray::IndexOfStartingAt(const nsISupports* aPossibleElement, 1.298 + uint32_t aStartIndex) 1.299 +{ 1.300 + if (aStartIndex < mCount) { 1.301 + const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior 1.302 + const nsISupports** ep = (start + aStartIndex); 1.303 + const nsISupports** end = (start + mCount); 1.304 + while (ep < end) { 1.305 + if (aPossibleElement == *ep) { 1.306 + return (ep - start); 1.307 + } 1.308 + ep++; 1.309 + } 1.310 + } 1.311 + return -1; 1.312 +} 1.313 + 1.314 +NS_IMETHODIMP_(int32_t) 1.315 +nsSupportsArray::LastIndexOf(const nsISupports* aPossibleElement) 1.316 +{ 1.317 + if (0 < mCount) { 1.318 + const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior 1.319 + const nsISupports** ep = (start + mCount); 1.320 + while (start <= --ep) { 1.321 + if (aPossibleElement == *ep) { 1.322 + return (ep - start); 1.323 + } 1.324 + } 1.325 + } 1.326 + return -1; 1.327 +} 1.328 + 1.329 +NS_IMETHODIMP_(bool) 1.330 +nsSupportsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex) 1.331 +{ 1.332 + if (aIndex <= mCount) { 1.333 + if (mArraySize < (mCount + 1)) { 1.334 + // need to grow the array 1.335 + GrowArrayBy(1); 1.336 + } 1.337 + 1.338 + // Could be slightly more efficient if GrowArrayBy knew about the 1.339 + // split, but the difference is trivial. 1.340 + uint32_t slide = (mCount - aIndex); 1.341 + if (0 < slide) { 1.342 + ::memmove(mArray + aIndex + 1, mArray + aIndex, slide * sizeof(nsISupports*)); 1.343 + } 1.344 + 1.345 + mArray[aIndex] = aElement; 1.346 + NS_IF_ADDREF(aElement); 1.347 + mCount++; 1.348 + 1.349 +#if DEBUG_SUPPORTSARRAY 1.350 + if (mCount > mMaxCount && 1.351 + mCount < (int32_t)(sizeof(MaxElements)/sizeof(MaxElements[0]))) 1.352 + { 1.353 + MaxElements[mCount]++; 1.354 + MaxElements[mMaxCount]--; 1.355 + mMaxCount = mCount; 1.356 + } 1.357 +#endif 1.358 + return true; 1.359 + } 1.360 + return false; 1.361 +} 1.362 + 1.363 +NS_IMETHODIMP_(bool) 1.364 +nsSupportsArray::InsertElementsAt(nsISupportsArray* aElements, uint32_t aIndex) 1.365 +{ 1.366 + if (!aElements) { 1.367 + return false; 1.368 + } 1.369 + uint32_t countElements; 1.370 + if (NS_FAILED( aElements->Count( &countElements ) )) 1.371 + return false; 1.372 + 1.373 + if (aIndex <= mCount) { 1.374 + if (mArraySize < (mCount + countElements)) { 1.375 + // need to grow the array 1.376 + GrowArrayBy(countElements); 1.377 + } 1.378 + 1.379 + // Could be slightly more efficient if GrowArrayBy knew about the 1.380 + // split, but the difference is trivial. 1.381 + uint32_t slide = (mCount - aIndex); 1.382 + if (0 < slide) { 1.383 + ::memmove(mArray + aIndex + countElements, mArray + aIndex, 1.384 + slide * sizeof(nsISupports*)); 1.385 + } 1.386 + 1.387 + for (uint32_t i = 0; i < countElements; ++i, ++mCount) { 1.388 + // use GetElementAt to copy and do AddRef for us 1.389 + if (NS_FAILED( aElements->GetElementAt( i, mArray + aIndex + i) )) 1.390 + return false; 1.391 + } 1.392 + 1.393 +#if DEBUG_SUPPORTSARRAY 1.394 + if (mCount > mMaxCount && 1.395 + mCount < (int32_t)(sizeof(MaxElements)/sizeof(MaxElements[0]))) 1.396 + { 1.397 + MaxElements[mCount]++; 1.398 + MaxElements[mMaxCount]--; 1.399 + mMaxCount = mCount; 1.400 + } 1.401 +#endif 1.402 + return true; 1.403 + } 1.404 + return false; 1.405 +} 1.406 + 1.407 +NS_IMETHODIMP_(bool) 1.408 +nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) 1.409 +{ 1.410 + if (aIndex < mCount) { 1.411 + NS_IF_ADDREF(aElement); // addref first in case it's the same object! 1.412 + NS_IF_RELEASE(mArray[aIndex]); 1.413 + mArray[aIndex] = aElement; 1.414 + return true; 1.415 + } 1.416 + return false; 1.417 +} 1.418 + 1.419 +NS_IMETHODIMP_(bool) 1.420 +nsSupportsArray::RemoveElementsAt(uint32_t aIndex, uint32_t aCount) 1.421 +{ 1.422 + if (aIndex + aCount <= mCount) { 1.423 + for (uint32_t i = 0; i < aCount; i++) 1.424 + NS_IF_RELEASE(mArray[aIndex+i]); 1.425 + mCount -= aCount; 1.426 + int32_t slide = (mCount - aIndex); 1.427 + if (0 < slide) { 1.428 + ::memmove(mArray + aIndex, mArray + aIndex + aCount, 1.429 + slide * sizeof(nsISupports*)); 1.430 + } 1.431 + return true; 1.432 + } 1.433 + return false; 1.434 +} 1.435 + 1.436 +NS_IMETHODIMP_(bool) 1.437 +nsSupportsArray::RemoveElement(const nsISupports* aElement, uint32_t aStartIndex) 1.438 +{ 1.439 + int32_t theIndex = IndexOfStartingAt(aElement,aStartIndex); 1.440 + if (theIndex >= 0) 1.441 + return RemoveElementAt(theIndex); 1.442 + 1.443 + return false; 1.444 +} 1.445 + 1.446 +NS_IMETHODIMP_(bool) 1.447 +nsSupportsArray::RemoveLastElement(const nsISupports* aElement) 1.448 +{ 1.449 + int32_t theIndex = LastIndexOf(aElement); 1.450 + if (theIndex >= 0) 1.451 + return RemoveElementAt(theIndex); 1.452 + 1.453 + return false; 1.454 +} 1.455 + 1.456 +NS_IMETHODIMP_(bool) 1.457 +nsSupportsArray::MoveElement(int32_t aFrom, int32_t aTo) 1.458 +{ 1.459 + nsISupports *tempElement; 1.460 + 1.461 + if (aTo == aFrom) 1.462 + return true; 1.463 + 1.464 + if (aTo < 0 || aFrom < 0 || 1.465 + (uint32_t) aTo >= mCount || (uint32_t) aFrom >= mCount) 1.466 + { 1.467 + // can't extend the array when moving an element. Also catches mImpl = null 1.468 + return false; 1.469 + } 1.470 + tempElement = mArray[aFrom]; 1.471 + 1.472 + if (aTo < aFrom) 1.473 + { 1.474 + // Moving one element closer to the head; the elements inbetween move down 1.475 + ::memmove(mArray + aTo + 1, mArray + aTo, 1.476 + (aFrom-aTo) * sizeof(mArray[0])); 1.477 + mArray[aTo] = tempElement; 1.478 + } 1.479 + else // already handled aFrom == aTo 1.480 + { 1.481 + // Moving one element closer to the tail; the elements inbetween move up 1.482 + ::memmove(mArray + aFrom, mArray + aFrom + 1, 1.483 + (aTo-aFrom) * sizeof(mArray[0])); 1.484 + mArray[aTo] = tempElement; 1.485 + } 1.486 + 1.487 + return true; 1.488 +} 1.489 + 1.490 +NS_IMETHODIMP 1.491 +nsSupportsArray::Clear(void) 1.492 +{ 1.493 + if (0 < mCount) { 1.494 + do { 1.495 + --mCount; 1.496 + NS_IF_RELEASE(mArray[mCount]); 1.497 + } while (0 != mCount); 1.498 + } 1.499 + return NS_OK; 1.500 +} 1.501 + 1.502 +NS_IMETHODIMP 1.503 +nsSupportsArray::Compact(void) 1.504 +{ 1.505 +#if DEBUG_SUPPORTSARRAY 1.506 + uint32_t oldArraySize = mArraySize; 1.507 +#endif 1.508 + if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) { 1.509 + nsISupports** oldArray = mArray; 1.510 + if (mCount <= kAutoArraySize) { 1.511 + mArray = mAutoArray; 1.512 + mArraySize = kAutoArraySize; 1.513 + } 1.514 + else { 1.515 + mArray = new nsISupports*[mCount]; 1.516 + if (!mArray) { 1.517 + mArray = oldArray; 1.518 + return NS_OK; 1.519 + } 1.520 + mArraySize = mCount; 1.521 + } 1.522 +#if DEBUG_SUPPORTSARRAY 1.523 + if (oldArray == mArray && 1.524 + oldArray != &(mAutoArray[0])) // can't happen without use of realloc 1.525 + ADD_TO_STATS(GrowInPlace,oldArraySize); 1.526 + if (oldArray != &(mAutoArray[0])) 1.527 + ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0])); 1.528 +#endif 1.529 + ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); 1.530 + delete[] oldArray; 1.531 + } 1.532 + return NS_OK; 1.533 +} 1.534 + 1.535 +NS_IMETHODIMP_(bool) 1.536 +nsSupportsArray::SizeTo(int32_t aSize) 1.537 +{ 1.538 +#if DEBUG_SUPPORTSARRAY 1.539 + uint32_t oldArraySize = mArraySize; 1.540 +#endif 1.541 + NS_ASSERTION(aSize >= 0, "negative aSize!"); 1.542 + 1.543 + // XXX for aSize < mCount we could resize to mCount 1.544 + if (mArraySize == (uint32_t) aSize || (uint32_t) aSize < mCount) 1.545 + return true; // nothing to do 1.546 + 1.547 + // switch back to autoarray if possible 1.548 + nsISupports** oldArray = mArray; 1.549 + if ((uint32_t) aSize <= kAutoArraySize) { 1.550 + mArray = mAutoArray; 1.551 + mArraySize = kAutoArraySize; 1.552 + } 1.553 + else { 1.554 + mArray = new nsISupports*[aSize]; 1.555 + if (!mArray) { 1.556 + mArray = oldArray; 1.557 + return false; 1.558 + } 1.559 + mArraySize = aSize; 1.560 + } 1.561 +#if DEBUG_SUPPORTSARRAY 1.562 + if (oldArray == mArray && 1.563 + oldArray != &(mAutoArray[0])) // can't happen without use of realloc 1.564 + ADD_TO_STATS(GrowInPlace,oldArraySize); 1.565 + if (oldArray != &(mAutoArray[0])) 1.566 + ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0])); 1.567 +#endif 1.568 + ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); 1.569 + if (oldArray != mAutoArray) 1.570 + delete[] oldArray; 1.571 + 1.572 + return true; 1.573 +} 1.574 + 1.575 +NS_IMETHODIMP 1.576 +nsSupportsArray::Enumerate(nsIEnumerator* *result) 1.577 +{ 1.578 + nsSupportsArrayEnumerator* e = new nsSupportsArrayEnumerator(this); 1.579 + if (!e) 1.580 + return NS_ERROR_OUT_OF_MEMORY; 1.581 + *result = e; 1.582 + NS_ADDREF(e); 1.583 + return NS_OK; 1.584 +} 1.585 + 1.586 +NS_IMETHODIMP 1.587 +nsSupportsArray::Clone(nsISupportsArray** aResult) 1.588 +{ 1.589 + nsCOMPtr<nsISupportsArray> newArray; 1.590 + nsresult rv = NS_NewISupportsArray(getter_AddRefs(newArray)); 1.591 + if (NS_WARN_IF(NS_FAILED(rv))) 1.592 + return rv; 1.593 + 1.594 + uint32_t count = 0; 1.595 + Count(&count); 1.596 + for (uint32_t i = 0; i < count; i++) { 1.597 + if (!newArray->InsertElementAt(mArray[i], i)) { 1.598 + return NS_ERROR_OUT_OF_MEMORY; 1.599 + } 1.600 + } 1.601 + 1.602 + newArray.forget(aResult); 1.603 + return NS_OK; 1.604 +} 1.605 + 1.606 +nsresult 1.607 +NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult) 1.608 +{ 1.609 + nsresult rv; 1.610 + rv = nsSupportsArray::Create(nullptr, NS_GET_IID(nsISupportsArray), 1.611 + (void**)aInstancePtrResult); 1.612 + return rv; 1.613 +}