LCOV - code coverage report
Current view: directory - xpcom/ds - nsSupportsArray.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 307 128 41.7 %
Date: 2012-06-02 Functions: 40 25 62.5 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Scott Collins <scc@mozilla.org>: |do_QueryElementAt|
      24                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include <string.h>
      41                 : #include "prbit.h"
      42                 : #include "nsSupportsArray.h"
      43                 : #include "nsSupportsArrayEnumerator.h"
      44                 : #include "nsAString.h"
      45                 : #include "nsIObjectInputStream.h"
      46                 : #include "nsIObjectOutputStream.h"
      47                 : 
      48                 : #if DEBUG_SUPPORTSARRAY
      49                 : #define MAXSUPPORTS 20
      50                 : 
      51                 : class SupportsStats {
      52                 : public:
      53                 :   SupportsStats();
      54                 :   ~SupportsStats();
      55                 : 
      56                 : };
      57                 : 
      58                 : static int sizesUsed; // number of the elements of the arrays used
      59                 : static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations.  sorted
      60                 : static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array)
      61                 : static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used)
      62                 : static int GrowInPlace[MAXSUPPORTS];
      63                 : 
      64                 : // these are per-allocation
      65                 : static int MaxElements[3000];
      66                 : 
      67                 : // very evil
      68                 : #define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
      69                 :                                   { \
      70                 :                                     if (sizesAlloced[i] == (int)(size)) \
      71                 :                                     { ((x)[i])++; break; } \
      72                 :                                   } \
      73                 :                                   if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \
      74                 :                                   { sizesAlloced[sizesUsed] = (size); \
      75                 :                                     ((x)[sizesUsed++])++; break; \
      76                 :                                   } \
      77                 :                                 } while (0);
      78                 : 
      79                 : #define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
      80                 :                                     { \
      81                 :                                       if (sizesAlloced[i] == (int)(size)) \
      82                 :                                       { ((x)[i])--; break; } \
      83                 :                                     } \
      84                 :                                   } while (0);
      85                 : 
      86                 : 
      87                 : SupportsStats::SupportsStats()
      88                 : {
      89                 :   sizesUsed = 1;
      90                 :   sizesAlloced[0] = 0;
      91                 : }
      92                 : 
      93                 : SupportsStats::~SupportsStats()
      94                 : {
      95                 :   int i;
      96                 :   for (i = 0; i < sizesUsed; i++)
      97                 :   {
      98                 :     printf("Size %d:\n",sizesAlloced[i]);
      99                 :     printf("\tNumber of SupportsArrays this size (max):     %d\n",NumberOfSize[i]);
     100                 :     printf("\tNumber of allocations this size (total):  %d\n",AllocedOfSize[i]);
     101                 :     printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]);
     102                 :   }
     103                 :   printf("Max Size of SupportsArray:\n");
     104                 :   for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++)
     105                 :   {
     106                 :     if (MaxElements[i])
     107                 :       printf("\t%d: %d\n",i,MaxElements[i]);
     108                 :   }
     109                 : }
     110                 : 
     111                 : // Just so constructor/destructor get called
     112                 : SupportsStats gSupportsStats;
     113                 : #endif
     114                 : 
     115                 : nsresult
     116               0 : nsQueryElementAt::operator()( const nsIID& aIID, void** aResult ) const
     117                 :   {
     118                 :     nsresult status = mCollection
     119               0 :                         ? mCollection->QueryElementAt(mIndex, aIID, aResult)
     120               0 :                         : NS_ERROR_NULL_POINTER;
     121                 : 
     122               0 :     if ( mErrorPtr )
     123               0 :       *mErrorPtr = status;
     124                 : 
     125               0 :     return status;
     126                 :   }
     127                 : 
     128                 : static const PRInt32 kGrowArrayBy = 8;
     129                 : static const PRInt32 kLinearThreshold = 16 * sizeof(nsISupports *);
     130                 : 
     131            1748 : nsSupportsArray::nsSupportsArray()
     132                 : {
     133            1748 :   mArray = mAutoArray;
     134            1748 :   mArraySize = kAutoArraySize;
     135            1748 :   mCount = 0;
     136                 : #if DEBUG_SUPPORTSARRAY
     137                 :   mMaxCount = 0;
     138                 :   mMaxSize = 0;
     139                 :   ADD_TO_STATS(NumberOfSize,kAutoArraySize*sizeof(mArray[0]));
     140                 :   MaxElements[0]++;
     141                 : #endif
     142            1748 : }
     143                 : 
     144            1748 : nsSupportsArray::~nsSupportsArray()
     145                 : {
     146            1748 :   DeleteArray();
     147            1748 : }
     148                 : 
     149            1863 : bool nsSupportsArray::GrowArrayBy(PRInt32 aGrowBy)
     150                 : {
     151                 :   // We have to grow the array. Grow by kGrowArrayBy slots if we're smaller
     152                 :   // than kLinearThreshold bytes, or a power of two if we're larger.
     153                 :   // This is much more efficient with most memory allocators, especially
     154                 :   // if it's very large, or of the allocator is binned.
     155            1863 :   if (aGrowBy < kGrowArrayBy)
     156            1863 :     aGrowBy = kGrowArrayBy;
     157                 : 
     158            1863 :   PRUint32 newCount = mArraySize + aGrowBy;  // Minimum increase
     159            1863 :   PRUint32 newSize = sizeof(mArray[0]) * newCount;
     160                 : 
     161            1863 :   if (newSize >= (PRUint32) kLinearThreshold)
     162                 :   {
     163                 :     // newCount includes enough space for at least kGrowArrayBy new slots.
     164                 :     // Select the next power-of-two size in bytes above that if newSize is
     165                 :     // not a power of two.
     166            1863 :     if (newSize & (newSize - 1))
     167            1540 :       newSize = PR_BIT(PR_CeilingLog2(newSize));
     168                 : 
     169            1863 :     newCount = newSize / sizeof(mArray[0]);
     170                 :   }
     171                 :   // XXX This would be far more efficient in many allocators if we used
     172                 :   // XXX PR_Realloc(), etc
     173            1863 :   nsISupports** oldArray = mArray;
     174                 : 
     175            3726 :   mArray = new nsISupports*[newCount];
     176            1863 :   if (!mArray) {                    // ran out of memory
     177               0 :     mArray = oldArray;
     178               0 :     return false;
     179                 :   }
     180            1863 :   mArraySize = newCount;
     181                 : 
     182                 : #if DEBUG_SUPPORTSARRAY
     183                 :   if (oldArray == mArray) // can't happen without use of realloc
     184                 :     ADD_TO_STATS(GrowInPlace,mCount);
     185                 :   ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
     186                 :   if (mArraySize > mMaxSize)
     187                 :   {
     188                 :     ADD_TO_STATS(NumberOfSize,mArraySize*sizeof(mArray[0]));
     189                 :     if (oldArray != &(mAutoArray[0]))
     190                 :       SUB_FROM_STATS(NumberOfSize,mCount*sizeof(mArray[0]));
     191                 :     mMaxSize = mArraySize;
     192                 :   }
     193                 : #endif
     194            1863 :   if (oldArray) {                   // need to move old data
     195            1863 :     if (0 < mCount) {
     196            1863 :       ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
     197                 :     }
     198            1863 :     if (oldArray != &(mAutoArray[0])) {
     199            1540 :       delete[] oldArray;
     200                 :     }
     201                 :   }
     202                 : 
     203            1863 :   return true;
     204                 : }
     205                 : 
     206                 : nsresult
     207            1748 : nsSupportsArray::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
     208                 : {
     209            1748 :   if (aOuter)
     210               0 :     return NS_ERROR_NO_AGGREGATION;
     211                 : 
     212            3496 :   nsCOMPtr<nsISupportsArray> it = new nsSupportsArray();
     213            1748 :   if (!it)
     214               0 :     return NS_ERROR_OUT_OF_MEMORY;
     215                 : 
     216            1748 :   return it->QueryInterface(aIID, aResult);
     217                 : }
     218                 : 
     219           21674 : NS_IMPL_THREADSAFE_ISUPPORTS3(nsSupportsArray, nsISupportsArray, nsICollection, nsISerializable)
     220                 : 
     221                 : NS_IMETHODIMP
     222               0 : nsSupportsArray::Read(nsIObjectInputStream *aStream)
     223                 : {
     224                 :   nsresult rv;
     225                 : 
     226                 :   PRUint32 newArraySize;
     227               0 :   rv = aStream->Read32(&newArraySize);
     228                 : 
     229               0 :   if (newArraySize <= kAutoArraySize) {
     230               0 :     if (mArray != mAutoArray) {
     231               0 :       delete[] mArray;
     232               0 :       mArray = mAutoArray;
     233                 :     }
     234               0 :     newArraySize = kAutoArraySize;
     235                 :   }
     236                 :   else {
     237               0 :     if (newArraySize <= mArraySize) {
     238                 :       // Keep non-default-size mArray, it's more than big enough.
     239               0 :       newArraySize = mArraySize;
     240                 :     }
     241                 :     else {
     242               0 :       nsISupports** array = new nsISupports*[newArraySize];
     243               0 :       if (!array)
     244               0 :         return NS_ERROR_OUT_OF_MEMORY;
     245               0 :       if (mArray != mAutoArray)
     246               0 :         delete[] mArray;
     247               0 :       mArray = array;
     248                 :     }
     249                 :   }
     250               0 :   mArraySize = newArraySize;
     251                 : 
     252               0 :   rv = aStream->Read32(&mCount);
     253               0 :   if (NS_FAILED(rv)) return rv;
     254                 : 
     255               0 :   NS_ASSERTION(mCount <= mArraySize, "overlarge mCount!");
     256               0 :   if (mCount > mArraySize)
     257               0 :     mCount = mArraySize;
     258                 : 
     259               0 :   for (PRUint32 i = 0; i < mCount; i++) {
     260               0 :     rv = aStream->ReadObject(true, &mArray[i]);
     261               0 :     if (NS_FAILED(rv)) return rv;
     262                 :   }
     263                 : 
     264               0 :   return NS_OK;
     265                 : }
     266                 : 
     267                 : NS_IMETHODIMP
     268               0 : nsSupportsArray::Write(nsIObjectOutputStream *aStream)
     269                 : {
     270                 :   nsresult rv;
     271                 : 
     272               0 :   rv = aStream->Write32(mArraySize);
     273               0 :   if (NS_FAILED(rv)) return rv;
     274                 : 
     275               0 :   rv = aStream->Write32(mCount);
     276               0 :   if (NS_FAILED(rv)) return rv;
     277                 : 
     278               0 :   for (PRUint32 i = 0; i < mCount; i++) {
     279               0 :     rv = aStream->WriteObject(mArray[i], true);
     280               0 :     if (NS_FAILED(rv)) return rv;
     281                 :   }
     282                 : 
     283               0 :   return NS_OK;
     284                 : }
     285                 : 
     286            1748 : void nsSupportsArray::DeleteArray(void)
     287                 : {
     288            1748 :   Clear();
     289            1748 :   if (mArray != &(mAutoArray[0])) {
     290             323 :     delete[] mArray;
     291             323 :     mArray = mAutoArray;
     292             323 :     mArraySize = kAutoArraySize;
     293                 :   }
     294            1748 : }
     295                 : 
     296                 : 
     297                 : NS_IMETHODIMP_(bool)
     298               0 : nsSupportsArray::Equals(const nsISupportsArray* aOther)
     299                 : {
     300               0 :   if (aOther) {
     301                 :     PRUint32 countOther;
     302               0 :     nsISupportsArray* other = const_cast<nsISupportsArray*>(aOther);
     303               0 :     nsresult rv = other->Count(&countOther);
     304               0 :     if (NS_FAILED( rv ))
     305               0 :       return false;
     306                 : 
     307               0 :     if (mCount == countOther) {
     308               0 :       PRUint32 index = mCount;
     309               0 :       nsCOMPtr<nsISupports> otherElem;
     310               0 :       while (index--) {
     311               0 :         if (NS_FAILED(other->GetElementAt(index, getter_AddRefs(otherElem))))
     312               0 :           return false;
     313               0 :         if (mArray[index] != otherElem)
     314               0 :           return false;
     315                 :       }
     316               0 :       return true;
     317                 :     }
     318                 :   }
     319               0 :   return false;
     320                 : }
     321                 : 
     322                 : NS_IMETHODIMP_(nsISupports*)
     323          130399 : nsSupportsArray::ElementAt(PRUint32 aIndex)
     324                 : {
     325          130399 :   if (aIndex < mCount) {
     326          130399 :     nsISupports*  element = mArray[aIndex];
     327          130399 :     NS_IF_ADDREF(element);
     328          130399 :     return element;
     329                 :   }
     330               0 :   return 0;
     331                 : }
     332                 : 
     333                 : NS_IMETHODIMP_(PRInt32)
     334               0 : nsSupportsArray::IndexOf(const nsISupports* aPossibleElement)
     335                 : {
     336               0 :   return IndexOfStartingAt(aPossibleElement, 0);
     337                 : }
     338                 : 
     339                 : NS_IMETHODIMP_(PRInt32)
     340              35 : nsSupportsArray::IndexOfStartingAt(const nsISupports* aPossibleElement,
     341                 :                                    PRUint32 aStartIndex)
     342                 : {
     343              35 :   if (aStartIndex < mCount) {
     344              35 :     const nsISupports** start = (const nsISupports**)mArray;  // work around goofy compiler behavior
     345              35 :     const nsISupports** ep = (start + aStartIndex);
     346              35 :     const nsISupports** end = (start + mCount);
     347             210 :     while (ep < end) {
     348             175 :       if (aPossibleElement == *ep) {
     349              35 :         return (ep - start);
     350                 :       }
     351             140 :       ep++;
     352                 :     }
     353                 :   }
     354               0 :   return -1;
     355                 : }
     356                 : 
     357                 : NS_IMETHODIMP_(PRInt32)
     358               0 : nsSupportsArray::LastIndexOf(const nsISupports* aPossibleElement)
     359                 : {
     360               0 :   if (0 < mCount) {
     361               0 :     const nsISupports** start = (const nsISupports**)mArray;  // work around goofy compiler behavior
     362               0 :     const nsISupports** ep = (start + mCount);
     363               0 :     while (start <= --ep) {
     364               0 :       if (aPossibleElement == *ep) {
     365               0 :         return (ep - start);
     366                 :       }
     367                 :     }
     368                 :   }
     369               0 :   return -1;
     370                 : }
     371                 : 
     372                 : NS_IMETHODIMP_(bool)
     373          137303 : nsSupportsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex)
     374                 : {
     375          137303 :   if (aIndex <= mCount) {
     376          137303 :     if (mArraySize < (mCount + 1)) {
     377                 :       // need to grow the array
     378            1863 :       if (!GrowArrayBy(1))
     379               0 :         return false;
     380                 :     }
     381                 : 
     382                 :     // Could be slightly more efficient if GrowArrayBy knew about the
     383                 :     // split, but the difference is trivial.
     384          137303 :     PRUint32 slide = (mCount - aIndex);
     385          137303 :     if (0 < slide) {
     386               0 :       ::memmove(mArray + aIndex + 1, mArray + aIndex, slide * sizeof(nsISupports*));
     387                 :     }
     388                 : 
     389          137303 :     mArray[aIndex] = aElement;
     390          137303 :     NS_IF_ADDREF(aElement);
     391          137303 :     mCount++;
     392                 : 
     393                 : #if DEBUG_SUPPORTSARRAY
     394                 :     if (mCount > mMaxCount &&
     395                 :         mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
     396                 :     {
     397                 :       MaxElements[mCount]++;
     398                 :       MaxElements[mMaxCount]--;
     399                 :       mMaxCount = mCount;
     400                 :     }
     401                 : #endif
     402          137303 :     return true;
     403                 :   }
     404               0 :   return false;
     405                 : }
     406                 : 
     407                 : NS_IMETHODIMP_(bool)
     408               0 : nsSupportsArray::InsertElementsAt(nsISupportsArray* aElements, PRUint32 aIndex)
     409                 : {
     410               0 :   if (!aElements) {
     411               0 :     return false;
     412                 :   }
     413                 :   PRUint32 countElements;
     414               0 :   if (NS_FAILED( aElements->Count( &countElements ) ))
     415               0 :     return false;
     416                 : 
     417               0 :   if (aIndex <= mCount) {
     418               0 :     if (mArraySize < (mCount + countElements)) {
     419                 :       // need to grow the array
     420               0 :       if (!GrowArrayBy(countElements))
     421               0 :         return false;
     422                 :     }
     423                 : 
     424                 :     // Could be slightly more efficient if GrowArrayBy knew about the
     425                 :     // split, but the difference is trivial.
     426               0 :     PRUint32 slide = (mCount - aIndex);
     427               0 :     if (0 < slide) {
     428               0 :       ::memmove(mArray + aIndex + countElements, mArray + aIndex,
     429               0 :                 slide * sizeof(nsISupports*));
     430                 :     }
     431                 : 
     432               0 :     for (PRUint32 i = 0; i < countElements; ++i, ++mCount) {
     433                 :       // use GetElementAt to copy and do AddRef for us
     434               0 :       if (NS_FAILED( aElements->GetElementAt( i, mArray + aIndex + i) ))
     435               0 :         return false;
     436                 :     }
     437                 : 
     438                 : #if DEBUG_SUPPORTSARRAY
     439                 :     if (mCount > mMaxCount &&
     440                 :         mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
     441                 :     {
     442                 :       MaxElements[mCount]++;
     443                 :       MaxElements[mMaxCount]--;
     444                 :       mMaxCount = mCount;
     445                 :     }
     446                 : #endif
     447               0 :     return true;
     448                 :   }
     449               0 :   return false;
     450                 : }
     451                 : 
     452                 : NS_IMETHODIMP_(bool)
     453               0 : nsSupportsArray::ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex)
     454                 : {
     455               0 :   if (aIndex < mCount) {
     456               0 :     NS_IF_ADDREF(aElement);  // addref first in case it's the same object!
     457               0 :     NS_IF_RELEASE(mArray[aIndex]);
     458               0 :     mArray[aIndex] = aElement;
     459               0 :     return true;
     460                 :   }
     461               0 :   return false;
     462                 : }
     463                 : 
     464                 : NS_IMETHODIMP_(bool)
     465              35 : nsSupportsArray::RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount)
     466                 : {
     467              35 :   if (aIndex + aCount <= mCount) {
     468              70 :     for (PRUint32 i = 0; i < aCount; i++)
     469              35 :       NS_IF_RELEASE(mArray[aIndex+i]);
     470              35 :     mCount -= aCount;
     471              35 :     PRInt32 slide = (mCount - aIndex);
     472              35 :     if (0 < slide) {
     473               0 :       ::memmove(mArray + aIndex, mArray + aIndex + aCount,
     474               0 :                 slide * sizeof(nsISupports*));
     475                 :     }
     476              35 :     return true;
     477                 :   }
     478               0 :   return false;
     479                 : }
     480                 : 
     481                 : NS_IMETHODIMP_(bool)
     482              35 : nsSupportsArray::RemoveElement(const nsISupports* aElement, PRUint32 aStartIndex)
     483                 : {
     484              35 :   PRInt32 theIndex = IndexOfStartingAt(aElement,aStartIndex);
     485              35 :   if (theIndex >= 0)
     486              35 :     return RemoveElementAt(theIndex);
     487                 : 
     488               0 :   return false;
     489                 : }
     490                 : 
     491                 : NS_IMETHODIMP_(bool)
     492               0 : nsSupportsArray::RemoveLastElement(const nsISupports* aElement)
     493                 : {
     494               0 :   PRInt32 theIndex = LastIndexOf(aElement);
     495               0 :   if (theIndex >= 0)
     496               0 :     return RemoveElementAt(theIndex);
     497                 : 
     498               0 :   return false;
     499                 : }
     500                 : 
     501                 : NS_IMETHODIMP_(bool)
     502               0 : nsSupportsArray::MoveElement(PRInt32 aFrom, PRInt32 aTo)
     503                 : {
     504                 :   nsISupports *tempElement;
     505                 : 
     506               0 :   if (aTo == aFrom)
     507               0 :     return true;
     508                 : 
     509               0 :   if (aTo < 0 || aFrom < 0 ||
     510                 :       (PRUint32) aTo >= mCount || (PRUint32) aFrom >= mCount)
     511                 :   {
     512                 :     // can't extend the array when moving an element.  Also catches mImpl = null
     513               0 :     return false;
     514                 :   }
     515               0 :   tempElement = mArray[aFrom];
     516                 : 
     517               0 :   if (aTo < aFrom)
     518                 :   {
     519                 :     // Moving one element closer to the head; the elements inbetween move down
     520               0 :     ::memmove(mArray + aTo + 1, mArray + aTo,
     521               0 :               (aFrom-aTo) * sizeof(mArray[0]));
     522               0 :     mArray[aTo] = tempElement;
     523                 :   }
     524                 :   else // already handled aFrom == aTo
     525                 :   {
     526                 :     // Moving one element closer to the tail; the elements inbetween move up
     527               0 :     ::memmove(mArray + aFrom, mArray + aFrom + 1,
     528               0 :               (aTo-aFrom) * sizeof(mArray[0]));
     529               0 :     mArray[aTo] = tempElement;
     530                 :   }
     531                 : 
     532               0 :   return true;
     533                 : }
     534                 : 
     535                 : NS_IMETHODIMP
     536            1748 : nsSupportsArray::Clear(void)
     537                 : {
     538            1748 :   if (0 < mCount) {
     539          137268 :     do {
     540          137268 :       --mCount;
     541          137268 :       NS_IF_RELEASE(mArray[mCount]);
     542                 :     } while (0 != mCount);
     543                 :   }
     544            1748 :   return NS_OK;
     545                 : }
     546                 : 
     547                 : NS_IMETHODIMP
     548               0 : nsSupportsArray::Compact(void)
     549                 : {
     550                 : #if DEBUG_SUPPORTSARRAY
     551                 :   PRUint32 oldArraySize = mArraySize;
     552                 : #endif
     553               0 :   if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) {
     554               0 :     nsISupports** oldArray = mArray;
     555               0 :     if (mCount <= kAutoArraySize) {
     556               0 :       mArray = mAutoArray;
     557               0 :       mArraySize = kAutoArraySize;
     558                 :     }
     559                 :     else {
     560               0 :       mArray = new nsISupports*[mCount];
     561               0 :       if (!mArray) {
     562               0 :         mArray = oldArray;
     563               0 :         return NS_OK;
     564                 :       }
     565               0 :       mArraySize = mCount;
     566                 :     }
     567                 : #if DEBUG_SUPPORTSARRAY
     568                 :     if (oldArray == mArray &&
     569                 :         oldArray != &(mAutoArray[0])) // can't happen without use of realloc
     570                 :       ADD_TO_STATS(GrowInPlace,oldArraySize);
     571                 :     if (oldArray != &(mAutoArray[0]))
     572                 :       ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
     573                 : #endif
     574               0 :     ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
     575               0 :     delete[] oldArray;
     576                 :   }
     577               0 :   return NS_OK;
     578                 : }
     579                 : 
     580                 : NS_IMETHODIMP_(bool)
     581               0 : nsSupportsArray::SizeTo(PRInt32 aSize)
     582                 : {
     583                 : #if DEBUG_SUPPORTSARRAY
     584                 :   PRUint32 oldArraySize = mArraySize;
     585                 : #endif
     586               0 :   NS_ASSERTION(aSize >= 0, "negative aSize!");
     587                 : 
     588                 :   // XXX for aSize < mCount we could resize to mCount
     589               0 :   if (mArraySize == (PRUint32) aSize || (PRUint32) aSize < mCount)
     590               0 :     return true;     // nothing to do
     591                 : 
     592                 :   // switch back to autoarray if possible
     593               0 :   nsISupports** oldArray = mArray;
     594               0 :   if ((PRUint32) aSize <= kAutoArraySize) {
     595               0 :     mArray = mAutoArray;
     596               0 :     mArraySize = kAutoArraySize;
     597                 :   }
     598                 :   else {
     599               0 :     mArray = new nsISupports*[aSize];
     600               0 :     if (!mArray) {
     601               0 :       mArray = oldArray;
     602               0 :       return false;
     603                 :     }
     604               0 :     mArraySize = aSize;
     605                 :   }
     606                 : #if DEBUG_SUPPORTSARRAY
     607                 :   if (oldArray == mArray &&
     608                 :       oldArray != &(mAutoArray[0])) // can't happen without use of realloc
     609                 :     ADD_TO_STATS(GrowInPlace,oldArraySize);
     610                 :   if (oldArray != &(mAutoArray[0]))
     611                 :     ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
     612                 : #endif
     613               0 :   ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
     614               0 :   if (oldArray != mAutoArray)
     615               0 :     delete[] oldArray;
     616                 : 
     617               0 :   return true;
     618                 : }
     619                 : 
     620                 : NS_IMETHODIMP_(bool)
     621               0 : nsSupportsArray::EnumerateForwards(nsISupportsArrayEnumFunc aFunc, void* aData)
     622                 : {
     623               0 :   PRInt32 aIndex = -1;
     624               0 :   bool    running = true;
     625                 : 
     626               0 :   while (running && (++aIndex < (PRInt32)mCount)) {
     627               0 :     running = (*aFunc)(mArray[aIndex], aData);
     628                 :   }
     629               0 :   return running;
     630                 : }
     631                 : 
     632                 : NS_IMETHODIMP_(bool)
     633           20182 : nsSupportsArray::EnumerateBackwards(nsISupportsArrayEnumFunc aFunc, void* aData)
     634                 : {
     635           20182 :   PRUint32 aIndex = mCount;
     636           20182 :   bool    running = true;
     637                 : 
     638           97813 :   while (running && (0 < aIndex--)) {
     639           57449 :     running = (*aFunc)(mArray[aIndex], aData);
     640                 :   }
     641           20182 :   return running;
     642                 : }
     643                 : 
     644                 : NS_IMETHODIMP
     645             306 : nsSupportsArray::Enumerate(nsIEnumerator* *result)
     646                 : {
     647             306 :   nsSupportsArrayEnumerator* e = new nsSupportsArrayEnumerator(this);
     648             306 :   if (!e)
     649               0 :     return NS_ERROR_OUT_OF_MEMORY;
     650             306 :   *result = e;
     651             306 :   NS_ADDREF(e);
     652             306 :   return NS_OK;
     653                 : }
     654                 : 
     655                 : static bool
     656               0 : CopyElement(nsISupports* aElement, void *aData)
     657                 : {
     658                 :   nsresult rv;
     659               0 :   nsISupportsArray* newArray = (nsISupportsArray*)aData;
     660               0 :   rv = newArray->AppendElement(aElement);
     661               0 :   return NS_SUCCEEDED(rv);
     662                 : }
     663                 : 
     664                 : NS_IMETHODIMP
     665               0 : nsSupportsArray::Clone(nsISupportsArray* *result)
     666                 : {
     667                 :   nsresult rv;
     668                 :   nsISupportsArray* newArray;
     669               0 :   rv = NS_NewISupportsArray(&newArray);
     670               0 :   bool ok = EnumerateForwards(CopyElement, newArray);
     671               0 :   if (!ok) return NS_ERROR_OUT_OF_MEMORY;
     672               0 :   *result = newArray;
     673               0 :   return NS_OK;
     674                 : }
     675                 : 
     676                 : nsresult
     677            1746 : NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult)
     678                 : {
     679                 :   nsresult rv;
     680                 :   rv = nsSupportsArray::Create(NULL, NS_GET_IID(nsISupportsArray),
     681            1746 :                                (void**)aInstancePtrResult);
     682            1746 :   return rv;
     683                 : }
     684                 : 
     685                 : class nsArrayEnumerator : public nsISimpleEnumerator
     686                 : {
     687                 : public:
     688                 :     // nsISupports interface
     689                 :     NS_DECL_ISUPPORTS
     690                 : 
     691                 :     // nsISimpleEnumerator interface
     692                 :     NS_IMETHOD HasMoreElements(bool* aResult);
     693                 :     NS_IMETHOD GetNext(nsISupports** aResult);
     694                 : 
     695                 :     // nsArrayEnumerator methods
     696                 :     nsArrayEnumerator(nsISupportsArray* aValueArray);
     697                 : 
     698                 : private:
     699                 :     ~nsArrayEnumerator(void);
     700                 : 
     701                 : protected:
     702                 :     nsISupportsArray* mValueArray;
     703                 :     PRInt32 mIndex;
     704                 : };
     705                 : 
     706              19 : nsArrayEnumerator::nsArrayEnumerator(nsISupportsArray* aValueArray)
     707                 :     : mValueArray(aValueArray),
     708              19 :       mIndex(0)
     709                 : {
     710              19 :     NS_IF_ADDREF(mValueArray);
     711              19 : }
     712                 : 
     713              19 : nsArrayEnumerator::~nsArrayEnumerator(void)
     714                 : {
     715              19 :     NS_IF_RELEASE(mValueArray);
     716              19 : }
     717                 : 
     718             114 : NS_IMPL_ISUPPORTS1(nsArrayEnumerator, nsISimpleEnumerator)
     719                 : 
     720                 : NS_IMETHODIMP
     721             368 : nsArrayEnumerator::HasMoreElements(bool* aResult)
     722                 : {
     723             368 :     NS_PRECONDITION(aResult != 0, "null ptr");
     724             368 :     if (! aResult)
     725               0 :         return NS_ERROR_NULL_POINTER;
     726                 : 
     727             368 :     if (!mValueArray) {
     728               0 :         *aResult = false;
     729               0 :         return NS_OK;
     730                 :     }
     731                 : 
     732                 :     PRUint32 cnt;
     733             368 :     nsresult rv = mValueArray->Count(&cnt);
     734             368 :     if (NS_FAILED(rv)) return rv;
     735             368 :     *aResult = (mIndex < (PRInt32) cnt);
     736             368 :     return NS_OK;
     737                 : }
     738                 : 
     739                 : NS_IMETHODIMP
     740             349 : nsArrayEnumerator::GetNext(nsISupports** aResult)
     741                 : {
     742             349 :     NS_PRECONDITION(aResult != 0, "null ptr");
     743             349 :     if (! aResult)
     744               0 :         return NS_ERROR_NULL_POINTER;
     745                 : 
     746             349 :     if (!mValueArray) {
     747               0 :         *aResult = nsnull;
     748               0 :         return NS_OK;
     749                 :     }
     750                 : 
     751                 :     PRUint32 cnt;
     752             349 :     nsresult rv = mValueArray->Count(&cnt);
     753             349 :     if (NS_FAILED(rv)) return rv;
     754             349 :     if (mIndex >= (PRInt32) cnt)
     755               0 :         return NS_ERROR_UNEXPECTED;
     756                 : 
     757             349 :     *aResult = mValueArray->ElementAt(mIndex++);
     758             349 :     return NS_OK;
     759                 : }
     760                 : 
     761                 : nsresult
     762              19 : NS_NewArrayEnumerator(nsISimpleEnumerator* *result,
     763                 :                       nsISupportsArray* array)
     764                 : {
     765              19 :     nsArrayEnumerator* enumer = new nsArrayEnumerator(array);
     766              19 :     if (enumer == nsnull)
     767               0 :         return NS_ERROR_OUT_OF_MEMORY;
     768              19 :     *result = enumer; 
     769              19 :     NS_ADDREF(*result);
     770              19 :     return NS_OK;
     771                 : }

Generated by: LCOV version 1.7