Mypal/xpcom/ds/nsSupportsArray.cpp

264 lines
5.9 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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