diff -r 000000000000 -r 6474c204b198 xpcom/ds/nsArray.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xpcom/ds/nsArray.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsArray.h" +#include "nsArrayEnumerator.h" +#include "nsIWeakReference.h" +#include "nsIWeakReferenceUtils.h" +#include "nsThreadUtils.h" + +// used by IndexOf() +struct findIndexOfClosure +{ + nsISupports *targetElement; + uint32_t startIndex; + uint32_t resultIndex; +}; + +static bool FindElementCallback(void* aElement, void* aClosure); + +NS_INTERFACE_MAP_BEGIN(nsArray) + NS_INTERFACE_MAP_ENTRY(nsIArray) + NS_INTERFACE_MAP_ENTRY(nsIMutableArray) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray) +NS_INTERFACE_MAP_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsArrayCC) + NS_INTERFACE_MAP_ENTRY(nsIArray) + NS_INTERFACE_MAP_ENTRY(nsIMutableArray) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutableArray) +NS_INTERFACE_MAP_END + +nsArray::~nsArray() +{ + Clear(); +} + + +NS_IMPL_ADDREF(nsArray) +NS_IMPL_RELEASE(nsArray) + +NS_IMPL_CYCLE_COLLECTION_CLASS(nsArrayCC) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsArrayCC) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsArrayCC) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsArrayCC) + tmp->Clear(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsArrayCC) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArray) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMETHODIMP +nsArray::GetLength(uint32_t* aLength) +{ + *aLength = mArray.Count(); + return NS_OK; +} + +NS_IMETHODIMP +nsArray::QueryElementAt(uint32_t aIndex, + const nsIID& aIID, + void ** aResult) +{ + nsISupports * obj = mArray.SafeObjectAt(aIndex); + if (!obj) return NS_ERROR_ILLEGAL_VALUE; + + // no need to worry about a leak here, because SafeObjectAt() + // doesn't addref its result + return obj->QueryInterface(aIID, aResult); +} + +NS_IMETHODIMP +nsArray::IndexOf(uint32_t aStartIndex, nsISupports* aElement, + uint32_t* aResult) +{ + // optimize for the common case by forwarding to mArray + if (aStartIndex == 0) { + uint32_t idx = mArray.IndexOf(aElement); + if (idx == UINT32_MAX) + return NS_ERROR_FAILURE; + + *aResult = idx; + return NS_OK; + } + + findIndexOfClosure closure = { aElement, aStartIndex, 0 }; + bool notFound = mArray.EnumerateForwards(FindElementCallback, &closure); + if (notFound) + return NS_ERROR_FAILURE; + + *aResult = closure.resultIndex; + return NS_OK; +} + +NS_IMETHODIMP +nsArray::Enumerate(nsISimpleEnumerator **aResult) +{ + return NS_NewArrayEnumerator(aResult, static_cast(this)); +} + +// nsIMutableArray implementation + +NS_IMETHODIMP +nsArray::AppendElement(nsISupports* aElement, bool aWeak) +{ + bool result; + if (aWeak) { + nsCOMPtr elementRef = do_GetWeakReference(aElement); + NS_ASSERTION(elementRef, "AppendElement: Trying to use weak references on an object that doesn't support it"); + if (!elementRef) + return NS_ERROR_FAILURE; + result = mArray.AppendObject(elementRef); + } + + else { + // add the object directly + result = mArray.AppendObject(aElement); + } + return result ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsArray::RemoveElementAt(uint32_t aIndex) +{ + bool result = mArray.RemoveObjectAt(aIndex); + return result ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex, bool aWeak) +{ + nsCOMPtr elementRef; + if (aWeak) { + elementRef = do_GetWeakReference(aElement); + NS_ASSERTION(elementRef, "InsertElementAt: Trying to use weak references on an object that doesn't support it"); + if (!elementRef) + return NS_ERROR_FAILURE; + } else { + elementRef = aElement; + } + bool result = mArray.InsertObjectAt(elementRef, aIndex); + return result ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex, bool aWeak) +{ + nsCOMPtr elementRef; + if (aWeak) { + elementRef = do_GetWeakReference(aElement); + NS_ASSERTION(elementRef, "ReplaceElementAt: Trying to use weak references on an object that doesn't support it"); + if (!elementRef) + return NS_ERROR_FAILURE; + } else { + elementRef = aElement; + } + bool result = mArray.ReplaceObjectAt(elementRef, aIndex); + return result ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsArray::Clear() +{ + mArray.Clear(); + return NS_OK; +} + +// +// static helper routines +// +bool +FindElementCallback(void *aElement, void* aClosure) +{ + findIndexOfClosure* closure = + static_cast(aClosure); + + nsISupports* element = + static_cast(aElement); + + // don't start searching until we're past the startIndex + if (closure->resultIndex >= closure->startIndex && + element == closure->targetElement) { + return false; // stop! We found it + } + closure->resultIndex++; + + return true; +} + +nsresult +nsArray::XPCOMConstructor(nsISupports *aOuter, const nsIID& aIID, void **aResult) +{ + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + nsCOMPtr inst = Create(); + return inst->QueryInterface(aIID, aResult); +} + +already_AddRefed +nsArray::Create() +{ + nsCOMPtr inst = NS_IsMainThread() ? new nsArrayCC : new nsArray; + return inst.forget(); +}