Back to index

lightning-sunbird  0.9+nobinonly
nsCOMPtr.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Scott Collins <scc@mozilla.org> (original author)
00024  *   L. David Baron <dbaron@dbaron.org>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #ifndef nsCOMPtr_h___
00041 #define nsCOMPtr_h___
00042 
00043 /*
00044   Having problems?
00045   
00046   See the User Manual at:
00047     http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
00048 
00049 
00050   nsCOMPtr
00051     better than a raw pointer
00052   for owning objects
00053                        -- scc
00054 */
00055 
00056 
00057   // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
00058 #ifndef nsDebug_h___
00059 #include "nsDebug.h"
00060   // for |NS_PRECONDITION|
00061 #endif
00062 
00063 #ifndef nsISupportsUtils_h__
00064 #include "nsISupportsUtils.h"
00065   // for |nsresult|, |NS_ADDREF|, |NS_GET_IID| et al
00066 #endif
00067 
00068 #ifndef nscore_h___
00069 #include "nscore.h"
00070   // for |NS_..._CAST|, |NS_COM_GLUE|
00071 #endif
00072 
00073 
00074 /*
00075   WARNING:
00076     This file defines several macros for internal use only.  These macros begin with the
00077     prefix |NSCAP_|.  Do not use these macros in your own code.  They are for internal use
00078     only for cross-platform compatibility, and are subject to change without notice.
00079 */
00080 
00081 
00082 #ifdef _MSC_VER
00083   #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
00084     // under VC++, we win by inlining StartAssignment
00085 
00086     // Also under VC++, at the highest warning level, we are overwhelmed  with warnings
00087     //  about (unused) inline functions being removed.  This is to be expected with
00088     //  templates, so we disable the warning.
00089   #pragma warning( disable: 4514 )
00090 #endif
00091 
00092 #define NSCAP_FEATURE_USE_BASE
00093 
00094 #ifdef NS_DEBUG
00095   #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
00096   #undef NSCAP_FEATURE_USE_BASE
00097 //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
00098 #endif
00099 
00100   /*
00101     |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is 
00102     problematic on a select few of our platforms, e.g., QNX.  Therefore, I'm providing
00103     a mechanism by which these features can be explicitly disabled from the command-line.
00104   */
00105 
00106 #ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
00107   #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
00108 #endif
00109 
00110 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
00111   // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
00112   // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
00113   // don't reorder instructions based on aliasing assumptions for
00114   // this variable.  Fortunately, gcc versions < 3.3 do not do any
00115   // optimizations that break nsCOMPtr.
00116 
00117   #define NS_MAY_ALIAS_PTR(t)    t*  __attribute__((__may_alias__))
00118 #else
00119   #define NS_MAY_ALIAS_PTR(t)    t*
00120 #endif
00121 
00122 #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
00123   #define NSCAP_FEATURE_USE_BASE
00124 #endif
00125 
00126 
00127 #ifdef HAVE_CPP_BOOL
00128   typedef bool NSCAP_BOOL;
00129 #else
00130   typedef PRBool NSCAP_BOOL;
00131 #endif
00132 
00133 
00134 
00135 
00136   /*
00137     The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
00138       allow external clients the ability to add logging or other interesting debug facilities.
00139       In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
00140       provide (e.g., in "nsTraceRefcnt.h") suitable definitions
00141 
00142         #define NSCAP_ADDREF(this, ptr)         NS_ADDREF(ptr)
00143         #define NSCAP_RELEASE(this, ptr)        NS_RELEASE(ptr)
00144   */
00145 
00146 #ifndef NSCAP_ADDREF
00147   #define NSCAP_ADDREF(this, ptr)     (ptr)->AddRef()
00148 #endif
00149 
00150 #ifndef NSCAP_RELEASE
00151   #define NSCAP_RELEASE(this, ptr)    (ptr)->Release()
00152 #endif
00153 
00154   // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
00155 #ifdef NSCAP_LOG_ASSIGNMENT
00156     // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
00157     //  to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
00158     //  the |nsCOMPtr|.
00159   #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
00160 #else
00161     // ...otherwise, just strip it out of the code
00162   #define NSCAP_LOG_ASSIGNMENT(this, ptr)
00163 #endif
00164 
00165 #ifndef NSCAP_LOG_RELEASE
00166   #define NSCAP_LOG_RELEASE(this, ptr)
00167 #endif
00168 
00169 
00170 
00171 
00172   /*
00173     WARNING:
00174       VC++4.2 is very picky.  To compile under VC++4.2, the classes must be defined
00175       in an order that satisfies:
00176     
00177         nsDerivedSafe < nsCOMPtr
00178         already_AddRefed < nsCOMPtr
00179         nsCOMPtr < nsGetterAddRefs
00180 
00181       The other compilers probably won't complain, so please don't reorder these
00182       classes, on pain of breaking 4.2 compatibility.
00183   */
00184 
00185 
00186 template <class T>
00187 class nsDerivedSafe : public T
00188     /*
00189       No client should ever see or have to type the name of this class.  It is the
00190       artifact that makes it a compile-time error to call |AddRef| and |Release|
00191       on a |nsCOMPtr|.  DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
00192 
00193       See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
00194 
00195       This type should be a nested class inside |nsCOMPtr<T>|.
00196     */
00197   {
00198     private:
00199 #ifdef HAVE_CPP_ACCESS_CHANGING_USING
00200       using T::AddRef;
00201       using T::Release;
00202 #else
00203       nsrefcnt AddRef(void);
00204       nsrefcnt Release(void);
00205 #endif
00206 
00207 #if !defined(AIX) && !defined(IRIX)
00208       void operator delete( void*, size_t );                  // NOT TO BE IMPLEMENTED
00209         // declaring |operator delete| private makes calling delete on an interface pointer a compile error
00210 #endif
00211 
00212       nsDerivedSafe<T>& operator=( const T& );                // NOT TO BE IMPLEMENTED
00213         // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
00214 
00215         /*
00216           Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=().
00217           If you see that, that means somebody checked in a [XP]COM interface class that declares an
00218           |operator=()|, and that's _bad_.  So bad, in fact, that this declaration exists explicitly
00219           to stop people from doing it.
00220         */
00221 
00222     protected:
00223       nsDerivedSafe();                                        // NOT TO BE IMPLEMENTED
00224         /*
00225           This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the
00226           default ctor but inheriting classes without an empty ctor. See bug 209667.
00227         */
00228   };
00229 
00230 #if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS)
00231 template <class T>
00232 nsrefcnt
00233 nsDerivedSafe<T>::AddRef()
00234   {
00235     return 0;
00236   }
00237 
00238 template <class T>
00239 nsrefcnt
00240 nsDerivedSafe<T>::Release()
00241   {
00242     return 0;
00243   }
00244 
00245 #endif
00246 
00247 
00248 
00249 template <class T>
00250 struct already_AddRefed
00251     /*
00252       ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
00253       |AddRef|ing it.  You might want to use this as a return type from a function
00254       that produces an already |AddRef|ed pointer as a result.
00255 
00256       See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
00257 
00258       This type should be a nested class inside |nsCOMPtr<T>|.
00259 
00260       Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
00261       avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
00262       case, and perhaps worth the savings in time and space that its specific
00263       implementation affords over the more general solution offered by
00264       |nsCOMPtr_helper|.
00265     */
00266   {
00267     already_AddRefed( T* aRawPtr )
00268         : mRawPtr(aRawPtr)
00269       {
00270         // nothing else to do here
00271       }
00272 
00273     T* get() const { return mRawPtr; }
00274 
00275     T* mRawPtr;
00276   };
00277 
00278 template <class T>
00279 inline
00280 const already_AddRefed<T>
00281 getter_AddRefs( T* aRawPtr )
00282     /*
00283       ...makes typing easier, because it deduces the template type, e.g., 
00284       you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
00285     */
00286   {
00287     return already_AddRefed<T>(aRawPtr);
00288   }
00289 
00290 template <class T>
00291 inline
00292 const already_AddRefed<T>
00293 getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
00294   {
00295     return aAlreadyAddRefedPtr;
00296   }
00297 
00298 template <class T>
00299 inline
00300 const already_AddRefed<T>
00301 dont_AddRef( T* aRawPtr )
00302   {
00303     return already_AddRefed<T>(aRawPtr);
00304   }
00305 
00306 template <class T>
00307 inline
00308 const already_AddRefed<T>
00309 dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
00310   {
00311     return aAlreadyAddRefedPtr;
00312   }
00313 
00314 
00315 
00316 class nsCOMPtr_helper
00317     /*
00318       An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
00319       that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
00320       Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
00321 
00322       Here are the rules for a helper:
00323         - it implements |operator()| to produce an interface pointer
00324         - (except for its name) |operator()| is a valid [XP]COM `getter'
00325         - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
00326         - it matches the type requested with the supplied |nsIID| argument
00327         - its constructor provides an optional |nsresult*| that |operator()| can fill
00328           in with an error when it is executed
00329           
00330       See |class nsGetInterface| for an example.
00331     */
00332   {
00333     public:
00334       virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
00335   };
00336 
00337 /*
00338   |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
00339   avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
00340   is called often enough that the codesize savings are big enough to
00341   warrant the specialcasing.
00342 */
00343 
00344 class NS_COM_GLUE nsQueryInterface
00345   {
00346     public:
00347       explicit
00348       nsQueryInterface( nsISupports* aRawPtr )
00349           : mRawPtr(aRawPtr)
00350         {
00351           // nothing else to do here
00352         }
00353 
00354       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
00355 
00356     private:
00357       nsISupports*  mRawPtr;
00358   };
00359 
00360 class NS_COM_GLUE nsQueryInterfaceWithError
00361   {
00362     public:
00363       nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
00364           : mRawPtr(aRawPtr),
00365             mErrorPtr(error)
00366         {
00367           // nothing else to do here
00368         }
00369 
00370       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
00371 
00372     private:
00373       nsISupports*  mRawPtr;
00374       nsresult*     mErrorPtr;
00375   };
00376 
00377 inline
00378 nsQueryInterface
00379 do_QueryInterface( nsISupports* aRawPtr )
00380   {
00381     return nsQueryInterface(aRawPtr);
00382   }
00383 
00384 inline
00385 nsQueryInterfaceWithError
00386 do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
00387   {
00388     return nsQueryInterfaceWithError(aRawPtr, error);
00389   }
00390 
00391 template <class T>
00392 inline
00393 void
00394 do_QueryInterface( already_AddRefed<T>& )
00395   {
00396     // This signature exists soley to _stop_ you from doing the bad thing.
00397     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
00398     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
00399   }
00400 
00401 template <class T>
00402 inline
00403 void
00404 do_QueryInterface( already_AddRefed<T>&, nsresult* )
00405   {
00406     // This signature exists soley to _stop_ you from doing the bad thing.
00407     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
00408     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
00409   }
00410 
00411 
00413 // Using servicemanager with COMPtrs
00414 class NS_COM_GLUE nsGetServiceByCID
00415 {
00416  public:
00417     nsGetServiceByCID(const nsCID& aCID)
00418         : mCID(aCID)
00419         {
00420             // nothing else to do
00421         }
00422     
00423     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
00424     
00425  private:
00426     const nsCID&                mCID;
00427 };
00428 
00429 class NS_COM_GLUE nsGetServiceByCIDWithError
00430 {
00431  public:
00432     nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
00433         : mCID(aCID),
00434           mErrorPtr(aErrorPtr)
00435         {
00436             // nothing else to do
00437         }
00438     
00439     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
00440     
00441  private:
00442     const nsCID&                mCID;
00443     nsresult*                   mErrorPtr;
00444 };
00445 
00446 class NS_COM_GLUE nsGetServiceByContractID
00447 {
00448  public:
00449     nsGetServiceByContractID(const char* aContractID)
00450         : mContractID(aContractID)
00451         {
00452             // nothing else to do
00453         }
00454     
00455     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
00456     
00457  private:
00458     const char*                 mContractID;
00459 };
00460 
00461 class NS_COM_GLUE nsGetServiceByContractIDWithError
00462 {
00463  public:
00464     nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
00465         : mContractID(aContractID),
00466           mErrorPtr(aErrorPtr)
00467         {
00468             // nothing else to do
00469         }
00470     
00471     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
00472     
00473  private:
00474     const char*                 mContractID;
00475     nsresult*                   mErrorPtr;
00476 };
00477 
00478 class nsCOMPtr_base
00479     /*
00480       ...factors implementation for all template versions of |nsCOMPtr|.
00481 
00482       This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
00483       because unlike the
00484 
00485       Here's the way people normally do things like this
00486       
00487         template <class T> class Foo { ... };
00488         template <> class Foo<void*> { ... };
00489         template <class T> class Foo<T*> : private Foo<void*> { ... };
00490     */
00491   {
00492     public:
00493 
00494       nsCOMPtr_base( nsISupports* rawPtr = 0 )
00495           : mRawPtr(rawPtr)
00496         {
00497           // nothing else to do here
00498         }
00499 
00500       NS_COM_GLUE NS_FASTCALL ~nsCOMPtr_base();
00501 
00502       NS_COM_GLUE void NS_FASTCALL   assign_with_AddRef( nsISupports* );
00503       NS_COM_GLUE void NS_FASTCALL   assign_from_qi( const nsQueryInterface, const nsIID& );
00504       NS_COM_GLUE void NS_FASTCALL   assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
00505       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
00506       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
00507       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
00508       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
00509       NS_COM_GLUE void NS_FASTCALL   assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
00510       NS_COM_GLUE void** NS_FASTCALL begin_assignment();
00511 
00512     protected:
00513       NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
00514 
00515       void
00516       assign_assuming_AddRef( nsISupports* newPtr )
00517         {
00518             /*
00519               |AddRef()|ing the new value (before entering this function) before
00520               |Release()|ing the old lets us safely ignore the self-assignment case.
00521               We must, however, be careful only to |Release()| _after_ doing the
00522               assignment, in case the |Release()| leads to our _own_ destruction,
00523               which would, in turn, cause an incorrect second |Release()| of our old
00524               pointer.  Thank <waterson@netscape.com> for discovering this.
00525             */
00526           nsISupports* oldPtr = mRawPtr;
00527           mRawPtr = newPtr;
00528           NSCAP_LOG_ASSIGNMENT(this, newPtr);
00529           NSCAP_LOG_RELEASE(this, oldPtr);
00530           if ( oldPtr )
00531             NSCAP_RELEASE(this, oldPtr);
00532         }
00533   };
00534 
00535 // template <class T> class nsGetterAddRefs;
00536 
00537 template <class T>
00538 class nsCOMPtr
00539 #ifdef NSCAP_FEATURE_USE_BASE
00540     : private nsCOMPtr_base
00541 #endif
00542   {
00543 
00544 #ifdef NSCAP_FEATURE_USE_BASE
00545   #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
00546 #else
00547   #define NSCAP_CTOR_BASE(x) mRawPtr(x)
00548 
00549     private:
00550       void    assign_with_AddRef( nsISupports* );
00551       void    assign_from_qi( const nsQueryInterface, const nsIID& );
00552       void    assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
00553       void    assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
00554       void    assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
00555       void    assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
00556       void    assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
00557       void    assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
00558       void**  begin_assignment();
00559 
00560       void
00561       assign_assuming_AddRef( T* newPtr )
00562         {
00563           T* oldPtr = mRawPtr;
00564           mRawPtr = newPtr;
00565           NSCAP_LOG_ASSIGNMENT(this, newPtr);
00566           NSCAP_LOG_RELEASE(this, oldPtr);
00567           if ( oldPtr )
00568             NSCAP_RELEASE(this, oldPtr);
00569         }
00570 
00571     private:
00572       T* mRawPtr;
00573 #endif
00574 
00575     public:
00576       typedef T element_type;
00577       
00578 #ifndef NSCAP_FEATURE_USE_BASE
00579      ~nsCOMPtr()
00580         {
00581           NSCAP_LOG_RELEASE(this, mRawPtr);
00582           if ( mRawPtr )
00583             NSCAP_RELEASE(this, mRawPtr);
00584         }
00585 #endif
00586 
00587 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
00588       void
00589       Assert_NoQueryNeeded()
00590         {
00591           if ( mRawPtr )
00592             {
00593               nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
00594               NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
00595             }
00596         }
00597 
00598   #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
00599 #else
00600   #define NSCAP_ASSERT_NO_QUERY_NEEDED()
00601 #endif
00602 
00603 
00604         // Constructors
00605 
00606       nsCOMPtr()
00607             : NSCAP_CTOR_BASE(0)
00608           // default constructor
00609         {
00610           NSCAP_LOG_ASSIGNMENT(this, 0);
00611         }
00612 
00613       nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
00614             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
00615           // copy-constructor
00616         {
00617           if ( mRawPtr )
00618             NSCAP_ADDREF(this, mRawPtr);
00619           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
00620         }
00621 
00622       nsCOMPtr( T* aRawPtr )
00623             : NSCAP_CTOR_BASE(aRawPtr)
00624           // construct from a raw pointer (of the right type)
00625         {
00626           if ( mRawPtr )
00627             NSCAP_ADDREF(this, mRawPtr);
00628           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
00629           NSCAP_ASSERT_NO_QUERY_NEEDED();
00630         }
00631 
00632       nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
00633             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
00634           // construct from |dont_AddRef(expr)|
00635         {
00636           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
00637           NSCAP_ASSERT_NO_QUERY_NEEDED();
00638         }
00639 
00640       nsCOMPtr( const nsQueryInterface qi )
00641             : NSCAP_CTOR_BASE(0)
00642           // construct from |do_QueryInterface(expr)|
00643         {
00644           NSCAP_LOG_ASSIGNMENT(this, 0);
00645           assign_from_qi(qi, NS_GET_IID(T));
00646         }
00647 
00648       nsCOMPtr( const nsQueryInterfaceWithError& qi )
00649             : NSCAP_CTOR_BASE(0)
00650           // construct from |do_QueryInterface(expr, &rv)|
00651         {
00652           NSCAP_LOG_ASSIGNMENT(this, 0);
00653           assign_from_qi_with_error(qi, NS_GET_IID(T));
00654         }
00655 
00656       nsCOMPtr( const nsGetServiceByCID gs )
00657             : NSCAP_CTOR_BASE(0)
00658           // construct from |do_GetService(cid_expr)|
00659         {
00660           NSCAP_LOG_ASSIGNMENT(this, 0);
00661           assign_from_gs_cid(gs, NS_GET_IID(T));
00662         }
00663 
00664       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
00665             : NSCAP_CTOR_BASE(0)
00666           // construct from |do_GetService(cid_expr, &rv)|
00667         {
00668           NSCAP_LOG_ASSIGNMENT(this, 0);
00669           assign_from_gs_cid_with_error(gs, NS_GET_IID(T));
00670         }
00671 
00672       nsCOMPtr( const nsGetServiceByContractID gs )
00673             : NSCAP_CTOR_BASE(0)
00674           // construct from |do_GetService(contractid_expr)|
00675         {
00676           NSCAP_LOG_ASSIGNMENT(this, 0);
00677           assign_from_gs_contractid(gs, NS_GET_IID(T));
00678         }
00679 
00680       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
00681             : NSCAP_CTOR_BASE(0)
00682           // construct from |do_GetService(contractid_expr, &rv)|
00683         {
00684           NSCAP_LOG_ASSIGNMENT(this, 0);
00685           assign_from_gs_contractid_with_error(gs, NS_GET_IID(T));
00686         }
00687 
00688       nsCOMPtr( const nsCOMPtr_helper& helper )
00689             : NSCAP_CTOR_BASE(0)
00690           // ...and finally, anything else we might need to construct from
00691           //  can exploit the |nsCOMPtr_helper| facility
00692         {
00693           NSCAP_LOG_ASSIGNMENT(this, 0);
00694           assign_from_helper(helper, NS_GET_IID(T));
00695           NSCAP_ASSERT_NO_QUERY_NEEDED();
00696         }
00697 
00698 
00699         // Assignment operators
00700 
00701       nsCOMPtr<T>&
00702       operator=( const nsCOMPtr<T>& rhs )
00703           // copy assignment operator
00704         {
00705           assign_with_AddRef(rhs.mRawPtr);
00706           return *this;
00707         }
00708 
00709       nsCOMPtr<T>&
00710       operator=( T* rhs )
00711           // assign from a raw pointer (of the right type)
00712         {
00713           assign_with_AddRef(rhs);
00714           NSCAP_ASSERT_NO_QUERY_NEEDED();
00715           return *this;
00716         }
00717 
00718       nsCOMPtr<T>&
00719       operator=( const already_AddRefed<T>& rhs )
00720           // assign from |dont_AddRef(expr)|
00721         {
00722           assign_assuming_AddRef(rhs.mRawPtr);
00723           NSCAP_ASSERT_NO_QUERY_NEEDED();
00724           return *this;
00725         }
00726 
00727       nsCOMPtr<T>&
00728       operator=( const nsQueryInterface rhs )
00729           // assign from |do_QueryInterface(expr)|
00730         {
00731           assign_from_qi(rhs, NS_GET_IID(T));
00732           return *this;
00733         }
00734 
00735       nsCOMPtr<T>&
00736       operator=( const nsQueryInterfaceWithError& rhs )
00737           // assign from |do_QueryInterface(expr, &rv)|
00738         {
00739           assign_from_qi_with_error(rhs, NS_GET_IID(T));
00740           return *this;
00741         }
00742 
00743       nsCOMPtr<T>&
00744       operator=( const nsGetServiceByCID rhs )
00745           // assign from |do_GetService(cid_expr)|
00746         {
00747           assign_from_gs_cid(rhs, NS_GET_IID(T));
00748           return *this;
00749         }
00750 
00751       nsCOMPtr<T>&
00752       operator=( const nsGetServiceByCIDWithError& rhs )
00753           // assign from |do_GetService(cid_expr, &rv)|
00754         {
00755           assign_from_gs_cid_with_error(rhs, NS_GET_IID(T));
00756           return *this;
00757         }
00758 
00759       nsCOMPtr<T>&
00760       operator=( const nsGetServiceByContractID rhs )
00761           // assign from |do_GetService(contractid_expr)|
00762         {
00763           assign_from_gs_contractid(rhs, NS_GET_IID(T));
00764           return *this;
00765         }
00766 
00767       nsCOMPtr<T>&
00768       operator=( const nsGetServiceByContractIDWithError& rhs )
00769           // assign from |do_GetService(contractid_expr, &rv)|
00770         {
00771           assign_from_gs_contractid_with_error(rhs, NS_GET_IID(T));
00772           return *this;
00773         }
00774 
00775       nsCOMPtr<T>&
00776       operator=( const nsCOMPtr_helper& rhs )
00777           // ...and finally, anything else we might need to assign from
00778           //  can exploit the |nsCOMPtr_helper| facility.
00779         {
00780           assign_from_helper(rhs, NS_GET_IID(T));
00781           NSCAP_ASSERT_NO_QUERY_NEEDED();
00782           return *this;
00783         }
00784 
00785       void
00786       swap( nsCOMPtr<T>& rhs )
00787           // ...exchange ownership with |rhs|; can save a pair of refcount operations
00788         {
00789 #ifdef NSCAP_FEATURE_USE_BASE
00790           nsISupports* temp = rhs.mRawPtr;
00791 #else
00792           T* temp = rhs.mRawPtr;
00793 #endif
00794           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
00795           NSCAP_LOG_ASSIGNMENT(this, temp);
00796           NSCAP_LOG_RELEASE(this, mRawPtr);
00797           NSCAP_LOG_RELEASE(&rhs, temp);
00798           rhs.mRawPtr = mRawPtr;
00799           mRawPtr = temp;
00800           // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
00801         }
00802 
00803       void
00804       swap( T*& rhs )
00805           // ...exchange ownership with |rhs|; can save a pair of refcount operations
00806         {
00807 #ifdef NSCAP_FEATURE_USE_BASE
00808           nsISupports* temp = rhs;
00809 #else
00810           T* temp = rhs;
00811 #endif
00812           NSCAP_LOG_ASSIGNMENT(this, temp);
00813           NSCAP_LOG_RELEASE(this, mRawPtr);
00814           rhs = NS_REINTERPRET_CAST(T*, mRawPtr);
00815           mRawPtr = temp;
00816           NSCAP_ASSERT_NO_QUERY_NEEDED();
00817         }
00818 
00819 
00820         // Other pointer operators
00821 
00822       nsDerivedSafe<T>*
00823       get() const
00824           /*
00825             Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
00826              Use |get()| _only_ to resolve ambiguity.
00827 
00828             Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
00829           */
00830         {
00831           return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
00832         }
00833 
00834       operator nsDerivedSafe<T>*() const
00835           /*
00836             ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
00837               and |delete|) whenever it is used in a context where a raw pointer is expected.  It is this operator
00838               that makes an |nsCOMPtr| substitutable for a raw pointer.
00839 
00840             Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
00841           */
00842         {
00843           return get();
00844         }
00845 
00846       nsDerivedSafe<T>*
00847       operator->() const
00848         {
00849           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
00850           return get();
00851         }
00852 
00853 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
00854   // broken version for IRIX
00855 
00856       nsCOMPtr<T>*
00857       get_address() const
00858           // This is not intended to be used by clients.  See |address_of|
00859           // below.
00860         {
00861           return NS_CONST_CAST(nsCOMPtr<T>*, this);
00862         }
00863 
00864 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00865 
00866       nsCOMPtr<T>*
00867       get_address()
00868           // This is not intended to be used by clients.  See |address_of|
00869           // below.
00870         {
00871           return this;
00872         }
00873 
00874       const nsCOMPtr<T>*
00875       get_address() const
00876           // This is not intended to be used by clients.  See |address_of|
00877           // below.
00878         {
00879           return this;
00880         }
00881 
00882 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00883 
00884     public:
00885       nsDerivedSafe<T>&
00886       operator*() const
00887         {
00888           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
00889           return *get();
00890         }
00891 
00892 #if 0
00893     private:
00894       friend class nsGetterAddRefs<T>;
00895 #endif
00896 
00897       T**
00898       StartAssignment()
00899         {
00900 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
00901           return NS_REINTERPRET_CAST(T**, begin_assignment());
00902 #else
00903           assign_assuming_AddRef(0);
00904           return NS_REINTERPRET_CAST(T**, &mRawPtr);
00905 #endif
00906         }
00907   };
00908 
00909 
00910 
00911   /*
00912     Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
00913     same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
00914     to any valid [XP]COM interface.  Otherwise, an |nsCOMPtr<nsISupports>| would only be able
00915     to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
00916     querying ensues.  Clients need to be able to pass around arbitrary interface pointers,
00917     without hassles, through intermediary code that doesn't know the exact type.
00918   */
00919 
00920 NS_SPECIALIZE_TEMPLATE
00921 class nsCOMPtr<nsISupports>
00922     : private nsCOMPtr_base
00923   {
00924     public:
00925       typedef nsISupports element_type;
00926 
00927         // Constructors
00928 
00929       nsCOMPtr()
00930             : nsCOMPtr_base(0)
00931           // default constructor
00932         {
00933           NSCAP_LOG_ASSIGNMENT(this, 0);
00934         }
00935 
00936       nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
00937             : nsCOMPtr_base(aSmartPtr.mRawPtr)
00938           // copy constructor
00939         {
00940           if ( mRawPtr )
00941             NSCAP_ADDREF(this, mRawPtr);
00942           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
00943         }
00944 
00945       nsCOMPtr( nsISupports* aRawPtr )
00946             : nsCOMPtr_base(aRawPtr)
00947           // construct from a raw pointer (of the right type)
00948         {
00949           if ( mRawPtr )
00950             NSCAP_ADDREF(this, mRawPtr);
00951           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
00952         }
00953 
00954       nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
00955             : nsCOMPtr_base(aSmartPtr.mRawPtr)
00956           // construct from |dont_AddRef(expr)|
00957         {
00958           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
00959         }
00960 
00961       nsCOMPtr( const nsQueryInterface qi )
00962             : nsCOMPtr_base(0)
00963           // assign from |do_QueryInterface(expr)|
00964         {
00965           NSCAP_LOG_ASSIGNMENT(this, 0);
00966           assign_from_qi(qi, NS_GET_IID(nsISupports));
00967         }
00968 
00969       nsCOMPtr( const nsQueryInterfaceWithError& qi )
00970             : nsCOMPtr_base(0)
00971           // assign from |do_QueryInterface(expr, &rv)|
00972         {
00973           NSCAP_LOG_ASSIGNMENT(this, 0);
00974           assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
00975         }
00976 
00977       nsCOMPtr( const nsGetServiceByCID gs )
00978             : nsCOMPtr_base(0)
00979           // assign from |do_GetService(cid_expr)|
00980         {
00981           NSCAP_LOG_ASSIGNMENT(this, 0);
00982           assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
00983         }
00984 
00985       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
00986             : nsCOMPtr_base(0)
00987           // assign from |do_GetService(cid_expr, &rv)|
00988         {
00989           NSCAP_LOG_ASSIGNMENT(this, 0);
00990           assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
00991         }
00992 
00993       nsCOMPtr( const nsGetServiceByContractID gs )
00994             : nsCOMPtr_base(0)
00995           // assign from |do_GetService(contractid_expr)|
00996         {
00997           NSCAP_LOG_ASSIGNMENT(this, 0);
00998           assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
00999         }
01000 
01001       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
01002             : nsCOMPtr_base(0)
01003           // assign from |do_GetService(contractid_expr, &rv)|
01004         {
01005           NSCAP_LOG_ASSIGNMENT(this, 0);
01006           assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
01007         }
01008 
01009       nsCOMPtr( const nsCOMPtr_helper& helper )
01010             : nsCOMPtr_base(0)
01011           // ...and finally, anything else we might need to construct from
01012           //  can exploit the |nsCOMPtr_helper| facility
01013         {
01014           NSCAP_LOG_ASSIGNMENT(this, 0);
01015           assign_from_helper(helper, NS_GET_IID(nsISupports));
01016         }
01017 
01018 
01019         // Assignment operators
01020 
01021       nsCOMPtr<nsISupports>&
01022       operator=( const nsCOMPtr<nsISupports>& rhs )
01023           // copy assignment operator
01024         {
01025           assign_with_AddRef(rhs.mRawPtr);
01026           return *this;
01027         }
01028 
01029       nsCOMPtr<nsISupports>&
01030       operator=( nsISupports* rhs )
01031           // assign from a raw pointer (of the right type)
01032         {
01033           assign_with_AddRef(rhs);
01034           return *this;
01035         }
01036 
01037       nsCOMPtr<nsISupports>&
01038       operator=( const already_AddRefed<nsISupports>& rhs )
01039           // assign from |dont_AddRef(expr)|
01040         {
01041           assign_assuming_AddRef(rhs.mRawPtr);
01042           return *this;
01043         }
01044 
01045       nsCOMPtr<nsISupports>&
01046       operator=( const nsQueryInterface rhs )
01047           // assign from |do_QueryInterface(expr)|
01048         {
01049           assign_from_qi(rhs, NS_GET_IID(nsISupports));
01050           return *this;
01051         }
01052 
01053       nsCOMPtr<nsISupports>&
01054       operator=( const nsQueryInterfaceWithError& rhs )
01055           // assign from |do_QueryInterface(expr, &rv)|
01056         {
01057           assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
01058           return *this;
01059         }
01060 
01061       nsCOMPtr<nsISupports>&
01062       operator=( const nsGetServiceByCID rhs )
01063           // assign from |do_GetService(cid_expr)|
01064         {
01065           assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
01066           return *this;
01067         }
01068 
01069       nsCOMPtr<nsISupports>&
01070       operator=( const nsGetServiceByCIDWithError& rhs )
01071           // assign from |do_GetService(cid_expr, &rv)|
01072         {
01073           assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
01074           return *this;
01075         }
01076 
01077       nsCOMPtr<nsISupports>&
01078       operator=( const nsGetServiceByContractID rhs )
01079           // assign from |do_GetService(contractid_expr)|
01080         {
01081           assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
01082           return *this;
01083         }
01084 
01085       nsCOMPtr<nsISupports>&
01086       operator=( const nsGetServiceByContractIDWithError& rhs )
01087           // assign from |do_GetService(contractid_expr, &rv)|
01088         {
01089           assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
01090           return *this;
01091         }
01092 
01093       nsCOMPtr<nsISupports>&
01094       operator=( const nsCOMPtr_helper& rhs )
01095           // ...and finally, anything else we might need to assign from
01096           //  can exploit the |nsCOMPtr_helper| facility.
01097         {
01098           assign_from_helper(rhs, NS_GET_IID(nsISupports));
01099           return *this;
01100         }
01101 
01102       void
01103       swap( nsCOMPtr<nsISupports>& rhs )
01104           // ...exchange ownership with |rhs|; can save a pair of refcount operations
01105         {
01106           nsISupports* temp = rhs.mRawPtr;
01107           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
01108           NSCAP_LOG_ASSIGNMENT(this, temp);
01109           NSCAP_LOG_RELEASE(this, mRawPtr);
01110           NSCAP_LOG_RELEASE(&rhs, temp);
01111           rhs.mRawPtr = mRawPtr;
01112           mRawPtr = temp;
01113         }
01114 
01115       void
01116       swap( nsISupports*& rhs )
01117           // ...exchange ownership with |rhs|; can save a pair of refcount operations
01118         {
01119           nsISupports* temp = rhs;
01120           NSCAP_LOG_ASSIGNMENT(this, temp);
01121           NSCAP_LOG_RELEASE(this, mRawPtr);
01122           rhs = mRawPtr;
01123           mRawPtr = temp;
01124         }
01125 
01126 
01127         // Other pointer operators
01128 
01129       nsDerivedSafe<nsISupports>*
01130       get() const
01131           /*
01132             Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
01133              Use |get()| _only_ to resolve ambiguity.
01134 
01135             Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|.
01136           */
01137         {
01138           return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
01139         }
01140 
01141       operator nsDerivedSafe<nsISupports>*() const
01142           /*
01143             ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
01144               and |delete|) whenever it is used in a context where a raw pointer is expected.  It is this operator
01145               that makes an |nsCOMPtr| substitutable for a raw pointer.
01146 
01147             Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
01148           */
01149         {
01150           return get();
01151         }
01152 
01153       nsDerivedSafe<nsISupports>*
01154       operator->() const
01155         {
01156           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
01157           return get();
01158         }
01159 
01160 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
01161   // broken version for IRIX
01162 
01163       nsCOMPtr<nsISupports>*
01164       get_address() const
01165           // This is not intended to be used by clients.  See |address_of|
01166           // below.
01167         {
01168           return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this);
01169         }
01170 
01171 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
01172 
01173       nsCOMPtr<nsISupports>*
01174       get_address()
01175           // This is not intended to be used by clients.  See |address_of|
01176           // below.
01177         {
01178           return this;
01179         }
01180 
01181       const nsCOMPtr<nsISupports>*
01182       get_address() const
01183           // This is not intended to be used by clients.  See |address_of|
01184           // below.
01185         {
01186           return this;
01187         }
01188 
01189 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
01190 
01191     public:
01192 
01193       nsDerivedSafe<nsISupports>&
01194       operator*() const
01195         {
01196           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
01197           return *get();
01198         }
01199 
01200 #if 0
01201     private:
01202       friend class nsGetterAddRefs<nsISupports>;
01203 #endif
01204 
01205       nsISupports**
01206       StartAssignment()
01207         {
01208 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
01209           return NS_REINTERPRET_CAST(nsISupports**, begin_assignment());
01210 #else
01211           assign_assuming_AddRef(0);
01212           return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr);
01213 #endif
01214         }
01215   };
01216 
01217 #ifndef NSCAP_FEATURE_USE_BASE
01218 template <class T>
01219 void
01220 nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
01221   {
01222     if ( rawPtr )
01223       NSCAP_ADDREF(this, rawPtr);
01224     assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr));
01225   }
01226 
01227 template <class T>
01228 void
01229 nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
01230   {
01231     T* newRawPtr;
01232     if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
01233       newRawPtr = 0;
01234     assign_assuming_AddRef(newRawPtr);
01235   }
01236 
01237 template <class T>
01238 void
01239 nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
01240   {
01241     T* newRawPtr;
01242     if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
01243       newRawPtr = 0;
01244     assign_assuming_AddRef(newRawPtr);
01245   }
01246 
01247 template <class T>
01248 void
01249 nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
01250   {
01251     T* newRawPtr;
01252     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
01253       newRawPtr = 0;
01254     assign_assuming_AddRef(newRawPtr);
01255   }
01256 
01257 template <class T>
01258 void
01259 nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
01260   {
01261     T* newRawPtr;
01262     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
01263       newRawPtr = 0;
01264     assign_assuming_AddRef(newRawPtr);
01265   }
01266 
01267 template <class T>
01268 void
01269 nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
01270   {
01271     T* newRawPtr;
01272     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
01273       newRawPtr = 0;
01274     assign_assuming_AddRef(newRawPtr);
01275   }
01276 
01277 template <class T>
01278 void
01279 nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
01280   {
01281     T* newRawPtr;
01282     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
01283       newRawPtr = 0;
01284     assign_assuming_AddRef(newRawPtr);
01285   }
01286 
01287 template <class T>
01288 void
01289 nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
01290   {
01291     T* newRawPtr;
01292     if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
01293       newRawPtr = 0;
01294     assign_assuming_AddRef(newRawPtr);
01295   }
01296 
01297 template <class T>
01298 void**
01299 nsCOMPtr<T>::begin_assignment()
01300   {
01301     assign_assuming_AddRef(0);
01302     return NS_REINTERPRET_CAST(void**, &mRawPtr);
01303   }
01304 #endif
01305 
01306 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
01307 
01308 // This is the broken version for IRIX, which can't handle the version below.
01309 
01310 template <class T>
01311 inline
01312 nsCOMPtr<T>*
01313 address_of( const nsCOMPtr<T>& aPtr )
01314   {
01315     return aPtr.get_address();
01316   }
01317 
01318 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
01319 
01320 template <class T>
01321 inline
01322 nsCOMPtr<T>*
01323 address_of( nsCOMPtr<T>& aPtr )
01324   {
01325     return aPtr.get_address();
01326   }
01327 
01328 template <class T>
01329 inline
01330 const nsCOMPtr<T>*
01331 address_of( const nsCOMPtr<T>& aPtr )
01332   {
01333     return aPtr.get_address();
01334   }
01335 
01336 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
01337 
01338 template <class T>
01339 class nsGetterAddRefs
01340     /*
01341       ...
01342 
01343       This class is designed to be used for anonymous temporary objects in the
01344       argument list of calls that return COM interface pointers, e.g.,
01345 
01346         nsCOMPtr<IFoo> fooP;
01347         ...->QueryInterface(iid, getter_AddRefs(fooP))
01348 
01349       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()| instead.
01350 
01351       When initialized with a |nsCOMPtr|, as in the example above, it returns
01352       a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
01353       case) can fill in.
01354 
01355       This type should be a nested class inside |nsCOMPtr<T>|.
01356     */
01357   {
01358     public:
01359       explicit
01360       nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
01361           : mTargetSmartPtr(aSmartPtr)
01362         {
01363           // nothing else to do
01364         }
01365 
01366 #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
01367      ~nsGetterAddRefs()
01368         {
01369 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
01370           NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
01371 #endif
01372 
01373 #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
01374           mTargetSmartPtr.Assert_NoQueryNeeded();
01375 #endif
01376         }
01377 #endif
01378 
01379       operator void**()
01380         {
01381           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
01382         }
01383 
01384       operator nsISupports**()
01385         {
01386           return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignment());
01387         }
01388 
01389       operator T**()
01390         {
01391           return mTargetSmartPtr.StartAssignment();
01392         }
01393 
01394       T*&
01395       operator*()
01396         {
01397           return *(mTargetSmartPtr.StartAssignment());
01398         }
01399 
01400     private:
01401       nsCOMPtr<T>& mTargetSmartPtr;
01402   };
01403 
01404 
01405 NS_SPECIALIZE_TEMPLATE
01406 class nsGetterAddRefs<nsISupports>
01407   {
01408     public:
01409       explicit
01410       nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
01411           : mTargetSmartPtr(aSmartPtr)
01412         {
01413           // nothing else to do
01414         }
01415 
01416 #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
01417      ~nsGetterAddRefs()
01418         {
01419           NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
01420         }
01421 #endif
01422 
01423       operator void**()
01424         {
01425           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
01426         }
01427 
01428       operator nsISupports**()
01429         {
01430           return mTargetSmartPtr.StartAssignment();
01431         }
01432 
01433       nsISupports*&
01434       operator*()
01435         {
01436           return *(mTargetSmartPtr.StartAssignment());
01437         }
01438 
01439     private:
01440       nsCOMPtr<nsISupports>& mTargetSmartPtr;
01441   };
01442 
01443 
01444 template <class T>
01445 inline
01446 nsGetterAddRefs<T>
01447 getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
01448     /*
01449       Used around a |nsCOMPtr| when 
01450       ...makes the class |nsGetterAddRefs<T>| invisible.
01451     */
01452   {
01453     return nsGetterAddRefs<T>(aSmartPtr);
01454   }
01455 
01456 
01457 
01458   // Comparing two |nsCOMPtr|s
01459 
01460 template <class T, class U>
01461 inline
01462 NSCAP_BOOL
01463 operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
01464   {
01465     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
01466   }
01467 
01468 
01469 template <class T, class U>
01470 inline
01471 NSCAP_BOOL
01472 operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
01473   {
01474     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
01475   }
01476 
01477 
01478   // Comparing an |nsCOMPtr| to a raw pointer
01479 
01480 template <class T, class U>
01481 inline
01482 NSCAP_BOOL
01483 operator==( const nsCOMPtr<T>& lhs, const U* rhs )
01484   {
01485     return NS_STATIC_CAST(const T*, lhs.get()) == rhs;
01486   }
01487 
01488 template <class T, class U>
01489 inline
01490 NSCAP_BOOL
01491 operator==( const U* lhs, const nsCOMPtr<T>& rhs )
01492   {
01493     return lhs == NS_STATIC_CAST(const T*, rhs.get());
01494   }
01495 
01496 template <class T, class U>
01497 inline
01498 NSCAP_BOOL
01499 operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
01500   {
01501     return NS_STATIC_CAST(const T*, lhs.get()) != rhs;
01502   }
01503 
01504 template <class T, class U>
01505 inline
01506 NSCAP_BOOL
01507 operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
01508   {
01509     return lhs != NS_STATIC_CAST(const T*, rhs.get());
01510   }
01511 
01512   // To avoid ambiguities caused by the presence of builtin |operator==|s
01513   // creating a situation where one of the |operator==| defined above
01514   // has a better conversion for one argument and the builtin has a
01515   // better conversion for the other argument, define additional
01516   // |operator==| without the |const| on the raw pointer.
01517   // See bug 65664 for details.
01518 
01519 // This is defined by an autoconf test, but VC++ also has a bug that
01520 // prevents us from using these.  (It also, fortunately, has the bug
01521 // that we don't need them either.)
01522 #if defined(_MSC_VER) && (_MSC_VER < 1310)
01523 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
01524 #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
01525 #endif
01526 #endif
01527 
01528 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
01529 template <class T, class U>
01530 inline
01531 NSCAP_BOOL
01532 operator==( const nsCOMPtr<T>& lhs, U* rhs )
01533   {
01534     return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
01535   }
01536 
01537 template <class T, class U>
01538 inline
01539 NSCAP_BOOL
01540 operator==( U* lhs, const nsCOMPtr<T>& rhs )
01541   {
01542     return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
01543   }
01544 
01545 template <class T, class U>
01546 inline
01547 NSCAP_BOOL
01548 operator!=( const nsCOMPtr<T>& lhs, U* rhs )
01549   {
01550     return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
01551   }
01552 
01553 template <class T, class U>
01554 inline
01555 NSCAP_BOOL
01556 operator!=( U* lhs, const nsCOMPtr<T>& rhs )
01557   {
01558     return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
01559   }
01560 #endif
01561 
01562 
01563 
01564   // Comparing an |nsCOMPtr| to |0|
01565 
01566 class NSCAP_Zero;
01567 
01568 template <class T>
01569 inline
01570 NSCAP_BOOL
01571 operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
01572     // specifically to allow |smartPtr == 0|
01573   {
01574     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
01575   }
01576 
01577 template <class T>
01578 inline
01579 NSCAP_BOOL
01580 operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
01581     // specifically to allow |0 == smartPtr|
01582   {
01583     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
01584   }
01585 
01586 template <class T>
01587 inline
01588 NSCAP_BOOL
01589 operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
01590     // specifically to allow |smartPtr != 0|
01591   {
01592     return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
01593   }
01594 
01595 template <class T>
01596 inline
01597 NSCAP_BOOL
01598 operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
01599     // specifically to allow |0 != smartPtr|
01600   {
01601     return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
01602   }
01603 
01604 
01605 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
01606 
01607   // We need to explicitly define comparison operators for `int'
01608   // because the compiler is lame.
01609 
01610 template <class T>
01611 inline
01612 NSCAP_BOOL
01613 operator==( const nsCOMPtr<T>& lhs, int rhs )
01614     // specifically to allow |smartPtr == 0|
01615   {
01616     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
01617   }
01618 
01619 template <class T>
01620 inline
01621 NSCAP_BOOL
01622 operator==( int lhs, const nsCOMPtr<T>& rhs )
01623     // specifically to allow |0 == smartPtr|
01624   {
01625     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
01626   }
01627 
01628 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
01629 
01630   // Comparing any two [XP]COM objects for identity
01631 
01632 inline
01633 NSCAP_BOOL
01634 SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
01635   {
01636     return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
01637   }
01638 
01639 
01640 
01641 template <class SourceType, class DestinationType>
01642 inline
01643 nsresult
01644 CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
01645   {
01646     return CallQueryInterface(aSourcePtr.get(), aDestPtr);
01647   }
01648 
01649 #endif // !defined(nsCOMPtr_h___)