Back to index

lightning-sunbird  0.9+nobinonly
nsArray.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is XPCOM Array implementation.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corp.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Alec Flett <alecf@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsArray.h"
00040 #include "nsArrayEnumerator.h"
00041 #include "nsWeakReference.h"
00042 
00043 // used by IndexOf()
00044 struct findIndexOfClosure
00045 {
00046     nsISupports *targetElement;
00047     PRUint32 startIndex;
00048     PRUint32 resultIndex;
00049 };
00050 
00051 PR_STATIC_CALLBACK(PRBool) FindElementCallback(void* aElement, void* aClosure);
00052 
00053 
00054 NS_IMPL_ISUPPORTS2(nsArray, nsIArray, nsIMutableArray)
00055 
00056 nsArray::~nsArray()
00057 {
00058     Clear();
00059 }
00060     
00061 NS_IMETHODIMP
00062 nsArray::GetLength(PRUint32* aLength)
00063 {
00064     *aLength = mArray.Count();
00065     return NS_OK;
00066 }
00067 
00068 NS_IMETHODIMP
00069 nsArray::QueryElementAt(PRUint32 aIndex,
00070                         const nsIID& aIID,
00071                         void ** aResult)
00072 {
00073     nsISupports * obj = mArray.ObjectAt(aIndex);
00074     if (!obj) return NS_ERROR_UNEXPECTED;
00075 
00076     // no need to worry about a leak here, because ObjectAt() doesn't
00077     // addref its result
00078     return obj->QueryInterface(aIID, aResult);
00079 }
00080 
00081 NS_IMETHODIMP
00082 nsArray::IndexOf(PRUint32 aStartIndex, nsISupports* aElement,
00083                  PRUint32* aResult)
00084 {
00085     // optimize for the common case by forwarding to mArray
00086     if (aStartIndex == 0) {
00087         *aResult = mArray.IndexOf(aElement);
00088         if (*aResult == PR_UINT32_MAX)
00089             return NS_ERROR_FAILURE;
00090         return NS_OK;
00091     }
00092 
00093     findIndexOfClosure closure = { aElement, aStartIndex, 0 };
00094     PRBool notFound = mArray.EnumerateForwards(FindElementCallback, &closure);
00095     if (notFound)
00096         return NS_ERROR_FAILURE;
00097 
00098     *aResult = closure.resultIndex;
00099     return NS_OK;
00100 }
00101 
00102 NS_IMETHODIMP
00103 nsArray::Enumerate(nsISimpleEnumerator **aResult)
00104 {
00105     return NS_NewArrayEnumerator(aResult, NS_STATIC_CAST(nsIArray*, this));
00106 }
00107 
00108 // nsIMutableArray implementation
00109 
00110 NS_IMETHODIMP
00111 nsArray::AppendElement(nsISupports* aElement, PRBool aWeak)
00112 {
00113     PRBool result;
00114     if (aWeak) {
00115         nsCOMPtr<nsISupports> elementRef =
00116             getter_AddRefs(NS_STATIC_CAST(nsISupports*,
00117                                           NS_GetWeakReference(aElement)));
00118         NS_ASSERTION(elementRef, "AppendElement: Trying to use weak references on an object that doesn't support it");
00119         if (!elementRef)
00120             return NS_ERROR_FAILURE;
00121         result = mArray.AppendObject(elementRef);
00122     }
00123 
00124     else {
00125         // add the object directly
00126         result = mArray.AppendObject(aElement);
00127     }
00128     return result ? NS_OK : NS_ERROR_FAILURE;
00129 }
00130 
00131 NS_IMETHODIMP
00132 nsArray::RemoveElementAt(PRUint32 aIndex)
00133 {
00134     PRBool result = mArray.RemoveObjectAt(aIndex);
00135     return result ? NS_OK : NS_ERROR_FAILURE;
00136 }
00137 
00138 NS_IMETHODIMP
00139 nsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex, PRBool aWeak)
00140 {
00141     nsCOMPtr<nsISupports> elementRef;
00142     if (aWeak) {
00143         elementRef =
00144             getter_AddRefs(NS_STATIC_CAST(nsISupports*,
00145                                           NS_GetWeakReference(aElement)));
00146         NS_ASSERTION(elementRef, "InsertElementAt: Trying to use weak references on an object that doesn't support it");
00147         if (!elementRef)
00148             return NS_ERROR_FAILURE;
00149     } else {
00150         elementRef = aElement;
00151     }
00152     PRBool result = mArray.InsertObjectAt(elementRef, aIndex);
00153     return result ? NS_OK : NS_ERROR_FAILURE;
00154 }
00155 
00156 NS_IMETHODIMP
00157 nsArray::ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex, PRBool aWeak)
00158 {
00159     nsCOMPtr<nsISupports> elementRef;
00160     if (aWeak) {
00161         elementRef =
00162             getter_AddRefs(NS_STATIC_CAST(nsISupports*,
00163                                           NS_GetWeakReference(aElement)));
00164         NS_ASSERTION(elementRef, "ReplaceElementAt: Trying to use weak references on an object that doesn't support it");
00165         if (!elementRef)
00166             return NS_ERROR_FAILURE;
00167     } else {
00168         elementRef = aElement;
00169     }
00170     PRBool result = mArray.ReplaceObjectAt(elementRef, aIndex);
00171     return result ? NS_OK : NS_ERROR_FAILURE;
00172 }
00173 
00174 NS_IMETHODIMP
00175 nsArray::Clear()
00176 {
00177     mArray.Clear();
00178     return NS_OK;
00179 }
00180 
00181 //
00182 // static helper routines
00183 //
00184 PRBool
00185 FindElementCallback(void *aElement, void* aClosure)
00186 {
00187     findIndexOfClosure* closure =
00188         NS_STATIC_CAST(findIndexOfClosure*, aClosure);
00189 
00190     nsISupports* element =
00191         NS_STATIC_CAST(nsISupports*, aElement);
00192     
00193     // don't start searching until we're past the startIndex
00194     if (closure->resultIndex >= closure->startIndex &&
00195         element == closure->targetElement) {
00196         return PR_FALSE;    // stop! We found it
00197     }
00198     closure->resultIndex++;
00199 
00200     return PR_TRUE;
00201 }
00202 
00203 //
00204 // do_QueryElementAt helper stuff
00205 //
00206 nsresult
00207 nsQueryArrayElementAt::operator()(const nsIID& aIID, void** aResult) const
00208   {
00209     nsresult status = mArray
00210         ? mArray->QueryElementAt(mIndex, aIID, aResult)
00211         : NS_ERROR_NULL_POINTER;
00212 
00213     if (mErrorPtr)
00214       *mErrorPtr = status;
00215 
00216     return status;
00217   }
00218 
00219 //
00220 // exported constructor routines
00221 //
00222 nsresult
00223 NS_NewArray(nsIMutableArray** aResult)
00224 {
00225     nsArray* arr = new nsArray;
00226     if (!arr) return NS_ERROR_OUT_OF_MEMORY;
00227 
00228     *aResult = NS_STATIC_CAST(nsIMutableArray*,arr);
00229     NS_ADDREF(*aResult);
00230     
00231     return NS_OK;
00232 }
00233 
00234 nsresult
00235 NS_NewArray(nsIMutableArray** aResult, const nsCOMArray_base& aBaseArray)
00236 {
00237     nsArray* arr = new nsArray(aBaseArray);
00238     if (!arr) return NS_ERROR_OUT_OF_MEMORY;
00239     
00240     *aResult = NS_STATIC_CAST(nsIMutableArray*, arr);
00241     NS_ADDREF(*aResult);
00242 
00243     return NS_OK;
00244 }