зеркало из https://github.com/mozilla/pjs.git
not part of build, more for bug 162115:
- fix some spelling, add documentation - add NS_NewArray(), including one that takes an existing nsCOMArray<T> - implement copy constructor for nsCOMArray_base, so that NS_NewArray can work not part of build
This commit is contained in:
Родитель
39be6a6c29
Коммит
e8e44bcfc3
|
@ -46,6 +46,9 @@ struct findIndexOfClosure
|
|||
PRUint32 resultIndex;
|
||||
};
|
||||
|
||||
static PRBool FindElementCallback(nsISupports* aElement, void* aClosure);
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsArray, nsIArray, nsIMutableArray)
|
||||
|
||||
nsArray::~nsArray()
|
||||
|
@ -80,8 +83,6 @@ nsArray::IndexOf(PRUint32 aStartIndex, nsISupports* aElement,
|
|||
*aResult = mArray.IndexOf(aElement);
|
||||
if (*aResult == -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -130,7 +131,8 @@ nsArray::Clear()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsArray::FindElementCallback(void *aElement, void* aClosure)
|
||||
PRBool
|
||||
FindElementCallback(nsISupports *aElement, void* aClosure)
|
||||
{
|
||||
findIndexOfClosure* closure =
|
||||
NS_STATIC_CAST(findIndexOfClosure*, aClosure);
|
||||
|
@ -144,3 +146,27 @@ nsArray::FindElementCallback(void *aElement, void* aClosure)
|
|||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewArray(nsIArray** aResult)
|
||||
{
|
||||
nsArray* arr = new nsArray;
|
||||
if (!arr) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*aResult = NS_STATIC_CAST(nsIArray*,arr);
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewArray(const nsCOMArray_base& aBaseArray, nsIArray** aResult)
|
||||
{
|
||||
nsArray* arr = new nsArray(aBaseArray);
|
||||
if (!arr) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*aResult = NS_STATIC_CAST(nsIArray*, arr);
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,9 @@ class nsArray : public nsIMutableArray
|
|||
{
|
||||
public:
|
||||
nsArray() { NS_INIT_ISUPPORTS(); }
|
||||
nsArray(const nsCOMArray_base& aBaseArray) : mArray(aBaseArray)
|
||||
{ NS_INIT_ISUPPORTS(); }
|
||||
|
||||
virtual ~nsArray();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -64,10 +67,17 @@ public:
|
|||
NS_DECL_NSIMUTABLEARRAY
|
||||
|
||||
private:
|
||||
static PRBool FindElementCallback(void* aElement, void* aClosure);
|
||||
nsCOMArray<nsISupports> mArray;
|
||||
};
|
||||
|
||||
|
||||
// create a new, empty array
|
||||
nsresult NS_COM
|
||||
NS_NewArray(nsIArray** aResult);
|
||||
|
||||
// makes a copy of an nsCOMArray<T> - any further changes to the base
|
||||
// array will not affect the new array
|
||||
nsresult NS_COM
|
||||
NS_NewArray(const nsCOMArray_base& base, nsIArray** aResult);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,8 +38,27 @@
|
|||
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
static PRBool AddRefObjects(void* aElement, void*);
|
||||
static PRBool ReleaseObjects(void* aElement, void*);
|
||||
|
||||
|
||||
// implementations of non-trivial methods in nsCOMArray_base
|
||||
|
||||
// copy constructor - we can't just memcpy here, because
|
||||
// we have to make sure we own our own array buffer, and that each
|
||||
// object gets another AddRef()
|
||||
nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther)
|
||||
{
|
||||
PRInt32 count = aOther.Count();
|
||||
// make sure we do only one allocation
|
||||
mArray.SizeTo(count);
|
||||
|
||||
PRInt32 i;
|
||||
for (i=0; i<count; i++) {
|
||||
ReplaceObjectAt(aOther[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsCOMArray_base::InsertObjectAt(nsISupports* aObject, PRInt32 aIndex) {
|
||||
PRBool result = mArray.InsertElementAt(aObject, aIndex);
|
||||
|
@ -98,8 +117,19 @@ nsCOMArray_base::RemoveObjectAt(PRInt32 aIndex)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ClearObjectsCallback(void* aElement, void*)
|
||||
|
||||
// useful for copy constructors
|
||||
PRBool
|
||||
AddRefObjects(void* aElement, void*)
|
||||
{
|
||||
nsISupports* element = NS_STATIC_CAST(nsISupports*,aElement);
|
||||
NS_IF_ADDREF(element);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// useful for destructors
|
||||
PRBool
|
||||
ReleaseObjects(void* aElement, void*)
|
||||
{
|
||||
nsISupports* element = NS_STATIC_CAST(nsISupports*, aElement);
|
||||
NS_IF_RELEASE(element);
|
||||
|
@ -109,6 +139,7 @@ ClearObjectsCallback(void* aElement, void*)
|
|||
void
|
||||
nsCOMArray_base::Clear()
|
||||
{
|
||||
mArray.EnumerateForwards(ClearObjectsCallback, nsnull);
|
||||
mArray.EnumerateForwards(ReleaseObjects, nsnull);
|
||||
mArray.Clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "nsVoidArray.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
// See below for the definition of nsCOMArray<T>
|
||||
|
||||
// a class that's nsISupports-specific, so that we can contain the
|
||||
// work of this class in the XPCOM dll
|
||||
class NS_COM nsCOMArray_base
|
||||
|
@ -49,6 +51,7 @@ class NS_COM nsCOMArray_base
|
|||
protected:
|
||||
nsCOMArray_base() {}
|
||||
nsCOMArray_base(PRInt32 aCount) : mArray(aCount) {}
|
||||
nsCOMArray_base(const nsCOMArray_base& other);
|
||||
|
||||
nsISupports* ObjectAt(PRInt32 aIndex) const {
|
||||
return NS_STATIC_CAST(nsISupports*, mArray.ElementAt(aIndex));
|
||||
|
@ -88,19 +91,35 @@ protected:
|
|||
nsVoidArray mArray;
|
||||
|
||||
// don't implement these, defaults will muck with refcounts!
|
||||
nsCOMArray_base(const nsCOMArray_base& other);
|
||||
nsCOMArray_base& operator=(const nsCOMArray_base& other);
|
||||
};
|
||||
|
||||
// a non-XPCOM, refcounting array of XPCOM objects
|
||||
// used as a member variable or stack variable - this object is NOT
|
||||
// refcounted, but the objects that it holds are
|
||||
//
|
||||
// most of the read-only accessors like ObjectAt()/etc do NOT refcount
|
||||
// on the way out. This means that you can do one of two things:
|
||||
//
|
||||
// * does an addref, but holds onto a reference
|
||||
// nsCOMPtr<T> foo = array[i];
|
||||
//
|
||||
// * avoids the refcount, but foo might go stale if array[i] is ever
|
||||
// * modified/removed. Be careful not to NS_RELEASE(foo)!
|
||||
// T* foo = array[i];
|
||||
//
|
||||
// This array will accept null as an argument for any object, and will
|
||||
// store null in the array, just like nsVoidArray. But that also means
|
||||
// that methods like ObjectAt() may return null when refering to an
|
||||
// existing, but null entry in the array.
|
||||
template <class T>
|
||||
class nsCOMArray : protected nsCOMArray_base
|
||||
{
|
||||
public:
|
||||
nsCOMArray() {}
|
||||
nsCOMArray(PRInt32 aCount) : nsCOMArray_base(aCount) {}
|
||||
|
||||
nsCOMArray(const nsCOMArray_base& aOther) : nsCOMArray_base(aOther) { }
|
||||
|
||||
~nsCOMArray() {}
|
||||
|
||||
|
@ -108,50 +127,72 @@ class nsCOMArray : protected nsCOMArray_base
|
|||
T* ObjectAt(PRInt32 aIndex) const {
|
||||
return NS_STATIC_CAST(T*,nsCOMArray_base::ObjectAt(aIndex));
|
||||
}
|
||||
|
||||
|
||||
// indexing operator for syntactic sugar
|
||||
T* operator[](PRInt32 aIndex) const {
|
||||
return ObjectAt(aIndex);
|
||||
}
|
||||
|
||||
// index of the element in question.. does NOT refcount
|
||||
PRInt32 IndexOf(T* aObject) {
|
||||
return nsCOMArray_base::IndexOf(aObject);
|
||||
}
|
||||
|
||||
|
||||
// inserts the object at aIndex, and move all objects after aIndex
|
||||
// to the right
|
||||
PRBool InsertObjectAt(T* aObject, PRInt32 aIndex) {
|
||||
return nsCOMArray_base::InsertObjectAt(aObject, aIndex);
|
||||
}
|
||||
|
||||
|
||||
// replaces an existing element. Warning: if the array grows,
|
||||
// the newly created entries will all be null
|
||||
PRBool ReplaceObjectAt(T* aObject, PRInt32 aIndex) {
|
||||
return nsCOMArray_base::ReplaceObjectAt(aObject, aIndex);
|
||||
}
|
||||
|
||||
// override nsVoidArray stuff so that they can be accessed by
|
||||
// other methods
|
||||
|
||||
// elements in the array (including null elements!)
|
||||
PRInt32 Count() const {
|
||||
return nsCOMArray_base::Count();
|
||||
}
|
||||
|
||||
// remove all elements in the array, and call NS_RELEASE on each one
|
||||
void Clear() {
|
||||
nsCOMArray_base::Clear();
|
||||
}
|
||||
|
||||
PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData) {
|
||||
return nsCOMArray_base::EnumerateForwards(aFunc, aData);
|
||||
}
|
||||
// Enumerator callback function. Return PR_FALSE to stop
|
||||
// Here's a more readable form:
|
||||
// PRBool PR_CALLBACK enumerate(T* aElement, void* aData)
|
||||
typedef PRBool (* PR_CALLBACK nsCOMArrayEnumFunc)
|
||||
(T* aElement, void *aData);
|
||||
|
||||
// enumerate through the array with a callback.
|
||||
PRBool EnumerateForwards(nsCOMArrayEnumFunc aFunc, void* aData) {
|
||||
return nsCOMArray_base::EnumerateForwards(nsVoidArrayEnumFunc(aFunc),
|
||||
aData);
|
||||
}
|
||||
|
||||
// append an object, growing the array as necessary
|
||||
PRBool AppendObject(T *aObject) {
|
||||
return nsCOMArray_base::AppendObject(aObject);
|
||||
}
|
||||
|
||||
// remove the first instance of the given object and shrink the
|
||||
// array as necessary
|
||||
// Warning: if you pass null here, it will remove the first null element
|
||||
PRBool RemoveObject(T *aObject) {
|
||||
return nsCOMArray_base::RemoveObject(aObject);
|
||||
}
|
||||
|
||||
|
||||
// remove an element at a specific position, shrinking the array
|
||||
// as necessary
|
||||
PRBool RemoveObjectAt(PRInt32 aIndex) {
|
||||
return nsCOMArray_base::RemoveObjectAt(aIndex);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// don't implement these!
|
||||
|
|
|
@ -101,7 +101,7 @@ interface nsIArray : nsISupports
|
|||
|
||||
/**
|
||||
* nsIMutableArray
|
||||
* A seperate set of methods that will act on the array. Consumers of
|
||||
* A separate set of methods that will act on the array. Consumers of
|
||||
* nsIArray should not QueryInterface to nsIMutableArray unless they
|
||||
* own the array.
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче