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:
alecf@netscape.com
2002-09-30 23:02:31 +00:00
parent 7a0f25c401
commit 4939acab42
5 changed files with 125 additions and 17 deletions

View File

@@ -46,6 +46,9 @@ struct findIndexOfClosure
PRUint32 resultIndex; PRUint32 resultIndex;
}; };
static PRBool FindElementCallback(nsISupports* aElement, void* aClosure);
NS_IMPL_ISUPPORTS2(nsArray, nsIArray, nsIMutableArray) NS_IMPL_ISUPPORTS2(nsArray, nsIArray, nsIMutableArray)
nsArray::~nsArray() nsArray::~nsArray()
@@ -80,8 +83,6 @@ nsArray::IndexOf(PRUint32 aStartIndex, nsISupports* aElement,
*aResult = mArray.IndexOf(aElement); *aResult = mArray.IndexOf(aElement);
if (*aResult == -1) if (*aResult == -1)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
NS_ADDREF(*aResult);
return NS_OK; return NS_OK;
} }
@@ -130,7 +131,8 @@ nsArray::Clear()
return NS_OK; return NS_OK;
} }
nsArray::FindElementCallback(void *aElement, void* aClosure) PRBool
FindElementCallback(nsISupports *aElement, void* aClosure)
{ {
findIndexOfClosure* closure = findIndexOfClosure* closure =
NS_STATIC_CAST(findIndexOfClosure*, aClosure); NS_STATIC_CAST(findIndexOfClosure*, aClosure);
@@ -144,3 +146,27 @@ nsArray::FindElementCallback(void *aElement, void* aClosure)
return PR_TRUE; 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;
}

View File

@@ -57,6 +57,9 @@ class nsArray : public nsIMutableArray
{ {
public: public:
nsArray() { NS_INIT_ISUPPORTS(); } nsArray() { NS_INIT_ISUPPORTS(); }
nsArray(const nsCOMArray_base& aBaseArray) : mArray(aBaseArray)
{ NS_INIT_ISUPPORTS(); }
virtual ~nsArray(); virtual ~nsArray();
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@@ -64,10 +67,17 @@ public:
NS_DECL_NSIMUTABLEARRAY NS_DECL_NSIMUTABLEARRAY
private: private:
static PRBool FindElementCallback(void* aElement, void* aClosure);
nsCOMArray<nsISupports> mArray; 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 #endif

View File

@@ -38,8 +38,27 @@
#include "nsCOMArray.h" #include "nsCOMArray.h"
static PRBool AddRefObjects(void* aElement, void*);
static PRBool ReleaseObjects(void* aElement, void*);
// implementations of non-trivial methods in nsCOMArray_base // 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 PRBool
nsCOMArray_base::InsertObjectAt(nsISupports* aObject, PRInt32 aIndex) { nsCOMArray_base::InsertObjectAt(nsISupports* aObject, PRInt32 aIndex) {
PRBool result = mArray.InsertElementAt(aObject, aIndex); PRBool result = mArray.InsertElementAt(aObject, aIndex);
@@ -98,8 +117,19 @@ nsCOMArray_base::RemoveObjectAt(PRInt32 aIndex)
return PR_FALSE; 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); nsISupports* element = NS_STATIC_CAST(nsISupports*, aElement);
NS_IF_RELEASE(element); NS_IF_RELEASE(element);
@@ -109,6 +139,7 @@ ClearObjectsCallback(void* aElement, void*)
void void
nsCOMArray_base::Clear() nsCOMArray_base::Clear()
{ {
mArray.EnumerateForwards(ClearObjectsCallback, nsnull); mArray.EnumerateForwards(ReleaseObjects, nsnull);
mArray.Clear(); mArray.Clear();
} }

View File

@@ -42,6 +42,8 @@
#include "nsVoidArray.h" #include "nsVoidArray.h"
#include "nsISupports.h" #include "nsISupports.h"
// See below for the definition of nsCOMArray<T>
// a class that's nsISupports-specific, so that we can contain the // a class that's nsISupports-specific, so that we can contain the
// work of this class in the XPCOM dll // work of this class in the XPCOM dll
class NS_COM nsCOMArray_base class NS_COM nsCOMArray_base
@@ -49,6 +51,7 @@ class NS_COM nsCOMArray_base
protected: protected:
nsCOMArray_base() {} nsCOMArray_base() {}
nsCOMArray_base(PRInt32 aCount) : mArray(aCount) {} nsCOMArray_base(PRInt32 aCount) : mArray(aCount) {}
nsCOMArray_base(const nsCOMArray_base& other);
nsISupports* ObjectAt(PRInt32 aIndex) const { nsISupports* ObjectAt(PRInt32 aIndex) const {
return NS_STATIC_CAST(nsISupports*, mArray.ElementAt(aIndex)); return NS_STATIC_CAST(nsISupports*, mArray.ElementAt(aIndex));
@@ -88,13 +91,27 @@ protected:
nsVoidArray mArray; nsVoidArray mArray;
// don't implement these, defaults will muck with refcounts! // don't implement these, defaults will muck with refcounts!
nsCOMArray_base(const nsCOMArray_base& other);
nsCOMArray_base& operator=(const nsCOMArray_base& other); nsCOMArray_base& operator=(const nsCOMArray_base& other);
}; };
// a non-XPCOM, refcounting array of XPCOM objects // a non-XPCOM, refcounting array of XPCOM objects
// used as a member variable or stack variable - this object is NOT // used as a member variable or stack variable - this object is NOT
// refcounted, but the objects that it holds are // 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> template <class T>
class nsCOMArray : protected nsCOMArray_base class nsCOMArray : protected nsCOMArray_base
{ {
@@ -102,6 +119,8 @@ class nsCOMArray : protected nsCOMArray_base
nsCOMArray() {} nsCOMArray() {}
nsCOMArray(PRInt32 aCount) : nsCOMArray_base(aCount) {} nsCOMArray(PRInt32 aCount) : nsCOMArray_base(aCount) {}
nsCOMArray(const nsCOMArray_base& aOther) : nsCOMArray_base(aOther) { }
~nsCOMArray() {} ~nsCOMArray() {}
// these do NOT refcount on the way out, for speed // these do NOT refcount on the way out, for speed
@@ -109,49 +128,71 @@ class nsCOMArray : protected nsCOMArray_base
return NS_STATIC_CAST(T*,nsCOMArray_base::ObjectAt(aIndex)); return NS_STATIC_CAST(T*,nsCOMArray_base::ObjectAt(aIndex));
} }
// indexing operator for syntactic sugar
T* operator[](PRInt32 aIndex) const { T* operator[](PRInt32 aIndex) const {
return ObjectAt(aIndex); return ObjectAt(aIndex);
} }
// index of the element in question.. does NOT refcount
PRInt32 IndexOf(T* aObject) { PRInt32 IndexOf(T* aObject) {
return nsCOMArray_base::IndexOf(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) { PRBool InsertObjectAt(T* aObject, PRInt32 aIndex) {
return nsCOMArray_base::InsertObjectAt(aObject, 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) { PRBool ReplaceObjectAt(T* aObject, PRInt32 aIndex) {
return nsCOMArray_base::ReplaceObjectAt(aObject, aIndex); return nsCOMArray_base::ReplaceObjectAt(aObject, aIndex);
} }
// override nsVoidArray stuff so that they can be accessed by // override nsVoidArray stuff so that they can be accessed by
// other methods // other methods
// elements in the array (including null elements!)
PRInt32 Count() const { PRInt32 Count() const {
return nsCOMArray_base::Count(); return nsCOMArray_base::Count();
} }
// remove all elements in the array, and call NS_RELEASE on each one
void Clear() { void Clear() {
nsCOMArray_base::Clear(); nsCOMArray_base::Clear();
} }
PRBool EnumerateForwards(nsVoidArrayEnumFunc aFunc, void* aData) { // Enumerator callback function. Return PR_FALSE to stop
return nsCOMArray_base::EnumerateForwards(aFunc, aData); // 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) { PRBool AppendObject(T *aObject) {
return nsCOMArray_base::AppendObject(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) { PRBool RemoveObject(T *aObject) {
return nsCOMArray_base::RemoveObject(aObject); return nsCOMArray_base::RemoveObject(aObject);
} }
// remove an element at a specific position, shrinking the array
// as necessary
PRBool RemoveObjectAt(PRInt32 aIndex) { PRBool RemoveObjectAt(PRInt32 aIndex) {
return nsCOMArray_base::RemoveObjectAt(aIndex); return nsCOMArray_base::RemoveObjectAt(aIndex);
} }
private: private:
// don't implement these! // don't implement these!

View File

@@ -101,7 +101,7 @@ interface nsIArray : nsISupports
/** /**
* nsIMutableArray * 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 * nsIArray should not QueryInterface to nsIMutableArray unless they
* own the array. * own the array.
* *