gecko-dev/xpcom/ds/nsCOMArray.cpp
Mike Hommey 404ef7af3e Bug 1407838 - Remove the remains of NS_Alloc/NS_Realloc/NS_Free. r=njn
Bug 1134923 removed the use of those functions in gecko, and left some
for the XPCOM standalone glue. The XPCOM standalone glue was severely
stripped down in bug 1306327, with the effect of removing the
implementation for those functions.

The remains in nsXPCOM.h are:
XPCOM_API(void*) NS_Alloc(size_t aSize);
XPCOM_API(void*) NS_Realloc(void* aPtr, size_t aSize);
XPCOM_API(void) NS_Free(void* aPtr);

With no implementation left, the first arm is never actually used, and
the second arm means every remaining use of those functions in the tree
is a macro expansion to one of moz_xmalloc, moz_xrealloc or free.

--HG--
extra : rebase_source : fd1669abc5a25d8edbd5c3a8522e22a5c3f558e2
2017-10-12 11:08:44 +09:00

325 lines
7.5 KiB
C++

/* -*- 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 "nsCOMArray.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/OperatorNewExtensions.h"
#include "nsQuickSort.h"
#include "nsCOMPtr.h"
// This specialization is private to nsCOMArray.
// It exists solely to automatically zero-out newly created array elements.
template<>
class nsTArrayElementTraits<nsISupports*>
{
typedef nsISupports* E;
public:
// Zero out the value
static inline void Construct(E* aE)
{
new (mozilla::KnownNotNull, static_cast<void*>(aE)) E();
}
// Invoke the copy-constructor in place.
template<class A>
static inline void Construct(E* aE, const A& aArg)
{
new (mozilla::KnownNotNull, static_cast<void*>(aE)) E(aArg);
}
// Invoke the destructor in place.
static inline void Destruct(E* aE)
{
aE->~E();
}
};
static void ReleaseObjects(nsTArray<nsISupports*>& aArray);
// implementations of non-trivial methods in nsCOMArray_base
nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther)
{
// make sure we do only one allocation
mArray.SetCapacity(aOther.Count());
AppendObjects(aOther);
}
nsCOMArray_base::~nsCOMArray_base()
{
Clear();
}
int32_t
nsCOMArray_base::IndexOf(nsISupports* aObject, uint32_t aStartIndex) const
{
return mArray.IndexOf(aObject, aStartIndex);
}
int32_t
nsCOMArray_base::IndexOfObject(nsISupports* aObject) const
{
nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject);
if (NS_WARN_IF(!supports)) {
return -1;
}
uint32_t i, count;
int32_t retval = -1;
count = mArray.Length();
for (i = 0; i < count; ++i) {
nsCOMPtr<nsISupports> arrayItem = do_QueryInterface(mArray[i]);
if (arrayItem == supports) {
retval = i;
break;
}
}
return retval;
}
bool
nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const
{
for (uint32_t index = 0; index < mArray.Length(); ++index) {
if (!(*aFunc)(mArray[index], aData)) {
return false;
}
}
return true;
}
bool
nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const
{
for (uint32_t index = mArray.Length(); index--; ) {
if (!(*aFunc)(mArray[index], aData)) {
return false;
}
}
return true;
}
int
nsCOMArray_base::nsCOMArrayComparator(const void* aElement1,
const void* aElement2,
void* aData)
{
nsCOMArrayComparatorContext* ctx =
static_cast<nsCOMArrayComparatorContext*>(aData);
return (*ctx->mComparatorFunc)(*static_cast<nsISupports* const*>(aElement1),
*static_cast<nsISupports* const*>(aElement2),
ctx->mData);
}
void
nsCOMArray_base::Sort(nsBaseArrayComparatorFunc aFunc, void* aData)
{
if (mArray.Length() > 1) {
nsCOMArrayComparatorContext ctx = {aFunc, aData};
NS_QuickSort(mArray.Elements(), mArray.Length(), sizeof(nsISupports*),
nsCOMArrayComparator, &ctx);
}
}
bool
nsCOMArray_base::InsertObjectAt(nsISupports* aObject, int32_t aIndex)
{
if ((uint32_t)aIndex > mArray.Length()) {
return false;
}
if (!mArray.InsertElementAt(aIndex, aObject)) {
return false;
}
NS_IF_ADDREF(aObject);
return true;
}
void
nsCOMArray_base::InsertElementAt(uint32_t aIndex, nsISupports* aElement)
{
mArray.InsertElementAt(aIndex, aElement);
NS_IF_ADDREF(aElement);
}
void
nsCOMArray_base::InsertElementAt(uint32_t aIndex, already_AddRefed<nsISupports> aElement)
{
mArray.InsertElementAt(aIndex, aElement.take());
}
bool
nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex)
{
if ((uint32_t)aIndex > mArray.Length()) {
return false;
}
if (!mArray.InsertElementsAt(aIndex, aObjects.mArray)) {
return false;
}
// need to addref all these
uint32_t count = aObjects.Length();
for (uint32_t i = 0; i < count; ++i) {
NS_IF_ADDREF(aObjects[i]);
}
return true;
}
void
nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
const nsCOMArray_base& aElements)
{
mArray.InsertElementsAt(aIndex, aElements.mArray);
// need to addref all these
uint32_t count = aElements.Length();
for (uint32_t i = 0; i < count; ++i) {
NS_IF_ADDREF(aElements[i]);
}
}
void
nsCOMArray_base::InsertElementsAt(uint32_t aIndex,
nsISupports* const* aElements,
uint32_t aCount)
{
mArray.InsertElementsAt(aIndex, aElements, aCount);
// need to addref all these
for (uint32_t i = 0; i < aCount; ++i) {
NS_IF_ADDREF(aElements[i]);
}
}
void
nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, int32_t aIndex)
{
mArray.EnsureLengthAtLeast(aIndex + 1);
nsISupports* oldObject = mArray[aIndex];
// Make sure to addref first, in case aObject == oldObject
NS_IF_ADDREF(mArray[aIndex] = aObject);
NS_IF_RELEASE(oldObject);
}
bool
nsCOMArray_base::RemoveObject(nsISupports* aObject)
{
bool result = mArray.RemoveElement(aObject);
if (result) {
NS_IF_RELEASE(aObject);
}
return result;
}
bool
nsCOMArray_base::RemoveObjectAt(int32_t aIndex)
{
if (uint32_t(aIndex) < mArray.Length()) {
nsISupports* element = mArray[aIndex];
mArray.RemoveElementAt(aIndex);
NS_IF_RELEASE(element);
return true;
}
return false;
}
void
nsCOMArray_base::RemoveElementAt(uint32_t aIndex)
{
nsISupports* element = mArray[aIndex];
mArray.RemoveElementAt(aIndex);
NS_IF_RELEASE(element);
}
bool
nsCOMArray_base::RemoveObjectsAt(int32_t aIndex, int32_t aCount)
{
if (uint32_t(aIndex) + uint32_t(aCount) <= mArray.Length()) {
nsTArray<nsISupports*> elementsToDestroy(aCount);
elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
mArray.RemoveElementsAt(aIndex, aCount);
ReleaseObjects(elementsToDestroy);
return true;
}
return false;
}
void
nsCOMArray_base::RemoveElementsAt(uint32_t aIndex, uint32_t aCount)
{
nsTArray<nsISupports*> elementsToDestroy(aCount);
elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount);
mArray.RemoveElementsAt(aIndex, aCount);
ReleaseObjects(elementsToDestroy);
}
// useful for destructors
void
ReleaseObjects(nsTArray<nsISupports*>& aArray)
{
for (uint32_t i = 0; i < aArray.Length(); ++i) {
NS_IF_RELEASE(aArray[i]);
}
}
void
nsCOMArray_base::Clear()
{
nsTArray<nsISupports*> objects;
objects.SwapElements(mArray);
ReleaseObjects(objects);
}
bool
nsCOMArray_base::SetCount(int32_t aNewCount)
{
NS_ASSERTION(aNewCount >= 0, "SetCount(negative index)");
if (aNewCount < 0) {
return false;
}
int32_t count = mArray.Length();
if (count > aNewCount) {
RemoveObjectsAt(aNewCount, mArray.Length() - aNewCount);
}
mArray.SetLength(aNewCount);
return true;
}
void
nsCOMArray_base::Adopt(nsISupports** aElements, uint32_t aSize)
{
Clear();
mArray.AppendElements(aElements, aSize);
// Free the allocated array as well.
free(aElements);
}
uint32_t
nsCOMArray_base::Forget(nsISupports*** aElements)
{
uint32_t length = Length();
size_t array_size = sizeof(nsISupports*) * length;
nsISupports** array = static_cast<nsISupports**>(moz_xmalloc(array_size));
memmove(array, Elements(), array_size);
*aElements = array;
// Don't Release the contained pointers; the caller of the method will
// do this eventually.
mArray.Clear();
return length;
}