diff options
Diffstat (limited to 'xpcom/ds/nsSupportsArray.cpp')
-rw-r--r-- | xpcom/ds/nsSupportsArray.cpp | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp new file mode 100644 index 000000000..67de8ae16 --- /dev/null +++ b/xpcom/ds/nsSupportsArray.cpp @@ -0,0 +1,264 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 <stdint.h> +#include <string.h> + +#include "nsArrayEnumerator.h" +#include "nsIObjectInputStream.h" +#include "nsIObjectOutputStream.h" +#include "nsSupportsArray.h" +#include "nsSupportsArrayEnumerator.h" + +// Disable deprecation warnings generated by nsISupportsArray and associated +// classes. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4996) +#endif + +nsresult +nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const +{ + nsresult status = + mCollection ? mCollection->QueryElementAt(mIndex, aIID, aResult) : + NS_ERROR_NULL_POINTER; + + if (mErrorPtr) { + *mErrorPtr = status; + } + + return status; +} + +nsSupportsArray::nsSupportsArray() +{ +} + +nsSupportsArray::~nsSupportsArray() +{ + Clear(); +} + +nsresult +nsSupportsArray::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult) +{ + if (aOuter) { + return NS_ERROR_NO_AGGREGATION; + } + + nsCOMPtr<nsISupportsArray> it = new nsSupportsArray(); + + return it->QueryInterface(aIID, aResult); +} + +NS_IMPL_ISUPPORTS(nsSupportsArray, nsIArray, nsISupportsArray, nsICollection, + nsISerializable) + +NS_IMETHODIMP +nsSupportsArray::Read(nsIObjectInputStream* aStream) +{ + nsresult rv; + + uint32_t newArraySize; + rv = aStream->Read32(&newArraySize); + if (NS_FAILED(rv)) { + return rv; + } + + uint32_t count; + rv = aStream->Read32(&count); + if (NS_FAILED(rv)) { + return rv; + } + + NS_ASSERTION(count <= newArraySize, "overlarge mCount!"); + if (count > newArraySize) { + count = newArraySize; + } + + // Don't clear out our array until we know we have enough space for the new + // one and have successfully copied everything out of the stream. + nsCOMArray<nsISupports> tmp; + tmp.SetCapacity(newArraySize); + tmp.SetCount(count); + + auto elems = tmp.Elements(); + for (uint32_t i = 0; i < count; i++) { + rv = aStream->ReadObject(true, &elems[i]); + if (NS_FAILED(rv)) { + return rv; + } + } + + // Now clear out existing refs and replace with the new array. + mArray.Clear(); + mArray.SwapElements(tmp); + + return NS_OK; +} + +NS_IMETHODIMP +nsSupportsArray::Write(nsIObjectOutputStream* aStream) +{ + nsresult rv; + + rv = aStream->Write32(mArray.Capacity()); + if (NS_FAILED(rv)) { + return rv; + } + + rv = aStream->Write32(mArray.Length()); + if (NS_FAILED(rv)) { + return rv; + } + + for (size_t i = 0; i < mArray.Length(); i++) { + rv = aStream->WriteObject(mArray[i], true); + if (NS_FAILED(rv)) { + return rv; + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports** aOutPtr) +{ + nsCOMPtr<nsISupports> elm = mArray.SafeElementAt(aIndex); + elm.forget(aOutPtr); + return NS_OK; +} + +NS_IMETHODIMP_(int32_t) +nsSupportsArray::IndexOf(const nsISupports* aPossibleElement) +{ + // nsCOMArray takes a non-const param, but it just passes through to + // nsTArray which takes a const param. + return mArray.IndexOf(const_cast<nsISupports*>(aPossibleElement)); +} + +NS_IMETHODIMP_(bool) +nsSupportsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex) +{ + return mArray.InsertObjectAt(aElement, aIndex); +} + +NS_IMETHODIMP_(bool) +nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) +{ + // nsCOMArray::ReplaceObjectAt will grow the array if necessary. Instead + // we do the bounds check and only replace if it's in range. + if (aIndex < mArray.Length()) { + mArray.ReplaceElementAt(aIndex, aElement); + return true; + } + return false; +} + +NS_IMETHODIMP_(bool) +nsSupportsArray::RemoveElementAt(uint32_t aIndex) +{ + return mArray.RemoveObjectAt(aIndex); +} + +NS_IMETHODIMP +nsSupportsArray::RemoveElement(nsISupports* aElement) +{ + return mArray.RemoveObject(aElement) ? NS_OK : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSupportsArray::Clear(void) +{ + mArray.Clear(); + return NS_OK; +} + +NS_IMETHODIMP +nsSupportsArray::DeprecatedEnumerate(nsIEnumerator** aResult) +{ + RefPtr<nsSupportsArrayEnumerator> e = new nsSupportsArrayEnumerator(this); + e.forget(aResult); + return NS_OK; +} + +NS_IMETHODIMP +nsSupportsArray::Clone(nsISupportsArray** aResult) +{ + nsCOMPtr<nsISupportsArray> newArray; + nsresult rv = NS_NewISupportsArray(getter_AddRefs(newArray)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + for (size_t i = 0; i < mArray.Length(); i++) { + // AppendElement does an odd cast of bool to nsresult, we just cast back + // here. + if (!(bool)newArray->AppendElement(mArray[i])) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + newArray.forget(aResult); + return NS_OK; +} + +nsresult +NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult) +{ + nsresult rv; + rv = nsSupportsArray::Create(nullptr, NS_GET_IID(nsISupportsArray), + (void**)aInstancePtrResult); + return rv; +} + +/** + * nsIArray adapters. + */ +NS_IMETHODIMP +nsSupportsArray::GetLength(uint32_t* aLength) { + return Count(aLength); +} + +NS_IMETHODIMP +nsSupportsArray::QueryElementAt(uint32_t aIndex, const nsIID& aIID, void** aResult) +{ + nsISupports* element = mArray.SafeElementAt(aIndex); + if (element) { + return element->QueryInterface(aIID, aResult); + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSupportsArray::IndexOf(uint32_t aStartIndex, nsISupports* aElement, uint32_t* aResult) +{ + int32_t idx = mArray.IndexOf(aElement, aStartIndex); + if (idx < 0) { + return NS_ERROR_FAILURE; + } + + *aResult = static_cast<uint32_t>(idx); + return NS_OK; +} + +NS_IMETHODIMP +nsSupportsArray::Enumerate(nsISimpleEnumerator** aResult) +{ + return NS_NewArrayEnumerator(aResult, this); +} + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning (pop) +#endif + |