diff -r 000000000000 -r 6474c204b198 xpcom/base/nsAutoPtr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xpcom/base/nsAutoPtr.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,1477 @@ +/* -*- Mode: C++; tab-width: 2; 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/. */ + +#ifndef nsAutoPtr_h___ +#define nsAutoPtr_h___ + +#include "nsCOMPtr.h" + +#include "nsCycleCollectionNoteChild.h" +#include "mozilla/MemoryReporting.h" + +/*****************************************************************************/ + +// template class nsAutoPtrGetterTransfers; + +template +class nsAutoPtr + { + private: + void** + begin_assignment() + { + assign(0); + return reinterpret_cast(&mRawPtr); + } + + void + assign( T* newPtr ) + { + T* oldPtr = mRawPtr; + + if (newPtr != nullptr && newPtr == oldPtr) { + NS_RUNTIMEABORT("Logic flaw in the caller"); + } + + mRawPtr = newPtr; + delete oldPtr; + } + + // |class Ptr| helps us prevent implicit "copy construction" + // through |operator T*() const| from a |const nsAutoPtr| + // because two implicit conversions in a row aren't allowed. + // It still allows assignment from T* through implicit conversion + // from |T*| to |nsAutoPtr::Ptr| + class Ptr + { + public: + Ptr( T* aPtr ) + : mPtr(aPtr) + { + } + + operator T*() const + { + return mPtr; + } + + private: + T* mPtr; + }; + + private: + T* mRawPtr; + + public: + typedef T element_type; + + ~nsAutoPtr() + { + delete mRawPtr; + } + + // Constructors + + nsAutoPtr() + : mRawPtr(0) + // default constructor + { + } + + nsAutoPtr( Ptr aRawPtr ) + : mRawPtr(aRawPtr) + // construct from a raw pointer (of the right type) + { + } + + // This constructor shouldn't exist; we should just use the && + // constructor. + nsAutoPtr( nsAutoPtr& aSmartPtr ) + : mRawPtr( aSmartPtr.forget() ) + // Construct by transferring ownership from another smart pointer. + { + } + + nsAutoPtr( nsAutoPtr&& aSmartPtr ) + : mRawPtr( aSmartPtr.forget() ) + // Construct by transferring ownership from another smart pointer. + { + } + + // Assignment operators + + nsAutoPtr& + operator=( T* rhs ) + // assign from a raw pointer (of the right type) + { + assign(rhs); + return *this; + } + + nsAutoPtr& operator=( nsAutoPtr& rhs ) + // assign by transferring ownership from another smart pointer. + { + assign(rhs.forget()); + return *this; + } + + // Other pointer operators + + T* + get() const + /* + Prefer the implicit conversion provided automatically by + |operator T*() const|. Use |get()| _only_ to resolve + ambiguity. + */ + { + return mRawPtr; + } + + operator T*() const + /* + ...makes an |nsAutoPtr| act like its underlying raw pointer + type whenever it is used in a context where a raw pointer + is expected. It is this operator that makes an |nsAutoPtr| + substitutable for a raw pointer. + + Prefer the implicit use of this operator to calling |get()|, + except where necessary to resolve ambiguity. + */ + { + return get(); + } + + T* + forget() + { + T* temp = mRawPtr; + mRawPtr = 0; + return temp; + } + + T* + operator->() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->()."); + return get(); + } + + // This operator is needed for gcc <= 4.0.* and for Sun Studio; it + // causes internal compiler errors for some MSVC versions. (It's not + // clear to me whether it should be needed.) +#ifndef _MSC_VER + template + U& + operator->*(U V::* aMember) + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->*()."); + return get()->*aMember; + } +#endif + + nsAutoPtr* + get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + const nsAutoPtr* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + public: + T& + operator*() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator*()."); + return *get(); + } + + T** + StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return reinterpret_cast(begin_assignment()); +#else + assign(0); + return reinterpret_cast(&mRawPtr); +#endif + } + }; + +template +inline +nsAutoPtr* +address_of( nsAutoPtr& aPtr ) + { + return aPtr.get_address(); + } + +template +inline +const nsAutoPtr* +address_of( const nsAutoPtr& aPtr ) + { + return aPtr.get_address(); + } + +template +class nsAutoPtrGetterTransfers + /* + ... + + This class is designed to be used for anonymous temporary objects in the + argument list of calls that return COM interface pointers, e.g., + + nsAutoPtr fooP; + ...->GetTransferedPointer(getter_Transfers(fooP)) + + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead. + + When initialized with a |nsAutoPtr|, as in the example above, it returns + a |void**|, a |T**|, or an |nsISupports**| as needed, that the + outer call (|GetTransferedPointer| in this case) can fill in. + + This type should be a nested class inside |nsAutoPtr|. + */ + { + public: + explicit + nsAutoPtrGetterTransfers( nsAutoPtr& aSmartPtr ) + : mTargetSmartPtr(aSmartPtr) + { + // nothing else to do + } + + operator void**() + { + return reinterpret_cast(mTargetSmartPtr.StartAssignment()); + } + + operator T**() + { + return mTargetSmartPtr.StartAssignment(); + } + + T*& + operator*() + { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsAutoPtr& mTargetSmartPtr; + }; + +template +inline +nsAutoPtrGetterTransfers +getter_Transfers( nsAutoPtr& aSmartPtr ) + /* + Used around a |nsAutoPtr| when + ...makes the class |nsAutoPtrGetterTransfers| invisible. + */ + { + return nsAutoPtrGetterTransfers(aSmartPtr); + } + + + + // Comparing two |nsAutoPtr|s + +template +inline +bool +operator==( const nsAutoPtr& lhs, const nsAutoPtr& rhs ) + { + return static_cast(lhs.get()) == static_cast(rhs.get()); + } + + +template +inline +bool +operator!=( const nsAutoPtr& lhs, const nsAutoPtr& rhs ) + { + return static_cast(lhs.get()) != static_cast(rhs.get()); + } + + + // Comparing an |nsAutoPtr| to a raw pointer + +template +inline +bool +operator==( const nsAutoPtr& lhs, const U* rhs ) + { + return static_cast(lhs.get()) == static_cast(rhs); + } + +template +inline +bool +operator==( const U* lhs, const nsAutoPtr& rhs ) + { + return static_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsAutoPtr& lhs, const U* rhs ) + { + return static_cast(lhs.get()) != static_cast(rhs); + } + +template +inline +bool +operator!=( const U* lhs, const nsAutoPtr& rhs ) + { + return static_cast(lhs) != static_cast(rhs.get()); + } + + // To avoid ambiguities caused by the presence of builtin |operator==|s + // creating a situation where one of the |operator==| defined above + // has a better conversion for one argument and the builtin has a + // better conversion for the other argument, define additional + // |operator==| without the |const| on the raw pointer. + // See bug 65664 for details. + +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ +template +inline +bool +operator==( const nsAutoPtr& lhs, U* rhs ) + { + return static_cast(lhs.get()) == const_cast(rhs); + } + +template +inline +bool +operator==( U* lhs, const nsAutoPtr& rhs ) + { + return const_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsAutoPtr& lhs, U* rhs ) + { + return static_cast(lhs.get()) != const_cast(rhs); + } + +template +inline +bool +operator!=( U* lhs, const nsAutoPtr& rhs ) + { + return const_cast(lhs) != static_cast(rhs.get()); + } +#endif + + + + // Comparing an |nsAutoPtr| to |0| + +template +inline +bool +operator==( const nsAutoPtr& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr == 0| + { + return static_cast(lhs.get()) == reinterpret_cast(rhs); + } + +template +inline +bool +operator==( NSCAP_Zero* lhs, const nsAutoPtr& rhs ) + // specifically to allow |0 == smartPtr| + { + return reinterpret_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsAutoPtr& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr != 0| + { + return static_cast(lhs.get()) != reinterpret_cast(rhs); + } + +template +inline +bool +operator!=( NSCAP_Zero* lhs, const nsAutoPtr& rhs ) + // specifically to allow |0 != smartPtr| + { + return reinterpret_cast(lhs) != static_cast(rhs.get()); + } + + +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO + + // We need to explicitly define comparison operators for `int' + // because the compiler is lame. + +template +inline +bool +operator==( const nsAutoPtr& lhs, int rhs ) + // specifically to allow |smartPtr == 0| + { + return static_cast(lhs.get()) == reinterpret_cast(rhs); + } + +template +inline +bool +operator==( int lhs, const nsAutoPtr& rhs ) + // specifically to allow |0 == smartPtr| + { + return reinterpret_cast(lhs) == static_cast(rhs.get()); + } + +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) + +/*****************************************************************************/ + +// template class nsAutoArrayPtrGetterTransfers; + +template +class nsAutoArrayPtr + { + private: + void** + begin_assignment() + { + assign(0); + return reinterpret_cast(&mRawPtr); + } + + void + assign( T* newPtr ) + { + T* oldPtr = mRawPtr; + mRawPtr = newPtr; + delete [] oldPtr; + } + + private: + T* mRawPtr; + + public: + typedef T element_type; + + ~nsAutoArrayPtr() + { + delete [] mRawPtr; + } + + // Constructors + + nsAutoArrayPtr() + : mRawPtr(0) + // default constructor + { + } + + nsAutoArrayPtr( T* aRawPtr ) + : mRawPtr(aRawPtr) + // construct from a raw pointer (of the right type) + { + } + + nsAutoArrayPtr( nsAutoArrayPtr& aSmartPtr ) + : mRawPtr( aSmartPtr.forget() ) + // Construct by transferring ownership from another smart pointer. + { + } + + + // Assignment operators + + nsAutoArrayPtr& + operator=( T* rhs ) + // assign from a raw pointer (of the right type) + { + assign(rhs); + return *this; + } + + nsAutoArrayPtr& operator=( nsAutoArrayPtr& rhs ) + // assign by transferring ownership from another smart pointer. + { + assign(rhs.forget()); + return *this; + } + + // Other pointer operators + + T* + get() const + /* + Prefer the implicit conversion provided automatically by + |operator T*() const|. Use |get()| _only_ to resolve + ambiguity. + */ + { + return mRawPtr; + } + + operator T*() const + /* + ...makes an |nsAutoArrayPtr| act like its underlying raw pointer + type whenever it is used in a context where a raw pointer + is expected. It is this operator that makes an |nsAutoArrayPtr| + substitutable for a raw pointer. + + Prefer the implicit use of this operator to calling |get()|, + except where necessary to resolve ambiguity. + */ + { + return get(); + } + + T* + forget() + { + T* temp = mRawPtr; + mRawPtr = 0; + return temp; + } + + T* + operator->() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->()."); + return get(); + } + + nsAutoArrayPtr* + get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + const nsAutoArrayPtr* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + public: + T& + operator*() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator*()."); + return *get(); + } + + T** + StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return reinterpret_cast(begin_assignment()); +#else + assign(0); + return reinterpret_cast(&mRawPtr); +#endif + } + + size_t + SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const + { + return aMallocSizeOf(mRawPtr); + } + + size_t + SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const + { + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); + } + }; + +template +inline +nsAutoArrayPtr* +address_of( nsAutoArrayPtr& aPtr ) + { + return aPtr.get_address(); + } + +template +inline +const nsAutoArrayPtr* +address_of( const nsAutoArrayPtr& aPtr ) + { + return aPtr.get_address(); + } + +template +class nsAutoArrayPtrGetterTransfers + /* + ... + + This class is designed to be used for anonymous temporary objects in the + argument list of calls that return COM interface pointers, e.g., + + nsAutoArrayPtr fooP; + ...->GetTransferedPointer(getter_Transfers(fooP)) + + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead. + + When initialized with a |nsAutoArrayPtr|, as in the example above, it returns + a |void**|, a |T**|, or an |nsISupports**| as needed, that the + outer call (|GetTransferedPointer| in this case) can fill in. + + This type should be a nested class inside |nsAutoArrayPtr|. + */ + { + public: + explicit + nsAutoArrayPtrGetterTransfers( nsAutoArrayPtr& aSmartPtr ) + : mTargetSmartPtr(aSmartPtr) + { + // nothing else to do + } + + operator void**() + { + return reinterpret_cast(mTargetSmartPtr.StartAssignment()); + } + + operator T**() + { + return mTargetSmartPtr.StartAssignment(); + } + + T*& + operator*() + { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsAutoArrayPtr& mTargetSmartPtr; + }; + +template +inline +nsAutoArrayPtrGetterTransfers +getter_Transfers( nsAutoArrayPtr& aSmartPtr ) + /* + Used around a |nsAutoArrayPtr| when + ...makes the class |nsAutoArrayPtrGetterTransfers| invisible. + */ + { + return nsAutoArrayPtrGetterTransfers(aSmartPtr); + } + + + + // Comparing two |nsAutoArrayPtr|s + +template +inline +bool +operator==( const nsAutoArrayPtr& lhs, const nsAutoArrayPtr& rhs ) + { + return static_cast(lhs.get()) == static_cast(rhs.get()); + } + + +template +inline +bool +operator!=( const nsAutoArrayPtr& lhs, const nsAutoArrayPtr& rhs ) + { + return static_cast(lhs.get()) != static_cast(rhs.get()); + } + + + // Comparing an |nsAutoArrayPtr| to a raw pointer + +template +inline +bool +operator==( const nsAutoArrayPtr& lhs, const U* rhs ) + { + return static_cast(lhs.get()) == static_cast(rhs); + } + +template +inline +bool +operator==( const U* lhs, const nsAutoArrayPtr& rhs ) + { + return static_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsAutoArrayPtr& lhs, const U* rhs ) + { + return static_cast(lhs.get()) != static_cast(rhs); + } + +template +inline +bool +operator!=( const U* lhs, const nsAutoArrayPtr& rhs ) + { + return static_cast(lhs) != static_cast(rhs.get()); + } + + // To avoid ambiguities caused by the presence of builtin |operator==|s + // creating a situation where one of the |operator==| defined above + // has a better conversion for one argument and the builtin has a + // better conversion for the other argument, define additional + // |operator==| without the |const| on the raw pointer. + // See bug 65664 for details. + +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ +template +inline +bool +operator==( const nsAutoArrayPtr& lhs, U* rhs ) + { + return static_cast(lhs.get()) == const_cast(rhs); + } + +template +inline +bool +operator==( U* lhs, const nsAutoArrayPtr& rhs ) + { + return const_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsAutoArrayPtr& lhs, U* rhs ) + { + return static_cast(lhs.get()) != const_cast(rhs); + } + +template +inline +bool +operator!=( U* lhs, const nsAutoArrayPtr& rhs ) + { + return const_cast(lhs) != static_cast(rhs.get()); + } +#endif + + + + // Comparing an |nsAutoArrayPtr| to |0| + +template +inline +bool +operator==( const nsAutoArrayPtr& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr == 0| + { + return static_cast(lhs.get()) == reinterpret_cast(rhs); + } + +template +inline +bool +operator==( NSCAP_Zero* lhs, const nsAutoArrayPtr& rhs ) + // specifically to allow |0 == smartPtr| + { + return reinterpret_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsAutoArrayPtr& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr != 0| + { + return static_cast(lhs.get()) != reinterpret_cast(rhs); + } + +template +inline +bool +operator!=( NSCAP_Zero* lhs, const nsAutoArrayPtr& rhs ) + // specifically to allow |0 != smartPtr| + { + return reinterpret_cast(lhs) != static_cast(rhs.get()); + } + + +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO + + // We need to explicitly define comparison operators for `int' + // because the compiler is lame. + +template +inline +bool +operator==( const nsAutoArrayPtr& lhs, int rhs ) + // specifically to allow |smartPtr == 0| + { + return static_cast(lhs.get()) == reinterpret_cast(rhs); + } + +template +inline +bool +operator==( int lhs, const nsAutoArrayPtr& rhs ) + // specifically to allow |0 == smartPtr| + { + return reinterpret_cast(lhs) == static_cast(rhs.get()); + } + +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) + + +/*****************************************************************************/ + +// template class nsRefPtrGetterAddRefs; + +template +class nsRefPtr + { + private: + + void + assign_with_AddRef( T* rawPtr ) + { + if ( rawPtr ) + rawPtr->AddRef(); + assign_assuming_AddRef(rawPtr); + } + + void** + begin_assignment() + { + assign_assuming_AddRef(0); + return reinterpret_cast(&mRawPtr); + } + + void + assign_assuming_AddRef( T* newPtr ) + { + T* oldPtr = mRawPtr; + mRawPtr = newPtr; + if ( oldPtr ) + oldPtr->Release(); + } + + private: + T* mRawPtr; + + public: + typedef T element_type; + + ~nsRefPtr() + { + if ( mRawPtr ) + mRawPtr->Release(); + } + + // Constructors + + nsRefPtr() + : mRawPtr(0) + // default constructor + { + } + + nsRefPtr(const nsRefPtr& aSmartPtr) + : mRawPtr(aSmartPtr.mRawPtr) + // copy-constructor + { + if ( mRawPtr ) + mRawPtr->AddRef(); + } + + nsRefPtr(nsRefPtr&& aRefPtr) + : mRawPtr(aRefPtr.mRawPtr) + { + aRefPtr.mRawPtr = nullptr; + } + + // construct from a raw pointer (of the right type) + + nsRefPtr(T* aRawPtr) + : mRawPtr(aRawPtr) + { + if ( mRawPtr ) + mRawPtr->AddRef(); + } + + template + nsRefPtr( already_AddRefed& aSmartPtr ) + : mRawPtr(aSmartPtr.take()) + // construct from |already_AddRefed| + { + } + + template + nsRefPtr( already_AddRefed&& aSmartPtr ) + : mRawPtr(aSmartPtr.take()) + // construct from |otherRefPtr.forget()| + { + } + + nsRefPtr( const nsCOMPtr_helper& helper ) + { + void* newRawPtr; + if (NS_FAILED(helper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) + newRawPtr = 0; + mRawPtr = static_cast(newRawPtr); + } + + // Assignment operators + + nsRefPtr& + operator=(const nsRefPtr& rhs) + // copy assignment operator + { + assign_with_AddRef(rhs.mRawPtr); + return *this; + } + + nsRefPtr& + operator=( T* rhs ) + // assign from a raw pointer (of the right type) + { + assign_with_AddRef(rhs); + return *this; + } + + template + nsRefPtr& + operator=( already_AddRefed& rhs ) + // assign from |already_AddRefed| + { + assign_assuming_AddRef(rhs.take()); + return *this; + } + + template + nsRefPtr& + operator=( already_AddRefed&& rhs ) + // assign from |otherRefPtr.forget()| + { + assign_assuming_AddRef(rhs.take()); + return *this; + } + + nsRefPtr& + operator=( const nsCOMPtr_helper& helper ) + { + void* newRawPtr; + if (NS_FAILED(helper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) + newRawPtr = 0; + assign_assuming_AddRef(static_cast(newRawPtr)); + return *this; + } + + nsRefPtr& + operator=(nsRefPtr&& aRefPtr) + { + assign_assuming_AddRef(aRefPtr.mRawPtr); + aRefPtr.mRawPtr = nullptr; + return *this; + } + + // Other pointer operators + + void + swap( nsRefPtr& rhs ) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { + T* temp = rhs.mRawPtr; + rhs.mRawPtr = mRawPtr; + mRawPtr = temp; + } + + void + swap( T*& rhs ) + // ...exchange ownership with |rhs|; can save a pair of refcount operations + { + T* temp = rhs; + rhs = mRawPtr; + mRawPtr = temp; + } + + already_AddRefed + forget() + // return the value of mRawPtr and null out mRawPtr. Useful for + // already_AddRefed return values. + { + T* temp = 0; + swap(temp); + return already_AddRefed(temp); + } + + template + void + forget( I** rhs) + // Set the target of rhs to the value of mRawPtr and null out mRawPtr. + // Useful to avoid unnecessary AddRef/Release pairs with "out" + // parameters where rhs bay be a T** or an I** where I is a base class + // of T. + { + NS_ASSERTION(rhs, "Null pointer passed to forget!"); + *rhs = mRawPtr; + mRawPtr = 0; + } + + T* + get() const + /* + Prefer the implicit conversion provided automatically by |operator T*() const|. + Use |get()| to resolve ambiguity or to get a castable pointer. + */ + { + return const_cast(mRawPtr); + } + + operator T*() const + /* + ...makes an |nsRefPtr| act like its underlying raw pointer type whenever it + is used in a context where a raw pointer is expected. It is this operator + that makes an |nsRefPtr| substitutable for a raw pointer. + + Prefer the implicit use of this operator to calling |get()|, except where + necessary to resolve ambiguity. + */ + { + return get(); + } + + T* + operator->() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->()."); + return get(); + } + + // This operator is needed for gcc <= 4.0.* and for Sun Studio; it + // causes internal compiler errors for some MSVC versions. (It's not + // clear to me whether it should be needed.) +#ifndef _MSC_VER + template + U& + operator->*(U V::* aMember) + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->*()."); + return get()->*aMember; + } +#endif + + nsRefPtr* + get_address() + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + const nsRefPtr* + get_address() const + // This is not intended to be used by clients. See |address_of| + // below. + { + return this; + } + + public: + T& + operator*() const + { + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator*()."); + return *get(); + } + + T** + StartAssignment() + { +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT + return reinterpret_cast(begin_assignment()); +#else + assign_assuming_AddRef(0); + return reinterpret_cast(&mRawPtr); +#endif + } + }; + +template +inline void +ImplCycleCollectionUnlink(nsRefPtr& aField) +{ + aField = nullptr; +} + +template +inline void +ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, + nsRefPtr& aField, + const char* aName, + uint32_t aFlags = 0) +{ + CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags); +} + +template +inline +nsRefPtr* +address_of( nsRefPtr& aPtr ) + { + return aPtr.get_address(); + } + +template +inline +const nsRefPtr* +address_of( const nsRefPtr& aPtr ) + { + return aPtr.get_address(); + } + +template +class nsRefPtrGetterAddRefs + /* + ... + + This class is designed to be used for anonymous temporary objects in the + argument list of calls that return COM interface pointers, e.g., + + nsRefPtr fooP; + ...->GetAddRefedPointer(getter_AddRefs(fooP)) + + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead. + + When initialized with a |nsRefPtr|, as in the example above, it returns + a |void**|, a |T**|, or an |nsISupports**| as needed, that the + outer call (|GetAddRefedPointer| in this case) can fill in. + + This type should be a nested class inside |nsRefPtr|. + */ + { + public: + explicit + nsRefPtrGetterAddRefs( nsRefPtr& aSmartPtr ) + : mTargetSmartPtr(aSmartPtr) + { + // nothing else to do + } + + operator void**() + { + return reinterpret_cast(mTargetSmartPtr.StartAssignment()); + } + + operator T**() + { + return mTargetSmartPtr.StartAssignment(); + } + + T*& + operator*() + { + return *(mTargetSmartPtr.StartAssignment()); + } + + private: + nsRefPtr& mTargetSmartPtr; + }; + +template +inline +nsRefPtrGetterAddRefs +getter_AddRefs( nsRefPtr& aSmartPtr ) + /* + Used around a |nsRefPtr| when + ...makes the class |nsRefPtrGetterAddRefs| invisible. + */ + { + return nsRefPtrGetterAddRefs(aSmartPtr); + } + + + + // Comparing two |nsRefPtr|s + +template +inline +bool +operator==( const nsRefPtr& lhs, const nsRefPtr& rhs ) + { + return static_cast(lhs.get()) == static_cast(rhs.get()); + } + + +template +inline +bool +operator!=( const nsRefPtr& lhs, const nsRefPtr& rhs ) + { + return static_cast(lhs.get()) != static_cast(rhs.get()); + } + + + // Comparing an |nsRefPtr| to a raw pointer + +template +inline +bool +operator==( const nsRefPtr& lhs, const U* rhs ) + { + return static_cast(lhs.get()) == static_cast(rhs); + } + +template +inline +bool +operator==( const U* lhs, const nsRefPtr& rhs ) + { + return static_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsRefPtr& lhs, const U* rhs ) + { + return static_cast(lhs.get()) != static_cast(rhs); + } + +template +inline +bool +operator!=( const U* lhs, const nsRefPtr& rhs ) + { + return static_cast(lhs) != static_cast(rhs.get()); + } + + // To avoid ambiguities caused by the presence of builtin |operator==|s + // creating a situation where one of the |operator==| defined above + // has a better conversion for one argument and the builtin has a + // better conversion for the other argument, define additional + // |operator==| without the |const| on the raw pointer. + // See bug 65664 for details. + +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ +template +inline +bool +operator==( const nsRefPtr& lhs, U* rhs ) + { + return static_cast(lhs.get()) == const_cast(rhs); + } + +template +inline +bool +operator==( U* lhs, const nsRefPtr& rhs ) + { + return const_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsRefPtr& lhs, U* rhs ) + { + return static_cast(lhs.get()) != const_cast(rhs); + } + +template +inline +bool +operator!=( U* lhs, const nsRefPtr& rhs ) + { + return const_cast(lhs) != static_cast(rhs.get()); + } +#endif + + + + // Comparing an |nsRefPtr| to |0| + +template +inline +bool +operator==( const nsRefPtr& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr == 0| + { + return static_cast(lhs.get()) == reinterpret_cast(rhs); + } + +template +inline +bool +operator==( NSCAP_Zero* lhs, const nsRefPtr& rhs ) + // specifically to allow |0 == smartPtr| + { + return reinterpret_cast(lhs) == static_cast(rhs.get()); + } + +template +inline +bool +operator!=( const nsRefPtr& lhs, NSCAP_Zero* rhs ) + // specifically to allow |smartPtr != 0| + { + return static_cast(lhs.get()) != reinterpret_cast(rhs); + } + +template +inline +bool +operator!=( NSCAP_Zero* lhs, const nsRefPtr& rhs ) + // specifically to allow |0 != smartPtr| + { + return reinterpret_cast(lhs) != static_cast(rhs.get()); + } + + +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO + + // We need to explicitly define comparison operators for `int' + // because the compiler is lame. + +template +inline +bool +operator==( const nsRefPtr& lhs, int rhs ) + // specifically to allow |smartPtr == 0| + { + return static_cast(lhs.get()) == reinterpret_cast(rhs); + } + +template +inline +bool +operator==( int lhs, const nsRefPtr& rhs ) + // specifically to allow |0 == smartPtr| + { + return reinterpret_cast(lhs) == static_cast(rhs.get()); + } + +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) + +template +inline +nsresult +CallQueryInterface( nsRefPtr& aSourcePtr, DestinationType** aDestPtr ) + { + return CallQueryInterface(aSourcePtr.get(), aDestPtr); + } + +/*****************************************************************************/ + +template +class nsQueryObject : public nsCOMPtr_helper +{ +public: + nsQueryObject(T* aRawPtr) + : mRawPtr(aRawPtr) {} + + virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** aResult ) const { + nsresult status = mRawPtr ? mRawPtr->QueryInterface(aIID, aResult) + : NS_ERROR_NULL_POINTER; + return status; + } +private: + T* mRawPtr; +}; + +template +class nsQueryObjectWithError : public nsCOMPtr_helper +{ +public: + nsQueryObjectWithError(T* aRawPtr, nsresult* aErrorPtr) + : mRawPtr(aRawPtr), mErrorPtr(aErrorPtr) {} + + virtual nsresult NS_FASTCALL operator()( const nsIID& aIID, void** aResult ) const { + nsresult status = mRawPtr ? mRawPtr->QueryInterface(aIID, aResult) + : NS_ERROR_NULL_POINTER; + if (mErrorPtr) + *mErrorPtr = status; + return status; + } +private: + T* mRawPtr; + nsresult* mErrorPtr; +}; + +template +inline +nsQueryObject +do_QueryObject(T* aRawPtr) +{ + return nsQueryObject(aRawPtr); +} + +template +inline +nsQueryObject +do_QueryObject(nsCOMPtr& aRawPtr) +{ + return nsQueryObject(aRawPtr); +} + +template +inline +nsQueryObject +do_QueryObject(nsRefPtr& aRawPtr) +{ + return nsQueryObject(aRawPtr); +} + +template +inline +nsQueryObjectWithError +do_QueryObject(T* aRawPtr, nsresult* aErrorPtr) +{ + return nsQueryObjectWithError(aRawPtr, aErrorPtr); +} + +template +inline +nsQueryObjectWithError +do_QueryObject(nsCOMPtr& aRawPtr, nsresult* aErrorPtr) +{ + return nsQueryObjectWithError(aRawPtr, aErrorPtr); +} + +template +inline +nsQueryObjectWithError +do_QueryObject(nsRefPtr& aRawPtr, nsresult* aErrorPtr) +{ + return nsQueryObjectWithError(aRawPtr, aErrorPtr); +} + +/*****************************************************************************/ + +#endif // !defined(nsAutoPtr_h___)