/* -*- 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 #include #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 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 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 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(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 e = new nsSupportsArrayEnumerator(this); e.forget(aResult); return NS_OK; } NS_IMETHODIMP nsSupportsArray::Clone(nsISupportsArray** aResult) { nsCOMPtr 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(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